From 8011e1ea9a82a42c0dd907b5cd929c60e428b882 Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Sat, 5 Dec 2020 14:16:55 +0800 Subject: [PATCH 01/59] update headers --- inc/external/acl/acl_base.h | 1 + inc/external/acl/acl_op.h | 1 + inc/external/acl/acl_op_compiler.h | 1 + inc/external/acl/error_codes/ge_error_codes.h | 4 +- inc/external/acl/error_codes/rt_error_codes.h | 182 +++++----- inc/external/acl/ops/acl_cblas.h | 1 + inc/external/runtime/rt_error_codes.h | 182 +++++----- .../inc/aicpu/common/aicpu_task_struct.h | 4 +- third_party/fwkacllib/inc/cce/aicpu_engine.h | 15 +- third_party/fwkacllib/inc/hccl/hccl_types.h | 101 ------ third_party/fwkacllib/inc/hccl/hcom.h | 145 -------- .../fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h | 46 ++- .../inc/mmpa/sub_inc/mmpa_typedef_win.h | 2 +- .../fwkacllib/inc/mmpa/sub_inc/mmpa_win.h | 3 +- third_party/fwkacllib/inc/runtime/base.h | 315 +----------------- third_party/fwkacllib/inc/runtime/config.h | 18 +- third_party/fwkacllib/inc/runtime/context.h | 10 +- third_party/fwkacllib/inc/runtime/dev.h | 14 +- .../fwkacllib/inc/runtime/dvfsprofile.h | 10 +- third_party/fwkacllib/inc/runtime/event.h | 10 +- third_party/fwkacllib/inc/runtime/kernel.h | 10 +- third_party/fwkacllib/inc/runtime/mem.h | 10 +- third_party/fwkacllib/inc/runtime/rt.h | 10 +- third_party/fwkacllib/inc/runtime/rt_model.h | 10 +- third_party/fwkacllib/inc/runtime/stream.h | 10 +- .../fwkacllib/inc/tdt/index_transform.h | 20 +- third_party/fwkacllib/inc/tdt/status.h | 9 +- .../inc/toolchain/adx_datadump_server.h | 22 +- .../fwkacllib/inc/toolchain/prof_acl_api.h | 250 +++++++++++++- .../fwkacllib/inc/toolchain/prof_mgr_core.h | 9 + .../fwkacllib/inc/toolchain/prof_reporter.h | 10 +- third_party/fwkacllib/inc/toolchain/slog.h | 25 ++ .../inc/toolchain/tuning_tool/tune_api.h | 18 +- 33 files changed, 634 insertions(+), 844 deletions(-) delete mode 100644 third_party/fwkacllib/inc/hccl/hccl_types.h diff --git a/inc/external/acl/acl_base.h b/inc/external/acl/acl_base.h index 224a8ef0..debadcfd 100644 --- a/inc/external/acl/acl_base.h +++ b/inc/external/acl/acl_base.h @@ -110,6 +110,7 @@ static const int ACL_ERROR_DUMP_ALREADY_RUN = 100044; static const int ACL_ERROR_DUMP_NOT_RUN = 100045; static const int ACL_ERROR_PROF_REPEAT_SUBSCRIBE = 148046; static const int ACL_ERROR_PROF_API_CONFLICT = 148047; +static const int ACL_ERROR_INVALID_MAX_OPQUEUE_NUM_CONFIG = 148048; static const int ACL_ERROR_BAD_ALLOC = 200000; static const int ACL_ERROR_API_NOT_SUPPORT = 200001; diff --git a/inc/external/acl/acl_op.h b/inc/external/acl/acl_op.h index 882c6ae6..d2e59bfb 100644 --- a/inc/external/acl/acl_op.h +++ b/inc/external/acl/acl_op.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef INC_EXTERNAL_ACL_ACL_OP_H_ #define INC_EXTERNAL_ACL_ACL_OP_H_ diff --git a/inc/external/acl/acl_op_compiler.h b/inc/external/acl/acl_op_compiler.h index 9bf5adf0..adae90c7 100644 --- a/inc/external/acl/acl_op_compiler.h +++ b/inc/external/acl/acl_op_compiler.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef INC_EXTERNAL_ACL_ACL_OP_COMPILER_H_ #define INC_EXTERNAL_ACL_ACL_OP_COMPILER_H_ diff --git a/inc/external/acl/error_codes/ge_error_codes.h b/inc/external/acl/error_codes/ge_error_codes.h index 6f82a897..20a7e0f9 100644 --- a/inc/external/acl/error_codes/ge_error_codes.h +++ b/inc/external/acl/error_codes/ge_error_codes.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef INC_EXTERNAL_GE_GE_ERROR_CODES_H_ #define INC_EXTERNAL_GE_GE_ERROR_CODES_H_ @@ -25,13 +26,10 @@ static const uint32_t ACL_ERROR_GE_PARAM_INVALID = 145000; static const uint32_t ACL_ERROR_GE_EXEC_NOT_INIT = 145001; static const uint32_t ACL_ERROR_GE_EXEC_MODEL_PATH_INVALID = 145002; static const uint32_t ACL_ERROR_GE_EXEC_MODEL_ID_INVALID = 145003; -static const uint32_t ACL_ERROR_GE_EXEC_MODEL_KEY_PATH_INVALID = 145004; -static const uint32_t ACL_ERROR_GE_EXEC_MODEL_NOT_SUPPORT_ENCRYPTION = 145005; static const uint32_t ACL_ERROR_GE_EXEC_MODEL_DATA_SIZE_INVALID = 145006; static const uint32_t ACL_ERROR_GE_EXEC_MODEL_ADDR_INVALID = 145007; static const uint32_t ACL_ERROR_GE_EXEC_MODEL_QUEUE_ID_INVALID = 145008; static const uint32_t ACL_ERROR_GE_EXEC_LOAD_MODEL_REPEATED = 145009; -static const uint32_t ACL_ERROR_GE_EXEC_MODEL_PARTITION_NUM_INVALID = 145010; static const uint32_t ACL_ERROR_GE_DYNAMIC_INPUT_ADDR_INVALID = 145011; static const uint32_t ACL_ERROR_GE_DYNAMIC_INPUT_LENGTH_INVALID = 145012; static const uint32_t ACL_ERROR_GE_DYNAMIC_BATCH_SIZE_INVALID = 145013; diff --git a/inc/external/acl/error_codes/rt_error_codes.h b/inc/external/acl/error_codes/rt_error_codes.h index 0ae5303d..2dd2c70c 100644 --- a/inc/external/acl/error_codes/rt_error_codes.h +++ b/inc/external/acl/error_codes/rt_error_codes.h @@ -1,91 +1,91 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef __INC_EXTERNEL_RT_ERROR_CODES_H__ -#define __INC_EXTERNEL_RT_ERROR_CODES_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -static const int32_t ACL_RT_SUCCESS = 0; // success - -static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid -static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id -static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null -static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context -static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context -static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal -static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned -static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed -static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed -static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream -static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread -static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set -static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create -static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream -static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type - -static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPROT = 207000; // feature not support -static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error -static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error - -static const int32_t ACL_ERROR_RT_INTERNEL_ERROR = 507000; // runtime internel error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error - -static const int32_t ACL_ERROR_RT_DRV_INTERNEL_ERROR = 507899; // drv internel error - -#ifdef __cplusplus -} -#endif - -#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ +/** + * Copyright 2019-2020 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. + */ + +#ifndef __INC_EXTERNEL_RT_ERROR_CODES_H__ +#define __INC_EXTERNEL_RT_ERROR_CODES_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static const int32_t ACL_RT_SUCCESS = 0; // success + +static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid +static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id +static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null +static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context +static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context +static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal +static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned +static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed +static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed +static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream +static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread +static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set +static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create +static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream +static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type + +static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPROT = 207000; // feature not support +static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error +static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error + +static const int32_t ACL_ERROR_RT_INTERNEL_ERROR = 507000; // runtime internel error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error + +static const int32_t ACL_ERROR_RT_DRV_INTERNEL_ERROR = 507899; // drv internel error + +#ifdef __cplusplus +} +#endif + +#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/inc/external/acl/ops/acl_cblas.h b/inc/external/acl/ops/acl_cblas.h index 571a1183..3d81eb2b 100644 --- a/inc/external/acl/ops/acl_cblas.h +++ b/inc/external/acl/ops/acl_cblas.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef INC_EXTERNAL_ACL_OPS_ACL_CBLAS_H_ #define INC_EXTERNAL_ACL_OPS_ACL_CBLAS_H_ diff --git a/inc/external/runtime/rt_error_codes.h b/inc/external/runtime/rt_error_codes.h index 0ae5303d..2dd2c70c 100644 --- a/inc/external/runtime/rt_error_codes.h +++ b/inc/external/runtime/rt_error_codes.h @@ -1,91 +1,91 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef __INC_EXTERNEL_RT_ERROR_CODES_H__ -#define __INC_EXTERNEL_RT_ERROR_CODES_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -static const int32_t ACL_RT_SUCCESS = 0; // success - -static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid -static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id -static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null -static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context -static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context -static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal -static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned -static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed -static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed -static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream -static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread -static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set -static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create -static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream -static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type - -static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPROT = 207000; // feature not support -static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error -static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error - -static const int32_t ACL_ERROR_RT_INTERNEL_ERROR = 507000; // runtime internel error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error - -static const int32_t ACL_ERROR_RT_DRV_INTERNEL_ERROR = 507899; // drv internel error - -#ifdef __cplusplus -} -#endif - -#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ +/** + * Copyright 2019-2020 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. + */ + +#ifndef __INC_EXTERNEL_RT_ERROR_CODES_H__ +#define __INC_EXTERNEL_RT_ERROR_CODES_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static const int32_t ACL_RT_SUCCESS = 0; // success + +static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid +static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id +static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null +static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context +static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context +static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal +static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned +static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed +static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed +static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream +static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread +static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set +static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create +static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream +static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type + +static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPROT = 207000; // feature not support +static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error +static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error + +static const int32_t ACL_ERROR_RT_INTERNEL_ERROR = 507000; // runtime internel error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error + +static const int32_t ACL_ERROR_RT_DRV_INTERNEL_ERROR = 507899; // drv internel error + +#ifdef __cplusplus +} +#endif + +#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h b/third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h index c3672663..72e21f6f 100644 --- a/third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h +++ b/third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h @@ -21,13 +21,15 @@ namespace aicpu { +#pragma pack(push, 1) struct AicpuParamHead { uint32_t length; // Total length: include cunstom message uint32_t ioAddrNum; // Input and output address number uint32_t extInfoLength; // extInfo struct Length uint64_t extInfoAddr; // extInfo address -} __attribute__ ((packed)); +}; +#pragma pack(pop) } // namespace aicpu diff --git a/third_party/fwkacllib/inc/cce/aicpu_engine.h b/third_party/fwkacllib/inc/cce/aicpu_engine.h index 740f1200..8bf0bdb6 100644 --- a/third_party/fwkacllib/inc/cce/aicpu_engine.h +++ b/third_party/fwkacllib/inc/cce/aicpu_engine.h @@ -17,6 +17,8 @@ #ifndef AICPU_ENGINE_H__ #define AICPU_ENGINE_H__ +#include + #ifdef __cplusplus extern "C" { #endif @@ -36,12 +38,23 @@ typedef enum { /** * @ingroup aicpu engine * @brief aeCallInterface: - * a interface to call a function in a op kernfel lib + * a interface to call a function in a op kernfel lib * @param [in] addr void *, should be STR_KERNEL * format * @return aeStatus_t */ aeStatus_t aeCallInterface(void *addr); +/** + * @ingroup aicpu engine + * @brief aeBatchLoadKernelSo: + * a interface to load kernel so + * @param [in] loadSoNum load so number + * @param [in] soPaths load so paths + * @param [in] soNames load so names + * @return aeStatus_t + */ +aeStatus_t aeBatchLoadKernelSo(const uint32_t loadSoNum, const char *soPaths[], const char *soNames[]); + #ifdef __cplusplus } #endif diff --git a/third_party/fwkacllib/inc/hccl/hccl_types.h b/third_party/fwkacllib/inc/hccl/hccl_types.h deleted file mode 100644 index 50a64795..00000000 --- a/third_party/fwkacllib/inc/hccl/hccl_types.h +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -/** - * @file hccl_types.h - * @brief HCCL data type definition - * - */ - -#ifndef HCCL_TYPES_H_ -#define HCCL_TYPES_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -/** - * @brief HCCL functions return value definition - */ -typedef enum { - HCCL_SUCCESS = 0, /**< success */ - HCCL_E_PARA = 1, /**< parameter error */ - HCCL_E_PTR = 2, /**< empty pointer */ - HCCL_E_MEMORY = 3, /**< memory error */ - HCCL_E_INTERNAL = 4, /**< internal error */ - HCCL_E_NOT_SUPPORT = 5, /**< not support feature */ - HCCL_E_NOT_FOUND = 6, /**< not found specific resource */ - HCCL_E_UNAVAIL = 7, /**< resource unavailable */ - HCCL_E_SYSCALL = 8, /**< call system interface error */ - HCCL_E_TIMEOUT = 9, /**< timeout */ - HCCL_E_OPEN_FILE_FAILURE = 10, /**< open file fail */ - HCCL_E_TCP_CONNECT = 11, /**< tcp connect fail */ - HCCL_E_ROCE_CONNECT = 12, /**< roce connect fail */ - HCCL_E_TCP_TRANSFER = 13, /**< tcp transfer fail */ - HCCL_E_ROCE_TRANSFER = 14, /**< roce transfer fail */ - HCCL_E_RUNTIME = 15, /**< call runtime api fail */ - HCCL_E_DRV = 16, /**< call driver api fail */ - HCCL_E_PROFILING = 17, /**< call profiling api fail */ - HCCL_E_CCE = 18, /**< call cce api fail */ - HCCL_E_NETWORK = 19, /**< call network api fail */ - HCCL_E_RESERVED /**< reserved */ -} HcclResult; - -/** - * @brief handle to HCCL communicator - */ -typedef void *HcclComm; - -/** - * @brief HCCL Reduction opperation - */ -typedef enum { - HCCL_REDUCE_SUM = 0, /**< sum */ - HCCL_REDUCE_PROD = 1, /**< prod */ - HCCL_REDUCE_MAX = 2, /**< max */ - HCCL_REDUCE_MIN = 3, /**< min */ - HCCL_REDUCE_RESERVED /**< reserved */ -} HcclReduceOp; - -/** - * @brief HCCL data type - */ -typedef enum { - HCCL_DATA_TYPE_INT8 = 0, /**< int8 */ - HCCL_DATA_TYPE_INT16 = 1, /**< int16 */ - HCCL_DATA_TYPE_INT32 = 2, /**< int32 */ - HCCL_DATA_TYPE_FP16 = 3, /**< fp16 */ - HCCL_DATA_TYPE_FP32 = 4, /**< fp32 */ - HCCL_DATA_TYPE_INT64 = 5, /**< int64 */ - HCCL_DATA_TYPE_UINT64 = 6, /**< uint64 */ - HCCL_DATA_TYPE_RESERVED /**< reserved */ -} HcclDataType; - -const uint32_t HCCL_ROOT_INFO_BYTES = 4108; // 4108: root info length - -/** - * @brief HCCL root info - */ -typedef struct HcclRootInfoDef { - char internal[HCCL_ROOT_INFO_BYTES]; -} HcclRootInfo; - -#ifdef __cplusplus -} -#endif // __cplusplus -#endif // HCCL_TYPES_H_ diff --git a/third_party/fwkacllib/inc/hccl/hcom.h b/third_party/fwkacllib/inc/hccl/hcom.h index 90b96ac7..de140b4b 100644 --- a/third_party/fwkacllib/inc/hccl/hcom.h +++ b/third_party/fwkacllib/inc/hccl/hcom.h @@ -29,104 +29,7 @@ extern "C" { #endif // __cplusplus -/** - * @brief Initialize HCOM. - * - * @param rank_table A string identifying the rank table file path, include file name. - * @param identify A string identifying the identify for the rank. - * @return HcclResult - * @see hcom_destroy() - */ -extern HcclResult hcom_init(const char *rank_table, const char *identify); - -/** - * @brief Destroy HCOM - * - * @return HcclResult - * @see hcom_init() - */ -extern HcclResult hcom_destroy(void); - -/** - * @brief Bind the model. - * - * @param model A pointer identifying the model information. - * @param stream A pointer identifying the stream information. - * @return HcclResult - * @see hcom_unbind_model() - */ -extern HcclResult hcom_bind_model(rtModel_t model, rtStream_t stream); - -/** - * @brief Unbind the model. - * - * @param model An pointer identifying the model information. - * @return HcclResult - * @see hcom_unbind_model() - */ -extern HcclResult hcom_unbind_model(rtModel_t model); - -/** - * @brief All-gather operator. - * - * @param tag A string identifying the tag of the operator. - * @param inputPtr A pointer identifying the input data address of the operator. - * @param outputPtr A pointer identifying the output data address of the operator. - * @param inputCount An integer(u64) identifying the number of the input data. - * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. - * @param group A string identifying the group name of ranks participating in the operator. - * @param stream A pointer identifying the stream information. - * @return HcclResult - */ -extern HcclResult hcom_all_gather(const char *tag, void *inputPtr, void *outputPtr, u64 inputCount, - HcclDataType dataType, const char *group, rtStream_t stream); - -/** - * @brief All-reduce operator. - * - * @param tag A string identifying the tag of the operator. - * @param inputPtr A pointer identifying the input data address of the operator. - * @param outputPtr A pointer identifying the output data address of the operator. - * @param count An integer(u64) identifying the number of the output data. - * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. - * @param op The reduction type of the operator, must be one of the following types: sum, min, max, prod. - * @param group A string identifying the group name of ranks participating in the operator. - * @param stream A pointer identifying the stream information. - * @return HcclResult - */ -extern HcclResult hcom_all_reduce(const char *tag, void *inputPtr, void *outputPtr, u64 count, - HcclDataType dataType, HcclReduceOp op, const char *group, rtStream_t stream); - -/** - * @brief Broadcast operator. - * - * @param tag A string identifying the tag of the operator. - * @param ptr A pointer identifying the data address of the operator. - * @param count An integer(u64) identifying the number of the data. - * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. - * @param root An integer(u32) identifying the the root rank in the operator. - * @param group A string identifying the group name of ranks participating in the operator. - * @param stream A pointer identifying the stream information. - * @return HcclResult - */ -extern HcclResult hcom_broadcast(const char *tag, void *ptr, u64 count, HcclDataType dataType, u32 root, - const char *group, rtStream_t stream); -/** - * @brief Reduce-scatter operator. - * - * @param tag A string identifying the tag of the operator. - * @param inputPtr A pointer identifying the input data address of the operator. - * @param outputPtr A pointer identifying the output data address of the operator. - * @param count An integer(u64) identifying the number of the data. - * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. - * @param op The reduction type of the operator, must be one of the following types: sum, min, max, prod. - * @param group A string identifying the group name of ranks participating in the operator. - * @param stream A pointer identifying the stream information. - * @return HcclResult - */ -extern HcclResult hcom_reduce_scatter(const char *tag, void *inputPtr, void *outputPtr, u64 count, - HcclDataType dataType, HcclReduceOp op, const char *group, rtStream_t stream); /** * @brief Get the rank number in the group. @@ -202,54 +105,6 @@ HcclResult hcom_create_group(const char *group, u32 rankNum, u32 *rankIds); */ HcclResult hcom_destroy_group(const char *group); -/** - * @brief Send operator. - * - * @param tag A string identifying the tag of the operator. - * @param inputPtr A pointer identifying the input data address of the operator. - * @param count An integer(u64) identifying the number of the data. - * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. - * @param destRank An integer identifying the destination rank. - * @param srTag An integer identifying the send/recv message tag. - * The message will be send by the receive operator with the same "sr_tag". - * @param group A string identifying the group name of ranks participating in the operator. - * @param stream A pointer identifying the stream information. - * @return HcclResult - */ -HcclResult hcom_send(const char *tag, void *inputPtr, u64 count, HcclDataType dataType, - u32 destRank, u32 srTag, const char *group, rtStream_t stream); - -/** - * @brief Receive operator. - * - * @param tag A string identifying the tag of the operator. - * @param outputPtr A pointer identifying the output data address of the operator. - * @param count An integer(u64) identifying the number of the data. - * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. - * @param srcRank An integer identifying the source rank. - * @param srTag An integer identifying the send/recv message tag. - * The message will be send by the send operator with the same "sr_tag". - * @param group A string identifying the group name of ranks participating in the operator. - * @param stream A pointer identifying the stream information. - * @return HcclResult - */ -HcclResult hcom_receive(const char *tag, void *outputPtr, u64 count, HcclDataType dataType, - u32 srcRank, u32 srTag, const char *group, rtStream_t stream); - -/** - * @brief Get the gradient split strategy with in the group. - * - * @param group A string identifying the group name. - * @param feature A pointer identifying the feature of the model. - * @param maxSegmentNum An integer(u32) identifying the max segments of gradients. - * @param segmentNum A pointer identifying the segments number of gradients. - * @param segmentIdx A list identifying the index of end gradient in each segment. - * @return HcclResult - */ -HcclResult hcom_get_split_strategy(const char *group, const struct model_feature *feature, u32 maxSegmentNum, - u32 *segmentNum, u32 *segmentIdx, GradSplitForceMode force = FORCE_NONE, - OriginalGraphShapeType shapeType = KNOWN_SHAPE); - /** * @brief Set the gradient split strategy with in the group, according to gradient index. * diff --git a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h index ea51f497..c74f95ac 100644 --- a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h +++ b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h @@ -227,6 +227,7 @@ typedef struct { #define M_BINARY O_RDONLY #define M_TRUNC O_TRUNC #define M_IRWXU S_IRWXU +#define M_APPEND O_APPEND #define M_IN_CREATE IN_CREATE #define M_IN_CLOSE_WRITE IN_CLOSE_WRITE @@ -342,17 +343,17 @@ MMPA_FUNC_VISIBILITY INT32 mmCloseSocket(mmSockHandle sockFd); MMPA_FUNC_VISIBILITY mmSsize_t mmSocketSend(mmSockHandle sockFd, VOID *sendBuf, INT32 sendLen, INT32 sendFlag); MMPA_FUNC_VISIBILITY mmSsize_t mmSocketRecv(mmSockHandle sockFd, VOID *recvBuf, INT32 recvLen, INT32 recvFlag); MMPA_FUNC_VISIBILITY INT32 mmSocketSendTo(mmSockHandle sockFd, - VOID *sendMsg, - INT32 sendLen, - UINT32 sendFlag, - const mmSockAddr* addr, - INT32 tolen); + VOID *sendMsg, + INT32 sendLen, + UINT32 sendFlag, + const mmSockAddr* addr, + INT32 tolen); MMPA_FUNC_VISIBILITY mmSsize_t mmSocketRecvFrom(mmSockHandle sockFd, - VOID *recvBuf, - mmSize recvLen, - UINT32 recvFlag, - mmSockAddr* addr, - mmSocklen_t *FromLen); + VOID *recvBuf, + mmSize recvLen, + UINT32 recvFlag, + mmSockAddr* addr, + mmSocklen_t *FromLen); MMPA_FUNC_VISIBILITY INT32 mmSAStartup(); MMPA_FUNC_VISIBILITY INT32 mmSACleanup(); MMPA_FUNC_VISIBILITY VOID *mmDlopen(const CHAR *fileName, INT32 mode); @@ -360,7 +361,10 @@ MMPA_FUNC_VISIBILITY INT32 mmDladdr(VOID *addr, mmDlInfo *info); MMPA_FUNC_VISIBILITY VOID *mmDlsym(VOID *handle, const CHAR *funcName); MMPA_FUNC_VISIBILITY INT32 mmDlclose(VOID *handle); MMPA_FUNC_VISIBILITY CHAR *mmDlerror(); -MMPA_FUNC_VISIBILITY INT32 mmCreateAndSetTimer(mmTimer *timerHandle, mmUserBlock_t *timerBlock, UINT milliSecond, UINT period); +MMPA_FUNC_VISIBILITY INT32 mmCreateAndSetTimer(mmTimer *timerHandle, + mmUserBlock_t *timerBlock, + UINT milliSecond, + UINT period); MMPA_FUNC_VISIBILITY INT32 mmDeleteTimer(mmTimer timerHandle); MMPA_FUNC_VISIBILITY INT32 mmStatGet(const CHAR *path, mmStat_t *buffer); MMPA_FUNC_VISIBILITY INT32 mmStat64Get(const CHAR *path, mmStat64_t *buffer); @@ -454,8 +458,11 @@ MMPA_FUNC_VISIBILITY VOID mmSetOpOpt(INT32 mmOptOpt); MMPA_FUNC_VISIBILITY CHAR *mmGetOptArg(); MMPA_FUNC_VISIBILITY VOID mmSetOptArg(CHAR *mmOptArg); MMPA_FUNC_VISIBILITY INT32 mmGetOpt(INT32 argc, char *const *argv, const char *opts); -MMPA_FUNC_VISIBILITY INT32 mmGetOptLong(INT32 argc, char *const *argv, const char *opts, const mmStructOption *longOpts, - INT32 *longIndex); +MMPA_FUNC_VISIBILITY INT32 mmGetOptLong(INT32 argc, + char *const *argv, + const char *opts, + const mmStructOption *longOpts, + INT32 *longIndex); MMPA_FUNC_VISIBILITY LONG mmLseek(INT32 fd, INT64 offset, INT32 seekFlag); MMPA_FUNC_VISIBILITY INT32 mmFtruncate(mmProcess fd, UINT32 length); @@ -521,11 +528,14 @@ MMPA_FUNC_VISIBILITY INT32 mmGetMac(mmMacInfo **list, INT32 *count); MMPA_FUNC_VISIBILITY INT32 mmGetMacFree(mmMacInfo *list, INT32 count); MMPA_FUNC_VISIBILITY INT32 mmGetCpuInfo(mmCpuDesc **cpuInfo, INT32 *count); MMPA_FUNC_VISIBILITY INT32 mmCpuInfoFree(mmCpuDesc *cpuInfo, INT32 count); -MMPA_FUNC_VISIBILITY INT32 mmCreateProcess(const CHAR *fileName, const mmArgvEnv *env, const char *stdoutRedirectFile, - mmProcess *id); - -MMPA_FUNC_VISIBILITY INT32 mmCreateTaskWithThreadAttr(mmThread *threadHandle, const mmUserBlock_t *funcBlock, - const mmThreadAttr *threadAttr); +MMPA_FUNC_VISIBILITY INT32 mmCreateProcess(const CHAR *fileName, + const mmArgvEnv *env, + const char *stdoutRedirectFile, + mmProcess *id); + +MMPA_FUNC_VISIBILITY INT32 mmCreateTaskWithThreadAttr(mmThread *threadHandle, + const mmUserBlock_t *funcBlock, + const mmThreadAttr *threadAttr); MMPA_FUNC_VISIBILITY mmFileHandle mmShmOpen(const CHAR *name, INT32 oflag, mmMode_t mode); MMPA_FUNC_VISIBILITY INT32 mmShmUnlink(const CHAR *name); MMPA_FUNC_VISIBILITY VOID *mmMmap(mmFd_t fd, mmSize_t size, mmOfft_t offset, mmFd_t *extra, INT32 prot, INT32 flags); diff --git a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_win.h b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_win.h index 8200bea6..1627d7a9 100644 --- a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_win.h +++ b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_win.h @@ -1,4 +1,4 @@ -/** +/** * Copyright 2019-2020 Huawei Technologies Co., Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h index 5db6bbf8..a5a22b4f 100644 --- a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h +++ b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h @@ -1,4 +1,4 @@ -/** +/** * Copyright 2019-2020 Huawei Technologies Co., Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -249,6 +249,7 @@ typedef VOID (*mmPf)(VOID); #define M_CREAT _O_CREAT #define M_BINARY _O_BINARY #define M_TRUNC _O_TRUNC +#define M_APPEND _O_APPEND #define M_IREAD _S_IREAD #define M_IRUSR _S_IREAD diff --git a/third_party/fwkacllib/inc/runtime/base.h b/third_party/fwkacllib/inc/runtime/base.h index 4e735438..85f16cc5 100644 --- a/third_party/fwkacllib/inc/runtime/base.h +++ b/third_party/fwkacllib/inc/runtime/base.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_BASE_H__ #define __CCE_RUNTIME_BASE_H__ @@ -32,309 +32,8 @@ extern "C" { #endif #endif -/** - * @ingroup dvrt_base - * @brief runtime error numbers. - */ -typedef enum tagRtError { - RT_ERROR_NONE = 0x0, // success - - RT_ERROR_DEVICE_BASE = 0x07010000, - RT_ERROR_DEVICE_NULL, - RT_ERROR_DEVICE_NEW, - RT_ERROR_DEVICE_ID, - RT_ERROR_DEVICE_CHIPTYPE, - RT_ERROR_DEVICE_DEPLOY, - RT_ERROR_DEVICE_RETAIN, - RT_ERROR_DEVICE_PLATFORM, - RT_ERROR_DEVICE_LOADER, - RT_ERROR_DEVICE_LIMIT, - RT_ERROR_DEVICE_PROC_HANG_OUT, - RT_ERROR_DEVICE_POWER_UP_FAIL, - RT_ERROR_DEVICE_POWER_DOWN_FAIL, - RT_ERROR_DEVICE_INVALID, - - RT_ERROR_DRV_BASE = 0x07020000, - RT_ERROR_DRV_NULL, - RT_ERROR_DRV_NEW, - RT_ERROR_DRV_MEMORY, - RT_ERROR_DRV_INPUT, - RT_ERROR_DRV_PTRNULL, - RT_ERROR_DRV_OPEN_AICPU, - RT_ERROR_DRV_CLOSE_AICPU, - RT_ERROR_DRV_SYM_AICPU, - RT_ERROR_DRV_OPEN_TSD, - RT_ERROR_DRV_CLOSE_TSD, - RT_ERROR_DRV_SYM_TSD, - RT_ERROR_DRV_SOURCE, - RT_ERROR_DRV_REPORT, - RT_ERROR_DRV_COMMAND, - RT_ERROR_DRV_OCCUPY, - RT_ERROR_DRV_ERR, - - RT_ERROR_STREAM_BASE = 0x07030000, - RT_ERROR_STREAM_NULL, - RT_ERROR_STREAM_NEW, - RT_ERROR_STREAM_CONTEXT, - RT_ERROR_STREAM_INVALID, - RT_ERROR_STREAM_MODEL, - RT_ERROR_STREAM_FUSION, - RT_ERROR_STREAM_FULL, - RT_ERROR_STREAM_EMPTY, - RT_ERROR_STREAM_NOT_COMPLETE, - RT_ERROR_STREAM_SYNC, - RT_ERROR_STREAM_NO_CB_REG, - RT_ERROR_STREAM_DUPLICATE, - RT_ERROR_STREAM_NOT_EXIST, - RT_ERROR_SQ_NO_EXIST_SQ_TO_REUSE, - RT_ERROR_SQID_FULL, - - RT_ERROR_MODEL_BASE = 0x07040000, - RT_ERROR_MODEL_NULL, - RT_ERROR_MODEL_NEW, - RT_ERROR_MODEL_CONTEXT, - RT_ERROR_MODEL_ENDGRAPH, - RT_ERROR_MODEL_STREAM, - RT_ERROR_MODEL_EXCUTOR, - RT_ERROR_MODEL_SETUP, - RT_ERROR_MODEL_ID, - RT_ERROR_MODEL_EXE_FAILED, - RT_ERROR_END_OF_SEQUENCE, // end of sequence - RT_ERROR_MODEL_EXIT, - RT_ERROR_MODEL_EXIT_STREAM_UNBIND, - RT_ERROR_MODEL_EXIT_ID, - RT_ERROR_MODEL_ABORT_NORMAL, - - RT_ERROR_EVENT_BASE = 0x07050000, - RT_ERROR_EVENT_NULL, - RT_ERROR_EVENT_NEW, - RT_ERROR_EVENT_RECORDER_NULL, - RT_ERROR_EVENT_TIMESTAMP_INVALID, - RT_ERROR_EVENT_TIMESTAMP_REVERSAL, - RT_ERROR_EVENT_NOT_COMPLETE, - - RT_ERROR_NOTIFY_BASE = 0x07060000, - RT_ERROR_NOTIFY_NULL, - RT_ERROR_NOTIFY_NEW, - RT_ERROR_NOTIFY_TYPE, - RT_ERROR_NOTIFY_NOT_COMPLETE, - - RT_ERROR_CONTEXT_BASE = 0x07070000, - RT_ERROR_CONTEXT_NULL, - RT_ERROR_CONTEXT_NEW, - RT_ERROR_CONTEXT_DEL, - RT_ERROR_CONTEXT_DEFAULT_STREAM_NULL, - RT_ERROR_CONTEXT_ONLINE_STREAM_NULL, - - RT_ERROR_KERNEL_BASE = 0x07080000, - RT_ERROR_KERNEL_NULL, - RT_ERROR_KERNEL_NEW, - RT_ERROR_KERNEL_LOOKUP, - RT_ERROR_KERNEL_NAME, - RT_ERROR_KERNEL_TYPE, - RT_ERROR_KERNEL_OFFSET, - RT_ERROR_KERNEL_DUPLICATE, - RT_ERROR_KERNEL_UNREGISTERING, - - RT_ERROR_PROGRAM_BASE = 0x07090000, - RT_ERROR_PROGRAM_NULL, - RT_ERROR_PROGRAM_NEW, - RT_ERROR_PROGRAM_DATA, - RT_ERROR_PROGRAM_SIZE, - RT_ERROR_PROGRAM_MEM_TYPE, - RT_ERROR_PROGRAM_MACHINE_TYPE, - RT_ERROR_PROGRAM_USEOUT, - - RT_ERROR_MODULE_BASE = 0x070a0000, - RT_ERROR_MODULE_NULL, - RT_ERROR_MODULE_NEW, - - RT_ERROR_INSTANCE_BASE = 0x070b0000, - RT_ERROR_INSTANCE_NULL, - RT_ERROR_INSTANCE_NEW, - RT_ERROR_INSTANCE_VERSION, - - RT_ERROR_API_BASE = 0x070c0000, - RT_ERROR_API_NULL, - RT_ERROR_API_NEW, - - RT_ERROR_DATADUMP_BASE = 0x070d0000, - RT_ERROR_DATADUMP_NULL, - RT_ERROR_DATADUMP_NEW, - RT_ERROR_DATADUMP_TIME, - RT_ERROR_DATADUMP_FILE, - RT_ERROR_DATADUMP_ADDRESS, - RT_ERROR_DATADUMP_LOAD_FAILED, - RT_ERROR_DUMP_ADDR_SET_FAILED, - - RT_ERROR_PROF_BASE = 0x070e0000, - RT_ERROR_PROF_NULL, - RT_ERROR_PROF_NEW, - RT_ERROR_PROF_START, - RT_ERROR_PROF_DEVICE_MEM, - RT_ERROR_PROF_HOST_MEM, - RT_ERROR_PROF_SET_DIR, - RT_ERROR_PROF_OPER, - RT_ERROR_PROF_FULL, - RT_ERROR_PROF_NAME, - - RT_ERROR_PCTRACE_BASE = 0x070f0000, - RT_ERROR_PCTRACE_NULL, - RT_ERROR_PCTRACE_NEW, - RT_ERROR_PCTRACE_TIME, - RT_ERROR_PCTRACE_FILE, - - RT_ERROR_TASK_BASE = 0x07100000, - RT_ERROR_TASK_NULL, - RT_ERROR_TASK_NEW, - RT_ERROR_TASK_TYPE, - RT_ERROR_TASK_ALLOCATOR, - - RT_ERROR_COMMON_BASE = 0x07110000, - RT_ERROR_INVALID_VALUE, // RT_ERROR_INPUT_INVALID - RT_ERROR_MEMORY_ADDRESS_UNALIGNED, - RT_ERROR_SEC_HANDLE, - RT_ERROR_OS_HANDLE, - RT_ERROR_MUTEX_LOCK, - RT_ERROR_MUTEX_UNLOCK, - RT_ERROR_CALLOC, - RT_ERROR_POOL_RESOURCE, - RT_ERROR_TRANS_ARGS, - RT_ERROR_METADATA, - RT_ERROR_LOST_HEARTBEAT, - RT_ERROR_REPORT_TIMEOUT, - RT_ERROR_FEATURE_NOT_SUPPROT, - RT_ERROR_MEMORY_ALLOCATION, - RT_ERROR_MEMORY_FREE, - RT_ERROR_INVALID_MEMORY_TYPE, - - RT_ERROR_DEBUG_BASE = 0x07120000, - RT_ERROR_DEBUG_NULL, - RT_ERROR_DEBUG_NEW, - RT_ERROR_DEBUG_SIGNAL, - RT_ERROR_DEBUG_OPEN, - RT_ERROR_DEBUG_WRITE, - RT_ERROR_DEBUG_REGISTER_FAILED, - RT_ERROR_DEBUG_UNREGISTER_FAILED, - - RT_ERROR_ENGINE_BASE = 0x07130000, - RT_ERROR_ENGINE_NULL, - RT_ERROR_ENGINE_NEW, - RT_ERROR_ENGINE_THREAD, - - RT_ERROR_LABEL_BASE = 0x07140000, - RT_ERROR_LABEL_NULL, - RT_ERROR_LABEL_NEW, - RT_ERROR_LABEL_CONTEXT, - RT_ERROR_LABEL_STREAM, - RT_ERROR_LABEL_MODEL, - RT_ERROR_LABEL_ALLOCATOR, - RT_ERROR_LABEL_FREE, - RT_ERROR_LABEL_SET, - RT_ERROR_LABEL_ID, - - RT_ERROR_TSFW_BASE = 0x07150000, - RT_ERROR_TSFW_UNKNOWN, - RT_ERROR_TSFW_NULL_PTR, - RT_ERROR_TSFW_ILLEGAL_AI_CORE_ID, - RT_ERROR_TSFW_ILLEGAL_PARAM, - RT_ERROR_TSFW_TASK_CMD_QUEUE_FULL, - RT_ERROR_TSFW_TASK_CMD_QUEUE_EMPTY, - RT_ERROR_TSFW_TASK_REPORT_QUEUE_FULL, - RT_ERROR_TSFW_TASK_REPORT_QUEUE_EMPTY, - RT_ERROR_TSFW_TASK_NODE_BUFF_ALL_OCCUPYED, - RT_ERROR_TSFW_TASK_NODE_BUFF_ALL_FREED, - RT_ERROR_TSFW_L2_MEM_INSUFFICIENT_SPACE, - RT_ERROR_TSFW_L2_MALLOC_FAILED, - RT_ERROR_TSFW_DMA_CHANNEL_ALL_OCCUPYED, - RT_ERROR_TSFW_MEMCPY_OP_FAILED, - RT_ERROR_TSFW_BS_SLOT_ALL_OCCUPYED, - RT_ERROR_TSFW_TBS_SLOT_REPEAT_FREE, - RT_ERROR_TSFW_PRIORITY_TASK_LIST_FULL, - RT_ERROR_TSFW_PRIORITY_TASK_LIST_EMPTY, - RT_ERROR_TSFW_NO_STREAM_LIST_NEED_TO_BE_PROCESSED, - RT_ERROR_TSFW_REPEAT_MARK_STREAM_NEED_SERVICE, - RT_ERROR_TSFW_SYS_DMA_CHANNEL_ALL_OCCUPAPYED, - RT_ERROR_TSFW_NO_HBML2TASKNODE_FOUND, - RT_ERROR_TSFW_SQNODE_NODE_SLOT_ALL_OCCUPAPYED, - RT_ERROR_TSFW_CQNODE_NODE_SLOT_ALL_OCCUPAPYED, - RT_ERROR_TSFW_SQNODE_NOT_ENOUGH, - RT_ERROR_TSFW_SQNODE_SLOT_REPEAT_FREE, - RT_ERROR_TSFW_CQNODE_SLOT_REPEAT_FREE, - RT_ERROR_TSFW_CQ_REPORT_FAILED, - RT_ERROR_TSFW_SYS_DMA_RESET_SUCCESS, - RT_ERROR_TSFW_SYS_DMA_RESET_FAILED, - RT_ERROR_TSFW_SYS_DMA_TRNSFER_FAILED, - RT_ERROR_TSFW_SYS_DMA_MEMADDRALIGN_FAILED, - RT_ERROR_TSFW_SYS_DMA_ERROR_QUEUE_FULL, - RT_ERROR_TSFW_SYS_DMA_ERROR_QUEUE_EMPTY, - RT_ERROR_TSFW_TIMER_EVENT_FULL, - RT_ERROR_TSFW_TASK_L2_DESC_ENTRY_NOT_ENOUGH, - RT_ERROR_TSFW_AICORE_TIMEOUT, - RT_ERROR_TSFW_AICORE_EXCEPTION, - RT_ERROR_TSFW_AICORE_TRAP_EXCEPTION, - RT_ERROR_TSFW_AICPU_TIMEOUT, - RT_ERROR_TSFW_SDMA_L2_TO_DDR_MALLOC_FAIL, - RT_ERROR_TSFW_AICPU_EXCEPTION, - RT_ERROR_TSFW_AICPU_DATADUMP_RSP_ERR, - RT_ERROR_TSFW_AICPU_MODEL_RSP_ERR, - RT_ERROR_TSFW_REPEAT_ACTIVE_MODEL_STREAM, - RT_ERROR_TSFW_REPEAT_NOTIFY_WAIT, - RT_ERROR_TSFW_DEBUG_INVALID_SQCQ, - RT_ERROR_TSFW_DEBUG_WRONG_COMMAND_TYPE, - RT_ERROR_TSFW_DEBUG_CMD_PROCESS, - RT_ERROR_TSFW_DEBUG_INVALID_DEVICE_STATUS, - RT_ERROR_TSFW_DEBUG_NOT_IN_DEBUG_STATUS, - RT_ERROR_TSFW_DEBUG_INVALID_TASK_STATUS, - RT_ERROR_TSFW_DEBUG_TASK_EMPTY, - RT_ERROR_TSFW_DEBUG_TASK_FULL, - RT_ERROR_TSFW_DEBUG_TASK_NOT_EXIST, - RT_ERROR_TSFW_DEBUG_AI_CORE_FULL, - RT_ERROR_TSFW_DEBUG_AI_CORE_NOT_EXIST, - RT_ERROR_TSFW_DEBUG_AI_CORE_EXCEPTION, - RT_ERROR_TSFW_DEBUG_AI_CORE_TIMEOUT, - RT_ERROR_TSFW_DEBUG_BREAKPOINT_FULL, - RT_ERROR_TSFW_DEBUG_READ_ERROR, - RT_ERROR_TSFW_DEBUG_WRITE_FAIL, - RT_ERROR_TSFW_QUEUE_FULL, - RT_ERROR_TSFW_QUEUE_EMPTY, - RT_ERROR_TSFW_QUEUE_ALLOC_MEM_FAIL, - RT_ERROR_TSFW_QUEUE_DATA_SIZE_UNMATCH, - RT_ERROR_TSFW_PCIE_DMA_INVLD_CPY_TYPE, - RT_ERROR_TSFW_INVLD_CPY_DIR, - RT_ERROR_TSFW_PCIE_DMA_INVLD_CQ_DES, - RT_ERROR_TSFW_PCIE_DMA_CPY_ERR, - RT_ERROR_TSFW_PCIE_DMA_LNK_CHN_BUSY, - RT_ERROR_TSFW_PROFILE_BUFF_FULL, - RT_ERROR_TSFW_PROFILE_MODE_CONFLICT, - RT_ERROR_TSFW_PROFILE_OTHER_PID_ON, - RT_ERROR_TSFW_SCHD_AIC_TASK_PRELOAD_FAILED, - RT_ERROR_TSFW_TSCPU_CLOSE_FAILED, - RT_ERROR_TSFW_EXPECT_FAIL, - RT_ERROR_TSFW_REPEAT_MODEL_STREAM, - RT_ERROR_TSFW_STREAM_MODEL_UNBIND, - RT_ERROR_TSFW_MODEL_EXE_FAILED, - RT_ERROR_TSFW_IPC_SEND_FAILED, - RT_ERROR_TSFW_IPC_PROC_REG_FAILED, - RT_ERROR_TSFW_STREAM_FULL, - RT_ERROR_TSFW_END_OF_SEQUENCE, - RT_ERROR_TSFW_SWITCH_STREAM_LABEL, - RT_ERROR_TSFW_TRANS_SQE_FAIL, - RT_ERROR_TSFW_RESERVED, - - RT_ERROR_SUBSCRIBE_BASE = 0x07160000, - RT_ERROR_SUBSCRIBE_NULL, - RT_ERROR_SUBSCRIBE_NEW, - RT_ERROR_SUBSCRIBE_STREAM, - RT_ERROR_SUBSCRIBE_THREAD, - RT_ERROR_SUBSCRIBE_GROUP, - - RT_ERROR_GROUP_BASE = 0x07170000, - RT_ERROR_GROUP_NOT_SET, - RT_ERROR_GROUP_NOT_CREATE, - - RT_ERROR_RESERVED = 0x07ff0000, - }rtError_t; +typedef int32_t rtError_t; +static const int32_t RT_ERROR_NONE = 0; // success /** * @ingroup dvrt_base diff --git a/third_party/fwkacllib/inc/runtime/config.h b/third_party/fwkacllib/inc/runtime/config.h index f1a70eaa..c471f128 100644 --- a/third_party/fwkacllib/inc/runtime/config.h +++ b/third_party/fwkacllib/inc/runtime/config.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_CONFIG_H__ #define __CCE_RUNTIME_CONFIG_H__ @@ -185,6 +185,14 @@ RTS_API rtError_t rtSetPlatformType(rtPlatformType_t platformType); */ RTS_API rtError_t rtMemGetL2Info(rtStream_t stream, void **ptr, uint32_t *size); +/** + * @ingroup + * @brief get runtime version. The version is returned as (1000 major + 10 minor). For example, RUNTIME 9.2 would be represented by 9020. + * @param [out] runtimeVersion + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtGetRuntimeVersion(uint32_t *runtimeVersion); #if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) } #endif diff --git a/third_party/fwkacllib/inc/runtime/context.h b/third_party/fwkacllib/inc/runtime/context.h index 4be49a8c..3346ff75 100644 --- a/third_party/fwkacllib/inc/runtime/context.h +++ b/third_party/fwkacllib/inc/runtime/context.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_CONTEXT_H__ #define __CCE_RUNTIME_CONTEXT_H__ diff --git a/third_party/fwkacllib/inc/runtime/dev.h b/third_party/fwkacllib/inc/runtime/dev.h index b378e3b0..c70a2372 100644 --- a/third_party/fwkacllib/inc/runtime/dev.h +++ b/third_party/fwkacllib/inc/runtime/dev.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_DEVICE_H__ #define __CCE_RUNTIME_DEVICE_H__ @@ -330,12 +330,12 @@ RTS_API rtError_t rtGetPairDevicesInfo(uint32_t devId, uint32_t otherDevId, int3 FEATURE_TYPE_MEMCPY = 0, FEATURE_TYPE_RSV, } rtFeatureType_t; - * @param [in] infoType info type + * @param [in] featureInfo info type typedef enum tagMemcpyInfo { MEMCPY_INFO_SUPPORT_ZEROCOPY = 0, MEMCPY_INFO _RSV, } rtMemcpyInfo_t; - * @param [out] value the capability info + * @param [out] value the capability info RT_CAPABILITY_SUPPORT or RT_CAPABILITY_NOT_SUPPORT * @return RT_ERROR_NONE for ok */ RTS_API rtError_t rtGetRtCapability(rtFeatureType_t featureType, int32_t featureInfo, int64_t *value); diff --git a/third_party/fwkacllib/inc/runtime/dvfsprofile.h b/third_party/fwkacllib/inc/runtime/dvfsprofile.h index 6e451695..e27cd832 100644 --- a/third_party/fwkacllib/inc/runtime/dvfsprofile.h +++ b/third_party/fwkacllib/inc/runtime/dvfsprofile.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_DVFSPROFILE_H__ #define __CCE_RUNTIME_DVFSPROFILE_H__ diff --git a/third_party/fwkacllib/inc/runtime/event.h b/third_party/fwkacllib/inc/runtime/event.h index 41e611ea..f9d2eae2 100644 --- a/third_party/fwkacllib/inc/runtime/event.h +++ b/third_party/fwkacllib/inc/runtime/event.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_EVENT_H__ #define __CCE_RUNTIME_EVENT_H__ diff --git a/third_party/fwkacllib/inc/runtime/kernel.h b/third_party/fwkacllib/inc/runtime/kernel.h index 5f519442..98862ad4 100644 --- a/third_party/fwkacllib/inc/runtime/kernel.h +++ b/third_party/fwkacllib/inc/runtime/kernel.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_KERNEL_H__ #define __CCE_RUNTIME_KERNEL_H__ diff --git a/third_party/fwkacllib/inc/runtime/mem.h b/third_party/fwkacllib/inc/runtime/mem.h index e65d8604..f175cd45 100644 --- a/third_party/fwkacllib/inc/runtime/mem.h +++ b/third_party/fwkacllib/inc/runtime/mem.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_MEM_H__ #define __CCE_RUNTIME_MEM_H__ diff --git a/third_party/fwkacllib/inc/runtime/rt.h b/third_party/fwkacllib/inc/runtime/rt.h index d3d5956f..c1872941 100644 --- a/third_party/fwkacllib/inc/runtime/rt.h +++ b/third_party/fwkacllib/inc/runtime/rt.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_RT_H__ #define __CCE_RUNTIME_RT_H__ diff --git a/third_party/fwkacllib/inc/runtime/rt_model.h b/third_party/fwkacllib/inc/runtime/rt_model.h index b72b142d..c96349a0 100644 --- a/third_party/fwkacllib/inc/runtime/rt_model.h +++ b/third_party/fwkacllib/inc/runtime/rt_model.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_MODEL_H__ #define __CCE_RUNTIME_MODEL_H__ diff --git a/third_party/fwkacllib/inc/runtime/stream.h b/third_party/fwkacllib/inc/runtime/stream.h index 388fd3c2..631c8083 100644 --- a/third_party/fwkacllib/inc/runtime/stream.h +++ b/third_party/fwkacllib/inc/runtime/stream.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_STREAM_H__ #define __CCE_RUNTIME_STREAM_H__ diff --git a/third_party/fwkacllib/inc/tdt/index_transform.h b/third_party/fwkacllib/inc/tdt/index_transform.h index a5af2c83..a62e0185 100644 --- a/third_party/fwkacllib/inc/tdt/index_transform.h +++ b/third_party/fwkacllib/inc/tdt/index_transform.h @@ -1,10 +1,18 @@ /** -* @file index_transform.h -* -* Copyright (C) Huawei Technologies Co., Ltd. 2018-2019. All Rights Reserved. -* -* This program is used to get logical device id by phy device id. -*/ + * Copyright 2019-2020 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. + */ #ifndef INC_TDT_INDEX_TRANSFORM_H #define INC_TDT_INDEX_TRANSFORM_H diff --git a/third_party/fwkacllib/inc/tdt/status.h b/third_party/fwkacllib/inc/tdt/status.h index d30564b8..dc9e670f 100644 --- a/third_party/fwkacllib/inc/tdt/status.h +++ b/third_party/fwkacllib/inc/tdt/status.h @@ -1,4 +1,4 @@ -/** +/** * Copyright 2019-2020 Huawei Technologies Co., Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -34,9 +34,16 @@ using TDT_StatusT = uint32_t; typedef uint32_t TDT_StatusT; #endif +#define LINUX 0 +#define WINDOWS 1 + #ifndef TDT_LIB_EXPORT +#if(TARGET_SYSTEM_NAME == WINDOWS) +#define TDT_LIB_EXPORT __declspec(dllexport) +#else #define TDT_LIB_EXPORT __attribute__((visibility("default"))) #endif +#endif /** * @ingroup tdt status. * diff --git a/third_party/fwkacllib/inc/toolchain/adx_datadump_server.h b/third_party/fwkacllib/inc/toolchain/adx_datadump_server.h index a1c39a51..67adecd9 100644 --- a/third_party/fwkacllib/inc/toolchain/adx_datadump_server.h +++ b/third_party/fwkacllib/inc/toolchain/adx_datadump_server.h @@ -1,12 +1,18 @@ /** -* @file adx_datadump_server.h -* -* Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -*/ + * Copyright 2019-2020 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. + */ #ifndef ADX_DATADUMP_SERVER_H #define ADX_DATADUMP_SERVER_H diff --git a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h index c8715041..430ed14d 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h +++ b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h @@ -14,11 +14,20 @@ * limitations under the License. */ -#ifndef MSPROF_ENGINE_PROF_ACL_API_H_ -#define MSPROF_ENGINE_PROF_ACL_API_H_ +#ifndef MSPROFILER_API_PROF_ACL_API_H_ +#define MSPROFILER_API_PROF_ACL_API_H_ #define MSVP_MAX_DEV_NUM 64 +#ifndef OS_TYPE +#define OS_TYPE 0 +#endif // OS_TYPE + + +#if (OS_TYPE != LINUX) +#define MSVP_PROF_API __declspec(dllexport) +#else #define MSVP_PROF_API __attribute__((visibility("default"))) +#endif // DataTypeConfig #define PROF_ACL_API 0x0001 @@ -78,6 +87,9 @@ enum ProfErrorCode { PROF_ERROR_UNSUPPORTED, // unsupported data type or ai core metrics PROF_ERROR_REPEAT_START, // profiilng has already been started PROF_ERROR_NOT_STARTED, // profiling has not been started + PROF_ERROR_REPEAT_SUBSCRIBE, // same model id has already been subscribed + PROF_ERROR_MODEL_ID_INVALID, // model id does not exist or has not been subscribed + PROF_ERROR_API_CONFLICT, // prof ctrl api mode conflicts with subscribe mode }; /** @@ -107,7 +119,8 @@ enum ProfAicoreMetrics { PROF_AICORE_MEMORY = 3, PROF_AICORE_INTERNAL_MEMORY = 4, PROF_AICORE_STALL = 5, - PROF_AICORE_EVENT = 255 + PROF_AICORE_METRICS_COUNT, + PROF_AICORE_NONE = 0xff, }; /** @@ -130,12 +143,54 @@ struct ProfConfig { MSVP_PROF_API int32_t ProfStartProfiling(const ProfConfig *profStartCfg); /** - * @name ProfStopConfig - * @brief struct of ProfStop + * @name ProfStopProfiling + * @brief stop profiling + * @param profStopCfg [IN] config to stop profiling + * @return ProfErrorCode */ -struct ProfStopConfig { - uint64_t padding; -}; +MSVP_PROF_API int32_t ProfStopProfiling(const ProfConfig *profStopCfg); + +/** + * @name ProfFinalize + * @brief finalize profiling task + * @return ProfErrorCode + */ +MSVP_PROF_API int32_t ProfFinalize(); + +/** + * @name ProfGetDataTypeConfig + * @brief get dataTypeConfig started with of one device + * @param deviceId [IN] deviceId to get dataTypeConfig + * @param dataTypeConfig [OUT] result get + * @return ProfErrorCode + */ +MSVP_PROF_API int32_t ProfGetDataTypeConfig(uint32_t deviceId, uint64_t &dataTypeConfig); + +namespace Msprofiler { +namespace Api { +/** + * @brief transfer profiling config in acl.json to sample config + * @param aclCfg [IN] profiling json string from acl.json as {"switch":"on", "result_path":"/home",...} + * @param sampleCfg [OUT] json string for GE as {"startCfg":[{"deviceID":"all","jobID":"1234",...}]} + * @return ProfErrorCode + */ +MSVP_PROF_API int32_t ProfAclCfgToSampleCfg(const std::string &aclCfg, std::string &sampleCfg); + +/** + * @name ProfInit + * @brief init profiling + * @param profInitCfg [IN] config of init profiling of json format + * @return ProfErrorCode + */ +MSVP_PROF_API int32_t ProfInit(const std::string &profInitCfg); + +/** + * @name ProfStartProfiling + * @brief start profiling + * @param profStartCfg [IN] config to start profiling + * @return ProfErrorCode + */ +MSVP_PROF_API int32_t ProfStartProfiling(const ProfConfig *profStartCfg); /** * @name ProfStopProfiling @@ -161,4 +216,181 @@ MSVP_PROF_API int32_t ProfFinalize(); */ MSVP_PROF_API int32_t ProfGetDataTypeConfig(uint32_t deviceId, uint64_t &dataTypeConfig); -#endif // MSPROF_ENGINE_PROF_ACL_API_H_ +/** + * @name WorkMode + * @brief profiling api work mode + */ +enum WorkMode { + WORK_MODE_OFF, // profiling not at work + WORK_MODE_API_CTRL, // profiling work on api ctrl mode, (ProfInit) + WORK_MODE_SUBSCRIBE, // profiling work on subscribe mode +}; + +/** + * @name ProfGetApiWorkMode + * @brief get profiling api work mode + * @return WorkMode + */ +MSVP_PROF_API WorkMode ProfGetApiWorkMode(); + +/** + * @name ProfSubscribeConfig + * @brief config of subscribe api + */ +struct ProfSubscribeConfig { + bool timeInfo; // subscribe op time + ProfAicoreMetrics aicoreMetrics; // subscribe ai core metrics + void* fd; // pipe fd +}; + +/** + * @name ProfGetDataTypeConfig + * @brief get DataTypeConfig of subscribe + * @param profSubscribeConfig [IN] config to subscribe data + * @return DataTypeConfig + */ +MSVP_PROF_API uint64_t ProfGetDataTypeConfig(const ProfSubscribeConfig *profSubscribeConfig); + +/** + * @name ProfModelSubscribe + * @brief subscribe data of one model id + * @param modelId [IN] model id to subscribe data + * @param devId [IN] device id of model + * @param profSubscribeConfig [IN] config to subscribe data + * @return ProfErrorCode + */ +MSVP_PROF_API int32_t ProfModelSubscribe(uint32_t modelId, uint32_t devId, + const ProfSubscribeConfig *profSubscribeConfig); + +/** + * @name ProfIsModelSubscribed + * @brief check if a model id is subscribed + * @param modeiId [IN] modei id to check + * @return true: subscribed, false: not + */ +MSVP_PROF_API bool ProfIsModelSubscribed(uint32_t modelId); + +/** + * @name ProfModelUnSubscribe + * @brief unsubscribe a model id + * @param modeiId [IN] modei id to unsubscribe + * @return ProfErrorCode + */ +MSVP_PROF_API int32_t ProfModelUnSubscribe(uint32_t modelId); + +/** + * @name ProfGetOpDescSize + * @brief get profiling data struct size + * @param opDescSize [OUT] bytes of profiling subscribe data struct + * @return ProfErrorCode + */ +MSVP_PROF_API int32_t ProfGetOpDescSize(uint32_t *opDescSize); + +/** + * @name ProfGetOpNum + * @brief get how many op data there are in data + * @param data [IN] data read from pipe + * @param len [IN] data length + * @param opNum [OUT] number of op in data + * @return ProfErrorCode + */ +MSVP_PROF_API int32_t ProfGetOpNum(const void *data, uint32_t len, uint32_t *opNum); + +/** + * @name ProfGetModelId + * @brief get model id of specific part of data + * @param data [IN] data read from pipe + * @param len [IN] data length + * @param index [IN] index of part(op) + * @return model id + */ +MSVP_PROF_API uint32_t ProfGetModelId(const void *data, uint32_t len, uint32_t index); + +/** + * @name ProfGetOpType + * @brief get op type of specific part of data + * @param data [IN] data read from pipe + * @param len [IN] data length + * @param opType [OUT] op type buffer + * @param opTypeLen [IN] buffer size of param opType + * @param index [IN] index of part(op) + * @return ProfErrorCode + */ +MSVP_PROF_API int32_t ProfGetOpType(const void *data, uint32_t len, char *opType, uint32_t opTypeLen, uint32_t index); + +/** + * @name ProfGetOpName + * @brief get op name of specific part of data + * @param data [IN] data read from pipe + * @param len [IN] data length + * @param opType [OUT] op name buffer + * @param opTypeLen [IN] buffer size of param opName + * @param index [IN] index of part(op) + * @return ProfErrorCode + */ +MSVP_PROF_API int32_t ProfGetOpName(const void *data, uint32_t len, char *opName, uint32_t opNameLen, uint32_t index); + +/** + * @name ProfGetOpStart + * @brief get op start timestamp of specific part of data + * @param data [IN] data read from pipe + * @param len [IN] data length + * @param index [IN] index of part(op) + * @return op start timestamp (us) + */ +MSVP_PROF_API uint64_t ProfGetOpStart(const void *data, uint32_t len, uint32_t index); + +/** + * @name ProfGetOpEnd + * @brief get op end timestamp of specific part of data + * @param data [IN] data read from pipe + * @param len [IN] data length + * @param index [IN] index of part(op) + * @return op end timestamp (us) + */ +MSVP_PROF_API uint64_t ProfGetOpEnd(const void *data, uint32_t len, uint32_t index); + +/** + * @name ProfGetOpDuration + * @brief get op duration of specific part of data + * @param data [IN] data read from pipe + * @param len [IN] data length + * @param index [IN] index of part(op) + * @return op duration (us) + */ +MSVP_PROF_API uint64_t ProfGetOpDuration(const void *data, uint32_t len, uint32_t index); + +/** + * @name ProfGetOpExecutionTime + * @brief get op execution time of specific part of data + * @param data [IN] data read from pipe + * @param len [IN] data length + * @param index [IN] index of part(op) + * @return op execution time (us) + */ +MSVP_PROF_API uint64_t ProfGetOpExecutionTime(const void *data, uint32_t len, uint32_t index); + +/** + * @name ProfGetOpCubeOps + * @brief get op cube fops of specific part of data + * @param data [IN] data read from pipe + * @param len [IN] data length + * @param index [IN] index of part(op) + * @return op cube fops + */ +MSVP_PROF_API uint64_t ProfGetOpCubeOps(const void *data, uint32_t len, uint32_t index); + +/** + * @name ProfGetOpVectorOps + * @brief get op vector fops of specific part of data + * @param data [IN] data read from pipe + * @param len [IN] data length + * @param index [IN] index of part(op) + * @return op vector fops + */ +MSVP_PROF_API uint64_t ProfGetOpVectorOps(const void *data, uint32_t len, uint32_t index); + +} // namespace Api +} // namespace Msprofiler + +#endif // MSPROFILER_API_PROF_ACL_API_H_ diff --git a/third_party/fwkacllib/inc/toolchain/prof_mgr_core.h b/third_party/fwkacllib/inc/toolchain/prof_mgr_core.h index 4f013eef..f8cb1b22 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_mgr_core.h +++ b/third_party/fwkacllib/inc/toolchain/prof_mgr_core.h @@ -16,7 +16,16 @@ #ifndef MSPROF_ENGINE_PROF_MGR_CORE_H_ #define MSPROF_ENGINE_PROF_MGR_CORE_H_ +#ifndef OS_TYPE +#define OS_TYPE 0 +#endif // OS_TYPE + +#if (OS_TYPE != LINUX) +#define MSVP_PROF_API __declspec(dllexport) +#else #define MSVP_PROF_API __attribute__((visibility("default"))) +#endif + #include #include diff --git a/third_party/fwkacllib/inc/toolchain/prof_reporter.h b/third_party/fwkacllib/inc/toolchain/prof_reporter.h index c734380c..949011d3 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_reporter.h +++ b/third_party/fwkacllib/inc/toolchain/prof_reporter.h @@ -16,7 +16,15 @@ #ifndef MSPROF_ENGINE_PROF_REPORTER_H_ #define MSPROF_ENGINE_PROF_REPORTER_H_ +#ifndef OS_TYPE +#define OS_TYPE 0 +#endif // OS_TYPE + +#if (OS_TYPE != LINUX) +#define MSVP_PROF_API __declspec(dllexport) +#else #define MSVP_PROF_API __attribute__((visibility("default"))) +#endif /** * @file prof_reporter.h @@ -86,4 +94,4 @@ class MSVP_PROF_API Reporter { } // namespace Engine } // namespace Msprof -#endif // MSPROF_ENGINE_PROF_REPORTER_H_ \ No newline at end of file +#endif // MSPROF_ENGINE_PROF_REPORTER_H_ diff --git a/third_party/fwkacllib/inc/toolchain/slog.h b/third_party/fwkacllib/inc/toolchain/slog.h index bce58f32..5faca0ae 100644 --- a/third_party/fwkacllib/inc/toolchain/slog.h +++ b/third_party/fwkacllib/inc/toolchain/slog.h @@ -18,7 +18,9 @@ #define D_SYSLOG_H_ #ifdef __cplusplus +#ifndef LOG_CPP extern "C" { +#endif #endif // __cplusplus #ifndef LINUX @@ -105,6 +107,7 @@ extern "C" { #define SECURITY_LOG_MASK (0x00100000) #define RUN_LOG_MASK (0x01000000) #define OPERATION_LOG_MASK (0x10000000) +#define RESERVERD_LENGTH 52 typedef struct tagDCODE { const char *cName; @@ -116,6 +119,18 @@ typedef struct tagKV { char *value; } KeyValue; +typedef enum { + APPLICATION = 0, + SYSTEM +} ProcessType; + +typedef struct { + ProcessType type; + unsigned int pid; + unsigned int deviceId; + char reserved[RESERVERD_LENGTH]; +} LogAttr; + /** * @ingroup slog * @@ -228,6 +243,14 @@ DLL_EXPORT int dlog_setlevel(int moduleId, int level, int enableEvent); */ DLL_EXPORT int CheckLogLevel(int moduleId, int logLevel); +/** + * @ingroup slog + * @brief DlogSetAttr: set log attr, default pid is 0, default device id is 0, default process type is APPLICATION + * @param [in]logAttr: attr info, include pid(must be larger than 0), process type and device id(chip ID) + * @return: 0: SUCCEED, others: FAILED + */ +DLL_EXPORT int DlogSetAttr(LogAttr logAttr); + /** * @ingroup slog * @brief dlog_error: print error log @@ -367,6 +390,8 @@ void DlogInner(int moduleId, int level, const char *fmt, ...); void DlogWithKVInner(int moduleId, int level, KeyValue *pstKVArray, int kvNum, const char *fmt, ...); #ifdef __cplusplus +#ifndef LOG_CPP } +#endif // LOG_CPP #endif // __cplusplus #endif // D_SYSLOG_H_ diff --git a/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h b/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h index 12b6aa1e..87fdcbeb 100644 --- a/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h +++ b/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h @@ -1,13 +1,19 @@ /** - * @file tune_api.h + * Copyright 2019-2020 Huawei Technologies Co., Ltd * - * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.\n + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n - * 描述:mstune调优接口头文件 + * 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. */ + /** @defgroup mstune mstune调优接口 */ #ifndef TUNE_API_H #define TUNE_API_H From fec2e70eda5bc44ebb6bee001815e8b09b6fd5ec Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Mon, 7 Dec 2020 14:58:44 +0800 Subject: [PATCH 02/59] find libraries from both atc and fwk paths --- CMakeLists.txt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a7528f95..6dd5e1e1 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -83,9 +83,9 @@ if (ENABLE_OPEN_SRC) find_module(msprofiler libmsprofiler.a ${GE_LIB_PATH}) #find_module(ascendcl_static libascendcl.a ${GE_LIB_PATH}) else() - find_module(slog libslog.so ${ASCEND_ATC_DIR}) - find_module(static_mmpa libmmpa.a ${ASCEND_ATC_DIR}) - find_module(error_manager liberror_manager.so ${ASCEND_ATC_DIR}) + find_module(slog libslog.so ${ASCEND_ATC_DIR} ${ASCEND_DRIVER_COMMON_DIR}) + find_module(static_mmpa libmmpa.a ${ASCEND_ATC_DIR} ${ASCEND_RUNTIME_DIR}) + find_module(error_manager liberror_manager.so ${ASCEND_ATC_DIR} ${ASCEND_RUNTIME_DIR}) if(PLATFORM STREQUAL "train") find_module(msprof libmsprof.so ${ASCEND_DRIVER_COMMON_DIR}) find_module(hccl libhccl.so ${ASCEND_RUNTIME_DIR}) From d7319181984e62c43bacbb382e86a4d053ea245d Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Mon, 7 Dec 2020 17:14:14 +0800 Subject: [PATCH 03/59] fix geruntime missing files and error codes --- ge/ge_runtime/CMakeLists.txt | 3 +++ ge/ge_runtime/runtime_model.cc | 4 ++-- ge/ge_runtime/task/task.h | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/ge/ge_runtime/CMakeLists.txt b/ge/ge_runtime/CMakeLists.txt index 42d3b344..ce1b89ea 100644 --- a/ge/ge_runtime/CMakeLists.txt +++ b/ge/ge_runtime/CMakeLists.txt @@ -13,6 +13,9 @@ set(GE_SRC_LIST "task/hccl_task.cc" "task/memcpy_async_task.cc" "task/profiler_task.cc" + "task/label_goto_task.cc" + "task/label_set_task.cc" + "task/label_switch_task.cc" ) add_library(ge_runtime SHARED ${GE_SRC_LIST}) diff --git a/ge/ge_runtime/runtime_model.cc b/ge/ge_runtime/runtime_model.cc index 0ff56ef1..fb0f3e85 100644 --- a/ge/ge_runtime/runtime_model.cc +++ b/ge/ge_runtime/runtime_model.cc @@ -307,8 +307,8 @@ bool RuntimeModel::Run() { ret = rtStreamSynchronize(rt_model_stream_); if (ret != RT_ERROR_NONE) { - if (ret == RT_ERROR_END_OF_SEQUENCE) { - GELOGI("Model stream RT_ERROR_END_OF_SEQUENCE signal received, ret = 0x%X", ret); + if (ret == ACL_ERROR_RT_END_OF_SEQUENCE) { + GELOGI("Model stream ACL_ERROR_RT_END_OF_SEQUENCE signal received, ret = 0x%X", ret); return true; } GELOGE(RT_FAILED, "Model stream sync failed, ret = 0x%X", ret); diff --git a/ge/ge_runtime/task/task.h b/ge/ge_runtime/task/task.h index 6c4df248..c255fd22 100644 --- a/ge/ge_runtime/task/task.h +++ b/ge/ge_runtime/task/task.h @@ -24,6 +24,7 @@ #include "runtime/rt_model.h" #include "ge_runtime/model_context.h" #include "ge_runtime/task_info.h" +#include "external/runtime/rt_error_codes.h" namespace ge { namespace model_runner { From d5a82a7f98bb7470fa7684f921e399312f5d5175 Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Wed, 9 Dec 2020 14:40:51 +0800 Subject: [PATCH 04/59] Synchronize latest Ascend software suite 09 Dec 2020 --- inc/external/acl/ops/acl_fv.h | 353 +++++++++++++++++++++++++ third_party/fwkacllib/inc/runtime/rt.h | 2 +- 2 files changed, 354 insertions(+), 1 deletion(-) create mode 100644 inc/external/acl/ops/acl_fv.h diff --git a/inc/external/acl/ops/acl_fv.h b/inc/external/acl/ops/acl_fv.h new file mode 100644 index 00000000..27dc367a --- /dev/null +++ b/inc/external/acl/ops/acl_fv.h @@ -0,0 +1,353 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef INC_EXTERNAL_ACL_OPS_ACL_RETR_H_ +#define INC_EXTERNAL_ACL_OPS_ACL_RETR_H_ + +#include "acl/acl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct aclfvInitPara aclfvInitPara; +typedef struct aclfvFeatureInfo aclfvFeatureInfo; +typedef struct aclfvRepoRange aclfvRepoRange; +typedef struct aclfvQueryTable aclfvQueryTable; +typedef struct aclfvSearchInput aclfvSearchInput; +typedef struct aclfvSearchResult aclfvSearchResult; + +// search operation type +enum aclfvSearchType { + SEARCH_1_N, // 1:N operation type + SEARCH_N_M // N:M operation type +}; + +/** + * @ingroup AscendCL + * @brief Create fv init param. + * + * @param fsNum [IN] The feature num + * + * @retval null for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY aclfvInitPara *aclfvCreateInitPara(uint64_t fsNum); + +/** + * @ingroup AscendCL + * @brief Destroy fv init param. + * + * @par Function + * Can only destroy fv init param information created + * through aclfvCreateInitPara interface. + * + * @param initPara [IN] fv init param. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclfvCreateInitPara + */ +ACL_FUNC_VISIBILITY aclError aclfvDestroyInitPara(aclfvInitPara *initPara); + +/** + * @ingroup AscendCL + * @brief set value for maxTopNumFor1N which in fv init param. + * + * @param initPara [IN|OUT] fv init param. + * @param maxTopNumFor1N [IN] maxTopNumFor1N value for init param. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclfvSet1NTopNum(aclfvInitPara *initPara, uint32_t maxTopNumFor1N); + +/** + * @ingroup AscendCL + * @brief set value for maxTopNumForNM which in fv init param. + * + * @param initPara [IN|OUT] fv init param. + * @param maxTopNumForNM [IN] maxTopNumForNM value for init param. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclfvSetNMTopNum(aclfvInitPara *initPara, uint32_t maxTopNumForNM); + +/** + * @ingroup AscendCL + * @brief Create fv feature info. + * + * @param id0 [IN] The first level library id0 + * @param id1 [IN] Secondary library id1 + * @param offset [IN] The offset of the first feature in the library + * @param featureLen [IN] Single feature length + * @param featureCount [IN] Single feature count + * @param featureData [IN] Feature value list + * @param featureDataLen [IN] Feature value list length + * + * @retval null for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY aclfvFeatureInfo *aclfvCreateFeatureInfo(uint32_t id0, uint32_t id1, uint32_t offset, + uint32_t featureLen, uint32_t featureCount, + uint8_t *featureData, uint32_t featureDataLen); + +/** + * @ingroup AscendCL + * @brief Destroy fv feature info. + * + * @par Function + * Can only destroy fv feature info information created + * through aclfvCreateFeatureInfo interface. + * + * @param featureInfo [IN] fv feature info. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclfvCreateFeatureInfo + */ +ACL_FUNC_VISIBILITY aclError aclfvDestroyFeatureInfo(aclfvFeatureInfo *featureInfo); + +/** + * @ingroup AscendCL + * @brief Create fv repo range. + * + * @param id0Min [IN] id0 start value + * @param id0Min [IN] id0 max + * @param id1Min [IN] id0 start value + * @param id1Max [IN] id1 max + * + * @retval null for failed. OtherValues success + */ +ACL_FUNC_VISIBILITY aclfvRepoRange *aclfvCreateRepoRange(uint32_t id0Min, uint32_t id0Max, uint32_t id1Min, + uint32_t id1Max); + +/** + * @ingroup AscendCL + * @brief Destroy fv repo range. + * + * @par Function + * Can only destroy fv repo range information created + * through aclfvCreateRepoRange interface. + * + * @param repoRange [IN] fv repo range. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclfvCreateRepoRange + */ +ACL_FUNC_VISIBILITY aclError aclfvDestroyRepoRange(aclfvRepoRange *repoRange); + +/** + * @ingroup AscendCL + * @brief Create query table. + * + * @param queryCnt [IN] Number of tables, the maximum number is 6 + * @param tableLen [IN] Single table length, table length is 32KB + * @param tableData [IN] Feature value list + * @param tableDataLen [IN] The length of memory requested by the featureData pointer + * + * @retval null for failed. OtherValues success + */ +ACL_FUNC_VISIBILITY aclfvQueryTable *aclfvCreateQueryTable(uint32_t queryCnt, uint32_t tableLen, uint8_t *tableData, + uint32_t tableDataLen); + +/** + * @ingroup AscendCL + * @brief Destroy query table. + * + * @par Function + * Can only destroy query table information created + * through aclfvCreateQueryTable interface. + * + * @param queryTable [IN] query table. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclfvCreateQueryTable + */ +ACL_FUNC_VISIBILITY aclError aclfvDestroyQueryTable(aclfvQueryTable *queryTable); + +/** + * @ingroup AscendCL + * @brief Create search input. + * + * @param queryTable [IN] query table + * @param repoRange [IN] query repo range + * @param topk [IN] query topk + * + * @retval null for failed. OtherValues success + */ +ACL_FUNC_VISIBILITY aclfvSearchInput *aclfvCreateSearchInput(aclfvQueryTable *queryTable, aclfvRepoRange *repoRange, + uint32_t topk); + +/** + * @ingroup AscendCL + * @brief Destroy search input. + * + * @par Function + * Can only destroy search input information created + * through aclfvCreateSearchInput interface. + * + * @param searchInput [IN] search input. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclfvCreateSearchInput + */ +ACL_FUNC_VISIBILITY aclError aclfvDestroySearchInput(aclfvSearchInput *searchInput); + +/** + * @ingroup AscendCL + * @brief Create search result. + * + * @param queryCnt [IN] Retrieve the number of features + * @param resultNum [IN] The number of search results for each feature, the number is queryCnt + * @param resultNumDataLen [IN] resultNum memory length + * @param id0 [IN] Level 1 library id0 + * @param id1 [IN] Secondary library id1 + * @param resultOffset [IN] The offset of the bottom library corresponding + * to each feature retrieval result, total length topK * queryCnt + * @param resultDistance [IN] Distance, total length topK * queryCnt + * @param dataLen [IN] The memory size requested by + * id0\id1\reslutOffset\resultDistance + * + * @retval null for failed. OtherValues success + */ +ACL_FUNC_VISIBILITY aclfvSearchResult *aclfvCreateSearchResult(uint32_t queryCnt, uint32_t *resultNum, + uint32_t resultNumDataLen, uint32_t *id0, uint32_t *id1, + uint32_t *resultOffset, float *resultDistance, + uint32_t dataLen); + +/** + * @ingroup AscendCL + * @brief Destroy search result. + * + * @par Function + * Can only destroy search result information created + * through aclfvCreateSearchResult interface. + * + * @param searchResult [IN] search result. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclfvCreateSearchResult + */ +ACL_FUNC_VISIBILITY aclError aclfvDestroySearchResult(aclfvSearchResult *searchResult); + +/** + * @ingroup AscendCL + * @brief fv IP initialize. + * + * @param initPara [IN] fv init param. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure. + */ +ACL_FUNC_VISIBILITY aclError aclfvInit(aclfvInitPara *initPara); + +/** + * @ingroup AscendCL + * @brief release fv resources. + * + * @par Function + * Can only release fv resources created + * through aclfvInit interface. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure. + * + * @see aclfvInit + */ +ACL_FUNC_VISIBILITY aclError aclfvRelease(); + +/** + * @ingroup AscendCL + * @brief fv repo add. + * + * @param type [IN] repo add type + * @param featureInfo [IN] add feature information + * @param stream [IN] stream of task execute + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure. + */ +ACL_FUNC_VISIBILITY aclError aclfvRepoAdd(aclfvSearchType type, aclfvFeatureInfo *featureInfo, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief fv repo del. + * + * @param type [IN] repo delete type + * @param repoRange [IN] repo range information + * @param stream [IN] stream of task execute + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure. + */ +ACL_FUNC_VISIBILITY aclError aclfvRepoDel(aclfvSearchType type, aclfvRepoRange *repoRange, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief fv accurate del. + * + * @param featureInfo [IN] accurate delete feature information + * @param stream [IN] stream of task execute + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure. + */ +ACL_FUNC_VISIBILITY aclError aclfvDel(aclfvFeatureInfo *featureInfo, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief fv accurate modify. + * + * @param featureInfo [IN] accurate modify feature information + * @param stream [IN] stream of task execute + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure. + */ +ACL_FUNC_VISIBILITY aclError aclfvModify(aclfvFeatureInfo *featureInfo, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief fv search. + * + * @param type [IN] search type + * @param searchInput [IN] search input + * @param searchRst [OUT] search result + * @param stream [IN] stream of task execute + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure. + */ +ACL_FUNC_VISIBILITY aclError aclfvSearch(aclfvSearchType type, aclfvSearchInput *searchInput, + aclfvSearchResult *searchRst, aclrtStream stream); + +#ifdef __cplusplus +} +#endif + +#endif // INC_EXTERNAL_ACL_OPS_ACL_RETR_H_ diff --git a/third_party/fwkacllib/inc/runtime/rt.h b/third_party/fwkacllib/inc/runtime/rt.h index c1872941..0d39389b 100644 --- a/third_party/fwkacllib/inc/runtime/rt.h +++ b/third_party/fwkacllib/inc/runtime/rt.h @@ -28,4 +28,4 @@ #include "rt_model.h" #include "stream.h" -#endif // __CCE_RUNTIME_RT_H__ \ No newline at end of file +#endif // __CCE_RUNTIME_RT_H__ From d77f36e017931d40609730f787f90a401b71bbd8 Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Wed, 9 Dec 2020 17:09:54 +0800 Subject: [PATCH 05/59] prioritize json downloading from gitee --- cmake/external_libs/json.cmake | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cmake/external_libs/json.cmake b/cmake/external_libs/json.cmake index c4a52843..ce473d4b 100755 --- a/cmake/external_libs/json.cmake +++ b/cmake/external_libs/json.cmake @@ -5,15 +5,15 @@ endif() include(ExternalProject) set(JSON_SRC_DIR ${CMAKE_BINARY_DIR}/opensrc/json/include) -#if (ENABLE_GITEE) -# set(REQ_URL "https://gitee.com/mirrors/JSON-for-Modern-CPP/repository/archive/v3.6.1.zip") -# set(MD5 "5bda78ce308e6cfcf614dcf1d5ff27a7") -# set(JSON_INCLUDE_DIR "${JSON_SRC_DIR}/include") -#else() -set(REQ_URL "https://github.com/nlohmann/json/releases/download/v3.6.1/include.zip") -set(MD5 "0dc903888211db3a0f170304cd9f3a89") -set(JSON_INCLUDE_DIR ${JSON_SRC_DIR}) -#endif () +if (ENABLE_GITEE) + set(REQ_URL "https://gitee.com/mirrors/JSON-for-Modern-CPP/repository/archive/v3.6.1.zip") + set(MD5 "5bda78ce308e6cfcf614dcf1d5ff27a7") + set(JSON_INCLUDE_DIR "${JSON_SRC_DIR}/include") +else() + set(REQ_URL "https://github.com/nlohmann/json/releases/download/v3.6.1/include.zip") + set(MD5 "0dc903888211db3a0f170304cd9f3a89") + set(JSON_INCLUDE_DIR ${JSON_SRC_DIR}) +endif () ExternalProject_Add(json_build URL ${REQ_URL} #URL /home/txd/workspace/cloud_code/pkg/include.zip From 411e71f1f3559768610e58538c8b04aced70015a Mon Sep 17 00:00:00 2001 From: changzherui Date: Sat, 16 Jan 2021 16:54:10 +0800 Subject: [PATCH 06/59] sync code h --- inc/external/acl/acl.h | 73 + inc/external/acl/acl_base.h | 116 +- inc/external/acl/acl_mdl.h | 1210 ++++++++ inc/external/acl/acl_op.h | 119 +- inc/external/acl/acl_op_compiler.h | 47 +- inc/external/acl/acl_prof.h | 296 ++ inc/external/acl/acl_rt.h | 950 +++++++ inc/external/acl/acl_tdt.h | 283 ++ inc/external/acl/error_codes/rt_error_codes.h | 125 +- inc/external/acl/ops/acl_cblas.h | 179 +- inc/external/acl/ops/acl_dvpp.h | 2461 +++++++++++++++++ inc/external/acl/ops/acl_fv.h | 14 +- inc/external/hccl/hccl.h | 133 + inc/external/hccl/hccl_types.h | 101 + inc/external/runtime/rt_error_codes.h | 125 +- .../aicpu/aicpu_schedule/aicpu_op_type_list.h | 40 +- third_party/fwkacllib/inc/cce/aicpu_engine.h | 1 + .../fwkacllib/inc/cce/fwk_adpt_struct.h | 1 + third_party/fwkacllib/inc/hccl/hcom.h | 28 + .../fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h | 3 +- .../inc/mmpa/sub_inc/mmpa_typedef_win.h | 166 +- .../fwkacllib/inc/mmpa/sub_inc/mmpa_win.h | 2 +- third_party/fwkacllib/inc/ops/aipp.h | 4 +- third_party/fwkacllib/inc/ops/all_ops.h | 3 +- third_party/fwkacllib/inc/ops/array_ops.h | 75 +- third_party/fwkacllib/inc/ops/audio_ops.h | 2 +- third_party/fwkacllib/inc/ops/batch_ops.h | 2 +- third_party/fwkacllib/inc/ops/bitwise_ops.h | 2 +- .../fwkacllib/inc/ops/boosted_trees_ops.h | 2 +- .../inc/ops/candidate_sampling_ops.h | 2 +- third_party/fwkacllib/inc/ops/condtake_ops.h | 2 +- .../fwkacllib/inc/ops/control_flow_ops.h | 2 +- third_party/fwkacllib/inc/ops/ctc_ops.h | 2 +- third_party/fwkacllib/inc/ops/data_flow_ops.h | 8 +- .../inc/ops/elewise_calculation_ops.h | 333 ++- .../fwkacllib/inc/ops/functional_ops.h | 2 +- third_party/fwkacllib/inc/ops/get_data_ops.h | 2 +- third_party/fwkacllib/inc/ops/hcom_ops.h | 47 +- third_party/fwkacllib/inc/ops/hvd_ops.h | 2 +- third_party/fwkacllib/inc/ops/image_ops.h | 196 +- third_party/fwkacllib/inc/ops/internal_ops.h | 2 +- third_party/fwkacllib/inc/ops/linalg_ops.h | 2 +- third_party/fwkacllib/inc/ops/list_ops.h | 230 ++ third_party/fwkacllib/inc/ops/logging_ops.h | 2 +- third_party/fwkacllib/inc/ops/lookup_ops.h | 2 +- third_party/fwkacllib/inc/ops/math_ops.h | 65 +- .../inc/ops/matrix_calculation_ops.h | 57 +- .../fwkacllib/inc/ops/nn_batch_norm_ops.h | 2 +- .../fwkacllib/inc/ops/nn_calculation_ops.h | 416 ++- third_party/fwkacllib/inc/ops/nn_detect_ops.h | 113 +- third_party/fwkacllib/inc/ops/nn_norm_ops.h | 267 +- third_party/fwkacllib/inc/ops/nn_ops.h | 2 +- .../fwkacllib/inc/ops/nn_pooling_ops.h | 331 ++- .../fwkacllib/inc/ops/nn_training_ops.h | 2 +- third_party/fwkacllib/inc/ops/no_op.h | 2 +- .../fwkacllib/inc/ops/nonlinear_fuc_ops.h | 204 +- .../fwkacllib/inc/ops/npu_loss_scale_ops.h | 2 +- third_party/fwkacllib/inc/ops/outfeed_ops.h | 2 +- third_party/fwkacllib/inc/ops/pad_ops.h | 56 +- third_party/fwkacllib/inc/ops/parsing_ops.h | 2 +- third_party/fwkacllib/inc/ops/quantize_ops.h | 2 +- .../fwkacllib/inc/ops/ragged_array_ops.h | 2 +- .../fwkacllib/inc/ops/ragged_conversion_ops.h | 2 +- .../fwkacllib/inc/ops/ragged_math_ops.h | 2 +- third_party/fwkacllib/inc/ops/random_ops.h | 56 +- third_party/fwkacllib/inc/ops/reduce_ops.h | 47 +- .../fwkacllib/inc/ops/resource_variable_ops.h | 2 +- third_party/fwkacllib/inc/ops/rnn.h | 307 +- third_party/fwkacllib/inc/ops/rpn_ops.h | 2 +- third_party/fwkacllib/inc/ops/save_ops.h | 2 +- third_party/fwkacllib/inc/ops/sdca_ops.h | 2 +- third_party/fwkacllib/inc/ops/selection_ops.h | 184 +- third_party/fwkacllib/inc/ops/set_ops.h | 2 +- third_party/fwkacllib/inc/ops/sparse_ops.h | 2 +- third_party/fwkacllib/inc/ops/spectral_ops.h | 2 +- .../fwkacllib/inc/ops/split_combination_ops.h | 2 +- third_party/fwkacllib/inc/ops/state_ops.h | 2 +- .../fwkacllib/inc/ops/stateful_random_ops.h | 2 +- .../fwkacllib/inc/ops/stateless_random_ops.h | 2 +- third_party/fwkacllib/inc/ops/string_ops.h | 2 +- third_party/fwkacllib/inc/ops/swap_co_ops.h | 2 +- .../inc/ops/target_crop_and_resize.h | 2 +- .../fwkacllib/inc/ops/transformation_ops.h | 19 +- .../fwkacllib/inc/ops/warp_perspective_ops.h | 2 +- third_party/fwkacllib/inc/runtime/base.h | 54 +- third_party/fwkacllib/inc/runtime/config.h | 144 +- third_party/fwkacllib/inc/runtime/context.h | 35 +- third_party/fwkacllib/inc/runtime/dev.h | 63 +- .../fwkacllib/inc/runtime/dvfsprofile.h | 10 +- third_party/fwkacllib/inc/runtime/event.h | 10 +- third_party/fwkacllib/inc/runtime/kernel.h | 99 +- third_party/fwkacllib/inc/runtime/mem.h | 131 +- third_party/fwkacllib/inc/runtime/rt.h | 10 +- third_party/fwkacllib/inc/runtime/rt_model.h | 10 +- third_party/fwkacllib/inc/runtime/stream.h | 10 +- .../fwkacllib/inc/tdt/index_transform.h | 20 +- third_party/fwkacllib/inc/tdt/status.h | 2 +- .../fwkacllib/inc/tdt/tdt_host_interface.h | 21 +- .../fwkacllib/inc/toolchain/prof_acl_api.h | 418 +-- .../fwkacllib/inc/toolchain/prof_reporter.h | 2 + .../inc/toolchain/tuning_tool/tune_api.h | 150 +- 101 files changed, 9406 insertions(+), 1356 deletions(-) create mode 100644 inc/external/acl/acl.h create mode 100644 inc/external/acl/acl_mdl.h create mode 100644 inc/external/acl/acl_prof.h create mode 100644 inc/external/acl/acl_rt.h create mode 100644 inc/external/acl/acl_tdt.h create mode 100644 inc/external/acl/ops/acl_dvpp.h create mode 100644 inc/external/hccl/hccl.h create mode 100644 inc/external/hccl/hccl_types.h create mode 100644 third_party/fwkacllib/inc/ops/list_ops.h diff --git a/inc/external/acl/acl.h b/inc/external/acl/acl.h new file mode 100644 index 00000000..ef5b4772 --- /dev/null +++ b/inc/external/acl/acl.h @@ -0,0 +1,73 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef INC_EXTERNAL_ACL_ACL_H_ +#define INC_EXTERNAL_ACL_ACL_H_ + +#include "acl_rt.h" +#include "acl_op.h" +#include "acl_mdl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Current version is 1.0.0 +#define ACL_MAJOR_VERSION 1 +#define ACL_MINOR_VERSION 0 +#define ACL_PATCH_VERSION 0 + +/** + * @ingroup AscendCL + * @brief acl initialize + * + * @par Restriction + * The aclInit interface can be called only once in a process + * @param configPath [IN] the config path,it can be NULL + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclInit(const char *configPath); + +/** + * @ingroup AscendCL + * @brief acl finalize + * + * @par Restriction + * Need to call aclFinalize before the process exits. + * After calling aclFinalize,the services cannot continue to be used normally. + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclFinalize(); + +/** + * @ingroup AscendCL + * @brief query ACL interface version + * + * @param majorVersion[OUT] ACL interface major version + * @param minorVersion[OUT] ACL interface minor version + * @param patchVersion[OUT] ACL interface patch version + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtGetVersion(int32_t *majorVersion, int32_t *minorVersion, int32_t *patchVersion); + +#ifdef __cplusplus +} +#endif + +#endif // INC_EXTERNAL_ACL_ACL_H_ diff --git a/inc/external/acl/acl_base.h b/inc/external/acl/acl_base.h index debadcfd..12a25119 100644 --- a/inc/external/acl/acl_base.h +++ b/inc/external/acl/acl_base.h @@ -134,38 +134,42 @@ static const int ACL_ERROR_PROFILING_FAILURE = 500005; #define ACL_UNKNOWN_RANK 0xFFFFFFFFFFFFFFFE typedef enum { - ACL_DT_UNDEFINED = -1, - ACL_FLOAT = 0, - ACL_FLOAT16 = 1, - ACL_INT8 = 2, - ACL_INT32 = 3, - ACL_UINT8 = 4, - ACL_INT16 = 6, - ACL_UINT16 = 7, - ACL_UINT32 = 8, - ACL_INT64 = 9, - ACL_UINT64 = 10, - ACL_DOUBLE = 11, - ACL_BOOL = 12, - ACL_STRING = 13, + ACL_DT_UNDEFINED = -1, + ACL_FLOAT = 0, + ACL_FLOAT16 = 1, + ACL_INT8 = 2, + ACL_INT32 = 3, + ACL_UINT8 = 4, + ACL_INT16 = 6, + ACL_UINT16 = 7, + ACL_UINT32 = 8, + ACL_INT64 = 9, + ACL_UINT64 = 10, + ACL_DOUBLE = 11, + ACL_BOOL = 12, + ACL_STRING = 13, } aclDataType; typedef enum { - ACL_FORMAT_UNDEFINED = -1, - ACL_FORMAT_NCHW = 0, - ACL_FORMAT_NHWC = 1, - ACL_FORMAT_ND = 2, - ACL_FORMAT_NC1HWC0 = 3, - ACL_FORMAT_FRACTAL_Z = 4, - ACL_FORMAT_NC1HWC0_C04 = 12, - ACL_FORMAT_FRACTAL_NZ = 29, + ACL_FORMAT_UNDEFINED = -1, + ACL_FORMAT_NCHW = 0, + ACL_FORMAT_NHWC = 1, + ACL_FORMAT_ND = 2, + ACL_FORMAT_NC1HWC0 = 3, + ACL_FORMAT_FRACTAL_Z = 4, + ACL_FORMAT_NC1HWC0_C04 = 12, + ACL_FORMAT_NDHWC = 27, + ACL_FORMAT_FRACTAL_NZ = 29, + ACL_FORMAT_NCDHW = 30, + ACL_FORMAT_NDC1HWC0 = 32, + ACL_FRACTAL_Z_3D = 33 } aclFormat; typedef enum { - ACL_DEBUG = 0, - ACL_INFO = 1, - ACL_WARNING = 2, - ACL_ERROR = 3, + ACL_DEBUG = 0, + ACL_INFO = 1, + ACL_WARNING = 2, + ACL_ERROR = 3, } aclLogLevel; /** @@ -223,6 +227,29 @@ ACL_FUNC_VISIBILITY aclDataBuffer *aclCreateDataBuffer(void *data, size_t size); */ ACL_FUNC_VISIBILITY aclError aclDestroyDataBuffer(const aclDataBuffer *dataBuffer); +/** + * @ingroup AscendCL + * @brief update new data of aclDataBuffer + * + * @param dataBuffer [OUT] pointer to aclDataBuffer + * @li The old data need to be released by the user, otherwise it may occur memory leak leakage + * call aclGetDataBufferAddr interface to get old data address + * call aclrtFree interface to release memory + * + * @param data [IN] pointer to new data + * @li Need to be managed by the user, + * call aclrtMalloc interface to apply for memory, + * call aclrtFree interface to release memory + * + * @param size [IN] size of data in bytes + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtMalloc | aclrtFree | aclGetDataBufferAddr + */ +ACL_FUNC_VISIBILITY aclError aclUpdateDataBuffer(aclDataBuffer *dataBuffer, void *data, size_t size); + /** * @ingroup AscendCL * @brief get data address from aclDataBuffer @@ -277,7 +304,9 @@ ACL_FUNC_VISIBILITY size_t aclDataTypeSize(aclDataType dataType); * @retval aclTensorDesc pointer. * @retval nullptr if param is invalid or run out of memory */ -ACL_FUNC_VISIBILITY aclTensorDesc *aclCreateTensorDesc(aclDataType dataType, int numDims, const int64_t *dims, +ACL_FUNC_VISIBILITY aclTensorDesc *aclCreateTensorDesc(aclDataType dataType, + int numDims, + const int64_t *dims, aclFormat format); /** @@ -299,7 +328,8 @@ ACL_FUNC_VISIBILITY void aclDestroyTensorDesc(const aclTensorDesc *desc); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclSetTensorShapeRange(aclTensorDesc *desc, size_t dimsCount, +ACL_FUNC_VISIBILITY aclError aclSetTensorShapeRange(aclTensorDesc* desc, + size_t dimsCount, int64_t dimsRange[][ACL_TENSOR_SHAPE_RANGE_NUM]); /** @@ -396,7 +426,9 @@ ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimV2(const aclTensorDesc *desc, si * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimRange(const aclTensorDesc *desc, size_t index, size_t dimRangeNum, +ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimRange(const aclTensorDesc *desc, + size_t index, + size_t dimRangeNum, int64_t *dimRange); /** @@ -433,7 +465,7 @@ ACL_FUNC_VISIBILITY const char *aclGetTensorDescName(aclTensorDesc *desc); * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclTransTensorDescFormat(const aclTensorDesc *srcDesc, aclFormat dstFormat, - aclTensorDesc **dstDesc); + aclTensorDesc **dstDesc); /** * @ingroup AscendCL @@ -521,7 +553,7 @@ ACL_FUNC_VISIBILITY aclError aclSetTensorOriginShape(aclTensorDesc *desc, int nu * * @retval null for failed. * @retval OtherValues success. - */ +*/ ACL_FUNC_VISIBILITY aclTensorDesc *aclGetTensorDescByIndex(aclTensorDesc *desc, size_t index); /** @@ -532,7 +564,7 @@ ACL_FUNC_VISIBILITY aclTensorDesc *aclGetTensorDescByIndex(aclTensorDesc *desc, * * @retval null for failed * @retval OtherValues success - */ +*/ ACL_FUNC_VISIBILITY void *aclGetTensorDescAddress(const aclTensorDesc *desc); /** @@ -547,6 +579,19 @@ ACL_FUNC_VISIBILITY void *aclGetTensorDescAddress(const aclTensorDesc *desc); */ ACL_FUNC_VISIBILITY aclError aclSetTensorDynamicInput(aclTensorDesc *desc, const char *dynamicInputName); +/** + * @ingroup AscendCL + * @brief Set const data specified by the tensor description + * + * @param desc [OUT] pointer to the instance of aclTensorDesc + * @param dataBuffer [IN] pointer to the const databuffer + * @param length [IN] the length of const databuffer + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclSetTensorConst(aclTensorDesc *desc, void *dataBuffer, size_t length); + /** * @ingroup AscendCL * @brief an interface for users to output APP logs @@ -559,12 +604,13 @@ ACL_FUNC_VISIBILITY aclError aclSetTensorDynamicInput(aclTensorDesc *desc, const * @param ... [IN] the value of current log */ ACL_FUNC_VISIBILITY void aclAppLog(aclLogLevel logLevel, const char *func, const char *file, uint32_t line, - const char *fmt, ...); + const char *fmt, ...); -#define ACL_APP_LOG(level, fmt, ...) aclAppLog(level, __FUNCTION__, __FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define ACL_APP_LOG(level, fmt, ...) \ + aclAppLog(level, __FUNCTION__, __FILE__, __LINE__, fmt, ##__VA_ARGS__) #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_BASE_H_ +#endif // INC_EXTERNAL_ACL_ACL_BASE_H_ diff --git a/inc/external/acl/acl_mdl.h b/inc/external/acl/acl_mdl.h new file mode 100644 index 00000000..4f3e257f --- /dev/null +++ b/inc/external/acl/acl_mdl.h @@ -0,0 +1,1210 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef INC_EXTERNAL_ACL_ACL_MODEL_H_ +#define INC_EXTERNAL_ACL_ACL_MODEL_H_ + +#include +#include + +#include "acl_base.h" +#include "acl_rt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ACL_MAX_DIM_CNT 128 +#define ACL_MAX_TENSOR_NAME_LEN 128 +#define ACL_MAX_BATCH_NUM 128 +#define ACL_MAX_HW_NUM 128 +#define ACL_MAX_SHAPE_COUNT 128 +#define ACL_INVALID_NODE_INDEX 0xFFFFFFFF + +#define ACL_MDL_LOAD_FROM_FILE 1 +#define ACL_MDL_LOAD_FROM_FILE_WITH_MEM 2 +#define ACL_MDL_LOAD_FROM_MEM 3 +#define ACL_MDL_LOAD_FROM_MEM_WITH_MEM 4 +#define ACL_MDL_LOAD_FROM_FILE_WITH_Q 5 +#define ACL_MDL_LOAD_FROM_MEM_WITH_Q 6 + +#define ACL_DYNAMIC_TENSOR_NAME "ascend_mbatch_shape_data" +#define ACL_DYNAMIC_AIPP_NAME "ascend_dynamic_aipp_data" + +typedef struct aclmdlDataset aclmdlDataset; +typedef struct aclmdlDesc aclmdlDesc; +typedef struct aclmdlAIPP aclmdlAIPP; +typedef struct aclAippExtendInfo aclAippExtendInfo; +typedef struct aclmdlConfigHandle aclmdlConfigHandle; + +typedef enum { + ACL_YUV420SP_U8 = 1, + ACL_XRGB8888_U8, + ACL_RGB888_U8, + ACL_YUV400_U8, + ACL_NC1HWC0DI_FP16, + ACL_NC1HWC0DI_S8, + ACL_ARGB8888_U8, + ACL_YUYV_U8, + ACL_YUV422SP_U8, + ACL_AYUV444_U8, + ACL_RAW10, + ACL_RAW12, + ACL_RAW16, + ACL_RAW24, + ACL_AIPP_RESERVED = 0xffff, +} aclAippInputFormat; + +typedef enum { + ACL_MDL_PRIORITY_INT32 = 0, + ACL_MDL_LOAD_TYPE_SIZET, + ACL_MDL_PATH_PTR, /**< pointer to model load path with deep copy */ + ACL_MDL_MEM_ADDR_PTR, /**< pointer to model memory with shallow copy */ + ACL_MDL_MEM_SIZET, + ACL_MDL_WEIGHT_ADDR_PTR, /**< pointer to weight memory of model with shallow copy */ + ACL_MDL_WEIGHT_SIZET, + ACL_MDL_WORKSPACE_ADDR_PTR, /**< pointer to worksapce memory of model with shallow copy */ + ACL_MDL_WORKSPACE_SIZET, + ACL_MDL_INPUTQ_NUM_SIZET, + ACL_MDL_INPUTQ_ADDR_PTR, /**< pointer to inputQ with shallow copy */ + ACL_MDL_OUTPUTQ_NUM_SIZET, + ACL_MDL_OUTPUTQ_ADDR_PTR /**< pointer to outputQ with shallow copy */ +} aclmdlConfigAttr; + +typedef enum { + ACL_DATA_WITHOUT_AIPP = 0, + ACL_DATA_WITH_STATIC_AIPP, + ACL_DATA_WITH_DYNAMIC_AIPP, + ACL_DYNAMIC_AIPP_NODE +} aclmdlInputAippType; + +typedef struct aclmdlIODims { + char name[ACL_MAX_TENSOR_NAME_LEN]; /**< tensor name */ + size_t dimCount; /**< dim array count */ + int64_t dims[ACL_MAX_DIM_CNT]; /**< dim data array */ +} aclmdlIODims; + +typedef struct aclAippDims { + aclmdlIODims srcDims; /**< input dims before model transform */ + size_t srcSize; /**< input size before model transform */ + aclmdlIODims aippOutdims; /**< aipp output dims */ + size_t aippOutSize; /**< aipp output size */ +} aclAippDims; + +typedef struct aclmdlBatch { + size_t batchCount; /**< batch array count */ + uint64_t batch[ACL_MAX_BATCH_NUM]; /**< batch data array */ +} aclmdlBatch; + +typedef struct aclmdlHW { + size_t hwCount; /**< height&width array count */ + uint64_t hw[ACL_MAX_HW_NUM][2]; /**< height&width data array */ +} aclmdlHW; + +typedef struct aclAippInfo { + aclAippInputFormat inputFormat; + int32_t srcImageSizeW; + int32_t srcImageSizeH; + int8_t cropSwitch; + int32_t loadStartPosW; + int32_t loadStartPosH; + int32_t cropSizeW; + int32_t cropSizeH; + int8_t resizeSwitch; + int32_t resizeOutputW; + int32_t resizeOutputH; + int8_t paddingSwitch; + int32_t leftPaddingSize; + int32_t rightPaddingSize; + int32_t topPaddingSize; + int32_t bottomPaddingSize; + int8_t cscSwitch; + int8_t rbuvSwapSwitch; + int8_t axSwapSwitch; + int8_t singleLineMode; + int32_t matrixR0C0; + int32_t matrixR0C1; + int32_t matrixR0C2; + int32_t matrixR1C0; + int32_t matrixR1C1; + int32_t matrixR1C2; + int32_t matrixR2C0; + int32_t matrixR2C1; + int32_t matrixR2C2; + int32_t outputBias0; + int32_t outputBias1; + int32_t outputBias2; + int32_t inputBias0; + int32_t inputBias1; + int32_t inputBias2; + int32_t meanChn0; + int32_t meanChn1; + int32_t meanChn2; + int32_t meanChn3; + float minChn0; + float minChn1; + float minChn2; + float minChn3; + float varReciChn0; + float varReciChn1; + float varReciChn2; + float varReciChn3; + aclFormat srcFormat; + aclDataType srcDatatype; + size_t srcDimNum; + size_t shapeCount; + aclAippDims outDims[ACL_MAX_SHAPE_COUNT]; + aclAippExtendInfo *aippExtend; /**< reserved parameters, current version needs to be null */ +} aclAippInfo; + +/** + * @ingroup AscendCL + * @brief Create data of type aclmdlDesc + * + * @retval the aclmdlDesc pointer + */ +ACL_FUNC_VISIBILITY aclmdlDesc *aclmdlCreateDesc(); + +/** + * @ingroup AscendCL + * @brief destroy data of type aclmdlDesc + * + * @param modelDesc [IN] Pointer to almdldlDesc to be destroyed + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlDestroyDesc(aclmdlDesc *modelDesc); + +/** + * @ingroup AscendCL + * @brief Get aclmdlDesc data of the model according to the model ID + * + * @param modelDesc [OUT] aclmdlDesc pointer + * @param modelId [IN] model id + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetDesc(aclmdlDesc *modelDesc, uint32_t modelId); + +/** + * @ingroup AscendCL + * @brief Get the number of the inputs of + * the model according to data of aclmdlDesc + * + * @param modelDesc [IN] aclmdlDesc pointer + * + * @retval input size with aclmdlDesc + */ +ACL_FUNC_VISIBILITY size_t aclmdlGetNumInputs(aclmdlDesc *modelDesc); + +/** + * @ingroup AscendCL + * @brief Get the number of the output of + * the model according to data of aclmdlDesc + * + * @param modelDesc [IN] aclmdlDesc pointer + * + * @retval output size with aclmdlDesc + */ +ACL_FUNC_VISIBILITY size_t aclmdlGetNumOutputs(aclmdlDesc *modelDesc); + +/** + * @ingroup AscendCL + * @brief Get the size of the specified input according to + * the data of type aclmdlDesc + * + * @param modelDesc [IN] aclmdlDesc pointer + * @param index [IN] the size of the number of inputs to be obtained, + * the index value starts from 0 + * + * @retval Specify the size of the input + */ +ACL_FUNC_VISIBILITY size_t aclmdlGetInputSizeByIndex(aclmdlDesc *modelDesc, size_t index); + +/** + * @ingroup AscendCL + * @brief Get the size of the specified output according to + * the data of type aclmdlDesc + * + * @param modelDesc [IN] aclmdlDesc pointer + * @param index [IN] the size of the number of outputs to be obtained, + * the index value starts from 0 + * + * @retval Specify the size of the output + */ +ACL_FUNC_VISIBILITY size_t aclmdlGetOutputSizeByIndex(aclmdlDesc *modelDesc, size_t index); + +/** + * @ingroup AscendCL + * @brief Create data of type aclmdlDataset + * + * @retval the aclmdlDataset pointer + */ +ACL_FUNC_VISIBILITY aclmdlDataset *aclmdlCreateDataset(); + +/** + * @ingroup AscendCL + * @brief destroy data of type aclmdlDataset + * + * @param dataset [IN] Pointer to aclmdlDataset to be destroyed + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlDestroyDataset(const aclmdlDataset *dataset); + +/** + * @ingroup AscendCL + * @brief Add aclDataBuffer to aclmdlDataset + * + * @param dataset [OUT] aclmdlDataset address of aclDataBuffer to be added + * @param dataBuffer [IN] aclDataBuffer address to be added + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlAddDatasetBuffer(aclmdlDataset *dataset, aclDataBuffer *dataBuffer); + +/** + * @ingroup AscendCL + * @brief Get the number of aclDataBuffer in aclmdlDataset + * + * @param dataset [IN] aclmdlDataset poiter + * + * @retval the number of aclDataBuffer + */ +ACL_FUNC_VISIBILITY size_t aclmdlGetDatasetNumBuffers(const aclmdlDataset *dataset); + +/** + * @ingroup AscendCL + * @brief Get the aclDataBuffer in aclmdlDataset by index + * + * @param dataset [IN] aclmdlDataset poiter + * @param index [IN] the index of aclDataBuffer + * + * @retval Get successfully, return the address of aclDataBuffer + * @retval Failure return NULL + */ +ACL_FUNC_VISIBILITY aclDataBuffer *aclmdlGetDatasetBuffer(const aclmdlDataset *dataset, size_t index); + +/** + * @ingroup AscendCL + * @brief Load offline model data from files + * and manage memory internally by the system + * + * @par Function + * After the system finishes loading the model, + * the model ID returned is used as a mark to identify the model + * during subsequent operations + * + * @param modelPath [IN] Storage path for offline model files + * @param modelId [OUT] Model ID generated after + * the system finishes loading the model + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFile(const char *modelPath, uint32_t *modelId); + +/** + * @ingroup AscendCL + * @brief Load offline model data from memory and manage the memory of + * model running internally by the system + * + * @par Function + * After the system finishes loading the model, + * the model ID returned is used as a mark to identify the model + * during subsequent operations + * + * @param model [IN] Model data stored in memory + * @param modelSize [IN] model data size + * @param modelId [OUT] Model ID generated after + * the system finishes loading the model + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMem(const void *model, size_t modelSize, + uint32_t *modelId); + +/** + * @ingroup AscendCL + * @brief Load offline model data from a file, + * and the user manages the memory of the model run by itself + * + * @par Function + * After the system finishes loading the model, + * the model ID returned is used as a mark to identify the model + * during subsequent operations. + * @param modelPath [IN] Storage path for offline model files + * @param modelId [OUT] Model ID generated after finishes loading the model + * @param workPtr [IN] A pointer to the working memory + * required by the model on the Device,can be null + * @param workSize [IN] The amount of working memory required by the model + * @param weightPtr [IN] Pointer to model weight memory on Device + * @param weightSize [IN] The amount of weight memory required by the model + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithMem(const char *modelPath, + uint32_t *modelId, void *workPtr, size_t workSize, + void *weightPtr, size_t weightSize); + +/** + * @ingroup AscendCL + * @brief Load offline model data from memory, + * and the user can manage the memory of model running + * + * @par Function + * After the system finishes loading the model, + * the model ID returned is used as a mark to identify the model + * during subsequent operations + * @param model [IN] Model data stored in memory + * @param modelSize [IN] model data size + * @param modelId [OUT] Model ID generated after finishes loading the model + * @param workPtr [IN] A pointer to the working memory + * required by the model on the Device,can be null + * @param workSize [IN] work memory size + * @param weightPtr [IN] Pointer to model weight memory on Device,can be null + * @param weightSize [IN] The amount of weight memory required by the model + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithMem(const void *model, size_t modelSize, + uint32_t *modelId, void *workPtr, size_t workSize, + void *weightPtr, size_t weightSize); + +/** + * @ingroup AscendCL + * @brief load model from file with async queue + * + * @param modelPath [IN] model path + * @param modelId [OUT] return model id if load success + * @param inputQ [IN] input queue pointer + * @param inputQNum [IN] input queue num + * @param outputQ [IN] output queue pointer + * @param outputQNum [IN] output queue num + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithQ(const char *modelPath, uint32_t *modelId, const uint32_t *inputQ, + size_t inputQNum, const uint32_t *outputQ, size_t outputQNum); + +/** + * @ingroup AscendCL + * @brief load model from memory with async queue + * + * @param model [IN] model memory which user manages + * @param modelSize [IN] model size + * @param modelId [OUT] return model id if load success + * @param inputQ [IN] input queue pointer + * @param inputQNum [IN] input queue num + * @param outputQ [IN] output queue pointer + * @param outputQNum [IN] output queue num + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithQ(const void *model, size_t modelSize, uint32_t *modelId, + const uint32_t *inputQ, size_t inputQNum, + const uint32_t *outputQ, size_t outputQNum); + +/** + * @ingroup AscendCL + * @brief Execute model synchronous inference until the inference result is returned + * + * @param modelId [IN] ID of the model to perform inference + * @param input [IN] Input data for model inference + * @param output [OUT] Output data for model inference + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlExecute(uint32_t modelId, const aclmdlDataset *input, aclmdlDataset *output); + +/** + * @ingroup AscendCL + * @brief Execute model asynchronous inference until the inference result is returned + * + * @param modelId [IN] ID of the model to perform inference + * @param input [IN] Input data for model inference + * @param output [OUT] Output data for model inference + * @param stream [IN] stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | + * aclmdlLoadFromMemWithMem + */ +ACL_FUNC_VISIBILITY aclError aclmdlExecuteAsync(uint32_t modelId, const aclmdlDataset *input, + aclmdlDataset *output, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief unload model with model id + * + * @param modelId [IN] model id to be unloaded + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlUnload(uint32_t modelId); + +/** + * @ingroup AscendCL + * @brief Get the weight memory size and working memory size + * required for model execution according to the model file + * + * @param fileName [IN] Model path to get memory information + * @param workSize [OUT] The amount of working memory for model executed + * @param weightSize [OUT] The amount of weight memory for model executed + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlQuerySize(const char *fileName, size_t *workSize, size_t *weightSize); + +/** + * @ingroup AscendCL + * @brief Obtain the weights required for + * model execution according to the model data in memory + * + * @par Restriction + * The execution and weight memory is Device memory, + * and requires user application and release. + * @param model [IN] model memory which user manages + * @param modelSize [IN] model data size + * @param workSize [OUT] The amount of working memory for model executed + * @param weightSize [OUT] The amount of weight memory for model executed + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlQuerySizeFromMem(const void *model, size_t modelSize, size_t *workSize, + size_t *weightSize); + +/** + * @ingroup AscendCL + * @brief In dynamic batch scenarios, + * it is used to set the number of images processed + * at one time during model inference + * + * @param modelId [IN] model id + * @param dataset [IN|OUT] data for model inference + * @param index [IN] index of dynamic tensor + * @param batchSize [IN] Number of images processed at a time during model + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | + * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetDynamicBatchSize(uint32_t modelId, aclmdlDataset *dataset, size_t index, + uint64_t batchSize); + +/** + * @ingroup AscendCL + * @brief Sets the H and W of the specified input of the model + * + * @param modelId [IN] model id + * @param dataset [IN|OUT] data for model inference + * @param index [IN] index of dynamic tensor + * @param height [IN] model height + * @param width [IN] model width + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | + * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetDynamicHWSize(uint32_t modelId, aclmdlDataset *dataset, size_t index, + uint64_t height, uint64_t width); + +/** + * @ingroup AscendCL + * @brief Sets the dynamic dims of the specified input of the model + * + * @param modelId [IN] model id + * @param dataset [IN|OUT] data for model inference + * @param index [IN] index of dynamic dims + * @param dims [IN] value of dynamic dims + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | + * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetInputDynamicDims(uint32_t modelId, aclmdlDataset *dataset, size_t index, + const aclmdlIODims *dims); + +/** + * @ingroup AscendCL + * @brief get input dims info + * + * @param modelDesc [IN] model description + * @param index [IN] input tensor index + * @param dims [OUT] dims info + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlGetInputDimsV2 + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetInputDims(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims); + +/** + * @ingroup AscendCL + * @brief get input dims info(version 2), especially for static aipp + * it is the same with aclmdlGetInputDims while model without static aipp + * + * @param modelDesc [IN] model description + * @param index [IN] input tensor index + * @param dims [OUT] dims info + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlGetInputDims + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetInputDimsV2(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims); + +/** + * @ingroup AscendCL + * @brief get output dims info + * + * @param modelDesc [IN] model description + * @param index [IN] output tensor index + * @param dims [OUT] dims info + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetOutputDims(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims); + +/** + * @ingroup AscendCL + * @brief get current output dims info + * + * @par Function + * The following use cases are supported: + * @li Get current output shape when model is dynamic and + * dynamic shape info is set + * @li Get max output shape when model is dynamic and + * dynamic shape info is not set + * @li Get actual output shape when model is static + * + * @param modelDesc [IN] model description + * @param index [IN] output tensor index + * @param dims [OUT] dims info + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetCurOutputDims(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims); + +/** + * @ingroup AscendCL + * @brief get input name by index + * + * @param modelDesc [IN] model description + * @param index [IN] intput tensor index + * + * @retval input tensor name,the same life cycle with modelDesc + */ +ACL_FUNC_VISIBILITY const char *aclmdlGetInputNameByIndex(const aclmdlDesc *modelDesc, size_t index); + +/** + * @ingroup AscendCL + * @brief get output name by index + * + * @param modelDesc [IN] model description + * @param index [IN] output tensor index + * + * @retval output tensor name,the same life cycle with modelDesc + */ +ACL_FUNC_VISIBILITY const char *aclmdlGetOutputNameByIndex(const aclmdlDesc *modelDesc, size_t index); + +/** + * @ingroup AscendCL + * @brief get input format by index + * + * @param modelDesc [IN] model description + * @param index [IN] intput tensor index + * + * @retval input tensor format + */ +ACL_FUNC_VISIBILITY aclFormat aclmdlGetInputFormat(const aclmdlDesc *modelDesc, size_t index); + +/** + * @ingroup AscendCL + * @brief get output format by index + * + * @param modelDesc [IN] model description + * @param index [IN] output tensor index + * + * @retval output tensor format + */ +ACL_FUNC_VISIBILITY aclFormat aclmdlGetOutputFormat(const aclmdlDesc *modelDesc, size_t index); + +/** + * @ingroup AscendCL + * @brief get input data type by index + * + * @param modelDesc [IN] model description + * @param index [IN] intput tensor index + * + * @retval input tensor data type + */ +ACL_FUNC_VISIBILITY aclDataType aclmdlGetInputDataType(const aclmdlDesc *modelDesc, size_t index); + +/** + * @ingroup AscendCL + * @brief get output data type by index + * + * @param modelDesc [IN] model description + * @param index [IN] output tensor index + * + * @retval output tensor data type + */ +ACL_FUNC_VISIBILITY aclDataType aclmdlGetOutputDataType(const aclmdlDesc *modelDesc, size_t index); + +/** + * @ingroup AscendCL + * @brief get input tensor index by name + * + * @param modelDesc [IN] model description + * @param name [IN] intput tensor name + * @param index [OUT] intput tensor index + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetInputIndexByName(const aclmdlDesc *modelDesc, const char *name, size_t *index); + +/** + * @ingroup AscendCL + * @brief get output tensor index by name + * + * @param modelDesc [IN] model description + * @param name [IN] output tensor name + * @param index [OUT] output tensor index + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetOutputIndexByName(const aclmdlDesc *modelDesc, const char *name, size_t *index); + +/** + * @ingroup AscendCL + * @brief get dynamic batch info + * + * @param modelDesc [IN] model description + * @param batch [OUT] dynamic batch info + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetDynamicBatch(const aclmdlDesc *modelDesc, aclmdlBatch *batch); + +/** + * @ingroup AscendCL + * @brief get dynamic height&width info + * + * @param modelDesc [IN] model description + * @param index [IN] input tensor index + * @param hw [OUT] dynamic height&width info + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetDynamicHW(const aclmdlDesc *modelDesc, size_t index, aclmdlHW *hw); + +/** + * @ingroup AscendCL + * @brief get dynamic gear count + * + * @param modelDesc [IN] model description + * @param index [IN] unused, must be -1 + * @param gearCount [OUT] dynamic gear count + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetInputDynamicGearCount(const aclmdlDesc *modelDesc, size_t index, + size_t *gearCount); + +/** + * @ingroup AscendCL + * @brief get dynamic dims info + * + * @param modelDesc [IN] model description + * @param index [IN] unused, must be -1 + * @param dims [OUT] value of dynamic dims + * @param gearCount [IN] dynamic gear count + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetInputDynamicDims(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims, + size_t gearCount); + +/** + * @ingroup AscendCL + * @brief Create data of type aclmdlAIPP + * + * @param batchSize [IN] batchsizes of model + * + * @retval the aclmdlAIPP pointer + */ +ACL_FUNC_VISIBILITY aclmdlAIPP *aclmdlCreateAIPP(uint64_t batchSize); + +/** + * @ingroup AscendCL + * @brief destroy data of type aclmdlAIPP + * + * @param aippParmsSet [IN] Pointer for aclmdlAIPP to be destroyed + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlDestroyAIPP(const aclmdlAIPP *aippParmsSet); + +/** + * @ingroup AscendCL + * @brief set InputFormat of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param inputFormat [IN] The inputFormat of aipp + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPInputFormat(aclmdlAIPP *aippParmsSet, aclAippInputFormat inputFormat); + +/** + * @ingroup AscendCL + * @brief set cscParms of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param csc_switch [IN] Csc switch + * @param cscMatrixR0C0 [IN] Csc_matrix_r0_c0 + * @param cscMatrixR0C1 [IN] Csc_matrix_r0_c1 + * @param cscMatrixR0C2 [IN] Csc_matrix_r0_c2 + * @param cscMatrixR1C0 [IN] Csc_matrix_r1_c0 + * @param cscMatrixR1C1 [IN] Csc_matrix_r1_c1 + * @param cscMatrixR1C2 [IN] Csc_matrix_r1_c2 + * @param cscMatrixR2C0 [IN] Csc_matrix_r2_c0 + * @param cscMatrixR2C1 [IN] Csc_matrix_r2_c1 + * @param cscMatrixR2C2 [IN] Csc_matrix_r2_c2 + * @param cscOutputBiasR0 [IN] Output Bias for RGB to YUV, element of row 0, unsigned number + * @param cscOutputBiasR1 [IN] Output Bias for RGB to YUV, element of row 1, unsigned number + * @param cscOutputBiasR2 [IN] Output Bias for RGB to YUV, element of row 2, unsigned number + * @param cscInputBiasR0 [IN] Input Bias for YUV to RGB, element of row 0, unsigned number + * @param cscInputBiasR1 [IN] Input Bias for YUV to RGB, element of row 1, unsigned number + * @param cscInputBiasR2 [IN] Input Bias for YUV to RGB, element of row 2, unsigned number + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, int8_t csc_switch, + int16_t cscMatrixR0C0, int16_t cscMatrixR0C1, int16_t cscMatrixR0C2, + int16_t cscMatrixR1C0, int16_t cscMatrixR1C1, int16_t cscMatrixR1C2, + int16_t cscMatrixR2C0, int16_t cscMatrixR2C1, int16_t cscMatrixR2C2, + uint8_t cscOutputBiasR0, uint8_t cscOutputBiasR1, + uint8_t cscOutputBiasR2, uint8_t cscInputBiasR0, + uint8_t cscInputBiasR1, uint8_t cscInputBiasR2); + +/** + * @ingroup AscendCL + * @brief set rb/ub swap switch of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param rbuvSwapSwitch [IN] rb/ub swap switch + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPRbuvSwapSwitch(aclmdlAIPP *aippParmsSet, int8_t rbuvSwapSwitch); + +/** + * @ingroup AscendCL + * @brief set RGBA->ARGB, YUVA->AYUV swap switch of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param axSwapSwitch [IN] RGBA->ARGB, YUVA->AYUV swap switch + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPAxSwapSwitch(aclmdlAIPP *aippParmsSet, int8_t axSwapSwitch); + +/** + * @ingroup AscendCL + * @brief set source image of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param srcImageSizeW [IN] Source image width + * @param srcImageSizeH [IN] Source image height + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPSrcImageSize(aclmdlAIPP *aippParmsSet, int32_t srcImageSizeW, + int32_t srcImageSizeH); + +/** + * @ingroup AscendCL + * @brief set resize switch of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param scfSwitch [IN] Resize switch + * @param scfInputSizeW [IN] Input width of scf + * @param scfInputSizeH [IN] Input height of scf + * @param scfOutputSizeW [IN] Output width of scf + * @param scfOutputSizeH [IN] Output height of scf + * @param batchIndex [IN] Batch parameter index + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPScfParams(aclmdlAIPP *aippParmsSet, + int8_t scfSwitch, + int32_t scfInputSizeW, + int32_t scfInputSizeH, + int32_t scfOutputSizeW, + int32_t scfOutputSizeH, + uint64_t batchIndex); + +/** + * @ingroup AscendCL + * @brief set cropParams of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param cropSwitch [IN] Crop switch + * @param cropStartPosW [IN] The start horizontal position of cropping + * @param cropStartPosH [IN] The start vertical position of cropping + * @param cropSizeW [IN] Crop width + * @param cropSizeH [IN] Crop height + * @param batchIndex [IN] Batch parameter index + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCropParams(aclmdlAIPP *aippParmsSet, + int8_t cropSwitch, + int32_t cropStartPosW, + int32_t cropStartPosH, + int32_t cropSizeW, + int32_t cropSizeH, + uint64_t batchIndex); + +/** + * @ingroup AscendCL + * @brief set paddingParams of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param paddingSwitch [IN] Padding switch + * @param paddingSizeTop [IN] Top padding size + * @param paddingSizeBottom [IN] Bottom padding size + * @param paddingSizeLeft [IN] Left padding size + * @param paddingSizeRight [IN] Right padding size + * @param batchIndex [IN] Batch parameter index + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPaddingParams(aclmdlAIPP *aippParmsSet, int8_t paddingSwitch, + int32_t paddingSizeTop, int32_t paddingSizeBottom, + int32_t paddingSizeLeft, int32_t paddingSizeRight, + uint64_t batchIndex); + +/** + * @ingroup AscendCL + * @brief set DtcPixelMean of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param dtcPixelMeanChn0 [IN] Mean value of channel 0 + * @param dtcPixelMeanChn1 [IN] Mean value of channel 1 + * @param dtcPixelMeanChn2 [IN] Mean value of channel 2 + * @param dtcPixelMeanChn3 [IN] Mean value of channel 3 + * @param batchIndex [IN] Batch parameter index + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMean(aclmdlAIPP *aippParmsSet, + int16_t dtcPixelMeanChn0, + int16_t dtcPixelMeanChn1, + int16_t dtcPixelMeanChn2, + int16_t dtcPixelMeanChn3, + uint64_t batchIndex); + +/** + * @ingroup AscendCL + * @brief set DtcPixelMin of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param dtcPixelMinChn0 [IN] Min value of channel 0 + * @param dtcPixelMinChn1 [IN] Min value of channel 1 + * @param dtcPixelMinChn2 [IN] Min value of channel 2 + * @param dtcPixelMinChn3 [IN] Min value of channel 3 + * @param batchIndex [IN] Batch parameter index + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMin(aclmdlAIPP *aippParmsSet, + float dtcPixelMinChn0, + float dtcPixelMinChn1, + float dtcPixelMinChn2, + float dtcPixelMinChn3, + uint64_t batchIndex); + +/** + * @ingroup AscendCL + * @brief set PixelVarReci of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param dtcPixelVarReciChn0 [IN] sfr_dtc_pixel_variance_reci_ch0 + * @param dtcPixelVarReciChn1 [IN] sfr_dtc_pixel_variance_reci_ch1 + * @param dtcPixelVarReciChn2 [IN] sfr_dtc_pixel_variance_reci_ch2 + * @param dtcPixelVarReciChn3 [IN] sfr_dtc_pixel_variance_reci_ch3 + * @param batchIndex [IN] Batch parameter index + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPixelVarReci(aclmdlAIPP *aippParmsSet, + float dtcPixelVarReciChn0, + float dtcPixelVarReciChn1, + float dtcPixelVarReciChn2, + float dtcPixelVarReciChn3, + uint64_t batchIndex); + +/** + * @ingroup AscendCL + * @brief set aipp parameters to model + * + * @param modelId [IN] model id + * @param dataset [IN] Pointer of dataset + * @param index [IN] index of input for aipp data(ACL_DYNAMIC_AIPP_NODE) + * @param aippParmsSet [IN] Pointer for aclmdlAIPP + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | + * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetInputAIPP(uint32_t modelId, + aclmdlDataset *dataset, + size_t index, + const aclmdlAIPP *aippParmsSet); + +/** + * @ingroup AscendCL + * @brief set aipp parameters to model + * + * @param modelId [IN] model id + * @param dataset [IN] Pointer of dataset + * @param index [IN] index of input for data which linked dynamic aipp(ACL_DATA_WITH_DYNAMIC_AIPP) + * @param aippParmsSet [IN] Pointer for aclmdlAIPP + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | + * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPByInputIndex(uint32_t modelId, + aclmdlDataset *dataset, + size_t index, + const aclmdlAIPP *aippParmsSet); + +/** + * @ingroup AscendCL + * @brief get input aipp type + * + * @param modelId [IN] model id + * @param index [IN] index of input + * @param type [OUT] aipp type for input.refrer to aclmdlInputAippType(enum) + * @param dynamicAttachedDataIndex [OUT] index for dynamic attached data(ACL_DYNAMIC_AIPP_NODE) + * valid when type is ACL_DATA_WITH_DYNAMIC_AIPP, invalid value is ACL_INVALID_NODE_INDEX + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | + * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP +*/ +ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, + size_t index, + aclmdlInputAippType *type, + size_t *dynamicAttachedDataIndex); + +/** + * @ingroup AscendCL + * @brief get static aipp parameters from model + * + * @param modelId [IN] model id + * @param index [IN] index of tensor + * @param aippinfo [OUT] Pointer for static aipp info + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval ACL_ERROR_MODEL_AIPP_NOT_EXIST The tensor of index is not configured with aipp + * @retval OtherValues Failure + * + * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | + * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName +*/ +ACL_FUNC_VISIBILITY aclError aclmdlGetFirstAippInfo(uint32_t modelId, size_t index, aclAippInfo *aippinfo); + +/** + * @ingroup AscendCL + * @brief get op description info + * + * @param deviceId [IN] device id + * @param streamId [IN] stream id + * @param taskId [IN] task id + * @param opName [OUT] pointer to op name + * @param opNameLen [IN] the length of op name + * @param inputDesc [OUT] pointer to input description + * @param numInputs [OUT] the number of input tensor + * @param outputDesc [OUT] pointer to output description + * @param numOutputs [OUT] the number of output tensor + * + * @retval ACL_SUCCESS The function is successfully executed + * @retval OtherValues Failure +*/ +ACL_FUNC_VISIBILITY aclError aclmdlCreateAndGetOpDesc(uint32_t deviceId, uint32_t streamId, + uint32_t taskId, char *opName, size_t opNameLen, aclTensorDesc **inputDesc, size_t *numInputs, + aclTensorDesc **outputDesc, size_t *numOutputs); + +/** + * @ingroup AscendCL + * @brief init dump + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure +*/ +ACL_FUNC_VISIBILITY aclError aclmdlInitDump(); + +/** + * @ingroup AscendCL + * @brief set param of dump + * + * @param dumpCfgPath [IN] the path of dump config + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetDump(const char *dumpCfgPath); + +/** + * @ingroup AscendCL + * @brief finalize dump. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure +*/ +ACL_FUNC_VISIBILITY aclError aclmdlFinalizeDump(); + +/** + * @ingroup AscendCL + * @brief load model with config + * + * @param handle [IN] pointer to model config handle + * @param modelId [OUT] pointer to model id + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure +*/ +ACL_FUNC_VISIBILITY aclError aclmdlLoadWithConfig(const aclmdlConfigHandle *handle, uint32_t *modelId); + +/** + * @ingroup AscendCL + * @brief create model config handle of type aclmdlConfigHandle + * + * @retval the aclmdlConfigHandle pointer + * + * @see aclmdlDestroyConfigHandle +*/ +ACL_FUNC_VISIBILITY aclmdlConfigHandle *aclmdlCreateConfigHandle(); + +/** + * @ingroup AscendCL + * @brief destroy data of type aclmdlConfigHandle + * + * @param handle [IN] pointer to model config handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateConfigHandle + */ +ACL_FUNC_VISIBILITY aclError aclmdlDestroyConfigHandle(aclmdlConfigHandle *handle); + +/** + * @ingroup AscendCL + * @brief set config for model load + * + * @param handle [OUT] pointer to model config handle + * @param attr [IN] config attr in model config handle to be set + * @param attrValue [IN] pointer to model config value + * @param valueSize [IN] memory size of attrValue + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetConfigOpt(aclmdlConfigHandle *handle, aclmdlConfigAttr attr, + const void *attrValue, size_t valueSize); + +#ifdef __cplusplus +} +#endif + +#endif // INC_EXTERNAL_ACL_ACL_MODEL_H_ diff --git a/inc/external/acl/acl_op.h b/inc/external/acl/acl_op.h index d2e59bfb..b1be0d6e 100644 --- a/inc/external/acl/acl_op.h +++ b/inc/external/acl/acl_op.h @@ -33,9 +33,9 @@ typedef void (*aclDataDeallocator)(void *data, size_t length); static const int ACL_COMPILE_FLAG_BIN_SELECTOR = 1; typedef enum aclEngineType { - ACL_ENGINE_SYS, - ACL_ENGINE_AICORE, - ACL_ENGINE_VECTOR, + ACL_ENGINE_SYS, + ACL_ENGINE_AICORE, + ACL_ENGINE_VECTOR, } aclopEngineType; /** @@ -148,7 +148,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrString(aclopAttr *attr, const char *att * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListBool(aclopAttr *attr, const char *attrName, int numValues, - const uint8_t *values); + const uint8_t *values); /** * @ingroup AscendCL @@ -163,7 +163,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListBool(aclopAttr *attr, const char *a * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListInt(aclopAttr *attr, const char *attrName, int numValues, - const int64_t *values); + const int64_t *values); /** * @ingroup AscendCL @@ -178,7 +178,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListInt(aclopAttr *attr, const char *at * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListFloat(aclopAttr *attr, const char *attrName, int numValues, - const float *values); + const float *values); /** * @ingroup AscendCL @@ -193,7 +193,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListFloat(aclopAttr *attr, const char * * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListString(aclopAttr *attr, const char *attrName, int numValues, - const char **values); + const char **values); /** * @ingroup AscendCL @@ -208,8 +208,11 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListString(aclopAttr *attr, const char * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, const char *attrName, int numLists, - const int *numValues, const int64_t *const values[]); +ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, + const char *attrName, + int numLists, + const int *numValues, + const int64_t *const values[]); /** * @ingroup AscendCL @@ -239,10 +242,15 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, const char * @retval OtherValues Failure */ ACL_DEPRECATED_MESSAGE("aclopExecute is deprecated, use aclopExecuteV2 instead") -ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], - const aclDataBuffer *const inputs[], int numOutputs, - const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], - const aclopAttr *attr, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, + int numInputs, + const aclTensorDesc *const inputDesc[], + const aclDataBuffer *const inputs[], + int numOutputs, + const aclTensorDesc *const outputDesc[], + aclDataBuffer *const outputs[], + const aclopAttr *attr, + aclrtStream stream); /** * @ingroup AscendCL @@ -272,9 +280,15 @@ ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, int numInputs, con * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, int numInputs, aclTensorDesc *inputDesc[], - aclDataBuffer *inputs[], int numOutputs, aclTensorDesc *outputDesc[], - aclDataBuffer *outputs[], aclopAttr *attr, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, + int numInputs, + aclTensorDesc *inputDesc[], + aclDataBuffer *inputs[], + int numOutputs, + aclTensorDesc *outputDesc[], + aclDataBuffer *outputs[], + aclopAttr *attr, + aclrtStream stream); /** * @ingroup AscendCL @@ -292,9 +306,12 @@ ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, int numInputs, a * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCreateHandle(const char *opType, int numInputs, - const aclTensorDesc *const inputDesc[], int numOutputs, - const aclTensorDesc *const outputDesc[], const aclopAttr *opAttr, +ACL_FUNC_VISIBILITY aclError aclopCreateHandle(const char *opType, + int numInputs, + const aclTensorDesc *const inputDesc[], + int numOutputs, + const aclTensorDesc *const outputDesc[], + const aclopAttr *opAttr, aclopHandle **handle); /** @@ -326,9 +343,12 @@ ACL_FUNC_VISIBILITY void aclopDestroyHandle(aclopHandle *handle); * * @see aclopCreateHandle | aclCreateDataBuffer */ -ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, int numInputs, - const aclDataBuffer *const inputs[], int numOutputs, - aclDataBuffer *const outputs[], aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, + int numInputs, + const aclDataBuffer *const inputs[], + int numOutputs, + aclDataBuffer *const outputs[], + aclrtStream stream); /** * @ingroup AscendCL @@ -344,8 +364,11 @@ ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, int numInp * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, const aclDataBuffer *srcBuffer, - const aclTensorDesc *dstDesc, aclDataBuffer *dstBuffer, uint8_t truncate, +ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, + const aclDataBuffer *srcBuffer, + const aclTensorDesc *dstDesc, + aclDataBuffer *dstBuffer, + uint8_t truncate, aclrtStream stream); /** @@ -360,9 +383,12 @@ ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, const aclDa * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, aclTensorDesc *dstDesc, uint8_t truncate, +ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, + aclTensorDesc *dstDesc, + uint8_t truncate, aclopHandle **handle); + /** * @ingroup AscendCL * @brief create kernel @@ -381,10 +407,15 @@ ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, ac * * @see aclopCompile */ -ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, const char *kernelId, const char *kernelName, - void *binData, int binSize, aclopEngineType enginetype, +ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, + const char *kernelId, + const char *kernelName, + void *binData, + int binSize, + aclopEngineType enginetype, aclDataDeallocator deallocator); + /** * @ingroup AscendCL * @brief create kernel @@ -399,8 +430,11 @@ ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, const char *k * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -typedef aclError (*aclopCompileFunc)(int numInputs, const aclTensorDesc *const inputDesc[], int numOutputs, - const aclTensorDesc *const outputDesc[], const aclopAttr *opAttr, +typedef aclError (*aclopCompileFunc)(int numInputs, + const aclTensorDesc *const inputDesc[], + int numOutputs, + const aclTensorDesc *const outputDesc[], + const aclopAttr *opAttr, aclopKernelDesc *aclopKernelDesc); /** @@ -441,8 +475,11 @@ ACL_FUNC_VISIBILITY aclError aclopUnregisterCompileFunc(const char *opType); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopSetKernelArgs(aclopKernelDesc *kernelDesc, const char *kernelId, uint32_t blockDim, - const void *args, uint32_t argSize); +ACL_FUNC_VISIBILITY aclError aclopSetKernelArgs(aclopKernelDesc *kernelDesc, + const char *kernelId, + uint32_t blockDim, + const void *args, + uint32_t argSize); /** * @ingroup AscendCL @@ -473,9 +510,12 @@ ACL_FUNC_VISIBILITY aclError aclopSetKernelWorkspaceSizes(aclopKernelDesc *kerne * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, int numInputs, - const aclTensorDesc *const inputDesc[], int numOutputs, - const aclTensorDesc *const outputDesc[], const aclopAttr *attr); +ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, + int numInputs, + const aclTensorDesc *const inputDesc[], + int numOutputs, + const aclTensorDesc *const outputDesc[], + const aclopAttr *attr); /** * @ingroup AscendCL @@ -493,12 +533,17 @@ ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, int numInputs * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopInferShape(const char *opType, int numInputs, aclTensorDesc *inputDesc[], - aclDataBuffer *inputs[], int numOutputs, aclTensorDesc *outputDesc[], +ACL_FUNC_VISIBILITY aclError aclopInferShape(const char *opType, + int numInputs, + aclTensorDesc *inputDesc[], + aclDataBuffer *inputs[], + int numOutputs, + aclTensorDesc *outputDesc[], aclopAttr *attr); + #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_OP_H_ +#endif // INC_EXTERNAL_ACL_ACL_OP_H_ diff --git a/inc/external/acl/acl_op_compiler.h b/inc/external/acl/acl_op_compiler.h index adae90c7..6bbb855c 100644 --- a/inc/external/acl/acl_op_compiler.h +++ b/inc/external/acl/acl_op_compiler.h @@ -24,18 +24,21 @@ extern "C" { #endif -typedef enum aclCompileType { ACL_COMPILE_SYS, ACL_COMPILE_UNREGISTERED } aclopCompileType; +typedef enum aclCompileType { + ACL_COMPILE_SYS, + ACL_COMPILE_UNREGISTERED +} aclopCompileType; typedef enum { - ACL_PRECISION_MODE, - ACL_AICORE_NUM, - ACL_AUTO_TUNE_MODE, - ACL_OP_SELECT_IMPL_MODE, - ACL_OPTYPELIST_FOR_IMPLMODE, - ACL_OP_DEBUG_LEVEL, - ACL_DEBUG_DIR, - ACL_OP_COMPILER_CACHE_MODE, - ACL_OP_COMPILER_CACHE_DIR + ACL_PRECISION_MODE, + ACL_AICORE_NUM, + ACL_AUTO_TUNE_MODE, + ACL_OP_SELECT_IMPL_MODE, + ACL_OPTYPELIST_FOR_IMPLMODE, + ACL_OP_DEBUG_LEVEL, + ACL_DEBUG_DIR, + ACL_OP_COMPILER_CACHE_MODE, + ACL_OP_COMPILER_CACHE_DIR } aclCompileOpt; /** @@ -56,10 +59,15 @@ typedef enum { * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], - int numOutputs, const aclTensorDesc *const outputDesc[], - const aclopAttr *attr, aclopEngineType engineType, - aclopCompileType compileFlag, const char *opPath); +ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, + int numInputs, + const aclTensorDesc *const inputDesc[], + int numOutputs, + const aclTensorDesc *const outputDesc[], + const aclopAttr *attr, + aclopEngineType engineType, + aclopCompileType compileFlag, + const char *opPath); /** * @ingroup AscendCL @@ -82,10 +90,11 @@ ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, int numInputs, con * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCompileAndExecute( - const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], const aclDataBuffer *const inputs[], - int numOutputs, const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], const aclopAttr *attr, - aclopEngineType engineType, aclopCompileType compileFlag, const char *opPath, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopCompileAndExecute(const char *opType, + int numInputs, const aclTensorDesc *const inputDesc[], const aclDataBuffer *const inputs[], + int numOutputs, const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], + const aclopAttr *attr, aclopEngineType engineType, aclopCompileType compileFlag, + const char *opPath, aclrtStream stream); /** * @ingroup AscendCL @@ -103,4 +112,4 @@ ACL_FUNC_VISIBILITY aclError aclSetCompileopt(aclCompileOpt opt, const char *val } #endif -#endif // INC_EXTERNAL_ACL_ACL_OP_COMPILER_H_ +#endif // INC_EXTERNAL_ACL_ACL_OP_COMPILER_H_ diff --git a/inc/external/acl/acl_prof.h b/inc/external/acl/acl_prof.h new file mode 100644 index 00000000..d2675124 --- /dev/null +++ b/inc/external/acl/acl_prof.h @@ -0,0 +1,296 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef INC_EXTERNAL_ACL_PROF_H_ +#define INC_EXTERNAL_ACL_PROF_H_ + +#include "acl_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ACL_PROF_ACL_API 0x0001 +#define ACL_PROF_TASK_TIME 0x0002 +#define ACL_PROF_AICORE_METRICS 0x0004 +#define ACL_PROF_AICPU 0x0008 + +#define ACL_PROF_MAX_OP_NAME_LEN 257 +#define ACL_PROF_MAX_OP_TYPE_LEN 65 + +typedef enum { + ACL_AICORE_ARITHMETIC_UTILIZATION = 0, + ACL_AICORE_PIPE_UTILIZATION = 1, + ACL_AICORE_MEMORY_BANDWIDTH = 2, + ACL_AICORE_L0B_AND_WIDTH = 3, + ACL_AICORE_RESOURCE_CONFLICT_RATIO = 4, + ACL_AICORE_NONE = 0xFF +} aclprofAicoreMetrics; + +typedef struct aclprofConfig aclprofConfig; +typedef struct aclprofStopConfig aclprofStopConfig; +typedef struct aclprofAicoreEvents aclprofAicoreEvents; +typedef struct aclprofSubscribeConfig aclprofSubscribeConfig; + +/** + * @ingroup AscendCL + * @brief profiling initialize + * + * @param profilerResultPath [IN] path of profiling result + * @param length [IN] length of profilerResultPath + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclprofFinalize + */ +ACL_FUNC_VISIBILITY aclError aclprofInit(const char *profilerResultPath, size_t length); + +/** + * @ingroup AscendCL + * @brief profiling finalize + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclprofInit + */ +ACL_FUNC_VISIBILITY aclError aclprofFinalize(); + +/** + * @ingroup AscendCL + * @brief Start profiling modules by profilerConfig + * + * @param profilerConfig [IN] config of profiling + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclprofStop + */ +ACL_FUNC_VISIBILITY aclError aclprofStart(const aclprofConfig *profilerConfig); + +/** + * @ingroup AscendCL + * @brief Create data of type aclprofConfig + * + * @param deviceIdList [IN] list of device id + * @param deviceNums [IN] number of devices + * @param aicoreMetrics [IN] type of aicore metrics + * @param aicoreEvents [IN] pointer to aicore events, only support NULL now + * @param dataTypeConfig [IN] config modules need profiling + * + * @retval the aclprofConfig pointer + * + * @see aclprofDestroyConfig + */ +ACL_FUNC_VISIBILITY aclprofConfig *aclprofCreateConfig(uint32_t *deviceIdList, uint32_t deviceNums, + aclprofAicoreMetrics aicoreMetrics, aclprofAicoreEvents *aicoreEvents, uint64_t dataTypeConfig); + +/** + * @ingroup AscendCL + * @brief Destroy data of type aclprofConfig + * + * @param profilerConfig [IN] config of profiling + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclprofCreateConfig + */ +ACL_FUNC_VISIBILITY aclError aclprofDestroyConfig(const aclprofConfig *profilerConfig); + +/** + * @ingroup AscendCL + * @brief stop profiling modules by stopProfilingConfig + * + * @param profilerConfig [IN] pointer to stop config of profiling + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclprofStart + */ +ACL_FUNC_VISIBILITY aclError aclprofStop(const aclprofConfig *profilerConfig); + +/** + * @ingroup AscendCL + * @brief subscribe profiling data of model + * + * @param modelId [IN] the model id subscribed + * @param profSubscribeConfig [IN] pointer to config of model subscribe + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclprofModelUnSubscribe + */ +ACL_FUNC_VISIBILITY aclError aclprofModelSubscribe(uint32_t modelId, + const aclprofSubscribeConfig *profSubscribeConfig); + +/** + * @ingroup AscendCL + * @brief unsubscribe profiling data of model + * + * @param modelId [IN] the model id unsubscribed + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclprofModelSubscribe + */ +ACL_FUNC_VISIBILITY aclError aclprofModelUnSubscribe(uint32_t modelId); + +/** + * @ingroup AscendCL + * @brief create subscribe config + * + * @param timeInfoSwitch [IN] switch whether get time info from model + * @param aicoreMetrics [IN] aicore metrics + * @param fd [IN] pointer to write pipe + * + * @retval the aclprofSubscribeConfig pointer + * + * @see aclprofDestroySubscribeConfig + */ +ACL_FUNC_VISIBILITY aclprofSubscribeConfig *aclprofCreateSubscribeConfig(int8_t timeInfoSwitch, + aclprofAicoreMetrics aicoreMetrics, void *fd); + +/** + * @ingroup AscendCL + * @brief destroy subscribe config + * + * @param profSubscribeConfig [IN] subscribe config + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclprofCreateSubscribeConfig + */ +ACL_FUNC_VISIBILITY aclError aclprofDestroySubscribeConfig(const aclprofSubscribeConfig *profSubscribeConfig); + +/** + * @ingroup AscendCL + * @brief create subscribe config + * + * @param opDescSize [OUT] size of op desc + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclprofGetOpDescSize(size_t *opDescSize); + +/** + * @ingroup AscendCL + * @brief get op number from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * @param opNumber [OUT] op number of subscription data + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclprofGetOpNum(const void *opInfo, size_t opInfoLen, uint32_t *opNumber); + +/** + * @ingroup AscendCL + * @brief get op type from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * @param index [IN] index of op array in opInfo + * @param opType [OUT] obtained op type string + * @param opTypeLen [IN] obtained length of op type string + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoLen, uint32_t index, + char *opType, size_t opTypeLen); + +/** + * @ingroup AscendCL + * @brief get op type from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * @param index [IN] index of op array in opInfo + * @param opName [OUT] obtained op name string + * @param opNameLen [IN] obtained length of op name string + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclprofGetOpName(const void *opInfo, size_t opInfoLen, uint32_t index, + char *opName, size_t opNameLen); + +/** + * @ingroup AscendCL + * @brief get start time of specified op from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * @param index [IN] index of op array in opInfo + * + * @retval start time(us) of specified op with timestamp + * @retval 0 for failed + */ +ACL_FUNC_VISIBILITY uint64_t aclprofGetOpStart(const void *opInfo, size_t opInfoLen, uint32_t index); + +/** + * @ingroup AscendCL + * @brief get end time of specified op from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * @param index [IN] index of op array in opInfo + * + * @retval end time(us) of specified op with timestamp + * @retval 0 for failed + */ +ACL_FUNC_VISIBILITY uint64_t aclprofGetOpEnd(const void *opInfo, size_t opInfoLen, uint32_t index); + +/** + * @ingroup AscendCL + * @brief get excution time of specified op from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * @param index [IN] index of op array in opInfo + * + * @retval execution time(us) of specified op with timestamp + * @retval 0 for failed + */ +ACL_FUNC_VISIBILITY uint64_t aclprofGetOpDuration(const void *opInfo, size_t opInfoLen, uint32_t index); + +/** + * @ingroup AscendCL + * @brief get model id from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * + * @retval model id of subscription data + * @retval 0 for failed + */ +ACL_FUNC_VISIBILITY size_t aclprofGetModelId(const void *opInfo, size_t opInfoLen, uint32_t index); + +#ifdef __cplusplus +} +#endif + +#endif // INC_EXTERNAL_ACL_PROF_H_ diff --git a/inc/external/acl/acl_rt.h b/inc/external/acl/acl_rt.h new file mode 100644 index 00000000..6fd2da6e --- /dev/null +++ b/inc/external/acl/acl_rt.h @@ -0,0 +1,950 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef INC_EXTERNAL_ACL_ACL_RT_H_ +#define INC_EXTERNAL_ACL_ACL_RT_H_ + +#include +#include +#include "acl_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum aclrtRunMode { + ACL_DEVICE, + ACL_HOST, +} aclrtRunMode; + +typedef enum aclrtTsId { + ACL_TS_ID_AICORE = 0, + ACL_TS_ID_AIVECTOR = 1, + ACL_TS_ID_RESERVED = 2, +} aclrtTsId; + +typedef enum aclrtEventStatus { + ACL_EVENT_STATUS_COMPLETE = 0, + ACL_EVENT_STATUS_NOT_READY = 1, + ACL_EVENT_STATUS_RESERVED = 2, +} aclrtEventStatus; + +typedef enum aclrtCallbackBlockType { + ACL_CALLBACK_NO_BLOCK, + ACL_CALLBACK_BLOCK, +} aclrtCallbackBlockType; + +typedef enum aclrtMemcpyKind { + ACL_MEMCPY_HOST_TO_HOST, + ACL_MEMCPY_HOST_TO_DEVICE, + ACL_MEMCPY_DEVICE_TO_HOST, + ACL_MEMCPY_DEVICE_TO_DEVICE, +} aclrtMemcpyKind; + +typedef enum aclrtMemMallocPolicy { + ACL_MEM_MALLOC_HUGE_FIRST, + ACL_MEM_MALLOC_HUGE_ONLY, + ACL_MEM_MALLOC_NORMAL_ONLY, + ACL_MEM_MALLOC_HUGE_FIRST_P2P, + ACL_MEM_MALLOC_HUGE_ONLY_P2P, + ACL_MEM_MALLOC_NORMAL_ONLY_P2P, +} aclrtMemMallocPolicy; + +typedef enum aclrtMemAttr { + ACL_DDR_MEM, + ACL_HBM_MEM, + ACL_DDR_MEM_HUGE, + ACL_DDR_MEM_NORMAL, + ACL_HBM_MEM_HUGE, + ACL_HBM_MEM_NORMAL, + ACL_DDR_MEM_P2P_HUGE, + ACL_DDR_MEM_P2P_NORMAL, + ACL_HBM_MEM_P2P_HUGE, + ACL_HBM_MEM_P2P_NORMAL, +} aclrtMemAttr; + +typedef enum aclrtGroupAttr { + ACL_GROUP_AICORE_INT, + ACL_GROUP_AIV_INT, + ACL_GROUP_AIC_INT, + ACL_GROUP_SDMANUM_INT, + ACL_GROUP_ASQNUM_INT +} aclrtGroupAttr; + +typedef struct tagRtGroupInfo aclrtGroupInfo; + +typedef struct rtExceptionInfo aclrtExceptionInfo; + +typedef void (*aclrtCallback)(void *userData); + +typedef void (*aclrtExceptionInfoCallback)(aclrtExceptionInfo *exceptionInfo); + +/** + * @ingroup AscendCL + * @brief Set a callback function to handle exception information + * + * @param callback [IN] callback function to handle exception information + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtSetExceptionInfoCallback(aclrtExceptionInfoCallback callback); + +/** + * @ingroup AscendCL + * @brief Get task id from exception information + * + * @param info [IN] pointer of exception information + * + * @retval The task id from exception information + * @retval 0xFFFFFFFF if info is null + */ +ACL_FUNC_VISIBILITY uint32_t aclrtGetTaskIdFromExceptionInfo(const aclrtExceptionInfo *info); + +/** + * @ingroup AscendCL + * @brief Get stream id from exception information + * + * @param info [IN] pointer of exception information + * + * @retval The stream id from exception information + * @retval 0xFFFFFFFF if info is null + */ +ACL_FUNC_VISIBILITY uint32_t aclrtGetStreamIdFromExceptionInfo(const aclrtExceptionInfo *info); + +/** + * @ingroup AscendCL + * @brief Get thread id from exception information + * + * @param info [IN] pointer of exception information + * + * @retval The thread id of fail task + * @retval 0xFFFFFFFF if info is null + */ +ACL_FUNC_VISIBILITY uint32_t aclrtGetThreadIdFromExceptionInfo(const aclrtExceptionInfo *info); + +/** + * @ingroup AscendCL + * @brief Get device id from exception information + * + * @param info [IN] pointer of exception information + * + * @retval The thread id of fail task + * @retval 0xFFFFFFFF if info is null + */ +ACL_FUNC_VISIBILITY uint32_t aclrtGetDeviceIdFromExceptionInfo(const aclrtExceptionInfo *info); + +/** + * @ingroup AscendCL + * @brief The thread that handles the callback function on the Stream + * + * @param threadId [IN] thread ID + * @param stream [IN] stream handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtSubscribeReport(uint64_t threadId, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Add a callback function to be executed on the host + * to the task queue of the Stream + * + * @param fn [IN] Specify the callback function to be added + * The function prototype of the callback function is: + * typedef void (*aclrtCallback)(void *userData); + * @param userData [IN] User data to be passed to the callback function + * @param blockType [IN] callback block type + * @param stream [IN] stream handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtLaunchCallback(aclrtCallback fn, void *userData, aclrtCallbackBlockType blockType, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief After waiting for a specified time, trigger callback processing + * + * @par Function + * The thread processing callback specified by + * the aclrtSubscribeReport interface + * + * @param timeout [IN] timeout value + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtSubscribeReport + */ +ACL_FUNC_VISIBILITY aclError aclrtProcessReport(int32_t timeout); + +/** + * @ingroup AscendCL + * @brief Cancel thread registration, + * the callback function on the specified Stream + * is no longer processed by the specified thread + * + * @param threadId [IN] thread ID + * @param stream [IN] stream handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtUnSubscribeReport(uint64_t threadId, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief create context and associates it with the calling thread + * + * @par Function + * The following use cases are supported: + * @li If you don't call the aclrtCreateContext interface + * to explicitly create the context, + * the system will use the default context, which is implicitly created + * when the aclrtSetDevice interface is called. + * @li If multiple contexts are created in a process + * (there is no limit on the number of contexts), + * the current thread can only use one of them at the same time. + * It is recommended to explicitly specify the context of the current thread + * through the aclrtSetCurrentContext interface to increase. + * the maintainability of the program. + * + * @param context [OUT] point to the created context + * @param deviceId [IN] device to create context on + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtSetDevice | aclrtSetCurrentContext + */ +ACL_FUNC_VISIBILITY aclError aclrtCreateContext(aclrtContext *context, int32_t deviceId); + +/** + * @ingroup AscendCL + * @brief destroy context instance + * + * @par Function + * Can only destroy context created through aclrtCreateContext interface + * + * @param context [IN] the context to destroy + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtCreateContext + */ +ACL_FUNC_VISIBILITY aclError aclrtDestroyContext(aclrtContext context); + +/** + * @ingroup AscendCL + * @brief set the context of the thread + * + * @par Function + * The following scenarios are supported: + * @li If the aclrtCreateContext interface is called in a thread to explicitly + * create a Context (for example: ctx1), the thread's Context can be specified + * without calling the aclrtSetCurrentContext interface. + * The system uses ctx1 as the context of thread1 by default. + * @li If the aclrtCreateContext interface is not explicitly created, + * the system uses the default context as the context of the thread. + * At this time, the aclrtDestroyContext interface cannot be used to release + * the default context. + * @li If the aclrtSetCurrentContext interface is called multiple times to + * set the thread's Context, the last one prevails. + * + * @par Restriction + * @li If the cevice corresponding to the context set for the thread + * has been reset, you cannot set the context as the context of the thread, + * otherwise a business exception will result. + * @li It is recommended to use the context created in a thread. + * If the aclrtCreateContext interface is called in thread A to create a context, + * and the context is used in thread B, + * the user must guarantee the execution order of tasks in the same stream + * under the same context in two threads. + * + * @param context [IN] the current context of the thread + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtCreateContext | aclrtDestroyContext + */ +ACL_FUNC_VISIBILITY aclError aclrtSetCurrentContext(aclrtContext context); + +/** + * @ingroup AscendCL + * @brief get the context of the thread + * + * @par Function + * If the user calls the aclrtSetCurrentContext interface + * multiple times to set the context of the current thread, + * then the last set context is obtained + * + * @param context [OUT] the current context of the thread + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtSetCurrentContext + */ +ACL_FUNC_VISIBILITY aclError aclrtGetCurrentContext(aclrtContext *context); + +/** + * @ingroup AscendCL + * @brief Specify the device to use for the operation + * implicitly create the default context and the default stream + * + * @par Function + * The following use cases are supported: + * @li Device can be specified in the process or thread. + * If you call the aclrtSetDevice interface multiple + * times to specify the same device, + * you only need to call the aclrtResetDevice interface to reset the device. + * @li The same device can be specified for operation + * in different processes or threads. + * @li Device is specified in a process, + * and multiple threads in the process can share this device to explicitly + * create a Context (aclrtCreateContext interface). + * @li In multi-device scenarios, you can switch to other devices + * through the aclrtSetDevice interface in the process. + * + * @param deviceId [IN] the device id + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtResetDevice |aclrtCreateContext + */ +ACL_FUNC_VISIBILITY aclError aclrtSetDevice(int32_t deviceId); + +/** + * @ingroup AscendCL + * @brief Reset the current operating Device and free resources on the device, + * including the default context, the default stream, + * and all streams created under the default context, + * and synchronizes the interface. + * If the task under the default context or stream has not been completed, + * the system will wait for the task to complete before releasing it. + * + * @par Restriction + * @li The Context, Stream, and Event that are explicitly created + * on the device to be reset. Before resetting, + * it is recommended to follow the following interface calling sequence, + * otherwise business abnormalities may be caused. + * @li Interface calling sequence: + * call aclrtDestroyEvent interface to release Event or + * call aclrtDestroyStream interface to release explicitly created Stream-> + * call aclrtDestroyContext to release explicitly created Context-> + * call aclrtResetDevice interface + * + * @param deviceId [IN] the device id + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtResetDevice(int32_t deviceId); + +/** + * @ingroup AscendCL + * @brief get target device of current thread + * + * @param deviceId [OUT] the device id + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtGetDevice(int32_t *deviceId); + +/** + * @ingroup AscendCL + * @brief get target side + * + * @param runMode [OUT] the run mode + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtGetRunMode(aclrtRunMode *runMode); + +/** + * @ingroup AscendCL + * @brief Wait for compute device to finish + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtSynchronizeDevice(void); + +/** + * @ingroup AscendCL + * @brief Set Scheduling TS + * + * @param tsId [IN] the ts id + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtSetTsDevice(aclrtTsId tsId); + +/** + * @ingroup AscendCL + * @brief get total device number. + * + * @param count [OUT] the device number + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtGetDeviceCount(uint32_t *count); + +/** + * @ingroup AscendCL + * @brief create event instance + * + * @param event [OUT] created event + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtCreateEvent(aclrtEvent *event); + +/** + * @ingroup AscendCL + * @brief destroy event instance + * + * @par Function + * Only events created through the aclrtCreateEvent interface can be + * destroyed, synchronous interfaces. When destroying an event, + * the user must ensure that the tasks involved in the aclrtSynchronizeEvent + * interface or the aclrtStreamWaitEvent interface are completed before + * they are destroyed. + * + * @param event [IN] event to destroy + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtCreateEvent | aclrtSynchronizeEvent | aclrtStreamWaitEvent + */ +ACL_FUNC_VISIBILITY aclError aclrtDestroyEvent(aclrtEvent event); + +/** + * @ingroup AscendCL + * @brief Record an Event in the Stream + * + * @param event [IN] event to record + * @param stream [IN] stream handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtRecordEvent(aclrtEvent event, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Reset an event + * + * @par Function + * Users need to make sure to wait for the tasks in the Stream + * to complete before resetting the Event + * + * @param event [IN] event to reset + * @param stream [IN] stream handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtResetEvent(aclrtEvent event, aclrtStream stream); + + /** + * @ingroup AscendCL + * @brief Queries an event's status + * + * @param event [IN] event to query + * @param status [OUT] event status + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtQueryEvent(aclrtEvent event, aclrtEventStatus *status); + +/** + * @ingroup AscendCL + * @brief Block Host Running, wait event to be complete + * + * @param event [IN] event to wait + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtSynchronizeEvent(aclrtEvent event); + +/** + * @ingroup AscendCL + * @brief computes the elapsed time between events. + * + * @param ms [OUT] time between start and end in ms + * @param start [IN] starting event + * @param end [IN] ending event + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtCreateEvent | aclrtRecordEvent | aclrtSynchronizeStream + */ +ACL_FUNC_VISIBILITY aclError aclrtEventElapsedTime(float *ms, aclrtEvent start, aclrtEvent end); + +/** + * @ingroup AscendCL + * @brief alloc memory on device + * + * @par Function + * alloc for size linear memory on device + * and return a pointer to allocated memory by *devPtr + * + * @par Restriction + * @li The memory requested by the aclrtMalloc interface needs to be released + * through the aclrtFree interface. + * @li Before calling the media data processing interface, + * if you need to apply memory on the device to store input or output data, + * you need to call acldvppMalloc to apply for memory. + * + * @param devPtr [OUT] pointer to pointer to allocated memory on device + * @param size [IN] alloc memory size + * @param policy [IN] memory alloc policy + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtFree | acldvppMalloc | aclrtMallocCached + */ +ACL_FUNC_VISIBILITY aclError aclrtMalloc(void **devPtr, + size_t size, + aclrtMemMallocPolicy policy); + +/** + * @ingroup AscendCL + * @brief allocate memory on device with cache + * + * @par Function + * alloc for size linear memory on device + * and return a pointer to allocated memory by *devPtr + * + * @par Restriction + * @li The memory requested by the aclrtMallocCached interface needs to be released + * through the aclrtFree interface. + * + * @param devPtr [OUT] pointer to pointer to allocated memory on device + * @param size [IN] alloc memory size + * @param policy [IN] memory alloc policy + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtFree | aclrtMalloc + */ +ACL_FUNC_VISIBILITY aclError aclrtMallocCached(void **devPtr, + size_t size, + aclrtMemMallocPolicy policy); + +/** + * @ingroup AscendCL + * @brief flush cache data to ddr + * + * @param devPtr [IN] the pointer that flush data to ddr + * @param size [IN] flush size + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtMemFlush(void *devPtr, size_t size); + +/** + * @ingroup AscendCL + * @brief invalidate cache data + * + * @param devPtr [IN] pointer to invalidate cache data + * @param size [IN] invalidate size + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtMemInvalidate(void *devPtr, size_t size); + +/** + * @ingroup AscendCL + * @brief free device memory + * + * @par Function + * can only free memory allocated through the aclrtMalloc interface + * + * @param devPtr [IN] Pointer to memory to be freed + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtMalloc + */ +ACL_FUNC_VISIBILITY aclError aclrtFree(void *devPtr); + +/** + * @ingroup AscendCL + * @brief alloc memory on host + * + * @par Restriction + * @li The requested memory cannot be used in the Device + * and needs to be explicitly copied to the Device. + * @li The memory requested by the aclrtMallocHost interface + * needs to be released through the aclrtFreeHost interface. + * + * @param hostPtr [OUT] pointer to pointer to allocated memory on the host + * @param size [IN] alloc memory size + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtFreeHost + */ +ACL_FUNC_VISIBILITY aclError aclrtMallocHost(void **hostPtr, size_t size); + +/** + * @ingroup AscendCL + * @brief free host memory + * + * @par Function + * can only free memory allocated through the aclrtMallocHost interface + * + * @param hostPtr [IN] free memory pointer + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtMallocHost + */ +ACL_FUNC_VISIBILITY aclError aclrtFreeHost(void *hostPtr); + +/** + * @ingroup AscendCL + * @brief synchronous memory replication between host and device + * + * @param dst [IN] destination address pointer + * @param destMax [IN] Max length of the destination address memory + * @param src [IN] source address pointer + * @param count [IN] the length of byte to copy + * @param kind [IN] memcpy type + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtMemcpy(void *dst, + size_t destMax, + const void *src, + size_t count, + aclrtMemcpyKind kind); + +/** + * @ingroup AscendCL + * @brief Initialize memory and set contents of memory to specified value + * + * @par Function + * The memory to be initialized is on the Host or device side, + * and the system determines whether + * it is host or device according to the address + * + * @param devPtr [IN] Starting address of memory + * @param maxCount [IN] Max length of destination address memory + * @param value [IN] Set value + * @param count [IN] The length of memory + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtMemset(void *devPtr, size_t maxCount, int32_t value, size_t count); + +/** + * @ingroup AscendCL + * @brief Asynchronous memory replication between Host and Device + * + * @par Function + * After calling this interface, + * be sure to call the aclrtSynchronizeStream interface to ensure that + * the task of memory replication has been completed + * + * @par Restriction + * @li For on-chip Device-to-Device memory copy, + * both the source and destination addresses must be 64-byte aligned + * + * @param dst [IN] destination address pointer + * @param destMax [IN] Max length of destination address memory + * @param src [IN] source address pointer + * @param count [IN] the number of byte to copy + * @param kind [IN] memcpy type + * @param stream [IN] asynchronized task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtSynchronizeStream + */ +ACL_FUNC_VISIBILITY aclError aclrtMemcpyAsync(void *dst, + size_t destMax, + const void *src, + size_t count, + aclrtMemcpyKind kind, + aclrtStream stream); + +/** +* @ingroup AscendCL +* @brief Asynchronous initialize memory +* and set contents of memory to specified value async +* +* @par Function + * The memory to be initialized is on the Host or device side, + * and the system determines whether + * it is host or device according to the address + * +* @param devPtr [IN] destination address pointer +* @param maxCount [IN] Max length of destination address memory +* @param value [IN] set value +* @param count [IN] the number of byte to set +* @param stream [IN] asynchronized task stream +* +* @retval ACL_SUCCESS The function is successfully executed. +* @retval OtherValues Failure +* +* @see aclrtSynchronizeStream +*/ +ACL_FUNC_VISIBILITY aclError aclrtMemsetAsync(void *devPtr, + size_t maxCount, + int32_t value, + size_t count, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief create stream instance + * + * @param stream [OUT] the created stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtCreateStream(aclrtStream *stream); + +/** + * @ingroup AscendCL + * @brief destroy stream instance + * + * @par Function + * Can only destroy streams created through the aclrtCreateStream interface + * + * @par Restriction + * Before calling the aclrtDestroyStream interface to destroy + * the specified Stream, you need to call the aclrtSynchronizeStream interface + * to ensure that the tasks in the Stream have been completed. + * + * @param stream [IN] the stream to destroy + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtCreateStream | aclrtSynchronizeStream + */ +ACL_FUNC_VISIBILITY aclError aclrtDestroyStream(aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief block the host until all tasks + * in the specified stream have completed + * + * @param stream [IN] the stream to wait + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtSynchronizeStream(aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Blocks the operation of the specified Stream until + * the specified Event is completed. + * Support for multiple streams waiting for the same event. + * + * @param stream [IN] the wait stream If using thedefault Stream, set NULL + * @param event [IN] the event to wait + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtStreamWaitEvent(aclrtStream stream, aclrtEvent event); + +/** + * @ingroup AscendCL + * @brief set group + * + * @par Function + * set the task to the corresponding group + * + * @param groupId [IN] group id + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtGetGroupCount | aclrtGetAllGroupInfo | aclrtGetGroupInfoDetail + */ +ACL_FUNC_VISIBILITY aclError aclrtSetGroup(int32_t groupId); + +/** + * @ingroup AscendCL + * @brief get the number of group + * + * @par Function + * get the number of group. if the number of group is zero, + * it means that group is not supported or group is not created. + * + * @param count [OUT] the number of group + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + */ +ACL_FUNC_VISIBILITY aclError aclrtGetGroupCount(uint32_t *count); + +/** + * @ingroup AscendCL + * @brief create group information + * + * @retval null for failed. + * @retval OtherValues success. + * + * @see aclrtDestroyGroupInfo + */ +ACL_FUNC_VISIBILITY aclrtGroupInfo *aclrtCreateGroupInfo(); + +/** + * @ingroup AscendCL + * @brief destroy group information + * + * @param groupInfo [IN] pointer to group information + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtCreateGroupInfo + */ +ACL_FUNC_VISIBILITY aclError aclrtDestroyGroupInfo(aclrtGroupInfo *groupInfo); + +/** + * @ingroup AscendCL + * @brief get all group information + * + * @param groupInfo [OUT] pointer to group information + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtGetGroupCount + */ +ACL_FUNC_VISIBILITY aclError aclrtGetAllGroupInfo(aclrtGroupInfo *groupInfo); + +/** + * @ingroup AscendCL + * @brief get detail information of group + * + * @param groupInfo [IN] pointer to group information + * @param groupId [IN] group index value + * @param attr [IN] group attribute + * @param attrValue [OUT] pointer to attribute value + * @param valueLen [IN] length of attribute value + * @param paramRetSize [OUT] pointer to real length of attribute value + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtGetGroupCount | aclrtGetAllGroupInfo + */ +ACL_FUNC_VISIBILITY aclError aclrtGetGroupInfoDetail(const aclrtGroupInfo *groupInfo, + int32_t groupId, + aclrtGroupAttr attr, + void *attrValue, + size_t valueLen, + size_t *paramRetSize); + +/** + * @ingroup AscendCL + * @brief checking whether current device and peer device support the p2p feature + * + * @param canAccessPeer [OUT] pointer to save the checking result + * @param deviceId [IN] current device id + * @param peerDeviceId [IN] peer device id + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtDeviceEnablePeerAccess | aclrtDeviceDisablePeerAccess + */ +ACL_FUNC_VISIBILITY aclError aclrtDeviceCanAccessPeer(int32_t *canAccessPeer, int32_t deviceId, int32_t peerDeviceId); + +/** + * @ingroup AscendCL + * @brief enable the peer device to support the p2p feature + * + * @param peerDeviceId [IN] the peer device id + * @param flags [IN] reserved field, now it must be zero + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtDeviceCanAccessPeer | aclrtDeviceDisablePeerAccess + */ +ACL_FUNC_VISIBILITY aclError aclrtDeviceEnablePeerAccess(int32_t peerDeviceId, uint32_t flags); + +/** + * @ingroup AscendCL + * @brief disable the peer device to support the p2p function + * + * @param peerDeviceId [IN] the peer device id + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtDeviceCanAccessPeer | aclrtDeviceEnablePeerAccess + */ +ACL_FUNC_VISIBILITY aclError aclrtDeviceDisablePeerAccess(int32_t peerDeviceId); + +/** + * @ingroup AscendCL + * @brief Obtain the free memory and total memory of specified attribute. + * the specified memory include normal memory and huge memory. + * + * @param attr [IN] the memory attribute of specified device + * @param free [OUT] the free memory of specified device + * @param total [OUT] the total memory of specified device. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtGetMemInfo(aclrtMemAttr attr, size_t *free, size_t *total); + +#ifdef __cplusplus +} +#endif + +#endif // INC_EXTERNAL_ACL_ACL_RT_H_ + diff --git a/inc/external/acl/acl_tdt.h b/inc/external/acl/acl_tdt.h new file mode 100644 index 00000000..61995121 --- /dev/null +++ b/inc/external/acl/acl_tdt.h @@ -0,0 +1,283 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef INC_EXTERNAL_ACL_ACL_TDT_H_ +#define INC_EXTERNAL_ACL_ACL_TDT_H_ + +#include "acl/acl_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum acltdtTensorType { + ACL_TENSOR_DATA_UNDEFINED = -1, + ACL_TENSOR_DATA_TENSOR, + ACL_TENSOR_DATA_END_OF_SEQUENCE, + ACL_TENSOR_DATA_ABNORMAL +}; + +typedef struct acltdtDataItem acltdtDataItem; +typedef struct acltdtDataset acltdtDataset; +typedef struct acltdtChannelHandle acltdtChannelHandle; + +/** + * @ingroup AscendCL + * @brief Get tensor type from item + * + * @param dataItem [IN] pointer to the data item + * + * @retval Tensor type. + * @retval ACL_DT_UNDEFINED if dataItem is null + */ +ACL_FUNC_VISIBILITY acltdtTensorType acltdtGetTensorTypeFromItem(const acltdtDataItem *dataItem); + +/** + * @ingroup AscendCL + * @brief Get data type from item + * + * @param dataItem [IN] pointer to the data item + * + * @retval Data type. + * @retval ACL_DT_UNDEFINED if dataItem is null + */ +ACL_FUNC_VISIBILITY aclDataType acltdtGetDataTypeFromItem(const acltdtDataItem *dataItem); + +/** + * @ingroup AscendCL + * @brief Get data address from item + * + * @param dataItem [IN] pointer to data item + * + * @retval null for failed + * @retval OtherValues success +*/ +ACL_FUNC_VISIBILITY void *acltdtGetDataAddrFromItem(const acltdtDataItem *dataItem); + +/** + * @ingroup AscendCL + * @brief Get data size from item + * + * @param dataItem [IN] pointer to data item + * + * @retval 0 for failed + * @retval OtherValues success +*/ +ACL_FUNC_VISIBILITY size_t acltdtGetDataSizeFromItem(const acltdtDataItem *dataItem); + +/** + * @ingroup AscendCL + * @brief Get dim's number from item + * + * @param dataItem [IN] pointer to data item + * + * @retval 0 for failed + * @retval OtherValues success +*/ +ACL_FUNC_VISIBILITY size_t acltdtGetDimNumFromItem(const acltdtDataItem *dataItem); + +/** + * @ingroup AscendCL + * @brief Get dims from item + * + * @param dataItem [IN] the struct of data item + * @param dims [IN|OUT] pointer to the dims of dataTtem + * @param dimNum [IN] the size of the dims + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acltdtGetDimsFromItem(const acltdtDataItem *dataItem, int64_t *dims, size_t dimNum); + +/** + * @ingroup AscendCL + * @brief Create the struct of data item + * + * @param tdtType [IN] Tdt tensor type + * @param dims [IN] pointer of tdtDataItem's dims + * @param dimNum [IN] Dim number + * @param dataType [IN] Data type + * @param data [IN] Data pointer + * @param size [IN] Data size + * + * @retval null for failed + * @retval OtherValues success + * + * @see acltdtDestroyDataItem + */ +ACL_FUNC_VISIBILITY acltdtDataItem *acltdtCreateDataItem(acltdtTensorType tdtType, + const int64_t *dims, + size_t dimNum, + aclDataType dataType, + void *data, + size_t size); + +/** + * @ingroup AscendCL + * @brief Destroy the struct of data item + * + * @param dataItem [IN] pointer to the data item + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtCreateDataItem + */ +ACL_FUNC_VISIBILITY aclError acltdtDestroyDataItem(acltdtDataItem *dataItem); + +/** + * @ingroup AscendCL + * @brief Create the tdt dataset + * + * @retval null for failed + * @retval OtherValues success + * + * @see acltdtDestroyDataset + */ +ACL_FUNC_VISIBILITY acltdtDataset *acltdtCreateDataset(); + +/** + * @ingroup AscendCL + * @brief Destroy the tdt dataset + * + * @param dataset [IN] pointer to the dataset + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtCreateDataset + */ +ACL_FUNC_VISIBILITY aclError acltdtDestroyDataset(acltdtDataset *dataset); + +/** + * @ingroup AscendCL + * @brief Get the data item + * + * @param dataset [IN] pointer to the dataset + * @param index [IN] index of the dataset + * + * @retval null for failed + * @retval OtherValues success + * + * @see acltdtAddDataItem + */ +ACL_FUNC_VISIBILITY acltdtDataItem *acltdtGetDataItem(const acltdtDataset *dataset, size_t index); + +/** + * @ingroup AscendCL + * @brief Get the data item + * + * @param dataset [OUT] pointer to the dataset + * @param dataItem [IN] pointer to the data item + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtGetDataItem + */ +ACL_FUNC_VISIBILITY aclError acltdtAddDataItem(acltdtDataset *dataset, acltdtDataItem *dataItem); + +/** + * @ingroup AscendCL + * @brief Get the size of dataset + * + * @param dataset [IN] pointer to the dataset + * + * @retval 0 for failed + * @retval OtherValues success + */ +ACL_FUNC_VISIBILITY size_t acltdtGetDatasetSize(const acltdtDataset *dataset); + +/** + * @ingroup AscendCL + * @brief Stop the channel + * + * @param handle [IN] pointer to the channel handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtCreateChannel | acltdtDestroyChannel + */ +ACL_FUNC_VISIBILITY aclError acltdtStopChannel(acltdtChannelHandle *handle); + +/** + * @ingroup AscendCL + * @brief Create the channel + * + * @param deviceId [IN] the device id + * @param name [IN] the channel's name + * + * @retval null for failed + * @retval OtherValues success + * + * @see acltdtStopChannel | acltdtDestroyChannel + */ +ACL_FUNC_VISIBILITY acltdtChannelHandle *acltdtCreateChannel(uint32_t deviceId, const char *name); + +/** + * @ingroup AscendCL + * @brief Destroy the channel + * + * @param handle [IN] pointer to the channel handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtCreateChannel | acltdtStopChannel + */ +ACL_FUNC_VISIBILITY aclError acltdtDestroyChannel(acltdtChannelHandle *handle); + +/** + * @ingroup AscendCL + * @brief Send tensor to device + * + * @param handle [IN] pointer to the channel handle + * @param dataset [IN] pointer to the dataset + * @param timeout [IN] to be reserved, now it must be -1 + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtReceiveTensor + */ +ACL_FUNC_VISIBILITY aclError acltdtSendTensor(const acltdtChannelHandle *handle, + const acltdtDataset *dataset, + int32_t timeout); + +/** + * @ingroup AscendCL + * @brief Receive tensor from device + * + * @param handle [IN] pointer to the channel handle + * @param dataset [OUT] pointer to the dataset + * @param timeout [IN] to be reserved, now it must be -1 + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtSendTensor + */ +ACL_FUNC_VISIBILITY aclError acltdtReceiveTensor(const acltdtChannelHandle *handle, + acltdtDataset *dataset, + int32_t timeout); + +#ifdef __cplusplus +} +#endif + +#endif //INC_EXTERNAL_ACL_ACL_TDT_H_ + diff --git a/inc/external/acl/error_codes/rt_error_codes.h b/inc/external/acl/error_codes/rt_error_codes.h index 2dd2c70c..73da559d 100644 --- a/inc/external/acl/error_codes/rt_error_codes.h +++ b/inc/external/acl/error_codes/rt_error_codes.h @@ -23,69 +23,80 @@ extern "C" { #endif -static const int32_t ACL_RT_SUCCESS = 0; // success +static const int32_t ACL_RT_SUCCESS = 0; // success -static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid -static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id -static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null -static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context -static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context -static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal -static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned -static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed -static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed -static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream -static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread -static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set -static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create -static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream -static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type +static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid +static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id +static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null +static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context +static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context +static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal +static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned +static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed +static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed +static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream +static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread +static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set +static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create +static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream +static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type +static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle +static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type -static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPROT = 207000; // feature not support -static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error -static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error +static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support +static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error +static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error +static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow +static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device +static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail +static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission +static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource +static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource +static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource +static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource -static const int32_t ACL_ERROR_RT_INTERNEL_ERROR = 507000; // runtime internel error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error + +static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error -static const int32_t ACL_ERROR_RT_DRV_INTERNEL_ERROR = 507899; // drv internel error #ifdef __cplusplus } #endif -#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ +#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/inc/external/acl/ops/acl_cblas.h b/inc/external/acl/ops/acl_cblas.h index 3d81eb2b..a2bd8c61 100644 --- a/inc/external/acl/ops/acl_cblas.h +++ b/inc/external/acl/ops/acl_cblas.h @@ -23,9 +23,17 @@ extern "C" { #endif -typedef enum aclTransType { ACL_TRANS_N, ACL_TRANS_T, ACL_TRANS_NZ, ACL_TRANS_NZ_T } aclTransType; +typedef enum aclTransType { + ACL_TRANS_N, + ACL_TRANS_T, + ACL_TRANS_NZ, + ACL_TRANS_NZ_T +} aclTransType; -typedef enum aclComputeType { ACL_COMPUTE_HIGH_PRECISION, ACL_COMPUTE_LOW_PRECISION } aclComputeType; +typedef enum aclComputeType { + ACL_COMPUTE_HIGH_PRECISION, + ACL_COMPUTE_LOW_PRECISION +} aclComputeType; /** * @ingroup AscendCL @@ -53,11 +61,12 @@ typedef enum aclComputeType { ACL_COMPUTE_HIGH_PRECISION, ACL_COMPUTE_LOW_PRECIS * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure - */ -ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, const void *alpha, const void *a, int lda, - aclDataType dataTypeA, const void *x, int incx, aclDataType dataTypeX, - const void *beta, void *y, int incy, aclDataType dataTypeY, - aclComputeType type, aclrtStream stream); +*/ +ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, + const void *alpha, const void *a, int lda, aclDataType dataTypeA, + const void *x, int incx, aclDataType dataTypeX, + const void *beta, void *y, int incy, aclDataType dataTypeY, + aclComputeType type, aclrtStream stream); /** * @ingroup AscendCL @@ -74,10 +83,15 @@ ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, co * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure - */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, int m, int n, aclDataType dataTypeA, - aclDataType dataTypeX, aclDataType dataTypeY, - aclComputeType type, aclopHandle **handle); +*/ +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, + int m, + int n, + aclDataType dataTypeA, + aclDataType dataTypeX, + aclDataType dataTypeY, + aclComputeType type, + aclopHandle **handle); /** * @ingroup AscendCL @@ -101,9 +115,18 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, i * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, int m, int n, const aclFloat16 *alpha, - const aclFloat16 *a, int lda, const aclFloat16 *x, int incx, - const aclFloat16 *beta, aclFloat16 *y, int incy, aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, + int m, + int n, + const aclFloat16 *alpha, + const aclFloat16 *a, + int lda, + const aclFloat16 *x, + int incx, + const aclFloat16 *beta, + aclFloat16 *y, + int incy, + aclComputeType type, aclrtStream stream); /** @@ -119,7 +142,10 @@ ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, int m, int n, con * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, int m, int n, aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, + int m, + int n, + aclComputeType type, aclopHandle **handle); /** @@ -145,9 +171,19 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, in * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, int m, int n, const int32_t *alpha, const int8_t *a, - int lda, const int8_t *x, int incx, const int32_t *beta, int32_t *y, - int incy, aclComputeType type, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, + int m, + int n, + const int32_t *alpha, + const int8_t *a, + int lda, + const int8_t *x, + int incx, + const int32_t *beta, + int32_t *y, + int incy, + aclComputeType type, + aclrtStream stream); /** * @ingroup AscendCL @@ -162,7 +198,10 @@ ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, int m, int n, co * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, int m, int n, aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, + int m, + int n, + aclComputeType type, aclopHandle **handle); /** @@ -194,11 +233,26 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, i * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, - int k, const void *alpha, const void *matrixA, int lda, - aclDataType dataTypeA, const void *matrixB, int ldb, aclDataType dataTypeB, - const void *beta, void *matrixC, int ldc, aclDataType dataTypeC, - aclComputeType type, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, + aclTransType transB, + aclTransType transC, + int m, + int n, + int k, + const void *alpha, + const void *matrixA, + int lda, + aclDataType dataTypeA, + const void *matrixB, + int ldb, + aclDataType dataTypeB, + const void *beta, + void *matrixC, + int ldc, + aclDataType dataTypeC, + aclComputeType type, + aclrtStream stream); + /** * @ingroup AscendCL @@ -220,10 +274,18 @@ ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, aclTransType tra * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, aclTransType transB, aclTransType transC, - int m, int n, int k, aclDataType dataTypeA, - aclDataType dataTypeB, aclDataType dataTypeC, - aclComputeType type, aclopHandle **handle); +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, + aclTransType transB, + aclTransType transC, + int m, + int n, + int k, + aclDataType dataTypeA, + aclDataType dataTypeB, + aclDataType dataTypeC, + aclComputeType type, + aclopHandle **handle); + /** * @ingroup AscendCL @@ -251,10 +313,22 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, a * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, - int k, const aclFloat16 *alpha, const aclFloat16 *matrixA, int lda, - const aclFloat16 *matrixB, int ldb, const aclFloat16 *beta, - aclFloat16 *matrixC, int ldc, aclComputeType type, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, + aclTransType transB, + aclTransType transC, + int m, + int n, + int k, + const aclFloat16 *alpha, + const aclFloat16 *matrixA, + int lda, + const aclFloat16 *matrixB, + int ldb, + const aclFloat16 *beta, + aclFloat16 *matrixC, + int ldc, + aclComputeType type, + aclrtStream stream); /** * @ingroup AscendCL @@ -272,8 +346,13 @@ ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, aclTransType tran * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, aclTransType transB, aclTransType transC, - int m, int n, int k, aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, + aclTransType transB, + aclTransType transC, + int m, + int n, + int k, + aclComputeType type, aclopHandle **handle); /** @@ -302,10 +381,23 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, ac * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, - int k, const int32_t *alpha, const int8_t *matrixA, int lda, - const int8_t *matrixB, int ldb, const int32_t *beta, int32_t *matrixC, - int ldc, aclComputeType type, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, + aclTransType transB, + aclTransType transC, + int m, + int n, + int k, + const int32_t *alpha, + const int8_t *matrixA, + int lda, + const int8_t *matrixB, + int ldb, + const int32_t *beta, + int32_t *matrixC, + int ldc, + aclComputeType type, + aclrtStream stream); + /** * @ingroup AscendCL @@ -323,12 +415,17 @@ ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, aclTransType tra * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemm(aclTransType transA, aclTransType transB, aclTransType transC, - int m, int n, int k, aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemm(aclTransType transA, + aclTransType transB, + aclTransType transC, + int m, + int n, + int k, + aclComputeType type, aclopHandle **handle); #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_CBLAS_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_CBLAS_H_ diff --git a/inc/external/acl/ops/acl_dvpp.h b/inc/external/acl/ops/acl_dvpp.h new file mode 100644 index 00000000..d2f5f650 --- /dev/null +++ b/inc/external/acl/ops/acl_dvpp.h @@ -0,0 +1,2461 @@ +/** + * Copyright 2019-2020 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. + */ + +#if !defined(ENABLE_DVPP_INTERFACE) +#if defined(_MSC_VER) +#error message("if you want to use dvpp funtions ,please use the macro definition (ENABLE_DVPP_INTERFACE).") +#else +#error "if you want to use dvpp funtions ,please use the macro definition (ENABLE_DVPP_INTERFACE)." +#endif +#endif + +#ifndef INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ +#define INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ + +#include +#include +#include "acl/acl.h" +#include "acl/acl_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct acldvppPicDesc acldvppPicDesc; +typedef struct acldvppBatchPicDesc acldvppBatchPicDesc; +typedef struct acldvppRoiConfig acldvppRoiConfig; +typedef struct acldvppResizeConfig acldvppResizeConfig; +typedef struct acldvppBorderConfig acldvppBorderConfig; +typedef struct acldvppLutMap acldvppLutMap; +typedef struct acldvppChannelDesc acldvppChannelDesc; +typedef struct acldvppJpegeConfig acldvppJpegeConfig; +typedef struct aclvdecChannelDesc aclvdecChannelDesc; +typedef struct acldvppStreamDesc acldvppStreamDesc; +typedef struct aclvdecFrameConfig aclvdecFrameConfig; +typedef struct aclvencChannelDesc aclvencChannelDesc; +typedef struct aclvencFrameConfig aclvencFrameConfig; +typedef struct acldvppHist acldvppHist; +typedef void (*aclvdecCallback)(acldvppStreamDesc *input, acldvppPicDesc *output, void *userData); +typedef void (*aclvencCallback)(acldvppPicDesc *input, acldvppStreamDesc *output, void *userdata); + +// Supported Pixel Format +enum acldvppPixelFormat { + PIXEL_FORMAT_YUV_400 = 0, // 0 + PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1, // 1 + PIXEL_FORMAT_YVU_SEMIPLANAR_420 = 2, // 2 + PIXEL_FORMAT_YUV_SEMIPLANAR_422 = 3, // 3 + PIXEL_FORMAT_YVU_SEMIPLANAR_422 = 4, // 4 + PIXEL_FORMAT_YUV_SEMIPLANAR_444 = 5, // 5 + PIXEL_FORMAT_YVU_SEMIPLANAR_444 = 6, // 6 + PIXEL_FORMAT_YUYV_PACKED_422 = 7, // 7 + PIXEL_FORMAT_UYVY_PACKED_422 = 8, // 8 + PIXEL_FORMAT_YVYU_PACKED_422 = 9, // 9 + PIXEL_FORMAT_VYUY_PACKED_422 = 10, // 10 + PIXEL_FORMAT_YUV_PACKED_444 = 11, // 11 + PIXEL_FORMAT_RGB_888 = 12, // 12 + PIXEL_FORMAT_BGR_888 = 13, // 13 + PIXEL_FORMAT_ARGB_8888 = 14, // 14 + PIXEL_FORMAT_ABGR_8888 = 15, // 15 + PIXEL_FORMAT_RGBA_8888 = 16, // 16 + PIXEL_FORMAT_BGRA_8888 = 17, // 17 + PIXEL_FORMAT_YUV_SEMI_PLANNER_420_10BIT = 18, // 18 + PIXEL_FORMAT_YVU_SEMI_PLANNER_420_10BIT = 19, // 19 + PIXEL_FORMAT_YVU_PLANAR_420 = 20, // 20 + PIXEL_FORMAT_YVU_PLANAR_422, + PIXEL_FORMAT_YVU_PLANAR_444, + PIXEL_FORMAT_RGB_444 = 23, + PIXEL_FORMAT_BGR_444, + PIXEL_FORMAT_ARGB_4444, + PIXEL_FORMAT_ABGR_4444, + PIXEL_FORMAT_RGBA_4444, + PIXEL_FORMAT_BGRA_4444, + PIXEL_FORMAT_RGB_555, + PIXEL_FORMAT_BGR_555, + PIXEL_FORMAT_RGB_565, + PIXEL_FORMAT_BGR_565, + PIXEL_FORMAT_ARGB_1555, + PIXEL_FORMAT_ABGR_1555, + PIXEL_FORMAT_RGBA_1555, + PIXEL_FORMAT_BGRA_1555, + PIXEL_FORMAT_ARGB_8565, + PIXEL_FORMAT_ABGR_8565, + PIXEL_FORMAT_RGBA_8565, + PIXEL_FORMAT_BGRA_8565, + PIXEL_FORMAT_RGB_BAYER_8BPP = 50, + PIXEL_FORMAT_RGB_BAYER_10BPP, + PIXEL_FORMAT_RGB_BAYER_12BPP, + PIXEL_FORMAT_RGB_BAYER_14BPP, + PIXEL_FORMAT_RGB_BAYER_16BPP, + PIXEL_FORMAT_BGR_888_PLANAR = 70, + PIXEL_FORMAT_HSV_888_PACKAGE, + PIXEL_FORMAT_HSV_888_PLANAR, + PIXEL_FORMAT_LAB_888_PACKAGE, + PIXEL_FORMAT_LAB_888_PLANAR, + PIXEL_FORMAT_S8C1, + PIXEL_FORMAT_S8C2_PACKAGE, + PIXEL_FORMAT_S8C2_PLANAR, + PIXEL_FORMAT_S16C1, + PIXEL_FORMAT_U8C1, + PIXEL_FORMAT_U16C1, + PIXEL_FORMAT_S32C1, + PIXEL_FORMAT_U32C1, + PIXEL_FORMAT_U64C1, + PIXEL_FORMAT_S64C1, + PIXEL_FORMAT_YUV_SEMIPLANAR_440 = 1000, + PIXEL_FORMAT_YVU_SEMIPLANAR_440, + PIXEL_FORMAT_FLOAT32, + PIXEL_FORMAT_BUTT, + PIXEL_FORMAT_UNKNOWN = 10000 +}; + +// Stream Format +enum acldvppStreamFormat { + H265_MAIN_LEVEL = 0, + H264_BASELINE_LEVEL, + H264_MAIN_LEVEL, + H264_HIGH_LEVEL +}; + +// Supported Channel Mode +enum acldvppChannelMode { + DVPP_CHNMODE_VPC = 1, + DVPP_CHNMODE_JPEGD = 2, + DVPP_CHNMODE_JPEGE = 4 +}; + +// Supported Border Type +enum acldvppBorderType { + BORDER_CONSTANT = 0, + BORDER_REPLICATE, + BORDER_REFLECT, + BORDER_REFLECT_101 +}; + +// Venc parameter type +enum aclvencChannelDescParamType { + ACL_VENC_THREAD_ID_UINT64 = 0, + ACL_VENC_CALLBACK_PTR, + ACL_VENC_PIXEL_FORMAT_UINT32, + ACL_VENC_ENCODE_TYPE_UINT32, + ACL_VENC_PIC_WIDTH_UINT32, + ACL_VENC_PIC_HEIGHT_UINT32, + ACL_VENC_KEY_FRAME_INTERVAL_UINT32, + ACL_VENC_BUF_ADDR_PTR, + ACL_VENC_BUF_SIZE_UINT32, + ACL_VENC_RC_MODE_UINT32, + ACL_VENC_SRC_RATE_UINT32, + ACL_VENC_MAX_BITRATE_UINT32, + ACL_VENC_MAX_IP_PROP_UINT32 +}; + +/** + * @ingroup AscendCL + * @brief alloc device memory for dvpp. + * + * @par Function + * @li It's mainly used for allocating memory to device media data processing. + * The requested memory meets the data processing requirements. + * After calling this interface to request memory, + * you must release the memory using the acldvppFree interface. + * @li When calling the acldvppMalloc interface to apply for memory, + * the size entered by the user is aligned upwards to 32 integer multiples, + * and an additional 32 bytes are applied. + * + * @par Restriction + * If the user uses the acldvppMalloc interface to apply for a large block of + * memory and divide and manage the memory by himself, + * when applying for memory, the user needs to align up to 32 integer + * times + 32 bytes (ALIGN_UP [len] +32 words) according to + * the actual data size of each picture Section) to manage memory. + * + * @param devPtr [OUT] memory pointer. + * @param size [IN] memory size. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppFree + */ +ACL_FUNC_VISIBILITY aclError acldvppMalloc(void **devPtr, size_t size); + +/** + * @ingroup AscendCL + * @brief free device memory for dvpp. + * + * @par Function + * Free the memory requested through the acldvppMalloc interface + * @param devPtr [IN] memory pointer to free. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppMalloc + */ +ACL_FUNC_VISIBILITY aclError acldvppFree(void *devPtr); + +/** + * @ingroup AscendCL + * @brief create DvppChannelDesc. + * + * @par Function + * Create a channel for image data processing. + * The same channel can be reused + * and is no longer available after destruction + * + * @retval null for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY acldvppChannelDesc *acldvppCreateChannelDesc(); + +/** + * @ingroup AscendCL + * @brief destroy dvppChannelDesc. + * + * @par Function + * Can only destroy channels created by the acldvppCreateChannel interface + * @param channelDesc [IN] the channel description. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannelDesc | acldvppDestroyChannel + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyChannelDesc(acldvppChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get dvpp channel Id. + * + * @par Restriction + * Interface calling sequence: + * acldvppCreateChannelDesc --> acldvppCreateChannel --> + * acldvppGetChannelDescChannelId + * + * @param channelDesc [IN] the channel description. + * + * @retval channel id. + * + * @see acldvppCreateChannelDesc | acldvppCreateChannel + */ +ACL_FUNC_VISIBILITY uint64_t acldvppGetChannelDescChannelId(const acldvppChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Create dvpp picture description. + * + * @retval null for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY acldvppPicDesc *acldvppCreatePicDesc(); + +/** + * @ingroup AscendCL + * @brief Destroy dvpp picture description. + * + * @par Function + * Can only destroy picture description information created + * through acldvppCreatePicDesc interface. + * @param picDesc [IN] dvpp picture description. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreatePicDesc + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyPicDesc(acldvppPicDesc *picDesc); + +/** + * @ingroup AscendCL + * @brief Set dvpp picture description's data. + * + * @param picDesc [OUT] dvpp picture description. + * @param dataDev [IN] dvpp picture dataDev.Must be the memory + * requested using the acldvppMalloc interface. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppMalloc + */ +ACL_FUNC_VISIBILITY aclError acldvppSetPicDescData(acldvppPicDesc *picDesc, void *dataDev); + +/** + * @ingroup AscendCL + * @brief Set dvpp picture description's size. + * + * @param picDesc [OUT] dvpp picture description. + * @param size dvpp [IN] picture size. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetPicDescSize(acldvppPicDesc *picDesc, uint32_t size); + +/** + * @ingroup AscendCL + * @brief Set dvpp picture description's format. + * + * @param picDesc [OUT] dvpp picture description. + * @param format [IN] dvpp picture format. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetPicDescFormat(acldvppPicDesc *picDesc, acldvppPixelFormat format); + +/** + * @ingroup AscendCL + * @brief Set dvpp picture description's width. + * + * @param picDesc [OUT] dvpp picture description. + * @param width [IN] dvpp picture width. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetPicDescWidth(acldvppPicDesc *picDesc, uint32_t width); + +/** + * @ingroup AscendCL + * @brief Set dvpp picture description's height. + * + * @param picDesc [OUT] dvpp picture description. + * @param height [IN] dvpp picture height. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetPicDescHeight(acldvppPicDesc *picDesc, uint32_t height); + +/** + * @ingroup AscendCL + * @brief Set dvpp picture description's widthStride. + * + * @par Restriction + * Width alignment requirements: + * @li The minimum stride is 32 and the maximum is 4096 * 4 + * (that is, an image in argb format with a width of 4096); + * @li For 8K scaling, widthStride is required to be aligned to 2; + * @li For non 8K scaling, the calculation formula for widthStride + * is different for different image formats: + * @li yuv400sp, yuv420sp, yuv422sp, yuv444sp: input image width aligned to 16 + * @li yuv422packed: input image width * 2 and then align to 16 + * @li yuv444packed, rgb888: input image width alignment * 3, alignment to 16 + * @li xrgb8888: input image width * 4, align to 16 + * @li HFBC:input image width + * + * @param picDesc [OUT] dvpp picture description. + * @param widthStride [IN] dvpp picture widthStride. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetPicDescWidthStride(acldvppPicDesc *picDesc, uint32_t widthStride); + +/** + * @ingroup AscendCL + * @brief Set dvpp picture description's heightStride. + * + * @par Restriction + * Height alignment requirements: + * @li The height of the input image is aligned to 2. + * High stride minimum 6 and maximum 4096. + * + * @param picDesc [OUT] dvpp picture description. + * @param heightStride [IN] dvpp picture heightStride. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetPicDescHeightStride(acldvppPicDesc *picDesc, uint32_t heightStride); + +/** + * @ingroup AscendCL + * @brief Set dvpp picture description's retcode. + * + * @param picDesc [OUT] dvpp picture description. + * @param retCode [IN] dvpp picture retcode. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetPicDescRetCode(acldvppPicDesc *picDesc, uint32_t retCode); + +/** + * @ingroup AscendCL + * @brief Get picture data. + * + * @param picDesc [IN] dvpp picture description. + * + * @retval picture data addr. + * @retval default nullptr. + */ +ACL_FUNC_VISIBILITY void *acldvppGetPicDescData(const acldvppPicDesc *picDesc); + +/** + * @ingroup AscendCL + * @brief Get picture data size. + * + * @param picDesc [IN] dvpp picture description. + * + * @retval picture data size. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescSize(const acldvppPicDesc *picDesc); + +/** + * @ingroup AscendCL + * @brief Get dvpp picture desc's format. + * + * @param picDesc [IN] dvpp picture description. + * + * @retval format + * @retval default PIXEL_FORMAT_YUV_400. + */ +ACL_FUNC_VISIBILITY acldvppPixelFormat acldvppGetPicDescFormat(const acldvppPicDesc *picDesc); + +/** + * @ingroup AscendCL + * @brief Get dvpp picture desc's width. + * + * @param picDesc [IN] dvpp picture description. + * + * @retval width. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescWidth(const acldvppPicDesc *picDesc); + +/** + * @ingroup AscendCL + * @brief Get dvpp picture desc's height. + * + * @param picDesc [IN] dvpp picture description. + * + * @retval height. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescHeight(const acldvppPicDesc *picDesc); + +/** + * @ingroup AscendCL + * @brief Get dvpp picture desc's widthStride. + * + * @par Restriction + * Width alignment requirements: + * @li The minimum stride is 32 and the maximum is 4096 * 4 + * (that is, an image in argb format with a width of 4096); + * @li For 8K scaling, widthStride is required to be aligned to 2; + * @li For non 8K scaling, the calculation formula for widthStride + * is different for different image formats: + * @li yuv400sp, yuv420sp, yuv422sp, yuv444sp: input image width aligned to 16 + * @li yuv422packed: input image width * 2 and then align to 16 + * @li yuv444packed, rgb888: input image width alignment * 3, alignment to 16 + * @li xrgb8888: input image width * 4, align to 16 + * @li HFBC:input image width + * + * @param picDesc [IN] dvpp picture description. + * + * @retval stride width. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescWidthStride(const acldvppPicDesc *picDesc); + +/** + * @ingroup AscendCL + * @brief Get dvpp picture desc's heightStride. + * + * @par Restriction + * Height alignment requirements: + * @li The height of the input image is aligned to 2. + * High stride minimum 6 and maximum 4096. + * + * @param picDesc [IN] dvpp picture description. + * + * @retval stride height. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescHeightStride(const acldvppPicDesc *picDesc); + +/** + * @ingroup AscendCL + * @brief Get dvpp picture desc's retcode. + * + * @param picDesc [IN] dvpp picture description. + * + * @retval ret code. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescRetCode(const acldvppPicDesc *picDesc); + +/** + * @ingroup AscendCL + * @brief Create dvpp roi config. + * + * @param left [IN] the left offset, must be even + * @param right [IN] the right offset, must be odd + * @param top [IN] the top offset, must be even + * @param bottom [IN] the bottom offset, must be odd + * + * @retval null for failed. + * @retval other success + */ +ACL_FUNC_VISIBILITY acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, + uint32_t right, + uint32_t top, + uint32_t bottom); + +/** + * @ingroup AscendCL + * @brief Destroy dvpp roi config. + * + * @par Function + * Destroys data created through the acldvppCreateRoiConfig interface + * @param roiConfig [IN] dvpp roi config. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateRoiConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyRoiConfig(acldvppRoiConfig *roiConfig); + +/** + * @ingroup AscendCL + * @brief Set left of RoiConfig. + * + * @param config [OUT] RoiConfig + * @param left [IN] left offset + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfigLeft(acldvppRoiConfig *config, uint32_t left); + +/** + * @ingroup AscendCL + * @brief Set right of RoiConfig. + * + * @param config [OUT] RoiConfig + * @param right [IN] right offset + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfigRight(acldvppRoiConfig *config, uint32_t right); + +/** + * @ingroup AscendCL + * @brief Set top of RoiConfig. + * + * @param config [OUT] RoiConfig + * @param top [IN] top offset + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfigTop(acldvppRoiConfig *config, uint32_t top); + +/** + * @ingroup AscendCL + * @brief Set bottom of RoiConfig. + * + * @param config [OUT] RoiConfig + * @param bottom [IN] bottom offset + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfigBottom(acldvppRoiConfig *config, uint32_t bottom); + +/** + * @ingroup AscendCL + * @brief Set RoiConfig. + * + * @param config [OUT] RoiConfig + * @param left [IN] left offset + * @param right [IN] right offset + * @param top [IN] top offset + * @param bottom [IN] bottom offset + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfig(acldvppRoiConfig *config, + uint32_t left, + uint32_t right, + uint32_t top, + uint32_t bottom); + +/** + * @ingroup AscendCL + * @brief Create dvpp resize config. + * The specified scaling algorithm is not supported. + * The default scaling algorithm is "nearest neighbor interpolation". + * + * @retval null for failed. + * @retval other success. + */ +ACL_FUNC_VISIBILITY acldvppResizeConfig *acldvppCreateResizeConfig(); + +/** + * @ingroup AscendCL + * @brief Destroy dvpp resize config. + * + * @par Function + * Destroys the scaling configuration data created by + * the acldvppCreateResizeConfig interface + * + * @param resizeConfig [IN] resize config. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateResizeConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyResizeConfig(acldvppResizeConfig *resizeConfig); + +/** + * @ingroup AscendCL + * @brief Create jpege config. + * + * @retval null for failed. + * @retval other success. + */ +ACL_FUNC_VISIBILITY acldvppJpegeConfig *acldvppCreateJpegeConfig(); + +/** + * @ingroup AscendCL + * @brief Destroy jpege config. + * + * @par Function + * Destroys the encoding configuration data created by + * the acldvppCreateJpegeConfig interface + * @param jpegeConfig [IN] config pointer to destroy. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateJpegeConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyJpegeConfig(acldvppJpegeConfig *jpegeConfig); + +/** + * @ingroup AscendCL + * @brief Set jpege config's level. + * + * @param jpegeConfig [OUT] Call the acldvppCreateJpegeConfig + * interface to create acldvppJpegeConfig data + * @param level [IN] Encoding quality range [0, 100], + * where level 0 encoding quality is similar to level 100, + * and the smaller the value in [1, 100], + * the worse the quality of the output picture. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetJpegeConfigLevel(acldvppJpegeConfig *jpegeConfig, uint32_t level); + +/** + * @ingroup AscendCL + * @brief Get jpege config's level. + * + * @param jpegeConfig [IN] jpege config. + * + * @retval compression level. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetJpegeConfigLevel(const acldvppJpegeConfig *jpegeConfig); + +/** + * @ingroup AscendCL + * @brief create vdecChannelDesc.Channel description information + * when creating a video data processing channel. + * + * @retval null for failed. + * @retval other success + */ +ACL_FUNC_VISIBILITY aclvdecChannelDesc *aclvdecCreateChannelDesc(); + +/** + * @ingroup AscendCL + * @brief destroy vdecChannelDesc. + * + * @par Function + * Can only destroy aclvdecChannelDesc type created + * through aclvdecCreateChannelDesc interface + * @param channelDesc [IN] channel description. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + + * @see aclvdecCreateChannelDesc + */ +ACL_FUNC_VISIBILITY aclError aclvdecDestroyChannelDesc(aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Set vdec channel description's channel id. + * + * @param channelDesc [OUT] vdec channel description. + * @param channelId [IN] decoding channel id: 0~15. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescChannelId(aclvdecChannelDesc *channelDesc, uint32_t channelId); + +/** + * @ingroup AscendCL + * @brief Set vdec channel description's thread id. + * + * @param channelDesc [OUT] vdec channel description. + * @param threadId [IN] thread id. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescThreadId(aclvdecChannelDesc *channelDesc, uint64_t threadId); + +/** + * @ingroup AscendCL + * @brief Set vdec channel description's callback function. + * + * @param channelDesc [OUT] vdec channel description. + * @param callback [IN] function callback.Function prototype: + * void (* aclvdecCallback) + * (acldvppStreamDesc * input, acldvppPicDesc * output, void* userdata) + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclvdecCallback + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescCallback(aclvdecChannelDesc *channelDesc, aclvdecCallback callback); + +/** + * @ingroup AscendCL + * @brief Set vdec channel description's video encoding type. + * + * @param channelDesc [OUT] vdec channel description. + * @param enType [IN] video encoding type. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescEnType(aclvdecChannelDesc *channelDesc, acldvppStreamFormat enType); + +/** + * @ingroup AscendCL + * @brief Set vdec channel description's out picture format. + * + * @param channelDesc [OUT] vdec channel description. + * @param outPicFormat [IN] out picture format (acldvppPixelFormat). + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutPicFormat(aclvdecChannelDesc *channelDesc, + acldvppPixelFormat outPicFormat); + +/** + * @ingroup AscendCL + * @brief Set vdec channel description's out picture width. + * + * @param channelDesc [OUT] vdec channel description. + * @param outPicWidth [IN] out picture width. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutPicWidth(aclvdecChannelDesc *channelDesc, uint32_t outPicWidth); + +/** + * @ingroup AscendCL + * @brief Set vdec channel description's out picture height. + * + * @param channelDesc [OUT] vdec channel description. + * @param outPicHeight [IN] out picture height. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutPicHeight(aclvdecChannelDesc *channelDesc, uint32_t outPicHeight); + +/** + * @ingroup AscendCL + * @brief Set vdec channel description's reference frame num. + * + * @param channelDesc [OUT] vdec channel description. + * @param refFrameNum [IN] reference frame num. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescRefFrameNum(aclvdecChannelDesc *channelDesc, uint32_t refFrameNum); + +/** + * @ingroup AscendCL + * @brief Set vdec channel description's bit depth. + * + * @param channelDesc [OUT] vdec channel description. + * @param bitDepth [IN] bit depth. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescBitDepth(aclvdecChannelDesc *channelDesc, uint32_t bitDepth); + +/** + * @ingroup AscendCL + * @brief Get vdec channel description's channel id. + * + * @param channelDesc [IN] vdec channel description. + * + * @retval decoding channel id: 0~15. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t aclvdecGetChannelDescChannelId(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get vdec channel description's thread id. + * + * @param channelDesc [IN] vdec channel description. + * + * @retval thread id. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint64_t aclvdecGetChannelDescThreadId(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get vdec channel description's callback function. + * + * @param channelDesc [IN] vdec channel description. + * + * @retval function callback.Function prototype: + * void (* aclvdecCallback) + * (acldvppStreamDesc * input, acldvppPicDesc * output, void* userdata) + * @retval default null. + * + * @see aclvdecCallback + */ +ACL_FUNC_VISIBILITY aclvdecCallback aclvdecGetChannelDescCallback(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get vdec channel description's video encoding type. + * + * @param channelDesc [IN] vdec channel description. + * + * @retval video encoding type. + * @retval default H265_MAIN_LEVEL. + */ +ACL_FUNC_VISIBILITY acldvppStreamFormat aclvdecGetChannelDescEnType(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get vdec channel description's out picture format. + * + * @param channelDesc [IN] vdec channel description. + * + * @retval out picture format. + * @retval default DVPP_OUTPUT_YUV420SP_UV. + */ +ACL_FUNC_VISIBILITY acldvppPixelFormat aclvdecGetChannelDescOutPicFormat(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get vdec channel description's out picture width. + * + * @param channelDesc [IN] vdec channel description. + * + * @retval out picture width. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t aclvdecGetChannelDescOutPicWidth(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get vdec channel description's out picture height. + * + * @param channelDesc [IN] vdec channel description. + * + * @retval out picture height (for vdec malloc memory). + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t aclvdecGetChannelDescOutPicHeight(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get vdec channel description's bit depth. + * + * @param channelDesc [IN] vdec channel description. + * + * @retval bit depth. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t aclvdecGetChannelDescBitDepth(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get vdec channel description's reference frame num. + * + * @param channelDesc [IN] vdec channel description. + * + * @retval reference frame num. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t aclvdecGetChannelDescRefFrameNum(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief create vencChannelDesc. + * + * @retval null for failed, other success + */ +ACL_FUNC_VISIBILITY aclvencChannelDesc *aclvencCreateChannelDesc(); + +/** + * @ingroup AscendCL + * @brief destroy vencChannelDesc. + * + * @param channelDesc [IN] channel desc. + * + * @retval ACL_SUCCESS:success, other:failed + */ +ACL_FUNC_VISIBILITY aclError aclvencDestroyChannelDesc(aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Set decoding thread id for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param threadId [IN] thread id + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescThreadId(aclvencChannelDesc *channelDesc, uint64_t threadId); + +/** + * @ingroup AscendCL + * @brief Set func callback for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param callback [IN] func callback + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescCallback(aclvencChannelDesc *channelDesc, aclvencCallback callback); + +/** + * @ingroup AscendCL + * @brief Set video encoding type for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param enType [IN] video encoding type + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescEnType(aclvencChannelDesc *channelDesc, acldvppStreamFormat enType); + +/** + * @ingroup AscendCL + * @brief Set pic format for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param picFormat [IN] pic format + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescPicFormat(aclvencChannelDesc *channelDesc, + acldvppPixelFormat picFormat); + +/** + * @ingroup AscendCL + * @brief Set out pic width for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param picWidth [IN] pic width + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescPicWidth(aclvencChannelDesc *channelDesc, uint32_t picWidth); + +/** + * @ingroup AscendCL + * @brief Set pic height for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param picHeight [IN] pic height + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescPicHeight(aclvencChannelDesc *channelDesc, uint32_t picHeight); + +/** + * @ingroup AscendCL + * @brief Set key frame interval for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param keyFrameInterval [IN] Interval of key frame + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescKeyFrameInterval(aclvencChannelDesc *channelDesc, + uint32_t keyFrameInterval); + +/** + * @ingroup AscendCL + * @brief Set output buffer address for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param bufAddr [IN] output buffer address + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescBufAddr(aclvencChannelDesc *channelDesc, void *bufAddr); + +/** + * @ingroup AscendCL + * @brief Set output buffer size for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param bufSize [IN] output buffer size + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescBufSize(aclvencChannelDesc *channelDesc, uint32_t bufSize); + +/** + * @ingroup AscendCL + * @brief Set rc model for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param rcMode [IN] venc rc mode(VBR=1, CBR=2) + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescRcMode(aclvencChannelDesc *channelDesc, uint32_t rcMode); + +/** + * @ingroup AscendCL + * @brief Set source rate for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param srcRate [IN] source rate + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescSrcRate(aclvencChannelDesc *channelDesc, uint32_t srcRate); + +/** + * @ingroup AscendCL + * @brief Set max bit rate for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param maxBitRate [IN] max bit rate + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescMaxBitRate(aclvencChannelDesc *channelDesc, uint32_t maxBitRate); + +/** + * @ingroup AscendCL + * @brief Set venc parameter for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param paramType [IN] parameter type + * @param length [IN] parameter length + * @param param [IN] pointer to parameter value + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescParam(aclvencChannelDesc *channelDesc, + aclvencChannelDescParamType paramType, size_t length, const void *param); + +/** + * @ingroup AscendCL + * @brief Get output buffer address for venc channel desc. + * + * @param channelDesc[IN] venc channel desc + * + * @retval output buffer address + */ +ACL_FUNC_VISIBILITY void *aclvencGetChannelDescBufAddr(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get output buffer size for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval output buffer size + */ +ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescBufSize(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get decoding channel id for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval decoding channel id: 0~15, default 0 + */ +ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescChannelId(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get decoding thread id for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval thread id, default 0 + */ +ACL_FUNC_VISIBILITY uint64_t aclvencGetChannelDescThreadId(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get func callback for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval func callback, default null + */ +ACL_FUNC_VISIBILITY aclvencCallback aclvencGetChannelDescCallback(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get video encoding type for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval video encoding type, default H265_MAIN_LEVEL + */ +ACL_FUNC_VISIBILITY acldvppStreamFormat aclvencGetChannelDescEnType(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get pic format for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval pic format + */ +ACL_FUNC_VISIBILITY acldvppPixelFormat aclvencGetChannelDescPicFormat(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get pic width for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval pic width, default 0 + */ +ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescPicWidth(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get pic height for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval pic height, default 0 + */ +ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescPicHeight(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get interval of key frame for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval interval of key frame, default 0 + */ +ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescKeyFrameInterval(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * + * @brief Get rc mode for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval rc mode, default 0 + */ +ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescRcMode(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * + * @brief Get source rate for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval source rate, default 0 + */ +ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescSrcRate(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * + * @brief Get max bit rate for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval max bit rate, default 0 + */ +ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescMaxBitRate(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * + * @brief Get venc parameter for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * @param paramType [IN] parameter type + * @param length [IN] parameter length + * @param paramRetSize [OUT] pointer to parameter real length + * @param param [OUT] pointer to parameter value + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencGetChannelDescParam(const aclvencChannelDesc *channelDesc, + aclvencChannelDescParamType paramType, size_t length, size_t *paramRetSize, void *param); + +/** + * @ingroup AscendCL + * @brief get forced restart of I-frame interval from config + * + * @param config [IN] venc frame config + * + * @retval 0: Not forced; 1: Forced restart of I-frame -1: error + */ +ACL_FUNC_VISIBILITY uint8_t aclvencGetFrameConfigForceIFrame(const aclvencFrameConfig *config); + +/** + * @ingroup AscendCL + * @brief get forced restart of I-frame interval from config + * + * @param config [IN] venc frame config + * + * @retval Whether it is the end frame: 0: no; 1: end frame + */ +ACL_FUNC_VISIBILITY uint8_t aclvencGetFrameConfigEos(const aclvencFrameConfig *config); + +/** + * @ingroup AscendCL + * @brief set single frame encoding configuration parameters + * + * @param config [OUT] venc frame config + * @param forceFrame [IN] forced restart of I-frame interval: 0: Not forced; 1: Forced restart of I-frame + * + * @retval ACL_SUCCESS for ok, others for fail + */ +ACL_FUNC_VISIBILITY aclError aclvencSetFrameConfigForceIFrame(aclvencFrameConfig *config, uint8_t forceIFrame); + +/** + * @ingroup AscendCL + * @brief set single frame encoding configuration parameters + * + * @param config [OUT] venc frame config + * @param eos [IN] Whether it is the end frame: 0: no; 1: end frame + * + * @retval ACL_SUCCESS for ok, others for fail + */ +ACL_FUNC_VISIBILITY aclError aclvencSetFrameConfigEos(aclvencFrameConfig *config, uint8_t eos); + +/** + * @ingroup AscendCL + * @brief dvpp venc destroy frame config + * + * @param config [IN] venc frame config + * + * @retval ACL_SUCCESS for ok, others for fail + */ +ACL_FUNC_VISIBILITY aclError aclvencDestroyFrameConfig(aclvencFrameConfig *config); + +/** + * @ingroup AscendCL + * @brief Create dvpp venc frame config. + * + * @retval null for failed, other aclvencFrameConfig ptr + */ +ACL_FUNC_VISIBILITY aclvencFrameConfig *aclvencCreateFrameConfig(); + +/** + * @ingroup AscendCL + * @brief Create dvpp venc channel. + * + * @param channelDesc [IN|OUT] venc channel desc + * + * @retval ACL_SUCCESS for ok, others for fail + */ +ACL_FUNC_VISIBILITY aclError aclvencCreateChannel(aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Destroy dvpp venc channel. + * + * @param channelDesc [IN] venc channel desc + * + * @retval ACL_SUCCESS for ok, others for fail + */ +ACL_FUNC_VISIBILITY aclError aclvencDestroyChannel(aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief dvpp venc launch send frame task. + * + * @param channelDesc [IN] venc channel desc + * @param input [IN] input picture desc + * @param reserve [IN] reserve parameter + * @param config [IN] dvpp frame config + * @param userdata [IN] user callback function + * + * @retval ACL_SUCCESS for ok, others for fail + */ +ACL_FUNC_VISIBILITY aclError aclvencSendFrame(aclvencChannelDesc *channelDesc, acldvppPicDesc *input, void *reserve, + aclvencFrameConfig *config, void *userdata); + +/** + * @ingroup AscendCL + * @brief Create dvpp stream description. + * + * @retval null for failed. + * @retval other success. + */ +ACL_FUNC_VISIBILITY acldvppStreamDesc *acldvppCreateStreamDesc(); + +/** + * @ingroup AscendCL + * @brief Destroy dvpp stream description. + * + * @par Function + * Can only destroy acldvppStreamDesc type created through + * acldvppCreateStreamDesc interface. + * + * @param streamDesc [IN] dvpp stream description. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateStreamDesc + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyStreamDesc(acldvppStreamDesc *streamDesc); + +/** + * @ingroup AscendCL + * @brief Set stream description's data addr. + * + * @param streamDesc [OUT] dvpp stream description. + * @param dataDev [IN] data addr. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetStreamDescData(acldvppStreamDesc *streamDesc, void *dataDev); + +/** + * @ingroup AscendCL + * @brief Set stream description's data size. + * + * @param streamDesc [OUT] dvpp stream description. + * @param size [IN] data size. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetStreamDescSize(acldvppStreamDesc *streamDesc, uint32_t size); + +/** + * @ingroup AscendCL + * @brief Set stream description's format. + * + * @param streamDesc [OUT] dvpp stream description. + * @param format [IN] stream format. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetStreamDescFormat(acldvppStreamDesc *streamDesc, acldvppStreamFormat format); + +/** + * @ingroup AscendCL + * @brief Set stream description's timestamp. + * + * @param streamDesc [OUT] dvpp stream description. + * @param timestamp [IN] current timestamp. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetStreamDescTimestamp(acldvppStreamDesc *streamDesc, uint64_t timestamp); + +/** + * @ingroup AscendCL + * @brief Set stream description's ret code. + * + * @param streamDesc [OUT] dvpp stream description. + * @param retCode [IN] result code. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetStreamDescRetCode(acldvppStreamDesc *streamDesc, uint32_t retCode); + +/** + * @ingroup AscendCL + * @brief Set stream description's eos. + * + * @param streamDesc [OUT] dvpp stream description. + * @param eos [IN] end flag of sequence. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetStreamDescEos(acldvppStreamDesc *streamDesc, uint8_t eos); + +/** + * @ingroup AscendCL + * @brief Get stream description's data addr. + * + * @param streamDesc [IN] dvpp stream description. + * + * @retval data addr. + * @retval deault nullptr. + */ +ACL_FUNC_VISIBILITY void *acldvppGetStreamDescData(const acldvppStreamDesc *streamDesc); + +/** + * @ingroup AscendCL + * @brief Get stream description's data size. + * + * @param streamDesc [IN] dvpp stream description. + * + * @retval data size. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetStreamDescSize(const acldvppStreamDesc *streamDesc); + +/** + * @ingroup AscendCL + * @brief Get stream description's format. + * + * @param streamDesc [IN] dvpp stream description. + * + * @retval stream format. + * @retval default ACL_DVPP_STREAM_H264. + */ +ACL_FUNC_VISIBILITY acldvppStreamFormat acldvppGetStreamDescFormat(const acldvppStreamDesc *streamDesc); + +/** + * @ingroup AscendCL + * @brief Get stream description's timestamp. + * + * @param streamDesc [IN] dvpp stream description. + * + * @retval current timestamp. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint64_t acldvppGetStreamDescTimestamp(const acldvppStreamDesc *streamDesc); + +/** + * @ingroup AscendCL + * @brief Get stream description's retCode. + * + * @param streamDesc [IN] dvpp stream description. + * + * @retval result code. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetStreamDescRetCode(const acldvppStreamDesc *streamDesc); + +/** + * @ingroup AscendCL + * @brief Get stream description's eos. + * + * @param streamDesc [IN] dvpp stream description. + * + * @retval end flag of sequence. + * @retval default 0(false). + */ +ACL_FUNC_VISIBILITY uint8_t acldvppGetStreamDescEos(const acldvppStreamDesc *streamDesc); + +/** + * @ingroup AscendCL + * @brief Create vdec frame config. + * + * @retval null for failed. + * @retval other success. + */ +ACL_FUNC_VISIBILITY aclvdecFrameConfig *aclvdecCreateFrameConfig(); + +/** + * @ingroup AscendCL + * @brief Destroy vdec frame config. + * + * @par Function + * Can only destroy aclvdecFrameConfig type created through + * aclvdecCreateFrameConfig interface + * + * @param vdecFrameConfig [IN] vdec frame config. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclvdecCreateFrameConfig + */ +ACL_FUNC_VISIBILITY aclError aclvdecDestroyFrameConfig(aclvdecFrameConfig *vdecFrameConfig); + +/** + * @ingroup AscendCL + * @brief Get image width and height of jpeg. + * + * @param data [IN] image data in host memory + * @param size [IN] the size of image data + * @param width [OUT] the width of image from image header + * @param height [OUT] the height of image from image header + * @param components [OUT] the components of image from image header + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, + uint32_t size, + uint32_t *width, + uint32_t *height, + int32_t *components); + +/** + * @ingroup AscendCL + * @brief Predict encode size of jpeg image. + * + * @param inputDesc [IN] dvpp image desc + * @param config [IN] jpeg encode config + * @param size [OUT] the size predicted of image + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppJpegPredictEncSize(const acldvppPicDesc *inputDesc, + const acldvppJpegeConfig *config, + uint32_t *size); + +/** + * @ingroup AscendCL + * @brief Predict decode size of jpeg image. + * + * @param data [IN] origin image data in host memory + * @param dataSize [IN] the size of origin image data + * @param outputPixelFormat [IN] the pixel format jpeg decode + * @param decSize [OUT] the size predicted for decode image + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, + uint32_t dataSize, + acldvppPixelFormat outputPixelFormat, + uint32_t *decSize); + +/** + * @ingroup AscendCL + * @brief Get image width and height of png. + * + * @param data [IN] image data in host memory + * @param size [IN] the size of image data + * @param width [OUT] the width of image from image header + * @param height [OUT] the height of image from image header + * @param components [OUT] the components of image from image header + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, + uint32_t dataSize, + uint32_t *width, + uint32_t *height, + int32_t *components); + +/** + * @ingroup AscendCL + * @brief Predict decode size of png image. + * + * @param data [IN] origin image data in host memory + * @param dataSize [IN] the size of origin image data + * @param outputPixelFormat [IN] the pixel format jpeg decode + * @param decSize [OUT] the size predicted for decode image + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppPngPredictDecSize(const void *data, + uint32_t dataSize, + acldvppPixelFormat outputPixelFormat, + uint32_t *decSize); + +/** + * @ingroup AscendCL + * @brief Create dvpp channel, the same channel can be reused + * and is no longer available after destruction. + * + * @param channelDesc [IN|OUT] the channel destruction + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannelDesc + */ +ACL_FUNC_VISIBILITY aclError acldvppCreateChannel(acldvppChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Destroy dvpp channel. + * + * @par Restriction + * Can only destroy channel created through the acldvppCreateChannel interface + * + * @param channelDesc [IN] the channel destruction + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyChannel(acldvppChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief dvpp vpc resize. + * + * @par Restriction + * Width alignment requirements: + * @li The minimum stride is 32 and the maximum is 4096 * 4 + * (that is, an image in argb format with a width of 4096); + * @li For 8K scaling, widthStride is required to be aligned to 2; + * @li For non 8K scaling, the calculation formula for widthStride + * is different for different image formats: + * @li yuv400sp, yuv420sp, yuv422sp, yuv444sp: input image width aligned to 16 + * @li yuv422packed: input image width * 2 and then align to 16 + * @li yuv444packed, rgb888: input image width alignment * 3, alignment to 16 + * @li xrgb8888: input image width * 4, align to 16 + * @li HFBC:input image width + * Height alignment requirements: + * @li The height of the input image is aligned to 2. + * High stride minimum 6 and maximum 4096. + * + * @param channelDesc [IN] the channel destruction + * @param inputDesc [IN] resize input picture destruction + * @param outputDesc [IN|OUT] resize output picture destruction + * @param resizeConfig [IN] resize config + * @param stream [IN] resize task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreatePicDesc + * | acldvppCreateResizeConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + acldvppResizeConfig *resizeConfig, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc crop. + * + * @par Function + * crop the input picture according to the specified area, + * and then store the picture in the output memory as the output picture + * + * @par Restriction + * Width alignment requirements: + * @li The minimum stride is 32 and the maximum is 4096 * 4 + * (that is, an image in argb format with a width of 4096); + * @li For 8K scaling, widthStride is required to be aligned to 2; + * @li For non 8K scaling, the calculation formula for widthStride + * is different for different image formats: + * @li yuv400sp, yuv420sp, yuv422sp, yuv444sp: input image width aligned to 16 + * @li yuv422packed: input image width * 2 and then align to 16 + * @li yuv444packed, rgb888: input image width alignment * 3, alignment to 16 + * @li xrgb8888: input image width * 4, align to 16 + * @li HFBC:input image width + * Height alignment requirements: + * @li The height of the input image is aligned to 2. + * High stride minimum 6 and maximum 4096. + * + * @param channelDesc [IN] the channel destruction + * @param inputDesc [IN] crop input picture destruction + * @param outputDesc [IN|OUT] crop output picture destruction + * @param cropArea [IN] crop area config + * @param stream [IN] crop task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + acldvppRoiConfig *cropArea, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc batch crop. + * + * @par Function + * crop the input batch picture according to the specified area + * as the output batch pictures + * + * @param channelDesc [IN] the channel destruction + * @param srcBatchPicDescs [IN] crop input batch picture destruction + * @param roiNums [IN] roi config numbers + * @param size [IN] roiNum size + * @param dstBatchPicDescs [IN|OUT] crop output batch picture destruction + * @param cropAreas [IN] crop area configs + * @param stream [IN] crop batch task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channelDesc, + acldvppBatchPicDesc *srcBatchPicDescs, + uint32_t *roiNums, + uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc crop and paste. + * + * @par Function + * crop the input picture according to the specified area, + * and paste the picture to the specified position of the target picture + * as the output picture + * + * @param channelDesc [IN] thechannel destruction + * @param inputDesc [IN] crop and paste input picture destruction + * @param outputDesc [IN|OUT] crop and paste output picture destruction + * @param cropArea [IN] crop area config + * @param pasteArea [IN] paste area config + * @param stream [IN] crop and paste task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateRoiConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + acldvppRoiConfig *cropArea, + acldvppRoiConfig *pasteArea, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc batch crop and paste. + * + * @par Function + * crop the input batch picture according to the specified area, + * and paste the pictures to the specified position of the target pictures + * as the output batch pictures + * + * @param channelDesc [IN] the channel destruction + * @param srcBatchPicDescs [IN] crop input batch picture destruction + * @param roiNums [IN] roi config numbers + * @param size [IN] roiNum size + * @param dstBatchPicDescs [IN|OUT] crop output batch picture destruction + * @param cropAreas [IN] crop area configs + * @param pasteAreas [IN] paste area configs + * @param stream [IN] crop batch task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig + */ + ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *channelDesc, + acldvppBatchPicDesc *srcBatchPicDescs, + uint32_t *roiNums, + uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + acldvppRoiConfig *pasteAreas[], + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc jpeg decode. + * + * @par Function + * For different source picture formats, after decoding, + * output pictures in the following format: + * @li jpeg(444) -> YUV444SP:V is front U is back, + * YUV420 SP V is front U is back, YUV420SP U is front V is back; + * @li jpeg(422) -> YUV422SP:V is in front U is behind, + * YUV420SP V is in front U is behind, YUV420SP U is in front V is behind; + * @li jpeg(420) -> YUV420SP: + * V is front U is back, YUV420SP U is front V is back; + * @li jpeg(400) -> YUV420SP:UV data is filled with 0 x 80. + * + * @param channelDesc [IN] the channel destruction + * @param data [IN] decode input picture destruction's data + * @param size [IN] decode input picture destruction's size + * @param outputDesc [IN|OUT] decode output picture destruction + * @param stream [IN] decode task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreatePicDesc + */ +ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, + const void *data, + uint32_t size, + acldvppPicDesc *outputDesc, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc jpeg encode. + * + * @param channelDesc [IN] the channel destruction + * @param inputDesc [IN] encode input picture destruction + * @param data [OUT] encode output picture destruction's data + * @param size [IN|OUT] encode output picture destruction's size + * @param config [IN] jpeg encode config + * @param stream [IN] encode task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreateJpegeConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + const void *data, + uint32_t *size, + acldvppJpegeConfig *config, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc png decode. + * + * @param channelDesc [IN] the channel destruction + * @param data [IN] decode input picture destruction's data + * @param size [IN] decode input picture destruction's size + * @param outputDesc [IN|OUT] decode output picture destruction + * @param stream [IN] decode task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreatePicDesc + */ +ACL_FUNC_VISIBILITY aclError acldvppPngDecodeAsync(acldvppChannelDesc *channelDesc, + const void *data, + uint32_t size, + acldvppPicDesc *outputDesc, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Create vdec channel. + * + * @par Function + * Create a channel for video data processing, + * the same channel can be reused, + * and is no longer available after destruction + * + * @param channelDesc [IN|OUT] the channel destruction + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclvdecCreateChannelDesc + */ +ACL_FUNC_VISIBILITY aclError aclvdecCreateChannel(aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Destroy vdec channel. + * + * @par Function + * Can only destroy channels created by the aclvdecCreateChannel interface + * + * @param channelDesc [IN] the channel destruction + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclvdecCreateChannel + */ +ACL_FUNC_VISIBILITY aclError aclvdecDestroyChannel(aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief dvpp vdec send frame. + * + * @par Function + * Pass the input memory to be decoded + * and the decoded output memory to the decoder for decoding + * + * @param channelDesc [IN] vdec channel destruction + * @param input [IN] input stream destruction + * @param output [IN|OUT] output picture destruction + * @param config [IN] vdec frame config + * @param userData [IN] user data for callback function + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclvdecCreateChannel | acldvppCreateStreamDesc | acldvppCreatePicDesc + */ +ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, + acldvppStreamDesc *input, + acldvppPicDesc *output, + aclvdecFrameConfig *config, + void *userData); + +/** + * @ingroup AscendCL + * @brief dvpp vdec send skipped frame. + * + * @par Function + * Pass video frame to decoder + * + * @param channelDesc [IN] vdec channel destruction + * @param input [IN] input stream destruction + * @param config [IN] vdec frame config + * @param userData [IN] user data for callback function + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclvdecCreateChannel | acldvppCreateStreamDesc | acldvppCreatePicDesc | aclvdecSendFrame + */ +ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channelDesc, + acldvppStreamDesc *input, + aclvdecFrameConfig *config, + void *userData); + +/** + * @ingroup AscendCL + * @brief dvpp vpc convert color. + * + * @par Restriction + * @li outputDesc:Width height stride, No changes are allowed. Just configure 0 + * @par Function + * Convert color gamut + * + * @param channelDesc [IN] the channel destruction + * @param inputDesc [IN] convert color input picture destruction + * @param outputDesc [IN|OUT] convert color output picture destruction + * @param stream [IN] convert color task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreatePicDesc + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc pyramid down. + * + * @par Restriction + * @li outputDesc:format only supported YUV400 + * @par Function + * Image pyramid down + * + * @param channelDesc [IN] the channel destruction + * @param inputDesc [IN] pyr down input picture destruction + * @param outputDesc [IN|OUT] pyr down output picture destruction + * @param reserve [IN] reserved param , must be nullptr + * @param stream [IN] pyr down task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreatePicDesc + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + void *reserve, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Set dvpp channel mode. + * + * @param channelDesc [OUT] the channel destruction + * @param mode [IN] channel mode + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetChannelDescMode(acldvppChannelDesc *channelDesc, + uint32_t mode); + +/** + * @ingroup AscendCL + * @brief Set resize config interpolation. + * + * @param resizeConfig [OUT] the resize config + * @param interpolation [IN] interpolation + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetResizeConfigInterpolation(acldvppResizeConfig *resizeConfig, + uint32_t interpolation); + +/** + * @ingroup AscendCL + * @brief Get resize config interpolation. + * + * @param resizeConfig [IN] the resize config + * + * @retval Interpolation of resize config. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetResizeConfigInterpolation(const acldvppResizeConfig *resizeConfig); + +/** + * @ingroup AscendCL + * @brief Set vdec channel out mode. + * + * @param channelDesc [OUT] the channel destruction + * @param outMode [IN] channel out mode + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutMode(aclvdecChannelDesc *channelDesc, + uint32_t outMode); + +/** + * @ingroup AscendCL + * @brief Get vdec channel out mode. + * + * @param channelDesc [IN] the channel destruction + * + * @retval Out mode of channel destruction + * @retval default 0 + */ +ACL_FUNC_VISIBILITY uint32_t aclvdecGetChannelDescOutMode(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Create dvpp batch picture description. + * + * @param batchSize [IN] batch size + * + * @retval null for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY acldvppBatchPicDesc *acldvppCreateBatchPicDesc(uint32_t batchSize); + +/** + * @ingroup AscendCL + * @brief Get dvpp picture description. + * + * @param batchPicDesc [IN] dvpp batch picture description. + * @param index [IN] index of batch + * + * @retval null for failed. + * @retval OtherValues Failure + * + * @see acldvppCreateBatchPicDesc + */ +ACL_FUNC_VISIBILITY acldvppPicDesc *acldvppGetPicDesc(acldvppBatchPicDesc *batchPicDesc, uint32_t index); + +/** + * @ingroup AscendCL + * @brief Destroy dvpp batch picture description. + * + * @par Function + * Can only destroy batch picture description information created + * through acldvppCreateBatchPicDesc interface. + * + * @param batchPicDesc [IN] dvpp batch picture description. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateBatchPicDesc + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyBatchPicDesc(acldvppBatchPicDesc *batchPicDesc); + +/** + * @ingroup AscendCL + * @brief Create dvpp lut map. + * + * @retval null for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY acldvppLutMap *acldvppCreateLutMap(); + +/** + * @ingroup AscendCL + * @brief Destroy lut map. + * + * @param lutMap [IN] lut map + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyLutMap(acldvppLutMap *lutMap); + +/** + * @ingroup AscendCL + * @brief Get lut map dims. + * + * @param lutMap [IN] lut map + * + * @retval 0 for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetLutMapDims(const acldvppLutMap *lutMap); + +/** + * @ingroup AscendCL + * @brief Get lut map data. + * + * @param lutMap [IN] lut map + * @param dim [IN] input dim of map + * @param data [OUT] the dim of lut map's data + * @param len [OUT] the dim of lut map's length + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, + uint32_t dim, + uint8_t **data, + uint32_t *len); +/** + * @ingroup AscendCL + * @brief Vpc equalize hist. + * + * @param channelDesc [IN] channel desc + * @param inputDesc [IN] input desc + * @param outputDesc [IN|OUT] output desc + * @param lutMap [IN] lut map param + * @param stream [IN] runtime stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel|acldvppCreatePicDesc|acldvppCreateLutMap + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcEqualizeHistAsync(const acldvppChannelDesc *channelDesc, + const acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + const acldvppLutMap *lutMap, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Create dvpp border config. + * + * @retval null for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY acldvppBorderConfig *acldvppCreateBorderConfig(); + +/** + * @ingroup AscendCL + * @brief Set value of border config. + * + * @param borderConfig [OUT] border config + * @param index [IN] index of value array + * @param value [IN] value + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigValue(acldvppBorderConfig *borderConfig, + uint32_t index, + double value); + +/** + * @ingroup AscendCL + * @brief Set border type of border config. + * + * @param borderConfig [OUT] border config + * @param borderType [IN] border type + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigBorderType(acldvppBorderConfig *borderConfig, + acldvppBorderType borderType); + +/** + * @ingroup AscendCL + * @brief Set top of border config. + * + * @param borderConfig [OUT] border config + * @param top [IN] top of border + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigTop(acldvppBorderConfig *borderConfig, uint32_t top); + +/** + * @ingroup AscendCL + * @brief Set bottom of border config. + * + * @param borderConfig [OUT] border config + * @param bottom [IN] bottom of border + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigBottom(acldvppBorderConfig *borderConfig, uint32_t bottom); + +/** + * @ingroup AscendCL + * @brief Set left of border config. + * + * @param borderConfig [OUT] border config + * @param left [IN] left of border + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigLeft(acldvppBorderConfig *borderConfig, uint32_t left); + +/** + * @ingroup AscendCL + * @brief Set right of border config. + * + * @param borderConfig [OUT] border config + * @param right [IN] right of border + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigRight(acldvppBorderConfig *borderConfig, uint32_t right); + +/** + * @ingroup AscendCL + * @brief Get value of border config. + * + * @param borderConfig [IN] border config + * @param index[IN] index of value array + * + * @retval invalid value is < 0, normal Value is >= 0 + */ +ACL_FUNC_VISIBILITY double acldvppGetBorderConfigValue(const acldvppBorderConfig *borderConfig, uint32_t index); + +/** + * @ingroup AscendCL + * @brief Get border type of border config. + * + * @param borderConfig [IN] border config + * @retval border type of border config + */ +ACL_FUNC_VISIBILITY acldvppBorderType acldvppGetBorderConfigBorderType(const acldvppBorderConfig *borderConfig); + +/** + * @ingroup AscendCL + * @brief Get right of border config. + * + * @param borderConfig [IN] border config + * + * @retval default 0, top value of border config + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetBorderConfigTop(const acldvppBorderConfig *borderConfig); + +/** + * @ingroup AscendCL + * @brief Get Bottom of border config. + * + * @param borderConfig [IN] border config + * + * @retval default 0, top value of border config + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetBorderConfigBottom(const acldvppBorderConfig *borderConfig); + +/** + * @ingroup AscendCL + * @brief Get left of border config. + * + * @param borderConfig [IN] border config + * + * @retval default 0, top value of border config + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetBorderConfigLeft(const acldvppBorderConfig *borderConfig); + +/** + * @ingroup AscendCL + * @brief Get right of border config. + * + * @param borderConfig [IN] border config + * + * @retval default 0, right value of border config + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetBorderConfigRight(const acldvppBorderConfig *borderConfig); + +/** + * @ingroup AscendCL + * @brief Destroy border config. + * + * @param borderConfig [IN] border config + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyBorderConfig(acldvppBorderConfig *borderConfig); + +/** + * @ingroup AscendCL + * @brief Vpc make border. + * + * @param channelDesc [IN] channel desc + * @param inputDesc [IN] input desc + * @param outputDesc [IN|OUT] output desc + * @param borderConfig [IN] border config param + * @param stream [IN] runtime stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel|acldvppCreatePicDesc|acldvppCreateBorderConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcMakeBorderAsync(const acldvppChannelDesc *channelDesc, + const acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + const acldvppBorderConfig *borderConfig, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Dvpp vpc calc hist. + * + * @param channelDesc [IN] the channel destruction + * @param srcPicDesc [IN] pyr down input picture destruction + * @param hist [IN|OUT] pyr down output picture destruction + * @param reserve [IN] reserved param, must be nullptr + * @param stream [IN] task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateHist + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *srcPicDesc, + acldvppHist *hist, + void *reserve, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Create vpc hist description. + * + * @retval null for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY acldvppHist* acldvppCreateHist(); + +/** + * @ingroup AscendCL + * @brief Destroy vpc hist description. + * + * @par Function + * Can only destroy hist description information created + * through acldvppCreateHist interface. + * + * @param hist [IN] vpc hist description. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateHist + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyHist(acldvppHist *hist); + +/** + * @ingroup AscendCL + * @brief Get dims of vpc hist description. + * + * @param hist [IN] vpc hist description. + * + * @retval dims of vpc hist description. + * + * @see acldvppCreateHist | acldvppVpcCalcHistAsync + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetHistDims(acldvppHist *hist); + +/** + * @ingroup AscendCL + * @brief Get data from vpc hist description by dim. + * + * @param hist [IN] vpc hist description. + * @param dim [IN] which dim to get data. + * @param data [OUT] address of output hist data. + * @param len [OUT] len of output hist data. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateHist | acldvppVpcCalcHistAsync + */ +ACL_FUNC_VISIBILITY aclError acldvppGetHistData(acldvppHist *hist, uint32_t dim, uint32_t **data, uint16_t *len); + +/** + * @ingroup AscendCL + * @brief Get dvpp calc hist process return code. + * + * @param hist [IN] vpc hist description. + * + * @retval Dvpp calc hist process return code. + * + * @see acldvppCreateHist | acldvppVpcCalcHistAsync + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist* hist); + +/** + * @ingroup AscendCL + * @brief Set vpc hist description to 0. + * + * @par Function + * Can only clear hist description information created + * through acldvppCreateHist interface. + * + * @param hist [IN] vpc hist description. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateHist + */ +ACL_FUNC_VISIBILITY aclError acldvppClearHist(acldvppHist *hist); + +#ifdef __cplusplus +} +#endif + +#endif // INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ diff --git a/inc/external/acl/ops/acl_fv.h b/inc/external/acl/ops/acl_fv.h index 27dc367a..40cd50cb 100644 --- a/inc/external/acl/ops/acl_fv.h +++ b/inc/external/acl/ops/acl_fv.h @@ -32,8 +32,8 @@ typedef struct aclfvSearchResult aclfvSearchResult; // search operation type enum aclfvSearchType { - SEARCH_1_N, // 1:N operation type - SEARCH_N_M // N:M operation type + SEARCH_1_N, // 1:N operation type + SEARCH_N_M // N:M operation type }; /** @@ -104,8 +104,7 @@ ACL_FUNC_VISIBILITY aclError aclfvSetNMTopNum(aclfvInitPara *initPara, uint32_t * @retval OtherValues success. */ ACL_FUNC_VISIBILITY aclfvFeatureInfo *aclfvCreateFeatureInfo(uint32_t id0, uint32_t id1, uint32_t offset, - uint32_t featureLen, uint32_t featureCount, - uint8_t *featureData, uint32_t featureDataLen); + uint32_t featureLen, uint32_t featureCount, uint8_t *featureData, uint32_t featureDataLen); /** * @ingroup AscendCL @@ -234,9 +233,8 @@ ACL_FUNC_VISIBILITY aclError aclfvDestroySearchInput(aclfvSearchInput *searchInp * @retval null for failed. OtherValues success */ ACL_FUNC_VISIBILITY aclfvSearchResult *aclfvCreateSearchResult(uint32_t queryCnt, uint32_t *resultNum, - uint32_t resultNumDataLen, uint32_t *id0, uint32_t *id1, - uint32_t *resultOffset, float *resultDistance, - uint32_t dataLen); + uint32_t resultNumDataLen, uint32_t *id0, uint32_t *id1, uint32_t *resultOffset, float *resultDistance, + uint32_t dataLen); /** * @ingroup AscendCL @@ -350,4 +348,4 @@ ACL_FUNC_VISIBILITY aclError aclfvSearch(aclfvSearchType type, aclfvSearchInput } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_RETR_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_RETR_H_ diff --git a/inc/external/hccl/hccl.h b/inc/external/hccl/hccl.h new file mode 100644 index 00000000..311e78f2 --- /dev/null +++ b/inc/external/hccl/hccl.h @@ -0,0 +1,133 @@ +/** + * Copyright 2019-2020 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. + */ + +/** + * @file hccl.h + * @brief HCCL API + */ + +#ifndef HCCL_H_ +#define HCCL_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * @brief Initialize HCCL. + * + * @param clusterInfo A string identifying the cluster info file path, include file name. + * @param rank A integer identifying the identify for the rank. + * @param comm A pointer identifying the initialized communication resource. + * @return HcclResult + * @see HcclCommDestroy() + */ +extern HcclResult HcclCommInitClusterInfo(const char *clusterInfo, uint32_t rank, HcclComm *comm); + +/** + * @brief Get hccl root info. + * + * @param rootInfo A pointer identifying the hccl root info. + * @return HcclResult + */ +extern HcclResult HcclGetRootInfo(HcclRootInfo *rootInfo); + +/** + * @brief Initialize HCCL with root info. + * + * @param nRanks A integer identifying the rank size of the cluster. + * @param rootInfo A struct identifying the hccl root info. + * @param rank A integer identifying the identify for the rank. + * @param comm A pointer identifying the initialized communication resource. + * @return HcclResult + * @see HcclCommDestroy() + */ +extern HcclResult HcclCommInitRootInfo(uint32_t nRanks, const HcclRootInfo *rootInfo, uint32_t rank, HcclComm *comm); + +/** + * @brief AllReduce operator. + * + * @param sendBuf A pointer identifying the input data address of the operator. + * @param recvBuf A pointer identifying the output data address of the operator. + * @param count An integer(u64) identifying the number of the output data. + * @param dataType The data type of the operator, must be one of the following types: int8, int16, int32, float16, float32. + * @param op The reduction type of the operator, must be one of the following types: sum, min, max, prod. + * @param comm A pointer identifying the communication resource based on. + * @param stream A pointer identifying the stream information. + * @return HcclResult + */ +extern HcclResult HcclAllReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType, +HcclReduceOp op, HcclComm comm, aclrtStream stream); + +/** + * @brief Broadcast operator. + * + * @param buf A pointer identifying the data address of the operator. + * @param count An integer(u64) identifying the number of the data. + * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. + * @param root An integer(u32) identifying the the root rank in the operator. + * @param comm A pointer identifying the communication resource based on + * @param stream A pointer identifying the stream information. + * @return HcclResult + */ +extern HcclResult HcclBroadcast(void *buf, uint64_t count, HcclDataType dataType, uint32_t root, HcclComm comm, +aclrtStream stream); + +/** + * @brief ReduceScatter operator. + * + * @param sendBuf A pointer identifying the input data address of the operator. + * @param recvBuf A pointer identifying the output data address of the operator. + * @param recvCount An integer(u64) identifying the number of the output data. + * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. + * @param op The reduction type of the operator, must be one of the following types: sum, min, max, prod. + * @param comm A pointer identifying the communication resource based on. + * @param stream A pointer identifying the stream information. + * @return HcclResult + */ +extern HcclResult HcclReduceScatter(void *sendBuf, void *recvBuf, uint64_t recvCount, HcclDataType dataType, +HcclReduceOp op, HcclComm comm, aclrtStream stream); + +/** + * @brief AllGather operator. + * + * @param sendBuf A pointer identifying the input data address of the operator. + * @param recvBuf A pointer identifying the output data address of the operator. + * @param sendCount An integer(u64) identifying the number of the input data. + * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. + * @param comm A pointer identifying the communication resource based on. + * @param stream A pointer identifying the stream information. + * @return HcclResult + */ +extern HcclResult HcclAllGather(void *sendBuf, void *recvBuf, uint64_t sendCount, HcclDataType dataType, +HcclComm comm, aclrtStream stream); + +/** + * @brief Destroy HCCL comm + * + * @param comm A pointer identifying the communication resource targetting + * @return HcclResult + * @see HcclCommInitClusterInfo() + */ +extern HcclResult HcclCommDestroy(HcclComm comm); + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // HCCL_H_ diff --git a/inc/external/hccl/hccl_types.h b/inc/external/hccl/hccl_types.h new file mode 100644 index 00000000..50a64795 --- /dev/null +++ b/inc/external/hccl/hccl_types.h @@ -0,0 +1,101 @@ +/** + * Copyright 2019-2020 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. + */ + +/** + * @file hccl_types.h + * @brief HCCL data type definition + * + */ + +#ifndef HCCL_TYPES_H_ +#define HCCL_TYPES_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * @brief HCCL functions return value definition + */ +typedef enum { + HCCL_SUCCESS = 0, /**< success */ + HCCL_E_PARA = 1, /**< parameter error */ + HCCL_E_PTR = 2, /**< empty pointer */ + HCCL_E_MEMORY = 3, /**< memory error */ + HCCL_E_INTERNAL = 4, /**< internal error */ + HCCL_E_NOT_SUPPORT = 5, /**< not support feature */ + HCCL_E_NOT_FOUND = 6, /**< not found specific resource */ + HCCL_E_UNAVAIL = 7, /**< resource unavailable */ + HCCL_E_SYSCALL = 8, /**< call system interface error */ + HCCL_E_TIMEOUT = 9, /**< timeout */ + HCCL_E_OPEN_FILE_FAILURE = 10, /**< open file fail */ + HCCL_E_TCP_CONNECT = 11, /**< tcp connect fail */ + HCCL_E_ROCE_CONNECT = 12, /**< roce connect fail */ + HCCL_E_TCP_TRANSFER = 13, /**< tcp transfer fail */ + HCCL_E_ROCE_TRANSFER = 14, /**< roce transfer fail */ + HCCL_E_RUNTIME = 15, /**< call runtime api fail */ + HCCL_E_DRV = 16, /**< call driver api fail */ + HCCL_E_PROFILING = 17, /**< call profiling api fail */ + HCCL_E_CCE = 18, /**< call cce api fail */ + HCCL_E_NETWORK = 19, /**< call network api fail */ + HCCL_E_RESERVED /**< reserved */ +} HcclResult; + +/** + * @brief handle to HCCL communicator + */ +typedef void *HcclComm; + +/** + * @brief HCCL Reduction opperation + */ +typedef enum { + HCCL_REDUCE_SUM = 0, /**< sum */ + HCCL_REDUCE_PROD = 1, /**< prod */ + HCCL_REDUCE_MAX = 2, /**< max */ + HCCL_REDUCE_MIN = 3, /**< min */ + HCCL_REDUCE_RESERVED /**< reserved */ +} HcclReduceOp; + +/** + * @brief HCCL data type + */ +typedef enum { + HCCL_DATA_TYPE_INT8 = 0, /**< int8 */ + HCCL_DATA_TYPE_INT16 = 1, /**< int16 */ + HCCL_DATA_TYPE_INT32 = 2, /**< int32 */ + HCCL_DATA_TYPE_FP16 = 3, /**< fp16 */ + HCCL_DATA_TYPE_FP32 = 4, /**< fp32 */ + HCCL_DATA_TYPE_INT64 = 5, /**< int64 */ + HCCL_DATA_TYPE_UINT64 = 6, /**< uint64 */ + HCCL_DATA_TYPE_RESERVED /**< reserved */ +} HcclDataType; + +const uint32_t HCCL_ROOT_INFO_BYTES = 4108; // 4108: root info length + +/** + * @brief HCCL root info + */ +typedef struct HcclRootInfoDef { + char internal[HCCL_ROOT_INFO_BYTES]; +} HcclRootInfo; + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // HCCL_TYPES_H_ diff --git a/inc/external/runtime/rt_error_codes.h b/inc/external/runtime/rt_error_codes.h index 2dd2c70c..73da559d 100644 --- a/inc/external/runtime/rt_error_codes.h +++ b/inc/external/runtime/rt_error_codes.h @@ -23,69 +23,80 @@ extern "C" { #endif -static const int32_t ACL_RT_SUCCESS = 0; // success +static const int32_t ACL_RT_SUCCESS = 0; // success -static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid -static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id -static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null -static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context -static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context -static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal -static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned -static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed -static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed -static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream -static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread -static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set -static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create -static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream -static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type +static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid +static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id +static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null +static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context +static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context +static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal +static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned +static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed +static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed +static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream +static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread +static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set +static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create +static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream +static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type +static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle +static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type -static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPROT = 207000; // feature not support -static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error -static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error +static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support +static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error +static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error +static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow +static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device +static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail +static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission +static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource +static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource +static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource +static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource -static const int32_t ACL_ERROR_RT_INTERNEL_ERROR = 507000; // runtime internel error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error + +static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error -static const int32_t ACL_ERROR_RT_DRV_INTERNEL_ERROR = 507899; // drv internel error #ifdef __cplusplus } #endif -#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ +#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h b/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h index 8d16467c..703225e8 100644 --- a/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h +++ b/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h @@ -18,43 +18,43 @@ #define AICPU_OP_TYPE_LIST_H_ enum OpKernelType { - TF_KERNEL, - CPU_KERNEL + TF_KERNEL, + CPU_KERNEL }; enum ReturnCode { - OP_TYPE_NOT_SUPPORT, - FORMAT_NOT_SUPPORT, - DTYPE_NOT_SUPPORT + OP_TYPE_NOT_SUPPORT, + FORMAT_NOT_SUPPORT, + DTYPE_NOT_SUPPORT }; #pragma pack(push, 1) //One byte alignment struct SysOpInfo { - uint64_t opLen; - uint64_t opType; - OpKernelType kernelsType; + uint64_t opLen; + uint64_t opType; + OpKernelType kernelsType; }; struct OpParamInfo { - uint64_t num; - uint64_t dtypeList; - uint64_t formatList; + uint64_t num; + uint64_t dtypeList; + uint64_t formatList; }; struct SysOpCheckInfo { - uint64_t opListNum; - uint64_t offSetLen; - uint64_t sysOpInfoList; - uint64_t opParamInfoList; + uint64_t opListNum; + uint64_t offSetLen; + uint64_t sysOpInfoList; + uint64_t opParamInfoList; }; struct SysOpCheckResp { - uint64_t opListNum; - bool isWithoutJson; - uint64_t returnCodeList; - uint64_t sysOpInfoList; - uint64_t opParamInfoList; + uint64_t opListNum; + bool isWithoutJson; + uint64_t returnCodeList; + uint64_t sysOpInfoList; + uint64_t opParamInfoList; }; #pragma pack(pop) #endif // AICPU_OP_TYPE_LIST_H_ diff --git a/third_party/fwkacllib/inc/cce/aicpu_engine.h b/third_party/fwkacllib/inc/cce/aicpu_engine.h index b83731a8..042d952b 100644 --- a/third_party/fwkacllib/inc/cce/aicpu_engine.h +++ b/third_party/fwkacllib/inc/cce/aicpu_engine.h @@ -31,6 +31,7 @@ typedef enum { AE_STATUS_KERNEL_API_INNER_ERROR = 5, AE_STATUS_END_OF_SEQUENCE = 6, AE_STATUS_DUMP_FAILED = 7, + AE_STATUS_TASK_WAIT = 101, AE_STATUS_RESERVED } aeStatus_t; diff --git a/third_party/fwkacllib/inc/cce/fwk_adpt_struct.h b/third_party/fwkacllib/inc/cce/fwk_adpt_struct.h index 50b39d91..7a2cbc50 100644 --- a/third_party/fwkacllib/inc/cce/fwk_adpt_struct.h +++ b/third_party/fwkacllib/inc/cce/fwk_adpt_struct.h @@ -60,6 +60,7 @@ enum FWKTaskExtInfoType { FWK_ADPT_EXT_UPDATE_ADDR, FWK_ADPT_EXT_OP_NAME, FWK_ADPT_EXT_SESSION_INFO, + FWK_ADPT_EXT_BITMAP, FWK_ADPT_EXT_INVALID }; diff --git a/third_party/fwkacllib/inc/hccl/hcom.h b/third_party/fwkacllib/inc/hccl/hcom.h index b47887e5..972f470c 100644 --- a/third_party/fwkacllib/inc/hccl/hcom.h +++ b/third_party/fwkacllib/inc/hccl/hcom.h @@ -110,6 +110,34 @@ HcclResult HcomDestroyGroup(const char *group); /** * @brief Set the gradient split strategy with in the group, according to gradient index. * + * @param group A string identifying the group name. + * @param segmentNum An integer(u32) identifying the segments number of gradients. + * @param IdxList A list identifying the index of end gradient in each segment. + * @return HcclResult + */ +extern HcclResult HcomSetGradFusionByIndex(const char *group, u32 segmentNum, const u32 *IdxList); + +/** + * @brief Set the gradient split strategy with in the group, according to gradient data size. + * + * @param group A string identifying the group name. + * @param segmentNum An integer(u32) identifying the segments number of gradients. + * @param sizeList A list identifying the percent of each segment. + * @return HcclResult + */ +extern HcclResult HcomSetGradFusionBySize(const char *group, u32 segmentNum, const float *sizeList); + +/** + * @brief Initialize hcom executor. + * + * @param void + * @return HcclResult + */ +HcclResult HcomExecInitialize(); + +/** + * @brief Finalize hcom executor. + * * @param void * @return HcclResult */ diff --git a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h index 005014ed..993f36ba 100644 --- a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h +++ b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h @@ -50,7 +50,7 @@ typedef int (*mmFilter)(const mmDirent *entry); typedef int (*mmFilter2)(const mmDirent2 *entry); typedef int (*mmSort)(const mmDirent **a, const mmDirent **b); typedef int (*mmSort2)(const mmDirent2 **a, const mmDirent2 **b); -typedef size_t mmSize_t; +typedef size_t mmSize_t; //lint !e410 !e1051 typedef off_t mmOfft_t; typedef pid_t mmPid_t; typedef long MM_LONG; @@ -283,6 +283,7 @@ typedef struct { #define M_W_OK W_OK #define M_R_OK R_OK + #define MM_DT_DIR DT_DIR #define MM_DT_REG DT_REG diff --git a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_win.h b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_win.h index 1627d7a9..58ebb1a0 100644 --- a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_win.h +++ b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_win.h @@ -1,83 +1,83 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef MMPA_TYPEDEF_WIN_H -#define MMPA_TYPEDEF_WIN_H - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif // __cpluscplus -#endif // __cpluscplus - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - -#define EN_OK 0 -#define EN_ERR 1 -#define EN_ERROR (-1) -#define EN_INVALID_PARAM (-2) -#define EN_TIMEOUT (-3) - -#define HANDLE_INVALID_VALUE (-1) -#define INVALID_SOCKET_HANDLE INVALID_SOCKET -#define MMPA_MEM_MAX_LEN (0x7fffffff) -#define MMPA_PROCESS_ERROR (0x7fffffff) - -#define MMPA_ONE_THOUSAND 1000 -#define MMPA_COMPUTER_BEGIN_YEAR 1900 -#define SUMMER_TIME_OR_NOT (-1) -#define MMPA_ZERO 0 -#define MMPA_VALUE_ONE 1 -#define MMPA_SOCKET_MAIN_EDITION 2 -#define MMPA_SOCKET_SECOND_EDITION 0 -#define MMPA_PIPE_BUF_SIZE 1024 -#define MMPA_MAX_SCANDIR_COUNT 1024 -#define MAX_IOVEC_SIZE 32 -#define MMPA_PIPE_COUNT 2 -#define MMPA_THREADNAME_SIZE 16 -#define MMPA_MIN_OS_NAME_SIZE (MAX_COMPUTERNAME_LENGTH + 1) -#define MMPA_MIN_OS_VERSION_SIZE 64 - -#define MMPA_MAX_NI 19 -#define MMPA_MIDDLE_NI 5 -#define MMPA_LOW_NI (-5) -#define MMPA_MIN_NI (-20) -#define MMPA_MAX_FILE 128 - -#define MMPA_MAX_THREAD_PIO 99 -#define MMPA_MIDDLE_THREAD_PIO 66 -#define MMPA_LOW_THREAD_PIO 33 -#define MMPA_MIN_THREAD_PIO 1 - -#define MMPA_THREAD_SCHED_RR 0 -#define MMPA_THREAD_SCHED_FIFO 0 -#define MMPA_THREAD_SCHED_OTHER 0 -#define MMPA_THREAD_MIN_STACK_SIZE 0 - -#define MM_MUTEX_INITIALIZER NULL - -#ifdef __cplusplus -#if __cplusplus -} -#endif // __cpluscplus -#endif // __cpluscplus -#endif // _MMPA_TYPEDEF_WIN_H_ +/** + * Copyright 2019-2020 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. + */ + +#ifndef MMPA_TYPEDEF_WIN_H +#define MMPA_TYPEDEF_WIN_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif // __cpluscplus +#endif // __cpluscplus + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#define EN_OK 0 +#define EN_ERR 1 +#define EN_ERROR (-1) +#define EN_INVALID_PARAM (-2) +#define EN_TIMEOUT (-3) + +#define HANDLE_INVALID_VALUE (-1) +#define INVALID_SOCKET_HANDLE INVALID_SOCKET +#define MMPA_MEM_MAX_LEN (0x7fffffff) +#define MMPA_PROCESS_ERROR (0x7fffffff) + +#define MMPA_ONE_THOUSAND 1000 +#define MMPA_COMPUTER_BEGIN_YEAR 1900 +#define SUMMER_TIME_OR_NOT (-1) +#define MMPA_ZERO 0 +#define MMPA_VALUE_ONE 1 +#define MMPA_SOCKET_MAIN_EDITION 2 +#define MMPA_SOCKET_SECOND_EDITION 0 +#define MMPA_PIPE_BUF_SIZE 1024 +#define MMPA_MAX_SCANDIR_COUNT 1024 +#define MAX_IOVEC_SIZE 32 +#define MMPA_PIPE_COUNT 2 +#define MMPA_THREADNAME_SIZE 16 +#define MMPA_MIN_OS_NAME_SIZE (MAX_COMPUTERNAME_LENGTH + 1) +#define MMPA_MIN_OS_VERSION_SIZE 64 + +#define MMPA_MAX_NI 19 +#define MMPA_MIDDLE_NI 5 +#define MMPA_LOW_NI (-5) +#define MMPA_MIN_NI (-20) +#define MMPA_MAX_FILE 128 + +#define MMPA_MAX_THREAD_PIO 99 +#define MMPA_MIDDLE_THREAD_PIO 66 +#define MMPA_LOW_THREAD_PIO 33 +#define MMPA_MIN_THREAD_PIO 1 + +#define MMPA_THREAD_SCHED_RR 0 +#define MMPA_THREAD_SCHED_FIFO 0 +#define MMPA_THREAD_SCHED_OTHER 0 +#define MMPA_THREAD_MIN_STACK_SIZE 0 + +#define MM_MUTEX_INITIALIZER NULL + +#ifdef __cplusplus +#if __cplusplus +} +#endif // __cpluscplus +#endif // __cpluscplus +#endif // _MMPA_TYPEDEF_WIN_H_ diff --git a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h index ecc86bf8..49e97a5d 100644 --- a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h +++ b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h @@ -1,4 +1,4 @@ -/** +/** * Copyright 2019-2020 Huawei Technologies Co., Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/third_party/fwkacllib/inc/ops/aipp.h b/third_party/fwkacllib/inc/ops/aipp.h index bed984bd..86805f72 100644 --- a/third_party/fwkacllib/inc/ops/aipp.h +++ b/third_party/fwkacllib/inc/ops/aipp.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -65,6 +65,8 @@ in aipp config file, framework will auto add one input node to graph at last. \n *@par Third-party framework compatibility *Compatible with the TensorFlow operator AippData. +*@par Restrictions: +*Warning: This operator can be integrated only by configuring INSERT_OP_FILE of aclgrphBuildModel. Please do not use it directly. */ REG_OP(AippData) .INPUT(data, TensorType::ALL()) diff --git a/third_party/fwkacllib/inc/ops/all_ops.h b/third_party/fwkacllib/inc/ops/all_ops.h index 1ac83783..cc11f5f9 100644 --- a/third_party/fwkacllib/inc/ops/all_ops.h +++ b/third_party/fwkacllib/inc/ops/all_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -39,6 +39,7 @@ #include "image_ops.h" #include "internal_ops.h" #include "linalg_ops.h" +#include "list_ops.h" #include "logging_ops.h" #include "lookup_ops.h" #include "math_ops.h" diff --git a/third_party/fwkacllib/inc/ops/array_ops.h b/third_party/fwkacllib/inc/ops/array_ops.h index e1f64421..375802fc 100644 --- a/third_party/fwkacllib/inc/ops/array_ops.h +++ b/third_party/fwkacllib/inc/ops/array_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -1153,6 +1153,79 @@ REG_OP(EditDistance) .OUTPUT(output, TensorType({DT_FLOAT})) .OP_END_FACTORY_REG(EditDistance) +/** +* @brief sort_v2. + +* @par Inputs: +* @li x: An ND tensor of type float16. + +* @par Attributes: + +* @li axis: An optional int. The dimension to sort along. This value defaults to -1. +* @li descending: An optional bool. Controls the sorting order (ascending or descending). This value defaults to False. + +* @par Outputs: +* @li y: An ND tensor of type float16. + +* @attention Constraints: +* @li Axis should select the last dim. +* @li When the sorting data is less than 150K, it is recommended to use this tbe ops, + and the descending performance is better than the ascending. +* @li The upper limit of data on Ascend910 is 2000K. +*/ +REG_OP(SortV2) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .ATTR(axis, Int, -1) + .ATTR(descending, Bool, false) + .OP_END_FACTORY_REG(SortV2) + +/** +* @brief Expand the input tensor to a compatible shape. \n + +* @par Inputs: +* One inputs, including: +* @li x: A Tensor. Must be one of the following types: +* float16, float32, int32, int8 ,uint8. \n +* @li shape: A Tensor to specify the shape that the input tensor expanded to. \n + +* @par Outputs: +* @li y: A Tensor. Has the same type as "x", and the shape specified by input and attr shape \n + +* @par Third-party framework compatibility +* Compatible with the ONNX operator Expand. +*/ + +REG_OP(Expand) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) + .INPUT(shape, TensorType({DT_INT16, DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) + .OP_END_FACTORY_REG(Expand) + +/** +* @brief Expand the input tensor to a compatible shape. \n + +* @par Inputs: +* One inputs, including: +* @li x: A Tensor. Must be one of the following types: +* float16, float32, int32, int8 ,uint8. \n + +* @par Attributes: +* @li shape: A required listInt to specify the shape that the input tensor expanded to. \n + + +* @par Outputs: +* @li y: A Tensor. Has the same type as "x", and the shape specified by input and attr shape \n + +* @par Third-party framework compatibility +* Compatible with the ONNX operator Expand. +*/ + +REG_OP(ExpandD) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) + .REQUIRED_ATTR(shape, ListInt) + .OP_END_FACTORY_REG(ExpandD) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_ARRAY_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/audio_ops.h b/third_party/fwkacllib/inc/ops/audio_ops.h index d9883253..f05135d1 100644 --- a/third_party/fwkacllib/inc/ops/audio_ops.h +++ b/third_party/fwkacllib/inc/ops/audio_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/batch_ops.h b/third_party/fwkacllib/inc/ops/batch_ops.h index 8a1c5a7b..a4786cd3 100644 --- a/third_party/fwkacllib/inc/ops/batch_ops.h +++ b/third_party/fwkacllib/inc/ops/batch_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/bitwise_ops.h b/third_party/fwkacllib/inc/ops/bitwise_ops.h index 5c83e161..39a28cf3 100644 --- a/third_party/fwkacllib/inc/ops/bitwise_ops.h +++ b/third_party/fwkacllib/inc/ops/bitwise_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/boosted_trees_ops.h b/third_party/fwkacllib/inc/ops/boosted_trees_ops.h index 550e8b7d..08e54824 100644 --- a/third_party/fwkacllib/inc/ops/boosted_trees_ops.h +++ b/third_party/fwkacllib/inc/ops/boosted_trees_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h b/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h index e20607bf..890c52ae 100644 --- a/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h +++ b/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/condtake_ops.h b/third_party/fwkacllib/inc/ops/condtake_ops.h index 5e91eb07..029cffbf 100644 --- a/third_party/fwkacllib/inc/ops/condtake_ops.h +++ b/third_party/fwkacllib/inc/ops/condtake_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/control_flow_ops.h b/third_party/fwkacllib/inc/ops/control_flow_ops.h index 7196b14f..c0b6ad72 100644 --- a/third_party/fwkacllib/inc/ops/control_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/control_flow_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/ctc_ops.h b/third_party/fwkacllib/inc/ops/ctc_ops.h index 2c75fd09..c6a265cc 100644 --- a/third_party/fwkacllib/inc/ops/ctc_ops.h +++ b/third_party/fwkacllib/inc/ops/ctc_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/data_flow_ops.h b/third_party/fwkacllib/inc/ops/data_flow_ops.h index bb937a75..45303828 100644 --- a/third_party/fwkacllib/inc/ops/data_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/data_flow_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -908,7 +908,7 @@ REG_OP(TensorArray) .OUTPUT(handle, TensorType({DT_RESOURCE})) .OUTPUT(flow, TensorType({DT_FLOAT})) .REQUIRED_ATTR(dtype, Type) - .ATTR(element_shape, ListInt, ge::UNKNOWN_SHAPE) + .ATTR(element_shape, ListInt, ge::UNKNOWN_RANK) .ATTR(dynamic_size, Bool, false) .ATTR(clear_after_read, Bool, true) .ATTR(identical_element_shapes, Bool, false) @@ -963,7 +963,7 @@ REG_OP(TensorArrayConcat) DT_QUINT8, DT_QINT32})) .OUTPUT(lengths, TensorType({DT_INT64})) .REQUIRED_ATTR(dtype, Type) - .ATTR(element_shape_except0, ListInt, ge::UNKNOWN_SHAPE) + .ATTR(element_shape_except0, ListInt, ge::UNKNOWN_RANK) .OP_END_FACTORY_REG(TensorArrayConcat) /** @@ -999,7 +999,7 @@ REG_OP(TensorArrayGather) DT_STRING, DT_COMPLEX64, DT_COMPLEX128, DT_QINT8, DT_QUINT8, DT_QINT32})) .REQUIRED_ATTR(dtype, Type) - .ATTR(element_shape, ListInt, ge::UNKNOWN_SHAPE) + .ATTR(element_shape, ListInt, ge::UNKNOWN_RANK) .OP_END_FACTORY_REG(TensorArrayGather) /** diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index c64bc138..e65c7027 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. @@ -122,7 +122,8 @@ REG_OP(MinimumGrad) *@par Inputs: *One input: *x:A Tensor. Must be one of the following types: bool, float16, float, int8, int32, uint32, uint8, - int64, uint64, int16, uint16, double, complex64, complex128, qint8, quint8, qint16, quint16, qint32. \n + int64, uint64, int16, uint16, double, complex64, complex128, qint8, quint8, qint16, quint16, qint32. + For float32 type, the actual calculation on the chip is based on float16. \n *@par Attributes: *dst_type: An required attribute of type int32, specifying the dst data type. \n @@ -611,6 +612,15 @@ REG_OP(Log1p) *@par Outputs: *y: A Tensor. Has the same type as "x1". + +*@attention Constraints: +*@li x2: The input data does not support 0 +*@li When NUM exceeds 2048 , the accuracy of operator cannot guarantee the +*requirement of double thousandths in the mini form +*@li Due to different architectures, the calculation results of this operator +*on NPU and CPU may be inconsistent +*@li If shape is expressed as (D1,D2... ,Dn), then D1*D2... *DN<=1000000,n<=8 + *@par Third-party framework compatibility *Compatible with the TensorFlow operator Mod. */ @@ -2042,6 +2052,15 @@ REG_OP(FloorDiv) * *@par Outputs: *y: Result remainder. + +*@attention Constraints: +*@li x2: The input data does not support 0 +*@li When NUM exceeds 2048 , the accuracy of operator cannot guarantee the +*requirement of double thousandths in the mini form +*@li Due to different architectures, the calculation results of this operator +*on NPU and CPU may be inconsistent +*@li If shape is expressed as (D1,D2... ,Dn), then D1*D2... *DN<=1000000,n<=8 + *@par Third-party framework compatibility * Compatible with the TensorFlow operator FloorMod. */ @@ -2168,6 +2187,14 @@ REG_OP(Tan) *@par Outputs: *y: A Tensor. Has the same type as "x1". \n +*@attention Constraints: +*@li x2: The input data does not support 0 +*@li When NUM exceeds 2048 , the accuracy of operator cannot guarantee the +*requirement of double thousandths in the mini form +*@li Due to different architectures, the calculation results of this operator +*on NPU and CPU may be inconsistent +*@li If shape is expressed as (D1,D2... ,Dn), then D1*D2... *DN<=1000000,n<=8 + *@par Third-party framework compatibility *@li Compatible with the TensorFlow operator TruncateMod. */ @@ -2829,9 +2856,9 @@ REG_OP(AdamApplyOneAssign) *Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(LambApplyOptimizerAssign) - .INPUT(input0, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(input1, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(input2, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(grad, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(inputv, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(inputm, TensorType({DT_FLOAT16,DT_FLOAT})) .INPUT(input3, TensorType({DT_FLOAT16,DT_FLOAT})) .INPUT(mul0_x, TensorType({DT_FLOAT16,DT_FLOAT})) .INPUT(mul1_x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -2842,6 +2869,8 @@ REG_OP(LambApplyOptimizerAssign) .INPUT(do_use_weight, TensorType({DT_FLOAT16,DT_FLOAT})) .INPUT(weight_decay_rate, TensorType({DT_FLOAT16,DT_FLOAT})) .OUTPUT(output0, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(inputv, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(inputm, TensorType({DT_FLOAT16,DT_FLOAT})) .OP_END_FACTORY_REG(LambApplyOptimizerAssign) /** @@ -2873,7 +2902,8 @@ REG_OP(LambApplyWeightAssign) .INPUT(input1, TensorType({DT_FLOAT16,DT_FLOAT})) .INPUT(input2, TensorType({DT_FLOAT16,DT_FLOAT})) .INPUT(input3, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(input4, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(input_param, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(input_param, TensorType({DT_FLOAT16,DT_FLOAT})) .OP_END_FACTORY_REG(LambApplyWeightAssign) /** @@ -3329,8 +3359,297 @@ REG_OP(TensorRedirect) .OUTPUT(output_x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8, DT_INT64, DT_INT16, DT_UINT16, DT_UINT64, DT_UINT32})) .OP_END_FACTORY_REG(TensorRedirect) -} // namespace ge +/** +* @brief Performs the element-wise division of tensor x2 by tensor x3, +* multiply the result by the scalar value and add it to tensor x1 + +* @par Inputs: +* Three inputs, including: +* @li input_data: A mutable input Tensor. Must be one of the following types: +* float16, float32. +* @li x1: A mutable input Tensor of the same type as x1. +* @li x2: A mutable input Tensor of the same type as x1. +* @li value: A mutable input Tensor. Must be one of the following types: +* float16, float32, int32. \n + +* @par Outputs: +* @li y: A mutable Tensor. Has the same type as "x1". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Addcdiv. +*/ +REG_OP(Addcdiv) + .INPUT(input_data, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(value, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT32 })) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(Addcdiv) + +/** +* @brief Performs the element-wise multiplication of tensor x2 by tensor x3, +* multiply the result by the scalar value and add it to tensor input_data + + +* @par Inputs: +* Three inputs, including: +* @li input_data: A mutable input Tensor. Must be one of the following types: +* float16, float32, int8, int32, uint8. +* @li x1: A mutable input Tensor of the same type as x1. +* @li x2: A mutable input Tensor of the same type as x1. +* @li value: A tensor which includes only one element of the same type as x1. \n + +* @par Outputs: +* @li y: A mutable output Tensor. Has the same type as "x1". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Addcmul. +*/ +REG_OP(Addcmul) + .INPUT(input_data, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8 })) + .INPUT(x1, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8 })) + .INPUT(x2, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8 })) + .INPUT(value, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8 })) + .OUTPUT(y, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8 })) + .OP_END_FACTORY_REG(Addcmul) + +/** +* @brief Computes the result of x2 * alpha + x1. + +* @par Inputs: +* @li x1: An ND tensor of type float16, float32, int32. +* @li x2: An ND tensor of type float16, float32, int32. +* @li alpha: A scalar tensor of type float16, float32. \n + +* @par Outputs: +* @li y: An ND tensor tensor with the same shape and type as "x1". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Axpy. +*/ +REG_OP(AxpyV2) + .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .INPUT(alpha, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OP_END_FACTORY_REG(AxpyV2) + +/** +* @brief Computes the result of x1 + x2. + +* @par Inputs: +* @li x1: An ND tensor of type float16, float, int32. +* @li x2: An ND tensor of type float16, float, int32. \n + +* @par Outputs: +* @li y: An ND tensor tensor with the same type as "x1". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Add. +*/ +REG_OP(PtAdd) + .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OP_END_FACTORY_REG(PtAdd) + +/** +* @brief Computes the result of x1 * x2. + +* @par Inputs: +* @li x1: An ND tensor of type float16, float32, int32. +* @li x2: An ND tensor of type float16, float32, int32. \n + +* @par Outputs: +* @li y: Same shape and type as the largest ND tensor in x1 x2. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator muls. +*/ +REG_OP(PtMuls) + .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OP_END_FACTORY_REG(PtMuls) + +/** +* @brief Computes the result of x1 - x2. + +* @par Inputs: +* @li x1: An ND tensor of type float16, float, int32. +* @li x2: An ND tensor of type float16, float, int32. \n + +* @par Outputs: +* @li y: An ND tensor tensor with the same type as "x1". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Sub. +*/ +REG_OP(PtSub) + .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OP_END_FACTORY_REG(PtSub) + +/** +* @brief Add the partial values of two tensors in format NC1HWC0. + +* @par Inputs: +* @li x1: A Tensor in 5HD, and must be one of the following types: float16, +* float32. \n +* @li x2: A Tensor of the same type as "x1", and the same shape as "x1", +* except for the C1 value. \n + +* @par Attributes: +* @li x1_c1_offset: A required int. Offset value of C1 in "x1". \n +* @li x2_c1_offset: A required int. Offset value of C1 in "x2". \n +* @li c1_len: A required int. C1 len of "y". The value must be less than +* the difference between C1 and offset in "x1" and "x2". \n + +* @par Outputs: +* @li y: A Tensor of the same type as "x1", and the same shape as "x1", +* except for the C1 value. Record the result after adding. \n +*/ +REG_OP(StrideAdd) + .INPUT(x1, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(x2, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .OUTPUT(y, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .REQUIRED_ATTR(x1_c1_offset, Int) + .REQUIRED_ATTR(x2_c1_offset, Int) + .REQUIRED_ATTR(c1_len, Int) + .OP_END_FACTORY_REG(StrideAdd) + +/** +* @brief Compare two tensors are totally equal or not, only output a bool value" +* @par Inputs: +* Two inputs, including: +* @li input_x: A Tensor. the first tensor. \n +* @li input_y: A Tensor. the second tensor. \n + +* @par Outputs: +* @li output_z: A Tensor. Bool type, compare result of the two inputs. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch equal operator. \n +*/ +REG_OP(TensorEqual) + .INPUT(input_x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) + .INPUT(input_y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) + .OUTPUT(output_z, TensorType({DT_BOOL})) + .OP_END_FACTORY_REG(TensorEqual) + +/** + * @brief Element-wise min of each of the input tensors (with Numpy-style broadcasting support). + * All inputs and outputs must have the same data type. This operator supports multidirectional + * (i.e., Numpy-style) broadcasting + * + * @par inputs + * one input including: + * @li x: dynamic input A Tensor. Must be one of the following types: float32, float16, double, int32, int64 + * + * @par output + * one output including: + * @li y:A Tensor of the same type as x + * + */ +REG_OP(MaxN) + .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_FLOAT64, DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_FLOAT64, DT_INT32, DT_INT64})) + .OP_END_FACTORY_REG(MaxN) + +/** + * @brief Element-wise min of each of the input tensors (with Numpy-style broadcasting support). + * All inputs and outputs must have the same data type. This operator supports multidirectional + * (i.e., Numpy-style) broadcasting + * + * @par inputs + * one input including: + * @li x: dynamic input A Tensor. Must be one of the following types: float32, float16, double, int32, int64 + * + * @par output + * one output including: + * @li y:A Tensor of the same type as x + * + */ +REG_OP(MinN) + .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_FLOAT64, + DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_FLOAT64, + DT_INT32, DT_INT64})) + .OP_END_FACTORY_REG(MinN) + +/** + * @brief Calculates x * maske * value. + * + * @par Inputs: + * @li x: An tensor of type float16 or float32, specifying the input to the data layer. + * @li mask: An tensor of type int8 or float16 or float32, be same shape with x. \n + * + * @par Attributes: + * value: A optional float. \n + * + * @par Outputs: + * y: The output tensor of type float16 or float32. + @ li y:A Tensor of the same type and shape as x + * + */ +REG_OP(MaskedScale) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT32})) + .INPUT(mask, TensorType({DT_INT8, DT_FLOAT16, DT_FLOAT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT32})) + .REQUIRED_ATTR(value, Float) + .OP_END_FACTORY_REG(MaskedScale) + +/** + * @brief Calculate the lerp function. \n + + * @par Inputs: + * Three inputs, including: + * @li start: A tensor. Must be one of the following types: + * float16, float32. \n + * @li end: A tensor. Must be one of the following types: + * float16, float32. \n + * @li weight: A tensor. Must be one of the following types: + * float16, float32. \n + + * @par Outputs: + * y: A Tensor with the same type and shape of input_x's. \n + + * @par Third-party framework compatibility + * Compatible with the Pytorch operator Lerp. \n + */ +REG_OP(Lerp) + .INPUT(start, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(end, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(weight, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(Lerp) + +/** +*@brief Hardmax(element in input, axis) = 1 if the element is the first maximum value along the specified axis, 0 +*otherwise The input does not need to explicitly be a 2D vector.The "axis" attribute indicates the dimension along +*which Hardmax will be performed.The output tensor has the same shape and contains the Hardmax values of the +*corresponding input. +* +*@par inputs +*one input including: +*@li x: input A Tensor.Must be one of the following types:float32,float16 +* +*@par Attributes: +*@li axis:A required int attribute that decides which dimension will be used to cal the hard_max +* +*@par output: +*one output including: +*@li y:A Tensor of the same type as x +* +*/ +REG_OP(HardMax) + .INPUT(x, TensorType({ DT_FLOAT16, DT_FLOAT })) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(axis, Int, -1) + .OP_END_FACTORY_REG(HardMax) +} // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_ELEWISE_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/functional_ops.h b/third_party/fwkacllib/inc/ops/functional_ops.h index 598d3ad3..b09ac058 100644 --- a/third_party/fwkacllib/inc/ops/functional_ops.h +++ b/third_party/fwkacllib/inc/ops/functional_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/get_data_ops.h b/third_party/fwkacllib/inc/ops/get_data_ops.h index 33dc4f14..e5518ef8 100644 --- a/third_party/fwkacllib/inc/ops/get_data_ops.h +++ b/third_party/fwkacllib/inc/ops/get_data_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/hcom_ops.h b/third_party/fwkacllib/inc/ops/hcom_ops.h index b90b225e..cb9fbe22 100644 --- a/third_party/fwkacllib/inc/ops/hcom_ops.h +++ b/third_party/fwkacllib/inc/ops/hcom_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. @@ -45,8 +45,6 @@ REG_OP(HcomAllGather) .OUTPUT(y, TensorType({DT_FLOAT, DT_INT32, DT_INT8, DT_INT16, DT_FLOAT16, DT_INT64, DT_UINT64})) .REQUIRED_ATTR(rank_size, Int) .REQUIRED_ATTR(group, String) - .ATTR(alpha, Float, 1.0) - .ATTR(beta, Float, 0.0) .OP_END_FACTORY_REG(HcomAllGather) /** @@ -77,8 +75,6 @@ REG_OP(HcomAllReduce) .REQUIRED_ATTR(group, String) .ATTR(fusion, Int, 1) .ATTR(fusion_id, Int, -1) - .ATTR(alpha, Float, 1.0) - .ATTR(beta, Float, 0.0) .OP_END_FACTORY_REG(HcomAllReduce) /** @@ -91,7 +87,7 @@ REG_OP(HcomAllReduce) input of this rank will be broadcast to other ranks. * @li fusion: A required integer identifying if the op need to fusion,the default value is none fusion - * @li fusion: A required integer identifying the fusion id if para fusion + * @li fusion_id: A required integer identifying the fusion id if para fusion is set. * @li group: A required string identifying the group name of ranks participating in the op. @@ -109,10 +105,39 @@ REG_OP(HcomBroadcast) .REQUIRED_ATTR(group, String) .ATTR(fusion, Int, 0) .ATTR(fusion_id, Int, -1) - .ATTR(alpha, Float, 1.0) - .ATTR(beta, Float, 0.0) .OP_END_FACTORY_REG(HcomBroadcast) +/** + * @brief preforms reduction from others rank to rootrank + * @par Inputs: +* @li root_rank: A required integer identifying the root rank in the op + the reduction result will be on this root rank + * x: A tensor. Must be one of the following types: int8, int16, int32, float16, + float32. + * @par Attributes: + * @li reduction: A required string identifying the reduction operation to + perform.The supported operation are: "sum", "max", "min", "prod". + * @li group: A required string identifying the group name of ranks + participating in the op. + * @li fusion: An optional integer identifying the fusion flag of the op. + 0: no fusion; 1 (default): fusion; 2: fusion the ops by fusion id. + * @li fusion_id: An optional integer identifying the fusion id of the op. + * The HcomReduce ops with the same fusion id will be fused. + * @par Outputs: + * y: A Tensor. Has the same type as "x". + * @attention Constraints: + *"group" is limited to 128 characters. Use "hccl_world_group" + as the name of a world group. + */ +REG_OP(HcomReduce) + .INPUT(x, TensorType({DT_FLOAT, DT_INT32, DT_INT8, DT_INT16, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_INT32, DT_INT8, DT_INT16, DT_FLOAT16})) + .REQUIRED_ATTR(root_rank, Int) + .REQUIRED_ATTR(reduction, String) + .REQUIRED_ATTR(group, String) + .ATTR(fusion, Int, 0) + .ATTR(fusion_id, Int, -1) + .OP_END_FACTORY_REG(HcomReduce) /** * @brief Performs reduction across all input tensors, scattering in equal blocks among ranks, each rank getting a chunk of data based on its rank @@ -139,8 +164,6 @@ REG_OP(HcomReduceScatter) .REQUIRED_ATTR(reduction, String) .REQUIRED_ATTR(group, String) .REQUIRED_ATTR(rank_size, Int) - .ATTR(alpha, Float, 1.0) - .ATTR(beta, Float, 0.0) .OP_END_FACTORY_REG(HcomReduceScatter) /** @@ -167,8 +190,6 @@ REG_OP(HcomSend) .REQUIRED_ATTR(group, String) .REQUIRED_ATTR(sr_tag, Int) .REQUIRED_ATTR(dest_rank, Int) - .ATTR(alpha, Float, 1.0) - .ATTR(beta, Float, 0.0) .OP_END_FACTORY_REG(HcomSend) /** @@ -202,8 +223,6 @@ REG_OP(HcomReceive) .REQUIRED_ATTR(src_rank, Int) .REQUIRED_ATTR(shape, ListInt) .REQUIRED_ATTR(dtype, Type) - .ATTR(alpha, Float, 1.0) - .ATTR(beta, Float, 0.0) .OP_END_FACTORY_REG(HcomReceive) /** diff --git a/third_party/fwkacllib/inc/ops/hvd_ops.h b/third_party/fwkacllib/inc/ops/hvd_ops.h index a49ec5ed..00299ef7 100644 --- a/third_party/fwkacllib/inc/ops/hvd_ops.h +++ b/third_party/fwkacllib/inc/ops/hvd_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/third_party/fwkacllib/inc/ops/image_ops.h b/third_party/fwkacllib/inc/ops/image_ops.h index ce3262f9..d7f60346 100644 --- a/third_party/fwkacllib/inc/ops/image_ops.h +++ b/third_party/fwkacllib/inc/ops/image_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -31,11 +31,12 @@ namespace ge { *@par Inputs: *Input images is a tensor of at least 3 dimensions. The last dimension is interpretted as channels, and must be three. Inputs include: -*@li images:A Tensor of type float. Images to adjust. At least 3-D. +*@li images:A Tensor of type float. Images to adjust. At least 3-D. The format +must be NHWC. *@li delta:A Tensor of type float. A float delta to add to the hue . \n *@par Outputs: -*y:A Tensor of type float . \n +*y:A Tensor of type float. The format must be NHWC. \n *@attention Constraints: *Input images is a tensor of at least 3 dimensions. The last dimension is @@ -57,11 +58,12 @@ REG_OP(AdjustHue) *@par Inputs: *Input images is a tensor of at least 3 dimensions. The last dimension is interpretted as channels, and must be three. Inputs include: -*@li images:A Tensor of type float. Images to adjust. At least 3-D. +*@li images:A Tensor of type float. Images to adjust. At least 3-D. The format +must be NHWC. *@li scale:A Tensor of type float. A float scale to add to the saturation . \n *@par Outputs: -*y:A Tensor of type float . \n +*y:A Tensor of type float. The format must be NHWC. \n *@attention Constraints: *Input images is a tensor of at least 3 dimensions. The last dimension is @@ -83,11 +85,12 @@ REG_OP(AdjustSaturation) *@par Inputs: *Input images is a tensor of at least 3 dimensions. The last 3 dimensions are interpreted as '[height, width, channels]'. Inputs include: -*@li images:A Tensor of type float. Images to adjust. At least 3-D. +*@li images:A Tensor of type float. Images to adjust. At least 3-D. The format +must be NHWC. *@li scale:A Tensor of type float. A float multiplier for adjusting contrast . \n *@par Outputs: -*y:A Tensor of type float . \n +*y:A Tensor of type float. The format must be NHWC. \n *@attention Constraints: *Input images is a tensor of at least 3 dimensions. The last dimension is @@ -112,7 +115,7 @@ nearest neighbor sampling to a common output size specified by crop_size . \n *Input images must be a 4-D tensor. Inputs include: *@li images:A Tensor. Must be one of the following types:uint8, uint16, int8, int16, int32, int64, float16, float, double. A 4-D tensor of shape -[batch, image_height, image_width, depth]. +[batch, image_height, image_width, depth]. The format must be NHWC. *@li boxes: A Tensor of type float. A 2-D tensor of shape [num_boxes, 4]. *@li box_index: A Tensor of type int32. A 1-D tensor of shape [num_boxes] with int32 values in [0, batch). @@ -127,7 +130,7 @@ extrapolation, when applicable. NearestNeighbor . \n *@par Outputs: -*y:A Tensor of type float . \n +*y:A Tensor of type float. The format must be NHWC. \n *@attention Constraints: *Input images must be a 4-D tensor . \n @@ -193,7 +196,9 @@ boxes tensor . \n *@par Inputs: *Input images and grads must be a 4-D tensor. Inputs include: *@li grads: A 4-D tensor of shape [num_boxes, crop_height, crop_width, depth]. +The format must be NHWC. *@li images: A 4-D tensor of shape [batch, image_height, image_width, depth]. +The format must be NHWC. Both image_height and image_width need to be positive. *@li boxes: A 2-D tensor of shape [num_boxes, 4]. The i-th row of the tensor specifies the coordinates of a box in the box_ind[i] image and is specified in @@ -233,6 +238,7 @@ images tensor . \n *@par Inputs: *Input grads must be a 4-D tensor. Inputs include: *@li grads: A 4-D tensor of shape [num_boxes, crop_height, crop_width, depth]. +The format must be NHWC. *@li boxes: A 2-D tensor of shape [num_boxes, 4]. The i-th row of the tensor specifies the coordinates of a box in the box_ind[i] image and is specified in normalized coordinates [y1, x1, y2, x2]. @@ -248,7 +254,8 @@ method: A string specifying the interpolation method. Only 'bilinear' is supported for now . \n *@par Outputs: -*y:A 4-D tensor of shape [batch, image_height, image_width, depth] . \n +*y:A 4-D tensor of shape [batch, image_height, image_width, depth]. The format +must be NHWC. \n *@attention Constraints: *Input grads must be a 4-D tensor . \n @@ -273,6 +280,7 @@ REG_OP(CropAndResizeGradImage) *@par Inputs: *Input x must be a 4-D tensor. Inputs include: *@li x: A 4-D float tensor of shape [batch_size, height, width, channels]. +The format must be NHWC. *@li size: A 1-D tensor of 2 elements containing the size of the glimpses to extract. The glimpse height must be specified first, following by the glimpse width. @@ -293,7 +301,7 @@ uniform_noise . \n *@par Outputs: *y:A tensor representing the glimpses [batch_size, glimpse_height, -glimpse_width, channels] . \n +glimpse_width, channels]. The format must be NHWC. \n *@attention Constraints: *Input x must be a 4-D tensor . \n @@ -340,7 +348,8 @@ REG_OP(HSVToRGB) *@par Inputs: *Input images must be a 4-D tensor. Inputs include: -*@li images: 4-D with shape [batch, height, width, channels]. +*@li images: 4-D with shape [batch, height, width, channels]. The format must +be NHWC. *@li size: A 1-D int32 Tensor of 2 elements: new_height, new_width. The new size for the images. *@li min: A Tensor of type float. @@ -354,6 +363,7 @@ the values at the corner pixels. Defaults to false. *@par Outputs: *@li resized_images: 4-D with shape [batch, new_height, new_width, channels]. +The format must be NHWC. *@li y_min: A Tensor of type float. *@li y_max: A Tensor of type float . \n @@ -381,7 +391,8 @@ REG_OP(QuantizedResizeBilinear) *@par Inputs: *Input images must be a 4-D tensor. Inputs include: -*@li images: 4-D with shape [batch, height, width, channels]. +*@li images: 4-D with shape [batch, height, width, channels]. The format must +be NHWC. *@li size: A 1-D int32 Tensor of 2 elements: new_height, new_width. The new size for the images . \n @@ -391,7 +402,8 @@ output tensors are aligned, preserving the values at the corner pixels. Defaults to false . \n *@par Outputs: -*y: 4-D with shape [batch, new_height, new_width, channels] . \n +*y: 4-D with shape [batch, new_height, new_width, channels]. The format must +be NHWC. \n *@attention Constraints: *Input images can be of different types but output images are always float . \n @@ -414,10 +426,10 @@ REG_OP(ResizeArea) *@par Inputs: *Input grads must be a 4-D tensor. Inputs include: *@li grads: A Tensor of type float. 4-D with shape [batch, height, width, -channels]. +channels]. The format must be NHWC. *@li original_image: A Tensor. Must be one of the following types: float, double. 4-D with shape [batch, orig_height, orig_width, channels], The image -tensor that was resized . \n +tensor that was resized. The format must be NHWC. \n *@par Attributes: *@li align_corners: An optional bool. Defaults to False. If true, the centers @@ -426,10 +438,10 @@ false. *@li half_pixel_centers: An optional bool. Defaults to False . \n *@par Outputs: -*y: A Tensor. Has the same type as original_image . \n +*y: A Tensor. Has the same type as original_image. The format must be NHWC. \n *@attention Constraints: -*Input images can be of different types but output images are always float . \n +*Input images can be of different types but output images are always float . *@par Third-party framework compatibility *Compatible with tensorflow ResizeBicubicGrad operator. @@ -448,7 +460,8 @@ REG_OP(ResizeBicubicGrad) *@par Inputs: *Input images must be a 4-D tensor. Inputs include: -*@li images: 4-D with shape [batch, height, width, channels]. +*@li images: 4-D with shape [batch, height, width, channels]. The format +must be NHWC. *@li size: A 1-D int32 Tensor of 2 elements: new_height, new_width. The new size for the images . \n @@ -459,10 +472,11 @@ Defaults to false. *@li half_pixel_centers: An optional bool. Defaults to False . \n *@par Outputs: -*y: 4-D with shape [batch, new_height, new_width, channels] . \n +*y: 4-D with shape [batch, new_height, new_width, channels]. The format +must be NHWC. \n *@attention Constraints: -*Input images can be of different types but output images are always float . \n +*Input images can be of different types but output images are always float . *@par Third-party framework compatibility *Compatible with tensorflow ResizeBicubic operator. @@ -483,7 +497,7 @@ REG_OP(ResizeBicubic) *@par Inputs: *Input grads must be a 4-D tensor. Inputs include: *@li grads: A Tensor. Must be one of the following types: uint8, int8, int32, -float16, float, double. 4-D with shape [batch, height, width, channels]. +float16, float, double. Must set the format, supported format list ["NCHW, NHWC"] *@li size: A 1-D int32 Tensor of 2 elements: orig_height, orig_width. The original input size . \n @@ -550,9 +564,8 @@ REG_OP(ResizeNearestNeighborV2GradD) *@par Inputs: *Input grads must be a 4-D tensor. Inputs include: -*@li grads: A Tensor of type float32. 4-D with shape [batch, height, width, -channels]. -*@li original_image: A Tensor. 4-D with shape [batch, orig_height, orig_width, +*@li grads: A Tensor of type float32. Must set the format, supported format list ["NCHW, NHWC"] +*@li original_image: A Tensor. 4-D shape. Must set the format, supported format list ["NCHW, NHWC"] channels], The image tensor that was resized . \n *@par Attributes: @@ -583,7 +596,7 @@ REG_OP(ResizeBilinearV2Grad) *@par Inputs: *Input images must be a 4-D tensor. Inputs include: -*@li x: 4-D with shape [batch, height, width, channels]. +*@li x: 4-D tensor. Must set the format, supported format list ["NCHW, NHWC"] *@li size: A 1-D int32 Tensor of 2 elements: new_height, new_width. The new size for the images . \n @@ -697,7 +710,7 @@ REG_OP(SampleDistortedBoundingBoxExt2) *@par Inputs: *Input x must be a 4-D tensor. Inputs include: -*@li x: 4-D with shape [batch, height, width, channels]. +*@li x: 4-D tensor. Must set the format, supported format list ["NCHW, NHWC"]. *@li size: A 1-D int32 Tensor of 2 elements: new_height, new_width. The new size for the images . \n @@ -729,12 +742,12 @@ REG_OP(ResizeNearestNeighborV2) *@par Inputs: *Input images must be a 4-D tensor. Inputs include: *@li images: A Tensor. Must be one of the following types: float. 4-D with -shape [batch, height, width, depth]. A batch of images. +shape [batch, height, width, depth]. A batch of images. The format must be NHWC. *@li boxes: A Tensor of type float32. 3-D with shape [batch, num_bounding_boxes, 4] containing bounding boxes . \n *@par Outputs: -*A Tensor. Has the same type as images . \n +*A Tensor. Has the same type as images. The format must be NHWC. \n *@attention Constraints: *Input images must be a 4-D tensor . \n @@ -1342,6 +1355,129 @@ REG_OP(SpatialTransformerD) .ATTR(use_default_theta, ListBool, {}) .OP_END_FACTORY_REG(SpatialTransformerD) -} // namespace ge +/** +* @brief Resize the input tensor. \n +currently, only support resize image tensor using nearest neighbor and linear interpolation. + +* @par Inputs: +* Input x must be a 4-D tensor. Inputs include: \n +* @li x: A Tensor. Must be one of the following types: uint8, int8, int16, \n +int32, int64, float16, float, double. 4-D with shape [batch, height, width, channels] \n +or shape [batch, channels, height, width]. +* @li roi: A 1-D float Tensor. only takes effect when attr coordinate_transformation_mode \n +is "tf_crop_and_resize" +* @li scales: A 1-D float Tensor, the scale array along each dimension, Only one of \n +'scales' and 'sizes' can be specified. +* @li sizes: A 1-D int64 Tensor, The size of the output tensor. nly one of \n +'scales' and 'sizes' can be specified. If 'size' is specified, then set scales \n +to empty data (zero shape) in this operator's input list. + +* @par Attributes: +* @li coordinate_transformation_mode: String. Defaults to half_pixel. how to transform \n +the coordinate in the resized tensor to the coordinate in the original tensor. \n +other optional: pytorch_half_pixel, align_corners, asymmetric, tf_half_pixel_for_nn, \n +tf_crop_and_resize. +* @li cubic_coeff_a: Float. Defaults to -0.75, only used in cubic interpolation. \n +other optional: -0.5 +* @li exclude_outside: Int. Defaults to 0, If set to 1, the weight of sampling \n +locations outside the tensor will be set to 0 and the weight will be renormalized \n +so that their sum is 1.0. +* @li extrapolation_value: Float. Defaults to 0.0f. When coordinate_transformation_mode \n +is "tf_crop_and_resize" and x_original is outside the range [0, length_original - 1], \n +this value is used as the corresponding output value. +* @li mode: String. Defaults to nearest. Three interpolation modes: nearest (default), \n +linear and cubic. +* @li nearest_mode: String. Defaults to round_prefer_floor. Four modes: round_prefer_floor, \n +round_prefer_ceil, floor, ceil. Only used by nearest interpolation. + +* @par Outputs: +* y: A Tensor. Has the same type as x. + +* @attention Constraints: \n +* Input x must be a 4-D tensor. + +* @par Third-party framework compatibility +* Compatible with tensorflow ResizeNearestNeighborV2 operator. +*/ + +REG_OP(Resize) + .INPUT(x, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, DT_INT32, + DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(roi, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(scales, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(sizes, TensorType({DT_INT64})) + .OUTPUT(y, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, DT_INT32, + DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .ATTR(coordinate_transformation_mode, String, "half_pixel") + .ATTR(cubic_coeff_a, Float, -0.75) + .ATTR(exclude_outside, Int, 0) + .ATTR(extrapolation_value, Float, 0) + .ATTR(mode, String, "nearest") + .ATTR(nearest_mode, String, "round_prefer_floor") + .OP_END_FACTORY_REG(Resize) + +/** +*@brief Function parse image from string to int. \n + +*@par Inputs: +*@li contents: A Tensor of type string. 0-D. The JPEG-encoded image. \n +*@par Attributes: +*@li channels: An optional int. Defaults to 0. Number of color channels for the decoded image. +*@li ratio: An optional int. Defaults to 1. Downscaling ratio. +*@li fancy_upscaling: An optional bool. Defaults to True. If true use a slower but nicer upscaling of the chroma planes +*@li try_recover_truncated: An optional bool. Defaults to False. If true try to recover an image from truncated input. +*@li acceptable_fraction: An optional float. Defaults to 1. The minimum required fraction of lines before a truncated input is accepted. +*@li dct_method: An optional string. Defaults to "". string specifying a hint about the algorithm used for decompression. \n + +*@par Outputs: +*image: A Tensor dtype of uint8. +*/ +REG_OP(DecodeJpeg) + .INPUT(contents, TensorType({DT_STRING})) + .OUTPUT(image, TensorType({DT_UINT8})) + .ATTR(channels, Int, 0) + .ATTR(ratio, Int, 1) + .ATTR(fancy_upscaling, Bool, true) + .ATTR(try_recover_truncated, Bool, false) + .ATTR(acceptable_fraction, Float, 1.0) + .ATTR(dct_method, String, "") + .OP_END_FACTORY_REG(DecodeJpeg) + +/** +*@brief Image warping using per-pixel flow vectors. \n + +*@par Inputs: +*@li images: 4-D Tensor with shape `[batch, height, width, channels]`. +*@li flow: 4-D Tensor with shape `[batch, height, width, 2]`. \n + +*@par Outputs: +*y: Returns 4-D with the same shape and dtype as `images`. \n +*/ +REG_OP(DenseImageWarp) + .INPUT(image, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(flow, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .OP_END_FACTORY_REG(DenseImageWarp) + +/** +*@brief Computes the gradients of DenseImageWarp with respect to image and flow. \n + +*@par Inputs: +*@li grad: gradients with respect to DenseImageWarp output. +*@li images: 4-D Tensor with shape `[batch, height, width, channels]`. +*@li flow: 4-D Tensor with shape `[batch, height, width, 2]`. \n + +*@par Outputs: +*grad_image: Returns 4-D with the same shape and dtype as `images`. +*grad_flow: Returns 4-D with the same shape and dtype as `flow`. \n +*/ +REG_OP(DenseImageWarpGrad) + .INPUT(grad, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(image, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(flow, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(grad_image, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(grad_flow, TensorType({DT_FLOAT, DT_FLOAT16})) + .OP_END_FACTORY_REG(DenseImageWarpGrad) +} // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_IMAGE_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/internal_ops.h b/third_party/fwkacllib/inc/ops/internal_ops.h index 9dde14a5..bcc3f1c3 100644 --- a/third_party/fwkacllib/inc/ops/internal_ops.h +++ b/third_party/fwkacllib/inc/ops/internal_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/linalg_ops.h b/third_party/fwkacllib/inc/ops/linalg_ops.h index 7a6fbc59..d8f45c5d 100644 --- a/third_party/fwkacllib/inc/ops/linalg_ops.h +++ b/third_party/fwkacllib/inc/ops/linalg_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/list_ops.h b/third_party/fwkacllib/inc/ops/list_ops.h new file mode 100644 index 00000000..292b1dbe --- /dev/null +++ b/third_party/fwkacllib/inc/ops/list_ops.h @@ -0,0 +1,230 @@ +/** + * Copyright 2019 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. + */ + +/*! + * \file list_ops.h + * \brief + */ +#ifndef OPS_BUILT_IN_OP_PROTO_INC_LIST_OPS_H_ +#define OPS_BUILT_IN_OP_PROTO_INC_LIST_OPS_H_ + +#include +#include "graph/operator_reg.h" +#include "graph/operator.h" + +namespace ge { + +/** +*@brief Creates and returns an empty tensor list. \n + +*@par Inputs: +*@li element_shape: A shape compatible with that of elements in the list. +*@li max_num_elements: The maximum number of elements. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li handle: An empty tensor list . \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow EmptyTensorList operator. +*/ +REG_OP(EmptyTensorList) + .INPUT(element_shape, TensorType({DT_INT32,DT_INT64})) + .INPUT(max_num_elements, TensorType({DT_INT32})) + .OUTPUT(handle, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(EmptyTensorList) + +/** +*@brief Returns a list which has the passed-in `Tensor` as last element +and the other elements of the given list in `input_handle`. \n + +*@par Inputs: +*@li input_handle: The old list. +*@li tensor: The tensor to put on the list. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li output_handle:A list with the elements of old list followed by tensor. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListPushBack operator. +*/ +REG_OP(TensorListPushBack) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(tensor, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL,DT_RESOURCE, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .OUTPUT(output_handle, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListPushBack) + +/** +*@brief The last element of the input list as well as a +list with all but that element. \n + +*@par Inputs: +*@li input_handle: The input list. +*@li element_shape: A shape compatible with that of elements in the list. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li output_handle:A list with the elements of the old list followed by tensor. +*@li tensor:The withdrawn last element of the list. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListPopBack operator. +*/ +REG_OP(TensorListPopBack) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(element_shape, TensorType({DT_INT32})) + .OUTPUT(output_handle, TensorType({DT_VARIANT})) + .OUTPUT(tensor, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL,DT_RESOURCE, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListPopBack) + +/** +*@brief The number of tensors in the input tensor list. \n + +*@par Inputs: +*@li input_handle: The input list. \n + +*@par Outputs: +*@li length:The number of tensors in the list. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListLength operator. +*/ +REG_OP(TensorListLength) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .OUTPUT(length, TensorType({DT_INT32})) + .OP_END_FACTORY_REG(TensorListLength) + +/** +*@brief The shape of elements in the input tensor list. \n + +*@par Inputs: +*@li input_handle: The input list. \n + +*@par Attributes: +*@li shape_type: The type of shape in the list. \n + +*@par Outputs: +*@li element_shape:A shape compatible with that of elements in the list. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListElementShape operator. +*/ +REG_OP(TensorListElementShape) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .OUTPUT(element_shape, TensorType({DT_INT32,DT_INT64})) + .ATTR(shape_type, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListElementShape) + +/** +*@brief List of the given size with empty elements. \n + +*@par Inputs: +*@li element_shape: A shape compatible with that of elements in the list. +*@li num_elements: The number of elements to reserve. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. +*@li shape_type: The type of shape in the list. \n + +*@par Outputs: +*@li handle: An output tensor list . \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListReserve operator. +*/ +REG_OP(TensorListReserve) + .INPUT(element_shape, TensorType({DT_INT32,DT_INT64})) + .INPUT(num_elements, TensorType({DT_INT32})) + .OUTPUT(handle, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .ATTR(shape_type, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListReserve) + +/** +*@brief Get input tensor list elements of index position. \n + +*@par Inputs: +*@li input_handle: The input list. +*@li index: A tensor of position. +*@li element_shape: A shape compatible with that of elements in the list. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li item: An output tensor value of index position . \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListGetItem operator. +*/ +REG_OP(TensorListGetItem) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(index, TensorType({DT_INT32})) + .INPUT(element_shape, TensorType({DT_INT32})) + .OUTPUT(item, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL,DT_RESOURCE, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListGetItem) + +/** +*@brief Sets the index-th position of the list to contain the given tensor. \n + +*@par Inputs: +*@li input_handle: The input list. +*@li index: The position in the list to which the tensor will be assigned. +*@li item: The element to be assigned to that position. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li output_handle: An output tensor list . \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListSetItem operator. +*/ +REG_OP(TensorListSetItem) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(index, TensorType({DT_INT32})) + .INPUT(item, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL,DT_RESOURCE, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .OUTPUT(output_handle, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListSetItem) + +} // namespace ge + +#endif // OPS_BUILT_IN_OP_PROTO_INC_LIST_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/logging_ops.h b/third_party/fwkacllib/inc/ops/logging_ops.h index bc8ae2b8..03be7757 100644 --- a/third_party/fwkacllib/inc/ops/logging_ops.h +++ b/third_party/fwkacllib/inc/ops/logging_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/lookup_ops.h b/third_party/fwkacllib/inc/ops/lookup_ops.h index b37ab048..5d928e5a 100644 --- a/third_party/fwkacllib/inc/ops/lookup_ops.h +++ b/third_party/fwkacllib/inc/ops/lookup_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/math_ops.h b/third_party/fwkacllib/inc/ops/math_ops.h index 149e0e37..4cbcc027 100644 --- a/third_party/fwkacllib/inc/ops/math_ops.h +++ b/third_party/fwkacllib/inc/ops/math_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -365,6 +365,27 @@ REG_OP(GetNext) .ATTR(channel_name, String, "") .OP_END_FACTORY_REG(GetNext) +/** +*@brief Get dynamic dims after GetNext. \n + +*@par Inputs: +*input: A nested structure of Tensor objects, from GetNext's output. \n + +*@par Attributes: +*@li shape_info: GE shape_info for each inputs, -1 means unknow dim. +*@li N: Inputs number. \n + +*@par Outputs: +*dims: GE unknow dims, a vector of int64. \n +*/ + +REG_OP(GetDynamicDims) + .DYNAMIC_INPUT(input, TensorType({DT_INT32, DT_INT64})) + .OUTPUT(dims, TensorType({DT_INT32, DT_INT64})) + .REQUIRED_ATTR(shape_info, ListInt) + .REQUIRED_ATTR(N, Int) + .OP_END_FACTORY_REG(GetDynamicDims) + /** *@brief End of sequence . \n @@ -710,6 +731,9 @@ REG_OP(IFMR) *@par Third-party framework compatibility *Compatible with mindspore + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(WtsARQ) @@ -741,6 +765,9 @@ REG_OP(WtsARQ) *@par Third-party framework compatibility *Compatible with mindspore + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(ActsULQ) @@ -768,6 +795,9 @@ REG_OP(ActsULQ) *@par Third-party framework compatibility *Compatible with mindspore + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(ActsULQInputGrad) @@ -790,6 +820,9 @@ REG_OP(ActsULQInputGrad) *@par Third-party framework compatibility *Compatible with mindspore + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(ActULQClampMaxGrad) @@ -812,6 +845,9 @@ REG_OP(ActULQClampMaxGrad) *@par Third-party framework compatibility *Compatible with mindspore + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(ActULQClampMinGrad) @@ -821,6 +857,33 @@ REG_OP(ActULQClampMinGrad) .OUTPUT(clamp_min_grad, TensorType({DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(ActULQClampMinGrad) +/** +* @brief Computes Lp norm. + +* @par Inputs: +* @li x: An ND tensor of type float16, float32. \n +* +* @par Attributes: +* @li p: Int, "inf" or "-inf", default value is 2. +* @li axes: ListInt, {} means all axes will be computed. +* @li keepdim: Bool, default is false. +* @li epsilon: Float, default is 1e-12. \n + +* @par Outputs: +* @li y: An ND tensor of type float16, float32. The shape of y is depending +* on axes and keepdim. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator LpNorm. +*/ +REG_OP(LpNorm) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(p, Int, 2) + .ATTR(axes, ListInt, {}) + .ATTR(keepdim, Bool, false) + .ATTR(epsilon, Float, 1e-12) + .OP_END_FACTORY_REG(LpNorm) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATH_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index ed23d3f6..33b596d8 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. @@ -38,8 +38,8 @@ namespace ge { * float32, int32. Has format [ND, NHWC] . \n *@par Attributes: -*@li transpose_a: A bool. If True, changes the shape of "x1" from [M, K] to [K, M]. -*@li transpose_b: A bool. If True, changes the shape of "x2" from [M, K] to [K, M] . \n +*@li transpose_x1: A bool. If True, changes the shape of "x1" from [M, K] to [K, M]. +*@li transpose_x2: A bool. If True, changes the shape of "x2" from [M, K] to [K, M] . \n *@par Outputs: *y: The result matrix Tensor. 2D. Must be one of the following types: float16, @@ -70,8 +70,8 @@ REG_OP(MatMul) * float32, int32. Has format [ND, NHWC] . \n *@par Attributes: -*@li transpose_a: A bool. If True, changes the shape of "x1" from [M, K] to [K, M]. -*@li transpose_b: A bool. If True, changes the shape of "x2" from [M, K] to [K, M] . \n +*@li transpose_x1: A bool. If True, changes the shape of "x1" from [M, K] to [K, M]. +*@li transpose_x2: A bool. If True, changes the shape of "x2" from [M, K] to [K, M] . \n *@par Outputs: *y: The result matrix Tensor. 2D. Must be one of the following types: float16, @@ -156,8 +156,8 @@ REG_OP(GEMM) * float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ] . \n *@par Attributes: -*@li adj_x: A bool. If True, changes the shape of "x1" from [B, M, K] to [B, K, M]. -*@li adj_y: A bool. If True, changes the shape of "x2" from [B, M, K] to [B, K, M] . \n +*@li adj_x1: A bool. If True, changes the shape of "x1" from [B, M, K] to [B, K, M]. +*@li adj_x2: A bool. If True, changes the shape of "x2" from [B, M, K] to [B, K, M] . \n *@par Outputs: *y: The result matrix Tensor. 2D or higher. Must be one of the following types: float16, @@ -175,6 +175,41 @@ REG_OP(BatchMatMul) .ATTR(adj_x2, Bool, false) .OP_END_FACTORY_REG(BatchMatMul) + +/** +* @brief Multiplies matrix "a" by matrix "b", producing "a * b" . \n + +* @par Inputs: +* Three inputs, including: +* @li x1: A matrix Tensor. Must be one of the following types: float16, +* float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ]. +* @li x2: A matrix Tensor. Must be one of the following types: float16, +* float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ] . \n +* @li bias: A matrix Tensor. Must be one of the following types: float16, +* float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ] . \n + +* @par Attributes: +* @li adj_x: A bool. If True, changes the shape of "x1" from [B, M, K] to [B, K, M]. +* @li adj_y: A bool. If True, changes the shape of "x2" from [B, M, K] to [B, K, M] . \n + +* @par Outputs: +* y: The result matrix Tensor. 2D or higher. Must be one of the following types: float16, +* float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ]. Has the same shape length as "x1" and "x2" . \n + +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator BatchMatmul. +*/ + +REG_OP(BatchMatMulV2) + .INPUT(x1, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .INPUT(x2, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .ATTR(adj_x1, Bool, false) + .ATTR(adj_x2, Bool, false) + .OP_END_FACTORY_REG(BatchMatMulV2) + + /** *@brief Computes half the L2 norm of a tensor without the sqrt . \n @@ -979,6 +1014,14 @@ REG_OP(MatrixDiagV2) .OUTPUT(output, TensorType::BasicType()) .OP_END_FACTORY_REG(MatrixDiagV2) +REG_OP(IndexAdd) + .INPUT(var, TensorType({DT_INT32, DT_INT8, DT_UINT8, DT_FLOAT32, DT_FLOAT16})) + .INPUT(indices, TensorType({DT_INT32})) + .INPUT(updates, TensorType({DT_INT32, DT_INT8, DT_UINT8, DT_FLOAT32, DT_FLOAT16})) + .OUTPUT(var_out, TensorType({DT_INT32, DT_INT8, DT_UINT8, DT_FLOAT32, DT_FLOAT16})) + .ATTR(axis, Int, 0) + .OP_END_FACTORY_REG(IndexAdd) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATRIX_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h index 0c6a5dff..a35cee03 100644 --- a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h index 35296870..c848668f 100644 --- a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -365,6 +365,25 @@ REG_OP(BiasAddGrad) * 4-D with shape [batch, out_height, out_width, out_channels] * or [batch, out_channels, out_height, out_width]. * Gradients with respect to the output of the convolution. + *\n + *\n + * The following are the supported data types and data formats: +*@verbatim + | Tensor | out_bckprop | filter | y + ------------|-------------|---------|-------- + | Data Type | float16 | float16 | float16 + | |-------------|---------|-------- + | | float32 | float32 | float32 + | |-------------|---------|-------- + | | float64 | float64 | float64 + ------------|-------------|---------|-------- + | Format | NCHW | NCHW | NCHW + | | NHWC | HWCN | NHWC +@endverbatim + * For float32 and float64 type, the actual calculation on the chip is based on + * float16. + *\n + * *@par Attributes: * Five attributes: * @li strides: A tuple/list of 4 integers. The stride of the sliding window @@ -377,8 +396,52 @@ REG_OP(BiasAddGrad) * channels. * @li data_format: An optional string from: "NHWC", "NCHW". Defaults to * "NHWC". Specify the data format of the input and output data. + *\n + *\n + * The following value range restrictions must be met: +*@verbatim + | Name | Field | Scope + -------------------|----------|-------------- + | input_size | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | Filter | H | [1, 255] + | | W | [1, 255] + -------------------|----------|-------------- + | out_backprop | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | y(fmap) | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | Stride | H | [1, 63] + | | W | [1, 63] + -------------------|----------|-------------- + | Padding | Top | [0, 255] + | | Bottom | [0, 255] + | | Left | [0, 255] + | | Right | [0, 255] + -------------------|----------|-------------- + | Dilation | H | [1, 255] + | | W | [1, 255] + +@endverbatim + * In Ascend910, fmap or out_backprop's H and W not support 1 when + * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 + *\n + * *@par Outputs: * y: A Tensor. Has the same type as filter,and has same format as input_size. + *\n + * out_backprop_height = (fmap_height + pad_top + pad_bottom - + * (dilation_h * (filter_height - 1) + 1)) + * / stride_h + 1 + *\n + * out_backprop_width = (fmap_width + pad_left + pad_right - + * (dilation_w * (filter_width - 1) + 1)) + * / stride_w + 1 + *\n + * *@par Third-party framework compatibility * Compatible with Tensorflow's conv2d_backprop_input */ @@ -454,6 +517,21 @@ REG_OP(Conv2DBackpropInputD) * @li bias: An optional tensor. Must have the same type as "y". * @li offset_w: An optional 1D tensor for quantized deconvolution. * Type is int8. Reserved.\n + *\n + *\n + * The following are the supported data types and data formats: +*@verbatim + | Tensor | x | filter | bias | y + ------------|---------|---------|---------|-------- + | Data Type | float16 | float16 | float16 | float16 + | |---------|---------|---------|-------- + | | int8 | int8 | int32 | int32 + ------------|---------|---------|---------|-------- + | Format | NCHW | NCHW | ND | NCHW +@endverbatim + * For int8, a dequant or requant operator must be followed. + *\n + * *@par Attributes: * Six attributes: * @li strides: A tuple or list of 2 integers. The stride of the sliding window @@ -468,8 +546,51 @@ REG_OP(Conv2DBackpropInputD) Specify the data format of the input and output data. * @li offset_x: An optional integer for quantized deconvolution. * Defaults to "0". + *\n + *\n + * The following value range restrictions must be met: +*@verbatim + | Name | Field | Scope + -------------------|----------|-------------- + | x (out_backprop) | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | Filter | H | [1, 255] + | | W | [1, 255] + -------------------|----------|-------------- + | y (fmap) | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | Stride | H | [1, 63] + | | W | [1, 63] + -------------------|----------|-------------- + | Padding | Top | [0, 255] + | | Bottom | [0, 255] + | | Left | [0, 255] + | | Right | [0, 255] + -------------------|----------|-------------- + | Dilation | H | [1, 255] + | | W | [1, 255] + -------------------|----------|-------------- + | Offset_x | | [-128, 127] + +@endverbatim + * In Ascend910, fmap or out_backprop's H and W not support 1 when + * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 + *\n + * *@par Outputs: * y: A Tensor. 4D tensor with shape [batch, channels, height, width]. + *\n + * out_backprop_height = (fmap_height + pad_top + pad_bottom - + * (dilation_h * (filter_height - 1) + 1)) + * / stride_h + 1 + *\n + * out_backprop_width = (fmap_width + pad_left + pad_right - + * (dilation_w * (filter_width - 1) + 1)) + * / stride_w + 1 + *\n + * * When type of x is float16, the type of y must be float16. * When type of x is int8, the type of y must be int32. */ @@ -502,6 +623,25 @@ REG_OP(Deconvolution) * [batch, out_height, out_width, out_channels] or [batch, out_channels, * out_height, out_width]. Gradients with respect to the output of the * convolution. + *\n + *\n + * The following are the supported data types and data formats: +*@verbatim + | Tensor | x | out_backprop | y + ------------|---------|--------------|--------- + | Data Type | float16 | float16 | float16 + | |---------|--------------|--------- + | | float32 | float32 | float32 + | |---------|--------------|--------- + | | float64 | float64 | float64 + |-----------|---------|--------------|--------- + | Format | NCHW | NCHW | NCHW + | | NHWC | NHWC | HWCN +@endverbatim + * For float32 and float64 type of x and outbackprop, the actual calculation on the chip + * is based on float16. + *\n + * *@par Attributes: * Five attributes: * @li strides: A tuple/list of 4 integers. The stride of the sliding window @@ -514,8 +654,52 @@ REG_OP(Deconvolution) * channels. * @li data_format: An optional string from: "NHWC", "NCHW". Defaults to * "NHWC". Specify the data format of the input and output data. + *\n +*\n +* The following value range restrictions must be met: +*@verbatim + | Name | Field | Scope + -------------------|----------|-------------- + | x(fmap) | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | Filter Size | H | [1, 255] + | | W | [1, 255] + -------------------|----------|-------------- + | out_backprop | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | y | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | Stride | H | [1, 63] + | | W | [1, 63] + -------------------|----------|-------------- + | Padding | Top | [0, 255] + | | Bottom | [0, 255] + | | Left | [0, 255] + | | Right | [0, 255] + -------------------|----------|-------------- + | Dilation | H | [1, 255] + | | W | [1, 255] + +@endverbatim + * In Ascend910, out_backprop's H and W not support 1 when + * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 + *\n + * *@par Outputs: * y: A Tensor. Has the same type as x, has the same format as filter_size. + *\n + * out_backprop_height = (in_height + pad_top + pad_bottom - + * (dilation_h * (filter_height - 1) + 1)) + * / stride_h + 1 + *\n + * out_backprop_width = (in_width + pad_left + pad_right - + * (dilation_w * (filter_width - 1) + 1)) + * / stride_w + 1 + *\n + * *@par Third-party framework compatibility * Compatible with Tensorflow's conv2d_backprop_filter */ @@ -617,8 +801,7 @@ REG_OP(Conv2DBackpropFilterD) * (top, bottom, left, right) side of the input. *@li dilations: Optional. A list of 4 integers. The dilation factor for each * dimension of input. The dimension order is determined by the data format of -* "x". The N and C dimensions must be set to 1. The H and W dimensions must be -* set to 1 for int8 type. Defaults to [1, 1, 1, 1]. +* "x". The N and C dimensions must be set to 1. Defaults to [1, 1, 1, 1]. *@li groups: Optional. An integer of type int32. The number of blocked * connections from input channels to output channels. In_channels and * out_channels must both be divisible by "groups". Defaults to 1. @@ -652,6 +835,8 @@ REG_OP(Conv2DBackpropFilterD) | Offset_x | | [-128, 127] @endverbatim +* The W dimension of the input image supports cases exceeding 4096, but it may +* cause compilation errors. *\n * *@par Outputs: @@ -666,21 +851,6 @@ REG_OP(Conv2DBackpropFilterD) * out_width = (in_width + pad_left + pad_right - * (dilation_w * (filter_width - 1) + 1)) * / stride_w + 1 -* -*@attention Constraints: -*@li The following restrictions on the output must be met: -*@verbatim - | Output | Restrictions - ----------|-------------------------------- - | H == 1 | H * W(input) == H * W(filter) - | W == 1 | - ----------|-------------------------------- - | H != 1 | W(input) == W(filter) - | W == 1 | Only for Ascend310 Hi3796V300CS -@endverbatim -* "H * W (input)" indicates the image size after padding and "H * W (filter)" -* indicates the filter size after dilation."W(input)" and W(filter) indicate -* the same rule on the W dimension. *\n * *@par Quantization supported or not @@ -778,7 +948,7 @@ REG_OP(Conv2DCompress) * With the format "HWCN" , the data is stored in the order of: [filter_height, * filter_width, in_channels / groups, out_channels]. *@li offsets: A 4D tensor of x-y coordinates offset and mask. With the format -* "NHWC", the data is stored in the order of: [batch, in_height, in_width, +* "NHWC", the data is stored in the order of: [batch, out_height, out_width, * deformable_groups * filter_height * filter_width * 3]. *@li bias: An optional 1D tensor of additive biases to the filter outputs. * The data is stored in the order of: [out_channels]. @@ -822,25 +992,12 @@ REG_OP(Conv2DCompress) *@verbatim | Name | Field | Scope --------------------|--------|---------------------------- - | Input Image Size | H | [1, 100000] - | | W | [1, 4096] + | Input Image Size | H | [1, 100000 / filter_height] + | | W | [1, 4096 / filter_width] --------------------|--------|---------------------------- - | Filter Size | H | [1, 255] - | | W | [1, 255] - --------------------|--------|---------------------------- - | Stride | H | [1, 63] + | Filter Size | H | [1, 63] | | W | [1, 63] - --------------------|--------|---------------------------- - | Padding | Top | [0, 255] - | | Bottom | [0, 255] - | | Left | [0, 255] - | | Right | [0, 255] - ------------ -------|--------|---------------------------- - | Dilation | H | [1, 255] - | | W | [1, 255] @endverbatim -* "W(input)" indicate the image width after padding and W(filter) indicates the -* filter width after dilation. *\n * *@par Outputs: @@ -855,21 +1012,7 @@ REG_OP(Conv2DCompress) * out_width = (in_width + pad_left + pad_right - * (dilation_w * (filter_width - 1) + 1)) * / stride_w + 1 -* -*@attention Constraints: -*@li The following restrictions on the output must be met: -*@verbatim - | Output | Restrictions - ----------|-------------------------------- - | H == 1 | H * W(input) == H * W(filter) - | W == 1 | - ----------|-------------------------------- - | H != 1 | W(input) == W(filter) - | W == 1 | Only for Ascend310 Hi3796V300CS -@endverbatim -* "H * W(input)" indicates the image size after padding and "H * W(filter)" -* indicates the filter size after dilation. "W(input)" and W(filter) indicate -* the same rule on the W dimension. +*\n * *@par Quantization supported or not *@li No @@ -920,8 +1063,8 @@ REG_OP(DeformableConv2D) * @li data_format: An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. * @li dilations: A list of 5 integers. Specifies the dilation factor for each - * dimension of "x", now only support [1,1,1,1,1] - * The N and C dimensions must be 1. Has the same format as "x". + * dimension of "x". + * The N, C and D dimensions must be 1. Has the same format as "x". * @li offset_x: An optional int. Input offset, used for quantized inference. * Defaults to 0. Reserved . \n @@ -967,8 +1110,8 @@ REG_OP(Conv3D) *@par Required Attributes: * @li strides: A list of 5 integers. Specifies the stride of the sliding window - * for each dimension of "x". - * The N and C dimensions must be 1. Has the same format as "x". + * for each dimension of "out_backprop". + * The N and C dimensions must be 1. Has the same format as "out_backprop". * @li pads: A list of 6 integers. * Supports only padding along the D, H and W dimensions in sequence of head, * tail, top, bottom, left and right . \n @@ -980,10 +1123,11 @@ REG_OP(Conv3D) * @li data_format: An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. * @li dilations: A tuple/list of 5 integers, The dilation factor for each - * dimension of the input, now only support [1,1,1,1,1] + * dimension of the input. + * The N, C and D dimensions must be 1. Has the same format as "out_backprop". *@par Outputs: - * y: A Tensor. Has the same type as filter,and has same format as input_size + * y: A Tensor. Has the same type as filter,and has same format as "input_size" *@par Third-party framework compatibility * Compatible with Tensorflow's conv3d_backprop_input @@ -1011,8 +1155,8 @@ REG_OP(Conv3DBackpropInput) *@par Required Attributes: * @li strides: A list of 5 integers. Specifies the stride of the sliding window - * for each dimension of "x". - * The N and C dimensions must be 1. Has the same format as "x". + * for each dimension of "out_backprop". + * The N and C dimensions must be 1. Has the same format as "out_backprop". * @li pads: A list of 6 integers. Supports only padding along the D, H and W * dimensions in sequence of head, tail, top, bottom, left and right. * @li input_size: A tuple/list of type int32, int64. An integer vector @@ -1027,9 +1171,10 @@ REG_OP(Conv3DBackpropInput) * @li data_format: An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. * @li dilations: A tuple/list of 5 integers, The dilation factor for each - * dimension of input, now only support [1,1,1,1,1] + * dimension of input. + * The N, C and D dimensions must be 1. Has the same format as "out_backprop". *@par Outputs: - * y: A Tensor. Has the same type and data format as out_backprop. + * y: A Tensor. Has the same type and data format as "out_backprop". *@par Third-party framework compatibility * Compatible with Tensorflow's conv3d_backprop_input @@ -1072,9 +1217,7 @@ REG_OP(Conv3DBackpropInputD) * @li c_t: A optinal Tensor dtype of float16, float32. The cell state at time t . \n *@par Third-party framework compatibility: -* Compatible with the Pytorch operator adds. -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* Compatible with the Caffe operator LSTM. */ REG_OP(LSTM) .INPUT(x, TensorType({DT_FLOAT16})) @@ -1121,14 +1264,15 @@ REG_OP(LSTM) *@par Attributes: * Three attributes: * @li dilations: A tuple/list of 5 integers, The dilation factor for each - * dimension of input, now only support [1,1,1,1,1]. + * dimension of input. + * The N, C and D dimensions must be 1. Has the same format as "x". * @li groups: Number of blocked connections from input channels to output * channels. Reserved. * @li data_format: An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. *@par Outputs: - * y: A Tensor that has the same type as x + * y: A Tensor that has the same type as "x" * and the format is NDHWC, NCDHW or DHWCN. *@par Third-party framework compatibility * Compatible with Tensorflow's conv3d_backprop_filter @@ -1172,7 +1316,8 @@ REG_OP(Conv3DBackpropFilter) *@par Attributes: * Three attributes: * @li dilations: A tuple/list of 5 integers, The dilation factor for each - * dimension of input, now only support [1,1,1,1,1]. + * dimension of input. + * The N, C and D dimensions must be 1. Has the same format as "x". * @li groups: Number of blocked connections from input channels to output * channels. Reserved. * @li data_format: An optional string from: "NDHWC", "NCDHW". @@ -1226,13 +1371,14 @@ REG_OP(Conv3DBackpropFilterD) * @li groups: Number of blocked connections from input channels to output * channels. Reserved. * @li dilations: A tuple/list of 5 integers, - * The dilation factor for each dimension of input, now only support [1,1,1,1,1] + * The dilation factor for each dimension of input. + * The N, C and D dimensions must be 1. Has the same format as "x". * @li data_format: An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. * @li output_padding: The size will be added in the output shape. * @li offset_x: Input offset_x value. Reserved. *@par Outputs: - * y: A Tensor. Has the same type and format as x. + * y: A Tensor. Has the same type and format as "x". */ REG_OP(Conv3DTranspose) .INPUT(input_size, TensorType({DT_INT32, DT_INT64})) @@ -1273,7 +1419,8 @@ REG_OP(Conv3DTranspose) *@par Attributes: * Five attributes: * @li dilations: A tuple/list of 5 integers, The dilation factor for each - * dimension of input, now only support [1,1,1,1,1] + * dimension of input. + * The N, C and D dimensions must be 1. Has the same format as "x". * @li groups: Number of blocked connections from input channels to output * channels. Reserved. * @li data_format: An optional string from: "NDHWC", "NCDHW". @@ -1281,7 +1428,7 @@ REG_OP(Conv3DTranspose) * @li output_padding: The size will be added in the output shape. * @li offset_x: Input offset_x value. Reserved. *@par Outputs: - * y: A Tensor. Has the same type and format as x. + * y: A Tensor. Has the same type and format as "x". *@par Restrictions: * Warning: THIS FUNCTION IS DEPRECATED. Please use Conv3DTranspose instead. */ @@ -1316,6 +1463,22 @@ REG_OP(Conv3DTransposeD) * or [out_channels, in_channel, filter_height, filter_width]. * @li bias: An optional 1D tensor of type float16 or int32. Format is "ND". * @li offset_w: An optional 1D tensor for quantized inference. Reserved. + *\n + *\n + * The following are the supported data types and data formats: +*@verbatim + | Tensor | x | filter | bias | y + ------------|---------|---------|---------|-------- + | Data Type | float16 | float16 | float16 | float16 + | |---------|---------|---------|-------- + | | int8 | int8 | int32 | int32 + ------------|---------|---------|---------|-------- + | Format | NCHW | NCHW | ND | NCHW + | | NHWC | HWCN | | NHWC +@endverbatim + * For int8, a dequant or requant operator must be followed. + *\n + * *@par Required Attributes: * @li strides: A required tuple/list of 4 integers. The stride of the sliding * window for H/W dimension. The index of H/W is same as data_format. @@ -1334,9 +1497,55 @@ REG_OP(Conv3DTransposeD) * to [0, 0, 0, 0]. * @li offset_x: An optional int. Input offset, used for quantized inference. * Defaults to "0". + *\n + *\n + * The following value range restrictions must be met: +*@verbatim + | Name | Field | Scope + -------------------|----------|-------------- + | input_size | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | x (out_backprop) | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | filter | H | [1, 255] + | | W | [1, 255] + -------------------|----------|-------------- + | y (fmap) | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | Stride | H | [1, 63] + | | W | [1, 63] + -------------------|----------|-------------- + | Padding | Top | [0, 255] + | | Bottom | [0, 255] + | | Left | [0, 255] + | | Right | [0, 255] + -------------------|----------|-------------- + | Dilation | H | [1, 255] + | | W | [1, 255] + -------------------|----------|-------------- + | Offset_x | | [-128, 127] + +@endverbatim + * In Ascend910, fmap or out_backprop's H and W not support 1 when + * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 + *\n + * *@par Outputs: * y: A Tensor. A Tensor of type float16 or int32, and has same format as * input_size. + *\n + * out_backprop_height = (fmap_height + pad_top + pad_bottom - + * (dilation_h * (filter_height - 1) + 1)) + * / stride_h + 1 + *\n + * out_backprop_width = (fmap_width + pad_left + pad_right - + * (dilation_w * (filter_width - 1) + 1)) + * / stride_w + 1 + *\n + * */ REG_OP(Conv2DTranspose) .INPUT(input_size, TensorType({DT_INT32, DT_INT64})) @@ -1405,13 +1614,13 @@ REG_OP(Conv2DTransposeD) /** *@brief Computes the deformed convolution output with the expected input *@par Inputs: - * Four inputs: + * Two inputs: * @li x: A Tensor of type float16,float32 * @li offsets: A Tensor of type float16,float32.Deformation offset parameter. *@par Required Attributes: * @li strides: A tuple/list of 4 integers.The stride of the sliding window for * height and width for H/W dimension. - * @li pads: A tuple/list of 4 integers.Padding added to each dimension + * @li pads: A tuple/list of 4 integers.Padding added to H/W dimension * of the input. * @li ksize: A tuple/list of 2 integers.kernel size. *@par Attributes: @@ -1420,6 +1629,7 @@ REG_OP(Conv2DTransposeD) * of input. Defaults to [1, 1, 1, 1] * @li data_format: An optional string from: "NCHW", "NHWC". Defaults to "NCHW". Specify the data format of the input x. * @li deformable_groups: Specify the c-axis grouping number of input x. + * @li modulated: Specify version of DeformableConv2D, true means v2, false means v1 *@par Outputs: * y: A Tensor. A Tensor of type float16, float32. */ @@ -1433,7 +1643,69 @@ REG_OP(DeformableOffsets) .ATTR(dilations, ListInt, {1, 1, 1, 1}) .ATTR(data_format, String, "NCHW") .ATTR(deformable_groups, Int, 1) + .ATTR(modulated, Bool, true) .OP_END_FACTORY_REG(DeformableOffsets) +/** +*@brief Computes the gradients of DeformableOffsets with respect to input and offsets +*@par Inputs: + * Three inputs: + * @li grad: A Tensor of type float16,float32. gradients with respect to DeformableOffsets output + * @li x: A Tensor of type float16,float32. + * @li offsets: A Tensor of type float16,float32.Deformation offset parameter. +*@par Required Attributes: + * @li strides: A tuple/list of 4 integers.The stride of the sliding window for + * height and width for H/W dimension. + * @li pads: A tuple/list of 4 integers.Padding added to H/W dimension + * of the input. + * @li ksize: A tuple/list of 2 integers.kernel size. +*@par Attributes: + * Three attributes: + * @li dilations: A tuple/list of 4 integers, The dilation factor for each dimension + * of input. Defaults to [1, 1, 1, 1] + * @li data_format: An optional string from: "NCHW", "NHWC". Defaults to "NCHW". Specify the data format of the input x. + * @li deformable_groups: Specify the c-axis grouping number of input x. + * @li modulated: Specify version of DeformableConv2D, true means v2, false means v1. +*@par Outputs: + * grad_x: A Tensor of type float16, float32. Gradients with respect to input_x + * grad_offsets: A Tensor of type float16, float32. Gradients with respect to input_offsets +*/ +REG_OP(DeformableOffsetsGrad) + .INPUT(grad, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(offsets, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(grad_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(grad_offsets, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(pads, ListInt) + .REQUIRED_ATTR(ksize, ListInt) + .ATTR(dilations, ListInt, {1, 1, 1, 1}) + .ATTR(data_format, String, "NCHW") + .ATTR(deformable_groups, Int, 1) + .ATTR(modulated, Bool, true) + .OP_END_FACTORY_REG(DeformableOffsetsGrad) + +/** +*@brief Computes the deformed dilation output with the expected input +*@par Inputs: + * One inputs: + * @li x: A Tensor of type int8, float16, float32 +*@par Required Attributes: + * @li dilations: A tuple/list of integers. +*@par Attributes: + * Two attributes: + * @li padding_value: default value filling in blank + * @li pads: A tuple/list of integers. +*@par Outputs: + * y: A Tensor. A Tensor of type int8, float16, float32. +*/ +REG_OP(Dilation) + .INPUT(x, TensorType({DT_INT8, DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_INT8, DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(dilations, ListInt) + .ATTR(pads, ListInt, {}) + .ATTR(padding_value, Float, 0.0) + .OP_END_FACTORY_REG(Dilation) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_detect_ops.h b/third_party/fwkacllib/inc/ops/nn_detect_ops.h index a013fb33..39b4b227 100644 --- a/third_party/fwkacllib/inc/ops/nn_detect_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_detect_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -1383,6 +1383,7 @@ REG_OP(DecodeWheelsTarget) *@attention Constraints: * Only computation of float16 data is supported. +* Note: when the class num per image * max_size_per_class is too big, will compile fail with ERROR-insufficient memory */ REG_OP(BatchMultiClassNonMaxSuppression) .INPUT(boxes, TensorType({DT_FLOAT16})) @@ -1485,7 +1486,10 @@ REG_OP(DecodeBboxV2) * *@par Outputs: * @li y1: A Tensor. Must have the same type as x. -* @li y2: A Tensor. Indices of y1 in x.Dtype must be int32. +* @li y2: A Tensor. Indices of y1 in x. Dtype must be int32. +* +*@attention Constraints: +* The upper limit of data on the direction axis is 7040. */ REG_OP(Sort) .INPUT(x, TensorType({ DT_FLOAT16 })) @@ -1495,6 +1499,111 @@ REG_OP(Sort) .ATTR(descending, Bool, false) .OP_END_FACTORY_REG(Sort) +REG_OP(PtIou) + .INPUT(bboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(gtboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(overlap, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(mode, String, "iou") + .OP_END_FACTORY_REG(PtIou) + +/** +*@brief Greedily selects a subset of bounding boxes in descending order of +score . \n + +*@par Inputs: +*Input boxes and scores must be float16 type. Inputs include: +*@li boxes: A input tensor with shape [num_batches,spatial_dimension,4]. +The single box data format is indicated by center_point_box. +*@li scores: A input tensor with shape [num_batches,num_classes,spatial_dimension] +*@li max_output_size: A scalar integer tensor representing the maximum number +of boxes to be selected by non max suppression. +*@li iou_threshold: A 0-D float tensor representing the threshold for deciding +whether boxes overlap too much with respect to IOU. +*@li score_threshold: A 0-D float tensor representing the threshold for +deciding when to remove boxes based on score . \n + +*@par Attributes: +*center_point_box:Integer indicate the format of the box data. +The default is 0. 0 - the box data is supplied as [y1, x1, y2, x2] +where (y1, x1) and (y2, x2) are the coordinates of any diagonal pair +of box corners and the coordinates can be provided as normalized +(i.e., lying in the interval [0, 1]) or absolute.Mostly used for TF models. +1 - the box data is supplied as [x_center, y_center, width, height]. + Mostly used for Pytorch models. \n + +*@par Outputs: +*@li selected_indices: A 2-D integer tensor of shape [M] representing the +selected indices from the boxes tensor, where M <= max_output_size. \n + +*@attention Constraints: +*Input boxes and scores must be float16 type . \n + +*@par Third-party framework compatibility +*Compatible with onnx NonMaxSuppression operator. +*/ + +REG_OP(NonMaxSuppressionV6) + .INPUT(boxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(scores, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(max_output_size, TensorType({DT_INT32})) + .OPTIONAL_INPUT(iou_threshold, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(score_threshold, TensorType({DT_FLOAT})) + .OUTPUT(selected_indices, TensorType({DT_INT32})) + .ATTR(center_point_box, Int, 0) + .ATTR(max_boxes_size, Int, 0) + .OP_END_FACTORY_REG(NonMaxSuppressionV6) + +/** +*@brief Greedily selects a subset of bounding boxes in descending order of +score . \n + +*@par Inputs: +*Input boxes and scores must be float16 type. Inputs include: +*@li boxes: A input tensor with shape [num_batches,spatial_dimension,4]. +The single box data format is indicated by center_point_box. +*@li scores: A input tensor with shape [num_batches,num_classes,spatial_dimension] +*@li max_output_size: A scalar integer tensor representing the maximum number +of boxes to be selected by non max suppression. +*@li iou_threshold: A 0-D float tensor representing the threshold for deciding +whether boxes overlap too much with respect to IOU. +*@li score_threshold: A 0-D float tensor representing the threshold for +deciding when to remove boxes based on score . \n +*@li index_id: A input tensor with shape [num_batches,num_classes,spatial_dimension,3] +the last dim representing (batch_id,class_id,index_id) . \n + +*@par Attributes: +*center_point_box:Integer indicate the format of the box data. +The default is 0. 0 - the box data is supplied as [y1, x1, y2, x2] +where (y1, x1) and (y2, x2) are the coordinates of any diagonal pair +of box corners and the coordinates can be provided as normalized +(i.e., lying in the interval [0, 1]) or absolute.Mostly used for TF models. +1 - the box data is supplied as [x_center, y_center, width, height]. + Mostly used for Pytorch models. \n + +*@par Outputs: +*@li selected_indices: A 2-D integer tensor of shape [M] representing the +selected indices from the boxes tensor, where M <= max_output_size. \n + +*@attention Constraints: +*Input boxes and scores must be float16 type . \n + +*@par Third-party framework compatibility +*Compatible with onnx NonMaxSuppression operator. +*/ + + +REG_OP(NonMaxSuppressionV7) + .INPUT(boxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(scores, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(max_output_size, TensorType({DT_INT32})) + .OPTIONAL_INPUT(iou_threshold, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(score_threshold, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(index_id, TensorType({DT_FLOAT16})) + .OUTPUT(selected_indices, TensorType({DT_INT32})) + .ATTR(center_point_box, Int, 0) + .ATTR(max_boxes_size, Int, 0) + .OP_END_FACTORY_REG(NonMaxSuppressionV7) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_DETECT_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index 35c4c7d4..af223552 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -160,20 +160,20 @@ REG_OP(SigmoidCrossEntropyWithLogits) .OP_END_FACTORY_REG(SigmoidCrossEntropyWithLogits) /** -*@brief Computes the sigmoid cross entropy loss of "predict" and "target" . \n +*@brief Computes the sigmoid cross entropy loss of "predict" and "target". *@par Inputs: * four inputs, including: *@li predict: A multi-dimensional Tensor of type float16 or float32, specifying the predictive value. -*@li target: A multi-dimensional Tensor of type float16 or float32, specifying the target value . \n -*@li weight: An multi-dimensional Tensor, specifying the weight value. \n +*@li target: A multi-dimensional Tensor of type float16 or float32, specifying the target value. +*@li weight: An multi-dimensional Tensor, specifying the weight value. *@li pos_weight: An multi-dimensional Tensor, specifying the pos weight value. \n *@par Attributes: -*reduction: A character string from "none", "mean", and "sum", specifying the reduction type to be applied to the output. Defaults to "mean" . \n +*reduction: A character string from "none", "mean", and "sum", specifying the reduction type to be applied to the output. Defaults to "mean". \n *@par Outputs: -*loss: Sigmoid cross entropy between the predictive value and target value. Has the same dimensions as "predict" . \n +*loss: Sigmoid cross entropy between the predictive value and target value. Has the same dimensions as "predict". \n *@par Third-party framework compatibility * Compatible with PyTorch operator BCEWithLogitsLoss. @@ -978,6 +978,261 @@ REG_OP(InHost) .OUTPUT(variance_sqrt, TensorType({DT_FLOAT})) .ATTR(epsilon, Float, 0.00001) .OP_END_FACTORY_REG(InHost) + +/** +* @brief perform instance normalization to x. \n + +* @par Inputs: +* Three inputs, including: +* @li x: A Tensor. Must be one of the following types: float16, float32, format is NC1HWC0. +* @li gamma: A Tensor. Must be one of the following types: float16, float32, format is ND. +* @li beta: A Tensor. Must be one of the following types: float16, float32, format is ND. + +* @par Attributes: +* @li data_format: An attribute of type String \n +* @li epsilon: An attribute of type Float, . \n + +* @par Outputs: +* @li y: A Tensor. Has the same type as "x", format is NC1HWC0. \n +* @li mean: A Tensor. Has the same type as "x", format is NC1HWC0 and the shape is [N, C1, 1, 1, C0]. \n +* @li variance: A Tensor. Has the same type as "x", format is NC1HWC0 and the shape is [N, C1, 1, 1, C0]. \n + +* @par Third-party framework compatibility +* Can be used by onnx InstanceNormalization +*/ +REG_OP(InstanceNorm) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(gamma, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(beta, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(mean, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(variance, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(data_format, String) + .REQUIRED_ATTR(epsilon, Float) + .OP_END_FACTORY_REG(InstanceNorm) + +REG_OP(KlDivLossGrad) + .INPUT(grad, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(input, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(target, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(reduction, String, "mean") + .ATTR(log_target, Bool, false) + .OP_END_FACTORY_REG(KlDivLossGrad) + +/** +* @brief Computes l1_loss_grad or l1_loss_backward. \n + +* @par Inputs: +* Three inputs, including: +* @li grads: A Tensor. Must be one of the following types: float16, float32. +* Required. +* @li predict: A Tensor. Has the same type as "grads". Required. +* @li label: A Tensor. Has the same type as "grads". Required. \n + +* @par Attributes: +* @li reduction: An optional attribute of type String. Defaults to "mean". \n + +* @par Outputs: +* @li y: A Tensor. Has the same type as "x". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator L1LossGrad. +*/ +REG_OP(L1LossGrad) + .INPUT(grads, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(predict, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(label, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(L1LossGrad) + +/** +* @brief Computes loss of lp, p=1,2,3.... + +* @par Inputs: +* @li predict: An ND tensor of type float16, float32. +* @li label: An ND tensor of type float16, float32. \n + +* @par Attributes: +* @li p: A required int attribute that decides which loss to compute, now the p only can be 1 to compute l1_loss. +* @li reduction: An optional string.Defaults to "mean". \n + +* @par Outputs: +* @li y: An ND tensor tensor with the same shape and type as "predict". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator LpLoss. +*/ +REG_OP(LpLoss) + .INPUT(predict, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(label, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(p, Int) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(LpLoss) + +/** +* @brief Computes gradients of mse loss. + +* @par Inputs: +* @li predict: An ND tensor of type float16, float32. +* @li label: An ND tensor of type float16, float32. +* @li dout: An ND tensor of type float16, float32. \n + +* @par Attributes: +* @li reduction: An optional string.Defaults to "mean". \n + +* @par Outputs: +* @li y: An ND tensor tensor with the same shape and type as "predict". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator MseLossGrad. +*/ +REG_OP(MseLossGrad) + .INPUT(predict, TensorType({DT_FLOAT32, DT_FLOAT16})) + .INPUT(label, TensorType({DT_FLOAT32, DT_FLOAT16})) + .INPUT(dout, TensorType({DT_FLOAT32, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT32, DT_FLOAT16})) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(MseLossGrad) + +/** +* @brief Computes mse loss. +* @par Inputs: +* two inputs, including: +* @li predict: An ND Tensor of dtype float16 or float32. +* @li label: An ND Tensor of dtype float16 or float32.\n +* +* @par Attributes: +* @li reduction:An optional str from sum, none, mean, Defaults to "mean".\n +* +* @par Outputs: +* @li y: when reduction=sum/mean, y is scale. when reduction=none, y has +* same type and shape as "predict".\n +*/ +REG_OP(MseLoss) + .INPUT(predict, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(label, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(MseLoss) + +/** +* @brief Calculates the reversed outputs of the function "smooth_l1_loss_v2". \n + +* @par Inputs: +* Three Inputs, including: +* @li predict: A Tensor. Must be one of the following types: +* float16, float32. +* @li label: A Tensor. Has the same type as "predict". +* @li dout: A Tensor. Has the same type as "predict". \n + +* @par Attributes: +* Two Attributes, including: +* @li sigma: An optional float. Defaults to 1.0. \n + +* @li reduction: An optional string. Defaults to "mean", +* Must be one of the following: "none", "mean", "sum". \n + +* @par Outputs: +* @li gradient: A Tensor. Has the same type as "predict". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator SmoothL1LossBackward. +*/ +REG_OP(SmoothL1LossGradV2) + .INPUT(predict, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(label, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(dout, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(gradient, TensorType({DT_FLOAT, DT_FLOAT16})) + .ATTR(sigma, Float, 1.0) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(SmoothL1LossGradV2) + +/** +* @brief Creates a criterion that uses a squared term if the absolute +* element-wise error falls below beta and an L1 term otherwise. It is +* less sensitive to outliers than the MSELoss and in some cases prevents +* exploding gradients. + +* @par Inputs: +* @li predict: A multi-dimensional Tensor of type float16 or float32, +* specifying the predictive value. \n +* @li label: A multi-dimensional Tensor of type float16 or float32, +* specifying the target value. \n + +* @par Attributes: +* @li sigma: An optional int. Specifies the threshold of loss. Defaults +* to "1.0". \n +* @li reduction: An optional str. Specifies the reduction to apply to +* the output: 'none' | 'mean' | 'sum'. 'none': no reduction will be applied, +* 'mean': the sum of the output will be divided by the number of elements in +* the output,'sum': the output will be summed. Default: 'mean'. \n + +* @par Outputs: +* @li loss: Indicates the loss between the predictive value and target value. +* Has the same dimensions as "predict". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator smooth_l1_loss. \n +*/ +REG_OP(SmoothL1LossV2) + .INPUT(predict, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(label, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .OUTPUT(loss, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .ATTR(sigma, Float, 1.0) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(SmoothL1LossV2) + +/** +* @brief Computes Centralization. result = x - mean(x, axes) + +* @par Inputs: +* @li x: An ND tensor of type float16, float32. +* @par Attributes: +* @li axes: The dimensions to reduce. Must be one of the following types: int, list, tuple, NoneType. +* Must be in the range [-rank(x), rank(x)). +* @par Outputs: +* @li y: A Tensor. Has the same type as "x". \n + +* @par Third-party framework compatibility +* custom operator \n +*/ +REG_OP(Centralization) + .INPUT(x, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .OUTPUT(y, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .ATTR(axes, ListInt, {-1}) + .OP_END_FACTORY_REG(Centralization) + +/** +* @brief Computes gradients of sigmoid_cross_entropy_with_logits_v2. + +* @par Inputs: +* @li predict: An ND tensor of type float16, float32. +* @li target: An ND tensor of type float16, float32. +* @li dout: An ND tensor of type float16, float32. +* @li weight: An optional ND tensor of type float16, float32. +* @li pos_weight: An optional ND tensor of type float16, float32. \n + +* @par Attributes: +* @li reduction: An optional string.Defaults to "mean". \n + +* @par Outputs: +* @li gradient: An ND tensor tensor with the same shape and type as "predict". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator SigmoidCrossEntropyWithLogitsGrad. +*/ +REG_OP(SigmoidCrossEntropyWithLogitsGradV2) + .INPUT(predict, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(target, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(dout, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(weight, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(pos_weight, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(gradient, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(SigmoidCrossEntropyWithLogitsGradV2) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_NORM_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_ops.h b/third_party/fwkacllib/inc/ops/nn_ops.h index 9edc469a..16552eee 100644 --- a/third_party/fwkacllib/inc/ops/nn_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h index ab35ba47..9f191ebe 100644 --- a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -182,6 +182,125 @@ REG_OP(AvgPool3D) .ATTR(data_format, String, "NDHWC") .OP_END_FACTORY_REG(AvgPool3D) + +/** +*@brief Performs average pooling on the input. + +*@par Inputs: +*@li x: A 5-D Tensor of shape [batch, depth, height, width, channels] and type float16, float32, double. +*@li filter: An optional tensor of type float16, float32, double, fractal_z_3d layout. +*@li multiplier: An optional tensor of float16, float32, double. + +*@par Attributes: +*@li ksize: List of ints that has length 1, 3 or 5. The size of the window for each dimension of the input tensor. +*@li strides:List of ints that has length 1, 3 or 5. The stride of the sliding window for each dimension of the input tensor. +*@li pads: List of ints, implicit zero paddings on both sides of the input. +*@li ceil_mode: When true, will use ceil instead of floor in the formula to compute the output shape. +*@li count_include_pad: When true, will include the zero-padding in the averaging calculation. +*@li divisor_override: if specified, it will be used as divisor, otherwise size of the pooling region will be used. +*@li data_format: A string, format of input data . \n + +*@par Outputs: +*y: The average pooled output tensor . \n + +*@attention Constraints: +*@li "ksize" is in the range [1, 255]. "strides" is in the range [1, 63] + +*@par Third-party framework compatibility +* Compatible with the TensorFlow operator AvgPool3D. +*/ +REG_OP(AvgPool3DD) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .OPTIONAL_INPUT(filter, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .OPTIONAL_INPUT(multiplier, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .REQUIRED_ATTR(ksize, ListInt) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(pads, ListInt) + .ATTR(ceil_mode, Bool, false) + .ATTR(count_include_pad, Bool, true) + .ATTR(divisor_override, Int, 0) + .ATTR(data_format, String, "NDHWC") + .OP_END_FACTORY_REG(AvgPool3DD) + +/** +* @brief Computes AvgPool3DGrad function. + +* @par Inputs: +* @li orig_input_shape: An NDHWC tensor of type float16, float32, or double. +* @li grads: An NDHWC tensor of type int32. + +* @par Attributes: +* @li ksize: List of ints that has length 1, 3 or 5. The size of the window for each dimension of the input tensor. +* @li strides:List of ints that has length 1, 3 or 5. The stride of the sliding window for each dimension of the input tensor. +* @li pads: List of ints, implicit zero paddings on both sides of the input. +* @li ceil_mode: When true, will use ceil instead of floor in the formula to compute the output shape. +* @li count_include_pad: When true, will include the zero-padding in the averaging calculation. +* @li divisor_override: if specified, it will be used as divisor, otherwise size of the pooling region will be used. +* @li data_format: A string, format of input data . + +* @par Outputs: +* @output: A mutable tensor with the same shape and type as "orig_input". + +* @par Third-party framework compatibility +* @li Compatible with the TensorFlow operator AvgPoolGrad. +*/ + +REG_OP(AvgPool3DGrad) + .INPUT(orig_input_shape, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .INPUT(grads, TensorType({DT_INT32})) + .OUTPUT(output, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .REQUIRED_ATTR(ksize, ListInt) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(pads, ListInt) + .ATTR(ceil_mode, Bool, false) + .ATTR(count_include_pad, Bool, true) + .ATTR(divisor_override, Int, 0) + .ATTR(data_format, String, "NDHWC") + .OP_END_FACTORY_REG(AvgPool3DGrad) + +/** +* @brief Performs average pooling on the input. + +* @par Inputs: +* @li grads: An NDHWC tensor of type float16. +* @li filter: An optional tensor of type float16, fractal_z_3d layout. +* @li multiplier: An optional tensor of float16. + +* @par Attributes: +* @li orig_input_shape: List of ints that has length 5. The size of the window for each dimension of the input tensor. +* @li ksize: List of ints that has length 3. The size of the window for each dimension of the input tensor. +* @li strides:List of ints that has length 3. The stride of the sliding window for each dimension of the input tensor. +* @li pads: List of ints, implicit zero paddings on both sides of the input. +* @li ceil_mode: When true, will use ceil instead of floor in the formula to compute the output shape. +* @li count_include_pad: When true, will include the zero-padding in the averaging calculation. +* @li divisor_override: if specified, it will be used as divisor, otherwise size of the pooling region will be used. +* @li data_format: A string, format of input data . \n + +* @par Outputs: +* @output: The average pooled output tensor . \n + +* @attention Constraints: +* @li "ksize" is in the range [1, 255]. "strides" is in the range [1, 63] + +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator AvgPool3DGradD. +*/ +REG_OP(AvgPool3DGradD) + .INPUT(grads, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(filter, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(multiplier, TensorType({DT_FLOAT16})) + .OUTPUT(output, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .REQUIRED_ATTR(orig_input_shape, ListInt) + .REQUIRED_ATTR(ksize, ListInt) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(pads, ListInt) + .ATTR(ceil_mode, Bool, false) + .ATTR(count_include_pad, Bool, true) + .ATTR(divisor_override, Int, 0) + .ATTR(data_format, String, "NDHWC") + .OP_END_FACTORY_REG(AvgPool3DGradD) + /** *@brief Performs max_pool_ext2 on the input . \n @@ -308,6 +427,31 @@ REG_OP(MaxPool3D) .ATTR(data_format, String, "NDHWC") .OP_END_FACTORY_REG(MaxPool3D) +/** +*@brief Applies a 2D adaptive max pooling over an input signal conposed of several input planes. \n +* The output is of size H x W, for any input size. + +* @par Inputs: +* One input, including: +* @li x: A Tensor. Must be one of the following data types: +* float16, float32, float64. \n + +* @par Attributes: +* @li output_size: A required list of 2 ints +* specifying the size (H,W) of the output tensor. \n + +* @par Outputs: +* @li y: A Tensor. Has the same data type as "x" \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator AdaptiveMaxPool2d. +*/ +REG_OP(AdaptiveMaxPool2d) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .OUTPUT(argmax, TensorType::IndexNumberType()) + .REQUIRED_ATTR(output_size, ListInt) + .OP_END_FACTORY_REG(AdaptiveMaxPool2d) /** * @brief Computes second-order gradients of the maxpooling3d function . \n @@ -477,8 +621,9 @@ REG_OP(MaxPoolV2) *@par Inputs: * One input: -*x: An NC1HWC0 Tensor. Supported type: float, double, int32, - * uint8, int16, int8, int64, uint16, half, uint32, uint64 . \n +*x: An 4D Tensor. Supported type: float, double, int32, + * uint8, int16, int8, int64, uint16, half, uint32, uint64. + * Must set the format, supported format list ["NCHW, NHWC"]. \n *@par Attributes: *@li ksize: A required list of int8, int16, int32, or int64 values, @@ -517,10 +662,12 @@ REG_OP(MaxPoolWithArgmax) *@par Inputs: * Three inputs, including: -*@li x: An NC1HWC0 tensor. Supported type: float, double, int32, +*@li x: An 4d tensor. Supported type: float, double, int32, * uint8, int16, int8, int64, uint16, half, uint32, uint64. -*@li grad: An NC1HWC0 tensor. Supported type: float, double, int32, + * Must set the format, supported format list ["NCHW, NHWC"] +*@li grad: An 4d tensor. Supported type: float, double, int32, * uint8, int16, int8, int64, uint16, half, uint32, uint64. + * Must set the format, supported format list ["NCHW, NHWC"] *@li argmx: An NC1HWC0 tensor of type int32 or int64 . \n *@par Attributes: @@ -1107,7 +1254,7 @@ REG_OP(AvgPool1DD) *@par Inputs: * One input: -*x: An NC1HWC0 Tensor of type float16. +*x: An 4d Tensor of type float16. Must set the format, supported format list ["NCHW, NHWC"]. *@par Attributes: *@li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for * each dimension of the input tensor. No default value. @@ -1148,9 +1295,9 @@ REG_OP(MaxPoolWithArgmaxV2) *@par Inputs: * Three inputs, including: -*@li x: An NC1HWC0 tensor of type float16. -*@li grad: An NC1HWC0 tensor of type float16. -*@li argmx: An NC1HWC0 tensor of type uint16 or int64 . \n +*@li x: An 4d tensor of type float16. Must set the format, supported format list ["NCHW, NHWC"] +*@li grad: An 4d tensor of type float16. Must set the format, supported format list ["NCHW, NHWC"] +*@li argmx: An 4d tensor of type uint16 or int64. Must set the format, supported format list ["NCHW, NHWC"] \n *@par Attributes: *@li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for @@ -1291,5 +1438,171 @@ REG_OP(MaxPoolV3Grad) .ATTR(global_pooling, Bool, false) .ATTR(ceil_mode, Bool, false) .OP_END_FACTORY_REG(MaxPoolV3Grad) + +/** +*@brief Performs dilation2d on the input . \n + +*@par Inputs: +*x: A tensor of shape is 4d, format is support NHWC. +*filter: A tensor of shape is 3d, the type is same with x, +and the c dimension is same with x. \n + +*@par Attributes: +*@li strides: A required list of 4 ints, specifying the stride of the sliding window. The strides of the N and C dimensions are 1. +*@li rates: A required list of 4 ints. The rates of the N and C dimensions are 1. +*@li padding_mode: A optional string. Defaults to "SAME", it support SAME and VALID. +*@li pads: An optional list of 4 ints. +*@li ceil_mode: An optional bool. Defaults to "false". Use ceil or floor to calculate the output size when padding_mode is "CALCULATED". +*@li data_format: An optional string, specifying the data format of "rates" and "strides", either "NCHW" or "NHWC" (default). \n + +*@par Outputs: +*y: The output tensor. Has the same type and format as input "x" . \n + +*@par Third-party framework compatibility +* Compatible with the TensorFlow operator Dilation2D. +*/ +REG_OP(Dilation2D) + .INPUT(x,TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .INPUT(filter,TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .OUTPUT(y,TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(rates, ListInt) + .ATTR(padding_mode, String, "SAME") + .ATTR(pads, ListInt, {0,0,0,0}) + .ATTR(ceil_mode, Bool, false) + .ATTR(data_format, String, "NHWC") + .OP_END_FACTORY_REG(Dilation2D) + +/** +* @brief Applies a 2D adaptive average pooling over +* an input signal composed of several input planes. \n + +* @par Inputs: +* One input, including: +* @li x: A Tensor. Must be one of the following data types: +* float16, float32. \n + +* @par Attributes: +* @li output_size: A required list of 2 ints +* specifying the size (H,W) of the output tensor. \n + +* @par Outputs: +* @li y: A Tensor. Has the same data type as "x" \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator AdaptiveAvgPool2d. +*/ +REG_OP(AdaptiveAvgPool2d) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .REQUIRED_ATTR(output_size, ListInt) + .OP_END_FACTORY_REG(AdaptiveAvgPool2d) + +/** +* @brief Compute gradients of adaptive averagev2 pooling function. + +* @par Inputs: +* @li input_grad: A NCHW Tensor. Must be one of the following data types: +* float16, float32. + +* @par Attributes: +* @li orig_input_shape: A required tuple or list of type int32. + +* @par Outputs: +* @li output_grad: A tensor with the same shape and type as "orig_input_shape". + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator AdaptiveAvgPool2dGrad. +*/ +REG_OP(AdaptiveAvgPool2dGrad) + .INPUT(input_grad, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(output_grad, TensorType({DT_FLOAT, DT_FLOAT16})) + .REQUIRED_ATTR(orig_input_shape, ListInt) + .OP_END_FACTORY_REG(AdaptiveAvgPool2dGrad) + +/** +* @brief Performs the backpropagation of MaxPoolWithGradArgmaxV1. + +* @par Inputs: +* Three inputs, including: +* @li x: An NC1HWC0 tensor of type float16. +* @li grad: An NC1HWC0 tensor of type float16. +* @li argmax: An NC1HWC0 tensor of type uint16 or int64. \n + +* @par Attributes: +* @li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for +* each dimension of the input tensor. No default value. +* @li strides: A required list of int8, int16, int32, or int64 values, specifying the stride of the sliding window for +* each dimension of the input tensor. No default value. +* @li pads: A required listint. \n + +* @par Outputs: +* y: A Tensor. Has the same type and format as input "x". \n + +* @attention Constraints: +* @li "ksize" is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, ksize[1] * ksize[2] <= 255. +* @li "strides" is a list that has length 4: strides[0] = 1 or strides[3] = 1 +* @li "pads" is listint. +* @li "ceil_mode" defaults to False. +* @li "data_format" defaults to "NC1HWC0". \n + +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator MaxPoolGradWithArgmaxV1. +*/ + +REG_OP(MaxPoolGradWithArgmaxV1) + .INPUT(x, TensorType({DT_FLOAT16})) + .INPUT(grad, TensorType({DT_FLOAT16})) + .INPUT(argmax, TensorType({DT_UINT16})) + .OUTPUT(y, TensorType({DT_FLOAT16})) + .REQUIRED_ATTR(ksize, ListInt) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(pads, ListInt) + .ATTR(dtype, Int, 3) + .ATTR(dilation, ListInt, {1, 1, 1, 1}) + .ATTR(ceil_mode, Bool, false) + .OP_END_FACTORY_REG(MaxPoolGradWithArgmaxV1) + +/** +* @brief Performs max pooling on the input and outputs both max values and indices. + +* @par Inputs: +* One input: +* x: An NC1HWC0 Tensor of type float16. \n + +* @par Attributes: +* @li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for +* each dimension of the input tensor. No default value. +* @li strides: A required list of int8, int16, int32, or int64 values, specifying the stride of the sliding window for +* each dimension of the input tensor. No default value. +* @li pads: A required string. No default value. \n + +* @par Outputs: +* y: A Tensor. Has the same type and format as input "x". +* argmax: A Tensor. type:uint16, format:NC1HWC0. \n + +* @attention Constraints: +* @li "ksize" is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, ksize[1] * ksize[2] <= 255. +* @li "stride is a list that has length 4: strides[0] = 1 or strides[3] = 1, strides[1] <= 63, strides[0] >= 1, +* strides[2] <= 63, strides[2] >= 1. +* @li "pads" is listint. +* @li "ceil_mode" defaults to False. +* @li "data_format" defaults to "NC1HWC0". \n + +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator MaxPoolWithArgmaxV1. +*/ +REG_OP(MaxPoolWithArgmaxV1) + .INPUT(x, TensorType({DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT16})) + .OUTPUT(argmax, TensorType({DT_UINT16})) + .REQUIRED_ATTR(ksize, ListInt) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(pads, ListInt) + .ATTR(dtype, Int, 3) + .ATTR(dilation, ListInt, {1, 1, 1, 1}) + .ATTR(ceil_mode, Bool, false) + .OP_END_FACTORY_REG(MaxPoolWithArgmaxV1) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_POOLING_OPS_H diff --git a/third_party/fwkacllib/inc/ops/nn_training_ops.h b/third_party/fwkacllib/inc/ops/nn_training_ops.h index 047fd6da..92074872 100644 --- a/third_party/fwkacllib/inc/ops/nn_training_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_training_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/third_party/fwkacllib/inc/ops/no_op.h b/third_party/fwkacllib/inc/ops/no_op.h index 7834591c..b27b1fa0 100644 --- a/third_party/fwkacllib/inc/ops/no_op.h +++ b/third_party/fwkacllib/inc/ops/no_op.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h index e0e5dfc6..e0897280 100644 --- a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h +++ b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. @@ -640,6 +640,208 @@ REG_OP(Mish) .OUTPUT(y, TensorType({ DT_FLOAT,DT_FLOAT16 })) .OP_END_FACTORY_REG(Mish) +/** + * @brief pytorch hardtanh_backward operator. + * + * @par Inputs: + * 2 inputs, including: + * @li result, minimum tensor of the linear region range, + * datatype: float16/float32, format:ND/5HD. + * @li grad, maximum tensor of the linear region range, + * datatype:float16/float32, format:ND/5HD. \n + + * @par Attributes: + * 2 attributes, including: + * @li min_val, minimum value of the linear region range, datatype:float. + * @li max_val, maximum value of the linear region range, datatype:float. \n + + * @par Outputs: + * 1 output, including: + * @li y, hardtanh_backward output tensor, datatype and format is same as + * input result. \n + + * @attention Constraints: + * This operator only supports dataType: float16/float32, format: ND/5HD. \n + + * @par Third-party framework compatibility + * Compatible with the Pytorch operator HardtanhGrad. + */ +REG_OP(HardtanhGrad) + .INPUT(result, TensorType({ DT_FLOAT16, DT_FLOAT })) /* "First operand." */ + .INPUT(grad, TensorType({ DT_FLOAT16, DT_FLOAT })) /* "Second operand." */ + .OUTPUT(y, TensorType({ DT_FLOAT16, DT_FLOAT })) /* "Result, has same element type as two inputs" */ + .ATTR(min_val, Float, -1.0) + .ATTR(max_val, Float, 1.0) + .OP_END_FACTORY_REG(HardtanhGrad) + +/** +* @brief Calculates the softplus loss function with attributes of beta and threshold. \n + +* @par Inputs: +* One inputs, including: +* @li x: A mutable Tensor. Must be one of the following types: +* float16, float32. \n + +* @par Attributes: +* @li beta: An optional float. Defaults to "1.0" \n + +* @li threshold: An optional float. Defaults to "20.0" \n + +* @par Outputs: +* @li y: A mutable Tensor. Has the same type as "x" \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Softplus. +*/ +REG_OP(SoftplusV2) + .INPUT(x, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .OUTPUT(y, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .ATTR(beta, Float, 1.0) + .ATTR(threshold, Float, 20.0) + .OP_END_FACTORY_REG(SoftplusV2) + +/** +* @brief Calculates the reversed outputs of the function "softplus_v2". \n + +* @par Inputs: +* Two inputs, including: +* @li input_gradients: A mutable Tensor. Must be one of the following types: +* float16, float32. +* @li input_features: A mutable Tensor of the same type as "input_gradients" \n + +* @par Attributes: +* @li beta: An optional float. Defaults to "1.0" \n + +* @li threshold: An optional float. Defaults to "20.0" \n + +* @par Outputs: +* @li output_backprops: A mutable Tensor. Has the same type as "input_gradients" \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator SoftplusGrad. +*/ +REG_OP(SoftplusV2Grad) + .INPUT(input_gradients, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(input_features, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .OUTPUT(output_backprops, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .ATTR(beta, Float, 1.0) + .ATTR(threshold, Float, 20.0) + .OP_END_FACTORY_REG(SoftplusV2Grad) + +/** + * @brief ThresholdedRelu takes one input data (Tensor) and produces one output data (Tensor) + * where the rectified linear function, y = x for x > alpha, y = 0 otherwise, is applied to the tensor elementwise. + * + * @par inputs + * one input including: + * @li x: input A Tensor. Must be one of the following types: float32, float16 + * + * @par output + * one output including: + * @li y:A Tensor of the same type as x + * + */ +REG_OP(ThresholdedRelu) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(alpha, Float, 1.0) + .OP_END_FACTORY_REG(ThresholdedRelu) + +/** +* @brief Calculate the hard shrinkage function. \n + +* @par Inputs: +* One inputs, including: +* @li input_x: A tensor. Must be one of the following types: +* float16, float32. \n + +* @par Attributes: +* @li lambd: An optional float. Defaults to 0.5. \n + +* @par Outputs: +* y: A Tensor with the same dtype and shape of input_x's. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Hardshrink. \n +*/ +REG_OP(HardShrink) + .INPUT(input_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(lambd, Float, 0.5) + .OP_END_FACTORY_REG(HardShrink) + +/** +* @brief Calculate the hard sigmoid function. \n + +* @par Inputs: +* One inputs, including: +* @li input_x: A tensor. Must be one of the following types: +* float16, float32, int32. \n + +* @par Attributes: +* @li alpha: An optional float. Defaults to 0.16666666. \n +* @li beta: An optional float. Defaults to 0.5. \n + +* @par Outputs: +* y: A Tensor with the same dtype and shape of input_x's. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Hardsigmoid. \n +*/ +REG_OP(HardSigmoid) + .INPUT(input_x, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .OUTPUT(output_y, TensorType({DT_FLOAT, DT_FLOAT16})) + .ATTR(alpha, Float, 0.16666666) + .ATTR(beta, Float, 0.5) + .OP_END_FACTORY_REG(HardSigmoid) + +/** +* @brief Calculate the soft shrinkage function. \n + +* @par Inputs: +* One inputs, including: +* @li input_x: A tensor. Must be one of the following types: +* float16, float32. \n + +* @par Attributes: +* @li lambd: An optional float. Defaults to 0.5. \n + +* @par Outputs: +* y: A Tensor with the same dtype and shape of input_x's. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Softshrink. \n +*/ +REG_OP(SoftShrink) + .INPUT(input_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(lambd, Float, 0.5) + .OP_END_FACTORY_REG(SoftShrink) + +/** +* @brief Calculate the reversed outputs of the function "soft_shrink". \n + +* @par Inputs: +* Two inputs, including: +* @li input_grad: A tensor. Must be one of the following types: +* float16, float32. \n +* @li input_x: A tensor of the same dtype as "input_grad". \n + +* @par Attributes: +* @li lambd: An optional float. Defaults to 0.5. \n + +* @par Outputs: +* y: A Tensor of the same dtype and shape as "input_graxd". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator SoftShrinkGrad. \n +*/ +REG_OP(SoftShrinkGrad) + .INPUT(input_grad, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(input_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(lambd, Float, 0.5) + .OP_END_FACTORY_REG(SoftShrinkGrad) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NONLINEAR_FUC_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h b/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h index 8d7ef9f9..f36d2935 100644 --- a/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h +++ b/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/outfeed_ops.h b/third_party/fwkacllib/inc/ops/outfeed_ops.h index e0b783bc..53b9d701 100644 --- a/third_party/fwkacllib/inc/ops/outfeed_ops.h +++ b/third_party/fwkacllib/inc/ops/outfeed_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/pad_ops.h b/third_party/fwkacllib/inc/ops/pad_ops.h index f746b3b3..8d71c5cd 100644 --- a/third_party/fwkacllib/inc/ops/pad_ops.h +++ b/third_party/fwkacllib/inc/ops/pad_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. @@ -161,7 +161,7 @@ REG_OP(Pad) *@brief Pads a tensor . \n *@par Inputs: -*x: A Tensor. Must be one of the following types: float16, float32, int8, uint8, int32 . \n +*x: A Tensor. Must be one of the following types: float16, float32, int32 . \n *@par Attributes: *paddings: An optional "vector>". Defaults to "{}". @@ -180,8 +180,8 @@ REG_OP(Pad) * Warning: THIS FUNCTION IS DEPRECATED. Please use Pad instead. */ REG_OP(PadD) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_UINT8, DT_FLOAT})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_UINT8, DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) .REQUIRED_ATTR(paddings, ListListInt) .OP_END_FACTORY_REG(PadD) @@ -213,7 +213,7 @@ REG_OP(PadV2) *@brief Pads a tensor . \n *@par Inputs: -*x: A Tensor. Must be one of the following types: float16, float32, int8, uint8, int32 . \n +*x: A Tensor. Must be one of the following types: float16, float32, int32 . \n *constant_values: A Tensor. Must have the same type as input. *@par Attributes: @@ -227,10 +227,7 @@ REG_OP(PadV2) *y: A Tensor of the same type as "x" . \n *@par Third-party framework compatibility: -* Compatible with TensorFlow operator Pad. -* -* @par Restrictions: -* Warning: THIS FUNCTION IS DEPRECATED. Please use Pad instead. +* Compatible with TensorFlow operator PadV2. */ REG_OP(PadV2D) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) @@ -403,5 +400,46 @@ REG_OP(EmbeddingRankId) .ATTR(mode, String, "mod") .OP_END_FACTORY_REG(EmbeddingRankId) +/** +* @brief Fill the value to a tensor has the specified shape. + +* @par Inputs: +* One inputs, including: +* @li dims: An Tensor, specify the shape that the value to fill. + +* @par Attributes: +* @li value: An optional float value. Defaults to 0.0. + +* @par Outputs: +* @li y: A Tensor. Has the shape specify by attr shape, and full of the value specify by attr value. + +* @par Third-party framework compatibility +* Compatible with the ONNX operator ConstantOfShape. +*/ +REG_OP(FillV2) + .INPUT(dims, TensorType({DT_INT16, DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT, DT_DOUBLE, DT_INT8, DT_INT16, DT_INT32, DT_INT64})) + .ATTR(value, Float, 0) + .OP_END_FACTORY_REG(FillV2) + +/** +* @brief Fill the value to a tensor has the specified shape. + +* @par Attributes: +* @li value: An optional float value. Defaults to 0.0. + +* @li dims: An required listInt to specify the shape that the value to fill. + +* @par Outputs: +* @li y: A Tensor. Has the shape specify by attr shape, and full of the value specify by attr value. + +* @par Third-party framework compatibility +* Compatible with the ONNX operator ConstantOfShape. +*/ +REG_OP(FillV2D) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT, DT_DOUBLE, DT_INT8, DT_UINT8, DT_INT16, DT_INT32, DT_INT64})) + .ATTR(value, Float, 0) + .REQUIRED_ATTR(dims, ListInt) + .OP_END_FACTORY_REG(FillV2D) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_PAD_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/parsing_ops.h b/third_party/fwkacllib/inc/ops/parsing_ops.h index 5c7adfd8..9a5cf504 100644 --- a/third_party/fwkacllib/inc/ops/parsing_ops.h +++ b/third_party/fwkacllib/inc/ops/parsing_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/quantize_ops.h b/third_party/fwkacllib/inc/ops/quantize_ops.h index b53cfeb6..806e28df 100644 --- a/third_party/fwkacllib/inc/ops/quantize_ops.h +++ b/third_party/fwkacllib/inc/ops/quantize_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/ragged_array_ops.h b/third_party/fwkacllib/inc/ops/ragged_array_ops.h index 9b31aa8e..20484623 100644 --- a/third_party/fwkacllib/inc/ops/ragged_array_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_array_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h b/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h index 13488a25..020e3da4 100644 --- a/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/ragged_math_ops.h b/third_party/fwkacllib/inc/ops/ragged_math_ops.h index 8af4f867..258b0ca1 100644 --- a/third_party/fwkacllib/inc/ops/ragged_math_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_math_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/random_ops.h b/third_party/fwkacllib/inc/ops/random_ops.h index b46da435..e2b00ce3 100644 --- a/third_party/fwkacllib/inc/ops/random_ops.h +++ b/third_party/fwkacllib/inc/ops/random_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -495,6 +495,60 @@ REG_OP(ShuffleChannel) DT_UINT16, DT_INT32, DT_UINT32,DT_INT64,DT_UINT64})) .ATTR(group, Int, 1) .OP_END_FACTORY_REG(ShuffleChannel) + +/** + * @briefGenerate a tensor of samples from a multinomial + * distribution according to the probabilities of each of + * the possible outcomes. + * + * @par inputs + * one input including: + * @li x:Input tensor with shape [batch_size, class_size], + * where class_size is the number of all possible outcomes. + * Each value along the axis zero represents the unnormalized + * log-probability of each corresponding outcome in a batch. + * + * @par output + * one output including: + * @li y:Output tensor with shape [batch_size, sample_size], + * where sample_size is the number of times to sample. + * Each value along the axis zero represents the outcome of + * the corresponding sample in a batch. + * + */ +REG_OP(MultinomialFuss) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_FLOAT64})) + .OUTPUT(y, TensorType({DT_INT32, DT_INT64})) + .ATTR(dtype, Int, 6) + .ATTR(sample_size, Int, 1) + .ATTR(seed, Float, 0) + .OP_END_FACTORY_REG(MultinomialFuss) + +/** +* @brief During training, randomly zeroes some of the elements of the input tensor +* with probability +* +* @par Inputs: +* @li x: A ND Tensor. Must be one of the following data types: Float, Float16 +* @li seed: A ND Tensor. Must be one of the following data types: Float +* +* @par Attributes: +* @li p: probability of an element to be zeroed +* +* @par Outputs: +* @li y: A tensor with the same shape and type as "x". +* @li mask: A tensor with the same shape and type as "x". +* @li new_seed: A tensor with the same shape and type as "seed". +*/ + +REG_OP(DropoutV2) + .INPUT(x, TensorType({ DT_FLOAT16, DT_FLOAT })) + .INPUT(seed, TensorType({ DT_FLOAT })) + .OUTPUT(y, TensorType({ DT_FLOAT16, DT_FLOAT })) + .OUTPUT(mask, TensorType({ DT_FLOAT })) + .OUTPUT(seed, TensorType({ DT_FLOAT })) + .REQUIRED_ATTR(p, Float) + .OP_END_FACTORY_REG(DropoutV2) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_RANDOM_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/reduce_ops.h b/third_party/fwkacllib/inc/ops/reduce_ops.h index 6f44093e..0b114134 100644 --- a/third_party/fwkacllib/inc/ops/reduce_ops.h +++ b/third_party/fwkacllib/inc/ops/reduce_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. @@ -635,8 +635,8 @@ REG_OP(ReduceMin) * Warning: THIS FUNCTION IS DEPRECATED. Please use ReduceMin instead. */ REG_OP(ReduceMinD) - .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT8,DT_UINT8})) - .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT8,DT_UINT8})) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT8,DT_UINT8,DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT8,DT_UINT8,DT_INT32})) .REQUIRED_ATTR(axes, ListInt) .ATTR(keep_dims, Bool, false) .OP_END_FACTORY_REG(ReduceMinD) @@ -821,7 +821,7 @@ Defaults to "0.00001" . \n *batch_ variance: A Tensor of type float32 for the result variance . \n *@attention Constraints: -*For Ascend 310, the result accuracy fails to reach 1 due to the square root instruction. +*For Ascend 310, the result accuracy fails to reach 0.001 due to the square root instruction. */ REG_OP(INInferV2) .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -882,7 +882,7 @@ REG_OP(INTrainingReduceV2) *@attention Constraints: *@li This operator is a InstanceNorm fusion operator for updating the moving averages for training. * This operator is used in conjunction with INTrainingReduceV2. -*@li For Ascend 310, the result accuracy fails to reach 1 due to the square root instruction. +*@li For Ascend 310, the result accuracy fails to reach 1‰ due to the square root instruction. */ REG_OP(INTrainingUpdateV2) .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -965,7 +965,7 @@ for the updated variance. *@attention Constraints: *@li This operator is a InstanceNorm fusion operator for updating the moving averages for training. * This operator is used in conjunction with GNTrainingUpdate. -*@li For Ascend 310, the result accuracy fails to reach 1 due to the square root instruction. +*@li For Ascend 310, the result accuracy fails to reach 1‰ due to the square root instruction. */ REG_OP(GNTrainingUpdate) .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -982,6 +982,41 @@ REG_OP(GNTrainingUpdate) .OUTPUT(batch_variance, TensorType({DT_FLOAT})) .OP_END_FACTORY_REG(GNTrainingUpdate) +/** +* @brief Calculates the standard deviation and average value of Tensors. + +* @par Inputs: +* @li x: A Tensor. Must be one of the following types: +* float16, float32. \n + +* @par Attributes: +* Three Attributes, including: +* @li dim: An optional listint, Defaults to "None". \n + +* @li unbiased: An optional bool. Defaults to "True". +* If "True", Use Bessel Correction. +* If "False", Do not use Bessel Correction. \n + +* @li keepdim: An optional bool. Defaults to "False". +* If "True", Keep the original tensor dimension. +* If "False", Do not keep the original tensor dimension. \n + +* @par Outputs: +* Two Outputs, including: +* @li y1: A Tensor. Has the same type as "x". +* @li y2: A Tensor. Has the same type as "x". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator ReduceStd. +*/ +REG_OP(ReduceStd) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y1, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y2, TensorType({DT_FLOAT, DT_FLOAT16})) + .ATTR(dim, ListInt, {}) + .ATTR(unbiased, Bool, true) + .ATTR(keepdim, Bool, false) + .OP_END_FACTORY_REG(ReduceStd) } //namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_REDUCE_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/resource_variable_ops.h b/third_party/fwkacllib/inc/ops/resource_variable_ops.h index 1b60d42a..74ac83f8 100644 --- a/third_party/fwkacllib/inc/ops/resource_variable_ops.h +++ b/third_party/fwkacllib/inc/ops/resource_variable_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/rnn.h b/third_party/fwkacllib/inc/ops/rnn.h index 84723872..12bb0ee8 100644 --- a/third_party/fwkacllib/inc/ops/rnn.h +++ b/third_party/fwkacllib/inc/ops/rnn.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -187,16 +187,16 @@ REG_OP(DynamicRNNGrad) *@brief: DynamicRNN calculation. *@par Inputs: *ten inputs: -*@li x:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li w:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. -*@li b:A 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. -*@li seq_length:A 1D Tensor. Must be one of the following types: int32. The format must be ND. -*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li init_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li wci:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. -*@li wcf:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. -*@li wco:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. -*@li mask:A 1D Tensor. Must be one of the following types: uint8. The format must be ND . \n +*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li w:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. +*@li seq_length:A optional 1D Tensor. Must be one of the following types: int32. The format must be ND. +*@li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li wcf:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li wco:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li mask:A 1D optional Tensor. Must be one of the following types: uint8. The format must be ND . \n *@par Attributes: *@li cell_type:An string identifying the cell type in the op. Default to "LSTM". Only LSTM is currently supported. @@ -221,6 +221,8 @@ REG_OP(DynamicRNNGrad) *@li f:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li o:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@par Third-party framework compatibility: +* Compatible with the TF operator LSTM. */ REG_OP(DynamicRNN) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -254,6 +256,63 @@ REG_OP(DynamicRNN) .ATTR(is_training, Bool, true) .OP_END_FACTORY_REG(DynamicRNN) +/** +*@brief: DynamicLSTMV2 calculation. +*@par Inputs: +*ten inputs: +*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li w:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. +*@li cont:A required 2D Tensor. Must be one of the following types: float16, float32. The format must be ND. +*@li w_xc_x_static:A optional 2D Tensor. Must be one of the following types: float16, float32. The format must be ND. +*@li h0:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li c0:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li wci:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li wcf:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li wco:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li mask:A optional 1D Tensor. Must be one of the following types: uint8. The format must be ND . + +*@par Attributes: +*@li num_output:An integer identifying the num projection in the op. Default to 0. +*@li expose_hidden:An bool identifying the expose_hidden in the op. Default to flase. +*@li need_output_last:An bool identifying the time major in the op. Default to true. +*@li forget_bias:An float identifying the forget bias in the op. Default to 0. + +*@par Outputs: +*eight outputs: +*@li y:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li output_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li output_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li last_output_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li last_output_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@par Third-party framework compatibility: +* Compatible with the Caffe operator LSTM. +*@par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(DynamicLSTMV2) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(w, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(b, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(cont, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(w_xc_x_static, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(h0, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(c0, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wci, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wcf, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wco, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(mask, TensorType({DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(last_output_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(last_output_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(num_output, Int, 0) + .ATTR(expose_hidden, Bool, false) + .ATTR(need_output_last, Bool, false) + .ATTR(forget_bias, Float, 0.0) + .OP_END_FACTORY_REG(DynamicLSTMV2) + /** *@brief: LSTMInputGrad calculation. *@par Inputs: @@ -475,9 +534,9 @@ REG_OP(BasicRNNCell) .OP_END_FACTORY_REG(BasicRNNCell) /** -*@brief: DynamicGRU calculation. +*@brief DynamicGRU calculation. *@par Inputs: -*seven inputs: \n +*seven inputs: *@li x:Must be one of the following types: float16. The format must be FRACTAL_NZ. *@li w:Must be one of the following types: float16. The format must be FRACTAL_Z. *@li b:Must be one of the following types: float16, float32. The format must be ND. @@ -497,7 +556,7 @@ REG_OP(BasicRNNCell) *@li is_training:An bool identifying is training in the op. Default to true. *@par Outputs: -*five outputs: \n +*five outputs: *@li y:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li output_h:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li r:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. @@ -531,9 +590,9 @@ REG_OP(DynamicGRU) .OP_END_FACTORY_REG(DynamicGRU) /** -*@brief: DynamicGRUV2 calculation. +*@brief DynamicGRUV2 calculation. *@par Inputs: -*seven inputs: \n +*seven inputs: *@li x:Must be one of the following types: float16. The format must be FRACTAL_NZ. *@li weight_input:Must be one of the following types: float16. The format must be FRACTAL_Z. *@li weight_hidden:Must be one of the following types: float16. The format must be FRACTAL_Z. @@ -555,7 +614,7 @@ REG_OP(DynamicGRU) *@li is_training:An bool identifying is training in the op. Default to true. *@par Outputs: -*six outputs: \n +*six outputs: *@li y:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li output_h:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li update:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. @@ -592,6 +651,68 @@ REG_OP(DynamicGRUV2) .ATTR(is_training, Bool, true) .OP_END_FACTORY_REG(DynamicGRUV2) + +/** +*@brief DynamicGRUV2Hidden calculation. +*@par Inputs: +*five inputs: +*@li x_weight_input:Must be one of the following types: float32. The format must be FRACTAL_NZ. +*@li weight_hidden:Must be one of the following types: float16. The format must be FRACTAL_Z. +*@li bias_hidden:Must be one of the following types: float16, float32. The format must be ND. +*@li seq_length:Must be one of the following types: int32. The format must be ND. +*@li init_h:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. + +*@par Attributes: +*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". +Only UNIDIRECTIONAL is currently supported. +*@li cell_depth:An integer identifying the cell depth in the op. Default to 1. +*@li keep_prob:An float identifying the keep prob in the op. Default to 1. +*@li cell_clip:An float identifying the cell clip in the op. Default to -1. +*@li num_proj:An integer identifying the num projection in the op. Default to 0. +*@li time_major:An bool identifying the time major in the op. Default to true. +*@li activation:An string identifying the type of activation function in the op. Default to "tanh". +Only tanh is currently supported. +*@li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. +*@li reset_after:An bool identifying whether to apply reset gate after matrix multiplication. Default to true. +*@li is_training:An bool identifying is training in the op. Default to true. + +*@par Outputs: +*six outputs: +*@li y:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li output_h:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li update:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li reset:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li new:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li hidden_new:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(DynamicGRUV2Hidden) + .INPUT(x_weight_input, TensorType({DT_FLOAT32})) + .INPUT(weight_hidden, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(bias_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32})) + .OPTIONAL_INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(update, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(reset, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(new, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(hidden_new, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(direction, String, "UNIDIRECTIONAL") + .ATTR(cell_depth, Int, 1) + .ATTR(keep_prob, Float, 1.0) + .ATTR(cell_clip, Float, -1.0) + .ATTR(num_proj, Int, 0) + .ATTR(time_major, Bool, true) + .ATTR(activation, String, "tanh") + .ATTR(gate_order, String, "zrh") + .ATTR(reset_after, Bool, true) + .ATTR(is_training, Bool, true) + .OP_END_FACTORY_REG(DynamicGRUV2Hidden) + + /** *@brief: DynamicGRUV2Grad calculation. *@par Inputs: @@ -618,7 +739,6 @@ REG_OP(DynamicGRUV2) *@li cell_clip:An float identifying the cell clip in the op. Default to -1. *@li num_proj:An integer identifying the num projection in the op. Default to 0. *@li time_major:An bool identifying the time major in the op. Default to true. -*@li bias_type:An string identifying the type of bias_type function in the op. Default to "double_bias". *@li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. *@li reset_after:An bool identifying whether to apply reset gate after matrix multiplication. Default to true. @@ -630,6 +750,9 @@ REG_OP(DynamicGRUV2) *@li db_hidden:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li dx:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(DynamicGRUV2Grad) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -658,7 +781,6 @@ REG_OP(DynamicGRUV2Grad) .ATTR(cell_clip, Float, -1.0) .ATTR(num_proj, Int, 0) .ATTR(time_major, Bool, true) - .ATTR(bias_type, String, "double_bias") .ATTR(gate_order, String, "zrh") .ATTR(reset_after, Bool, true) .OP_END_FACTORY_REG(DynamicGRUV2Grad) @@ -667,7 +789,7 @@ REG_OP(DynamicGRUV2Grad) *@brief: GRUV2HiddenGrad calculation. *@par Inputs: *nine inputs: \n -*@li weight_hidden:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dh_pre_t:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li dy:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. @@ -678,6 +800,7 @@ REG_OP(DynamicGRUV2Grad) *@li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@par Attributes: +*@li t_state:An Int identifying the current t state. Default to [0, 4]. *@li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. *@par Outputs: @@ -685,10 +808,12 @@ REG_OP(DynamicGRUV2Grad) *@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li dgate_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li dnt_x:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ -REG_OP(GRUV2HiddenGrad) - .INPUT(weight_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) +REG_OP(GRUV2HiddenGradCell) + .INPUT(dh_pre_t, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(h, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(dy, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(dh, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -699,8 +824,142 @@ REG_OP(GRUV2HiddenGrad) .OUTPUT(dh_prev, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(dgate_h, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(dnt_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(t_state, Int, 0) .ATTR(gate_order, String, "zrh") - .OP_END_FACTORY_REG(GRUV2HiddenGrad) + .OP_END_FACTORY_REG(GRUV2HiddenGradCell) + +/** +* @brief Calculates the reversed outputs of the function "embedding". \n + +* @par Inputs: +* Two inputs, including: +* @li grad: A mutable Tensor of word grad. Must be one of the following types: +* float32. +* @li indices: A mutable word index Tensor of the int32 type.\n + +* @par Attributes: +* @li num_weights: An int attr which use to judge how many words in dict. \n + +* @li padding_idx: An int attr judge which word to fill zeros. Defaults to "-1". \n + +* @li scale_grad_by_freq: An optional bool. Defaults to "False". +* If "True", "grad_weight" will be scale by word_frequency. +* If "False", "grad_weight" will not be scale by word_frequency. \n + +* @par Outputs: +* @li grad_weight: A mutable output Tensor of new word grad has the same type as "grads". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator EmbeddingDenseGrad. +*/ +REG_OP(EmbeddingDenseGrad) + .INPUT(grad, TensorType({ DT_FLOAT32 })) /* "First operand." */ + .INPUT(indices, TensorType({ DT_INT32 })) /* "Second operand." */ + .OUTPUT(y, TensorType({ DT_FLOAT32 })) /* "Result, has same element type as two inputs" */ + .REQUIRED_ATTR(num_weights, Int) + .ATTR(padding_idx, Int, -1) + .ATTR(scale_grad_by_freq, Bool, false) + .OP_END_FACTORY_REG(EmbeddingDenseGrad) + +/** +*@brief CommonLSTM calculation. +*@par Inputs: +*eight inputs: \n +*@li x:Each time step is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li w:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li r:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li b:An optional input. Each direction is a 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. +*@li sequence_lens:An optional input. A 1D Tensor.Must be one of the following types: int32. The format must be ND. +*@li initial_h:An optional input. Each direction is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li initial_c:An optional input. Each direction is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li p:An optional input. Each direction is a 1D Tensor.Must be one of the following types: float16, float32. The format must be ND. + +*@par Attributes: +*@li activation_alpha:Optional scaling values used by some activation functions. Empty is currently supported. +*@li activation_beta:Optional scaling values used by some activation functions. Empty is currently supported. +*@li activations:The list of activation functions. Empty is currently supported. +*@li clip:An float identifying the cell clip in the op. Default to -1. +*@li direction:Specify if the RNN is forward, reverse, or bidirectional. Must be one of forward(default), reverse, or bidirectional. +*@li hidden_size:Number of neurons in the hidden layer. Reserved. +*@li input_forget:Couple the input and forget gates if 1. Reserved. + +*@par Outputs: +*three outputs: \n +*@li y:First dimension is time step, second dimension is direction, others is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li y_h:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li y_c:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*/ + +REG_OP(CommonLSTM) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(w, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(r, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(b, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(sequence_lens, TensorType({DT_INT32})) + .OPTIONAL_INPUT(initial_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(initial_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(p, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(activation_alpha, ListFloat, {}) + .ATTR(activation_beta, ListFloat, {}) + .ATTR(activations, ListString, {}) + .ATTR(clip, Float, -1.0) + .ATTR(direction, String, "forward") + .REQUIRED_ATTR(hidden_size, Int) + .ATTR(input_forget, Int, 0) + .OP_END_FACTORY_REG(CommonLSTM) + +/** +* @brief Common GRU calculation. + +* @par Inputs: +* Eight inputs, including: +* @li x: The input sequences packed (and pontentially padded) into on 3D Tesnor(float16). The format must be FRACTAL_NZ +* @li w: The weight tensor for the gates is 3D Tensor(float16). The format must be FRACTAL_Z +* @li r: The recurrence weight tesnor is 3D Tensor(float16). The format must be FRACTAL_Z +* @li b: The bias tensor for the gates. The format must be ND +* @li sequence_lens: Optional tensor specifying lengths of sequences(int32). The format must be ND +* @li init_h: Optional initial value of the hidden(float16,float32). The format must be FRACTAL_NZ + +* @par Attributes: +* @li activation_alpha: Optional scaling values used by some activation functions. \n + +* @li activation_beta: Optional scaling values used by some activation functions. \n + +* @li activations: A list of 2 (or 4 if bidirectional) activation functions for update, reset, and hidden gates. \n + +* @li clip: Cell clip threshold. \n + +* @li direction: Specify if the RNN is forward, reverse, or bidirectional. \n + +* @li hidden_size: Number of neurons in the hidden layer. \n + +* @li linear_before_reset: When computing the output of the hidden gate, apply the linear transformation before multiplying by the output of the reset gate. \n + +* @par Outputs: +* @li y: A Tensor that concats all the intermediate output values of the hidden(float16,float32). The format must be FRACTAL_NZ + +* @li y_h: The last output value of the hidden(float16,float32). The format must be FRACTAL_NZ +*/ +REG_OP(CommonGRU) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(w, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(r, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(b, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(sequence_lens, TensorType({DT_INT32})) + .OPTIONAL_INPUT(initial_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(activation_alpha, ListFloat, {}) + .ATTR(activation_beta , ListFloat, {}) + .ATTR(activations , ListString, {}) + .ATTR(clip, Float, -1.0) + .ATTR(direction, String, "forward") + .REQUIRED_ATTR(hidden_size, Int) + .ATTR(linear_before_reset , Int, 0) + .OP_END_FACTORY_REG(CommonGRU) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_RNN_H_ diff --git a/third_party/fwkacllib/inc/ops/rpn_ops.h b/third_party/fwkacllib/inc/ops/rpn_ops.h index b7649a44..089af326 100644 --- a/third_party/fwkacllib/inc/ops/rpn_ops.h +++ b/third_party/fwkacllib/inc/ops/rpn_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/save_ops.h b/third_party/fwkacllib/inc/ops/save_ops.h index 0ce473b7..5ce6c2e0 100644 --- a/third_party/fwkacllib/inc/ops/save_ops.h +++ b/third_party/fwkacllib/inc/ops/save_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/sdca_ops.h b/third_party/fwkacllib/inc/ops/sdca_ops.h index cbd9839d..34c6a268 100644 --- a/third_party/fwkacllib/inc/ops/sdca_ops.h +++ b/third_party/fwkacllib/inc/ops/sdca_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/selection_ops.h b/third_party/fwkacllib/inc/ops/selection_ops.h index 2c99e82e..dee9e0f7 100644 --- a/third_party/fwkacllib/inc/ops/selection_ops.h +++ b/third_party/fwkacllib/inc/ops/selection_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -796,6 +796,34 @@ REG_OP(SliceD) .REQUIRED_ATTR(size, ListInt) .OP_END_FACTORY_REG(SliceD) +/** +*@brief Extracts a slice from a tensor. +* This operation extracts a slice of size "size" from a tensor "x" +* starting at the location specified by "begin" . \n + +*@par Inputs: +*@li x: A Tensor. Must be one of the following types: +* float16, float32, double, int64, int32, uint8, uint16, uint32, uint64, int8, +* int16, complex64, complex128, qint8, quint8, qint16, quint16, qint32 . \n + +*@par Inputs: +*@li offsets: The starting location for the slice. + +*@par Attributes: +*@li size: The tensor shape . \n + +*@par Outputs: +*y: A Tensor. Has the same type as "x". The slice extracted from the tensor. +*@par Restrictions: +*Warning: THIS FUNCTION IS DEPRECATED. Please use Slice instead. +*/ +REG_OP(SliceDV2) + .INPUT(x, TensorType::BasicType()) + .INPUT(offsets, TensorType::IndexNumberType()) + .OUTPUT(y, TensorType::BasicType()) + .REQUIRED_ATTR(size, ListInt) + .OP_END_FACTORY_REG(SliceDV2) + /** * @brief Finds values and indices of the "k" largest elements for the last * dimension . \n @@ -1921,6 +1949,160 @@ REG_OP(CumulativeLogsumexpD) .ATTR(exclusive, Bool, false) .ATTR(reverse, Bool, false) .OP_END_FACTORY_REG(CumulativeLogsumexpD) + +/** +* @brief Add updates to var according to axis and indices. + +* @par Inputs: +* Three inputs, including: +* @li var: A Tensor. Must be one of the following types: +* float16, float32, int16, int32, int8, uint8. +* @li indices: A Tensor of the indices, type should be int32. +* @li updates: A Tensor of the same type as "var". \n + +* @par Attributes: +* @li axis: An required int to specify the axis to perform indices add. \n + +* @par Outputs: +* @li var: A Tensor. Same as input "var". + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator index_add_. +*/ +REG_OP(InplaceIndexAdd) + .INPUT(var, TensorType({DT_INT16, DT_INT32, DT_INT8, + DT_UINT8, DT_FLOAT32, DT_FLOAT16})) + .INPUT(indices, TensorType({DT_INT32})) + .INPUT(updates, TensorType({DT_INT16, DT_INT32, DT_INT8, + DT_UINT8, DT_FLOAT32, DT_FLOAT16})) + .OUTPUT(var, TensorType({DT_INT16, DT_INT32, DT_INT8, + DT_UINT8, DT_FLOAT32, DT_FLOAT16})) + .REQUIRED_ATTR(axis, Int) + .OP_END_FACTORY_REG(InplaceIndexAdd) + +/** +* @brief Replace the value of X with value according to mask. +* @par Inputs: +* three inputs, including: +* @li x: A Tensor of dtype is float16 or float32 or int32 or int8. +* @li mask: A Tensor of dtype float16 or float32 or int32 or int8. +* @li value: A Tensor or scalar of dtype float16 or float32 or int32 or int8. \n + +* @par Outputs: +* @li y: A tensor. Must be one of the following dtypes: +* float16, float32, int32, int8. +*/ +REG_OP(MaskedFill) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32})) + .INPUT(mask, TensorType({DT_BOOL})) + .INPUT(value, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32})) + .OP_END_FACTORY_REG(MaskedFill) + +/** +* @brief Choose the value of X with value according to mask. + +* @par Inputs: +* two inputs, including: +* @li x: A Tensor of dtype is float16 or float32. +* @li mask: A Tensor of dtype is bool. \n + +* @par Outputs: +* @li y: A tensor with the same type as x. \n + +* @par Third-party framework compatibility +* Compatible with the Numpy operator select. +* Replaces the pytorch operator masked_select in some scenarios.\n +*/ +REG_OP(MaskedSelectV2) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(mask, TensorType({DT_BOOL})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(MaskedSelectV2) + +/** +* @brief Slice a tensor at its last dim, e.x. a[..., begin:end:stride]. \n + +* @par Inputs: +* One inputs, including: +* @li x: A Tensor. Must be one of the following types: float16, float32, int16, int32. + +* @par Attributes: +* @li start: An attribute of type Int, start index of last dim. \n +* @li end: An attribute of type Int, end index of last dim. \n +* @li stride: An attribute of type Int, stride of slice. \n + +* @par Outputs: +* @li y: A Tensor. Has the same type as "x". \n + +* @par Third-party framework compatibility +* No compatibility +*/ +REG_OP(SliceLastDim) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT8, DT_INT16, DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT8, DT_INT16, DT_INT32, DT_INT64})) + .REQUIRED_ATTR(start, Int) + .REQUIRED_ATTR(end, Int) + .ATTR(stride, Int, 1) + .OP_END_FACTORY_REG(SliceLastDim) + +/** +* @brief Extracts a strided slice of a tensor. Roughly speaking, this op \n +* extracts a slice of size (end-begin)/stride from the given input tensor. \n +* Starting at the location specified by begin the slice continues by \n +* adding stride to the index until all dimensions are not less than end. \n +* +* @par Inputs: +* Four inputs, including: +* @li x: A Tensor. Must be one of the following types: float32, float64, int32, uint8, int16, int8, \n +* complex64, int64, qint8, quint8, qint32, qint16, quint16, uint16, \n +* complex128, float16, uint32, uint64, complex64, complex128. \n +* @li begin: A Tensor of type int32 or int64, for the index of the first value to select. +* +* @li end: A Tensor of type int32 or int64, for the index of the last value to select. +* +* @li axes: A Tensor of type int32 or int64, indicate axis to be select. +* +* @li strides: A Tensor of type int32 or int64, for the increment. +* +* @par Attributes: +* @li begin_mask: A Tensor of type int32. \n +* A bitmask where a bit "i" being "1" means to ignore the begin \n +* value and instead use the largest interval possible. +* @li end_mask: A Tensor of type int32. \n +* Analogous to "begin_mask". +* @li ellipsis_mask: A Tensor of type int32. \n +* A bitmask where bit "i" being "1" means the "i"th position \n +* is actually an ellipsis. +* @li new_axis_mask: A Tensor of type int32. \n +* A bitmask where bit "i" being "1" means the "i"th \n +* specification creates a new shape 1 dimension. +* @li shrink_axis_mask: A Tensor of type int32. \n +* A bitmask where bit "i" implies that the "i"th \n +* specification should shrink the dimensionality. +* +* @par Outputs: +* y: A Tensor. Has the same type as "x". +* +* @attention Constraints: +* +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator StridedSliceV2. +*/ +REG_OP(StridedSliceV2) + .INPUT(x, TensorType::BasicType()) + .INPUT(begin, TensorType::IndexNumberType()) + .INPUT(end, TensorType::IndexNumberType()) + .OPTIONAL_INPUT(axes, TensorType::IndexNumberType()) + .OPTIONAL_INPUT(strides, TensorType::IndexNumberType()) + .ATTR(begin_mask, Int, 0) + .ATTR(end_mask, Int, 0) + .ATTR(ellipsis_mask, Int, 0) + .ATTR(new_axis_mask, Int, 0) + .ATTR(shrink_axis_mask, Int, 0) + .OUTPUT(y, TensorType::BasicType()) + .OP_END_FACTORY_REG(StridedSliceV2) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_SELECTION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/set_ops.h b/third_party/fwkacllib/inc/ops/set_ops.h index 1d02fa15..04e04f1b 100644 --- a/third_party/fwkacllib/inc/ops/set_ops.h +++ b/third_party/fwkacllib/inc/ops/set_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/sparse_ops.h b/third_party/fwkacllib/inc/ops/sparse_ops.h index d7512790..09d8ced9 100644 --- a/third_party/fwkacllib/inc/ops/sparse_ops.h +++ b/third_party/fwkacllib/inc/ops/sparse_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/spectral_ops.h b/third_party/fwkacllib/inc/ops/spectral_ops.h index 64fa7814..be3d7d00 100644 --- a/third_party/fwkacllib/inc/ops/spectral_ops.h +++ b/third_party/fwkacllib/inc/ops/spectral_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/split_combination_ops.h b/third_party/fwkacllib/inc/ops/split_combination_ops.h index efe4715d..f1a93fa6 100644 --- a/third_party/fwkacllib/inc/ops/split_combination_ops.h +++ b/third_party/fwkacllib/inc/ops/split_combination_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/state_ops.h b/third_party/fwkacllib/inc/ops/state_ops.h index db1f5353..3c8e32b6 100644 --- a/third_party/fwkacllib/inc/ops/state_ops.h +++ b/third_party/fwkacllib/inc/ops/state_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/stateful_random_ops.h b/third_party/fwkacllib/inc/ops/stateful_random_ops.h index 366112d6..c2f65c6a 100644 --- a/third_party/fwkacllib/inc/ops/stateful_random_ops.h +++ b/third_party/fwkacllib/inc/ops/stateful_random_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/stateless_random_ops.h b/third_party/fwkacllib/inc/ops/stateless_random_ops.h index dad3c379..ff9daaa3 100644 --- a/third_party/fwkacllib/inc/ops/stateless_random_ops.h +++ b/third_party/fwkacllib/inc/ops/stateless_random_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/string_ops.h b/third_party/fwkacllib/inc/ops/string_ops.h index 4a88bc79..ec84cc83 100644 --- a/third_party/fwkacllib/inc/ops/string_ops.h +++ b/third_party/fwkacllib/inc/ops/string_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/swap_co_ops.h b/third_party/fwkacllib/inc/ops/swap_co_ops.h index a1bf4f8b..6e8eaac3 100644 --- a/third_party/fwkacllib/inc/ops/swap_co_ops.h +++ b/third_party/fwkacllib/inc/ops/swap_co_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/target_crop_and_resize.h b/third_party/fwkacllib/inc/ops/target_crop_and_resize.h index 9c61f2c9..9bef1d7b 100644 --- a/third_party/fwkacllib/inc/ops/target_crop_and_resize.h +++ b/third_party/fwkacllib/inc/ops/target_crop_and_resize.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/transformation_ops.h b/third_party/fwkacllib/inc/ops/transformation_ops.h index 64e18fc7..1b30c2e1 100644 --- a/third_party/fwkacllib/inc/ops/transformation_ops.h +++ b/third_party/fwkacllib/inc/ops/transformation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -141,7 +141,7 @@ support "NHWC/NCHW" to "NC1HWC0" and "NC1HWC0" to "NHWC/NCHW" *@par Attributes: *@li src_format: A string source data format, can be "NHWC", "NCHW", "FRACTAL_Zn" etc. *@li dst_format: A string target data format, can be "NC1HWC0", "NCHW", "FRACTAL_Zn" etc. -*@li group: A required int32, default value is 1. \n +*@li group: A optional int32, default value is 1. \n *@par Outputs: *dst: A Tensor dtype of all types. @@ -151,7 +151,7 @@ REG_OP(TransData) .OUTPUT(dst, TensorType::BasicType()) .REQUIRED_ATTR(src_format, String) .REQUIRED_ATTR(dst_format, String) - .ATTR(group, Int, 1) + .ATTR(groups, Int, 1) .OP_END_FACTORY_REG(TransData) /** @@ -357,7 +357,7 @@ REG_OP(DepthToSpace) *@brief Permutes data into spatial data blocks and then prunes them . \n *@par Inputs: -*@li x: A 4D Tensor with format NHWC. +*@li x: A 4D Tensor with format. Must set the format, supported format list ["NCHW, NHWC"] *@li crops: A 1D list or tuple of int32 or int64 . \n *Must be one of the following types: float16, float32 @@ -434,9 +434,10 @@ REG_OP(BatchToSpaceD) *@par Inputs: * Two inputs, including: -*@li x: An NHWC Tensor. Must be one of the following types: +*@li x: An 4D Tensor. Must be one of the following types: * float16, float32, double, int64, int32, uint8, uint16, uint32, uint64, int8, * int16, complex64, complex128, qint8, quint8, qint16, quint16, qint32. +* Must set the format, supported format list ["NCHW, NHWC"] *@li paddings: A 2D tensor of type int, specifying the input . \n *@par Attributes: @@ -518,7 +519,8 @@ REG_OP(Unpack) * @par Inputs: * x: A 4D Tensor with shape [batch, in_rows, in_cols, depth], Must be one of the * following types:float32, double, int32, uint8, int16, int8, int64, uint16, -* float16, uint32, uint64 +* float16, uint32, uint64. The inputs must have data_format with one of follows: +* NHWC, NCHW. * @par Attributes: * @li ksizes: A required list or tuple. The size of the sliding window for each @@ -533,7 +535,6 @@ REG_OP(Unpack) * This is equivalent to rate in dilated (a.k.a. Atrous) convolutions. * @li padding: A required string. The type of padding algorithm to use, support "SAME" or "VALID". \n -* @li data_format: A required string. The format of input, only supported NHWC. \n * @par Outputs: * y: A 4D Tensor with shape [batch, out_rows, out_cols, ksize_rows * @@ -554,7 +555,6 @@ REG_OP(ExtractImagePatches) .REQUIRED_ATTR(strides, ListInt) .REQUIRED_ATTR(rates, ListInt) .REQUIRED_ATTR(padding, String) - .ATTR(data_format, String, "NHWC") .OP_END_FACTORY_REG(ExtractImagePatches) /** @@ -563,6 +563,7 @@ REG_OP(ExtractImagePatches) * @par Inputs: * x: A 5D Tensor with shape [batch, in_planes, in_rows, in_cols, depth] . \n +* The inputs must have data_format with one of follows: NDHWC, NCDHW. \n * @par Attributes: * @li ksizes: A required list or tuple. The size of the sliding window for each @@ -571,7 +572,6 @@ REG_OP(ExtractImagePatches) * patches are in "x". Must be: [1, stride_planes, stride_rows, stride_cols, 1]. * @li padding: A required string. The type of padding algorithm to use , * support "SAME" or "VALID" . \n -* @li data_format: An optional string. The format of input, only supported NDHWC. \n * @par Outputs: * Output: A 5D Tensor with shape [batch, out_planes, out_rows, out_cols, ksize_planes * @@ -590,7 +590,6 @@ REG_OP(ExtractVolumePatches) .REQUIRED_ATTR(ksizes, ListInt) .REQUIRED_ATTR(strides, ListInt) .REQUIRED_ATTR(padding, String) - .ATTR(data_format, String, "NDHWC") .OP_END_FACTORY_REG(ExtractVolumePatches) /** diff --git a/third_party/fwkacllib/inc/ops/warp_perspective_ops.h b/third_party/fwkacllib/inc/ops/warp_perspective_ops.h index e19cbd7c..8ef69d8b 100644 --- a/third_party/fwkacllib/inc/ops/warp_perspective_ops.h +++ b/third_party/fwkacllib/inc/ops/warp_perspective_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/runtime/base.h b/third_party/fwkacllib/inc/runtime/base.h index 62a6dcd9..7fbe9eb4 100644 --- a/third_party/fwkacllib/inc/runtime/base.h +++ b/third_party/fwkacllib/inc/runtime/base.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_BASE_H__ #define __CCE_RUNTIME_BASE_H__ @@ -41,12 +41,12 @@ static const int32_t RT_ERROR_NONE = 0; // success * @brief runtime exception numbers. */ typedef enum tagRtExceptionType { - RT_EXCEPTION_NONE = 0, - RT_EXCEPTION_TS_DOWN = 1, - RT_EXCEPTION_TASK_TIMEOUT = 2, - RT_EXCEPTION_TASK_FAILURE = 3, - RT_EXCEPTION_DEV_RUNNING_DOWN = 4, - RT_EXCEPTION_STREAM_ID_FREE_FAILED = 5 + RT_EXCEPTION_NONE = 0, + RT_EXCEPTION_TS_DOWN = 1, + RT_EXCEPTION_TASK_TIMEOUT = 2, + RT_EXCEPTION_TASK_FAILURE = 3, + RT_EXCEPTION_DEV_RUNNING_DOWN = 4, + RT_EXCEPTION_STREAM_ID_FREE_FAILED = 5 } rtExceptionType; /** @@ -54,12 +54,12 @@ typedef enum tagRtExceptionType { * @brief Switch type. */ typedef enum tagRtCondition { - RT_EQUAL = 0, - RT_NOT_EQUAL, - RT_GREATER, - RT_GREATER_OR_EQUAL, - RT_LESS, - RT_LESS_OR_EQUAL + RT_EQUAL = 0, + RT_NOT_EQUAL, + RT_GREATER, + RT_GREATER_OR_EQUAL, + RT_LESS, + RT_LESS_OR_EQUAL } rtCondition_t; /** @@ -67,25 +67,25 @@ typedef enum tagRtCondition { * @brief Data Type of Extensible Switch Task. */ typedef enum tagRtSwitchDataType { - RT_SWITCH_INT32 = 0, - RT_SWITCH_INT64 = 1, + RT_SWITCH_INT32 = 0, + RT_SWITCH_INT64 = 1, } rtSwitchDataType_t; typedef enum tagRtStreamFlagType { - RT_HEAD_STREAM = 0, // first stream - RT_INVALID_FLAG = 0xFFFFFFFF, + RT_HEAD_STREAM = 0, // first stream + RT_INVALID_FLAG = 0xFFFFFFFF, } rtStreamFlagType_t; typedef enum tagRtLimitType { - RT_LIMIT_TYPE_LOW_POWER_TIMEOUT = 0, // timeout for power down , ms + RT_LIMIT_TYPE_LOW_POWER_TIMEOUT = 0, // timeout for power down , ms } rtLimitType_t; typedef struct rtExceptionInfo { - uint32_t taskid; - uint32_t streamid; - uint32_t tid; - uint32_t deviceid; - uint32_t retcode; + uint32_t taskid; + uint32_t streamid; + uint32_t tid; + uint32_t deviceid; + uint32_t retcode; } rtExceptionInfo; typedef void (*rtErrorCallback)(rtExceptionType); diff --git a/third_party/fwkacllib/inc/runtime/config.h b/third_party/fwkacllib/inc/runtime/config.h index c1316f13..ee104693 100644 --- a/third_party/fwkacllib/inc/runtime/config.h +++ b/third_party/fwkacllib/inc/runtime/config.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_CONFIG_H__ #define __CCE_RUNTIME_CONFIG_H__ @@ -24,105 +24,106 @@ extern "C" { #endif #define PLAT_COMBINE(arch, chip, ver) ((arch << 16) | (chip << 8) | (ver)) -#define PLAT_GET_ARCH(type) ((type >> 16) & 0xffff) -#define PLAT_GET_CHIP(type) ((type >> 8) & 0xff) -#define PLAT_GET_VER(type) (type & 0xff) +#define PLAT_GET_ARCH(type) ((type >> 16) & 0xffff) +#define PLAT_GET_CHIP(type) ((type >> 8) & 0xff) +#define PLAT_GET_VER(type) (type & 0xff) typedef enum tagRtArchType { - ARCH_BEGIN = 0, - ARCH_V100 = ARCH_BEGIN, - ARCH_V200, - ARCH_END, + ARCH_BEGIN = 0, + ARCH_V100 = ARCH_BEGIN, + ARCH_V200, + ARCH_END, } rtArchType_t; typedef enum tagRtChipType { - CHIP_BEGIN = 0, - CHIP_MINI = CHIP_BEGIN, - CHIP_CLOUD, - CHIP_MDC, - CHIP_LHISI, - CHIP_DC, - CHIP_CLOUD_V2, - CHIP_END, + CHIP_BEGIN = 0, + CHIP_MINI = CHIP_BEGIN, + CHIP_CLOUD, + CHIP_MDC, + CHIP_LHISI, + CHIP_DC, + CHIP_CLOUD_V2, + CHIP_END, } rtChipType_t; typedef enum tagRtVersion { - VER_BEGIN = 0, - VER_NA = VER_BEGIN, - VER_ES, - VER_CS, - VER_END, + VER_BEGIN = 0, + VER_NA = VER_BEGIN, + VER_ES, + VER_CS, + VER_SD3403, + VER_END, } rtVersion_t; /* match rtChipType_t */ typedef enum tagRtPlatformType { - PLATFORM_BEGIN = 0, - PLATFORM_MINI_V1 = PLATFORM_BEGIN, - PLATFORM_CLOUD_V1, - PLATFORM_MINI_V2, - PLATFORM_LHISI_ES, - PLATFORM_LHISI_CS, - PLATFORM_DC, - PLATFORM_CLOUD_V2, - PLATFORM_END, + PLATFORM_BEGIN = 0, + PLATFORM_MINI_V1 = PLATFORM_BEGIN, + PLATFORM_CLOUD_V1, + PLATFORM_MINI_V2, + PLATFORM_LHISI_ES, + PLATFORM_LHISI_CS, + PLATFORM_DC, + PLATFORM_CLOUD_V2, + PLATFORM_END, } rtPlatformType_t; typedef enum tagRtCubeFracMKNFp16 { - RT_CUBE_MKN_FP16_2_16_16 = 0, - RT_CUBE_MKN_FP16_4_16_16, - RT_CUBE_MKN_FP16_16_16_16, - RT_CUBE_MKN_FP16_Default, + RT_CUBE_MKN_FP16_2_16_16 = 0, + RT_CUBE_MKN_FP16_4_16_16, + RT_CUBE_MKN_FP16_16_16_16, + RT_CUBE_MKN_FP16_Default, } rtCubeFracMKNFp16_t; typedef enum tagRtCubeFracMKNInt8 { - RT_CUBE_MKN_INT8_2_32_16 = 0, - RT_CUBE_MKN_INT8_4_32_4, - RT_CUBE_MKN_INT8_4_32_16, - RT_CUBE_MKN_INT8_16_32_16, - RT_CUBE_MKN_INT8_Default, + RT_CUBE_MKN_INT8_2_32_16 = 0, + RT_CUBE_MKN_INT8_4_32_4, + RT_CUBE_MKN_INT8_4_32_16, + RT_CUBE_MKN_INT8_16_32_16, + RT_CUBE_MKN_INT8_Default, } rtCubeFracMKNInt8_t; typedef enum tagRtVecFracVmulMKNFp16 { - RT_VEC_VMUL_MKN_FP16_1_16_16 = 0, - RT_VEC_VMUL_MKN_FP16_Default, + RT_VEC_VMUL_MKN_FP16_1_16_16 = 0, + RT_VEC_VMUL_MKN_FP16_Default, } rtVecFracVmulMKNFp16_t; typedef enum tagRtVecFracVmulMKNInt8 { - RT_VEC_VMUL_MKN_INT8_1_32_16 = 0, - RT_VEC_VMUL_MKN_INT8_Default, + RT_VEC_VMUL_MKN_INT8_1_32_16 = 0, + RT_VEC_VMUL_MKN_INT8_Default, } rtVecFracVmulMKNInt8_t; typedef struct tagRtAiCoreSpec { - uint32_t cubeFreq; - uint32_t cubeMSize; - uint32_t cubeKSize; - uint32_t cubeNSize; - rtCubeFracMKNFp16_t cubeFracMKNFp16; - rtCubeFracMKNInt8_t cubeFracMKNInt8; - rtVecFracVmulMKNFp16_t vecFracVmulMKNFp16; - rtVecFracVmulMKNInt8_t vecFracVmulMKNInt8; + uint32_t cubeFreq; + uint32_t cubeMSize; + uint32_t cubeKSize; + uint32_t cubeNSize; + rtCubeFracMKNFp16_t cubeFracMKNFp16; + rtCubeFracMKNInt8_t cubeFracMKNInt8; + rtVecFracVmulMKNFp16_t vecFracVmulMKNFp16; + rtVecFracVmulMKNInt8_t vecFracVmulMKNInt8; } rtAiCoreSpec_t; typedef struct tagRtAiCoreRatesPara { - uint32_t ddrRate; - uint32_t l2Rate; - uint32_t l2ReadRate; - uint32_t l2WriteRate; - uint32_t l1ToL0ARate; - uint32_t l1ToL0BRate; - uint32_t l0CToUBRate; - uint32_t ubToL2; - uint32_t ubToDDR; - uint32_t ubToL1; + uint32_t ddrRate; + uint32_t l2Rate; + uint32_t l2ReadRate; + uint32_t l2WriteRate; + uint32_t l1ToL0ARate; + uint32_t l1ToL0BRate; + uint32_t l0CToUBRate; + uint32_t ubToL2; + uint32_t ubToDDR; + uint32_t ubToL1; } rtAiCoreMemoryRates_t; typedef struct tagRtMemoryConfig { - uint32_t flowtableSize; - uint32_t compilerSize; + uint32_t flowtableSize; + uint32_t compilerSize; } rtMemoryConfig_t; typedef struct tagRtPlatformConfig { - uint32_t platformConfig; + uint32_t platformConfig; } rtPlatformConfig_t; /** @@ -165,7 +166,6 @@ RTS_API rtError_t rtGetAiCoreMemoryRates(rtAiCoreMemoryRates_t *aiCoreMemoryRate */ RTS_API rtError_t rtGetMemoryConfig(rtMemoryConfig_t *memoryConfig); - /** * @ingroup * @brief get l2 buffer Info,virtual baseaddr,Size @@ -176,14 +176,16 @@ RTS_API rtError_t rtMemGetL2Info(rtStream_t stream, void **ptr, uint32_t *size); /** * @ingroup - * @brief get runtime version. The version is returned as (1000 major + 10 minor). For example, RUNTIME 9.2 would be represented by 9020. + * @brief get runtime version. The version is returned as (1000 major + 10 minor). For example, RUNTIME 9.2 would be + * represented by 9020. * @param [out] runtimeVersion * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtGetRuntimeVersion(uint32_t *runtimeVersion); + #if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) } #endif -#endif // __CCE_RUNTIME_STREAM_H__ +#endif // __CCE_RUNTIME_STREAM_H__ diff --git a/third_party/fwkacllib/inc/runtime/context.h b/third_party/fwkacllib/inc/runtime/context.h index a42d380a..e95d4c89 100644 --- a/third_party/fwkacllib/inc/runtime/context.h +++ b/third_party/fwkacllib/inc/runtime/context.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_CONTEXT_H__ #define __CCE_RUNTIME_CONTEXT_H__ @@ -30,24 +30,24 @@ extern "C" { typedef void *rtContext_t; typedef enum tagDryRunFlag { - RT_DRYRUN_FLAG_FALSE = 0, - RT_DRYRUN_FLAG_TRUE = 1, + RT_DRYRUN_FLAG_FALSE = 0, + RT_DRYRUN_FLAG_TRUE = 1, } rtDryRunFlag_t; typedef enum tagCtxMode { - RT_CTX_NORMAL_MODE = 0, - RT_CTX_GEN_MODE = 1, + RT_CTX_NORMAL_MODE = 0, + RT_CTX_GEN_MODE = 1, } rtCtxMode_t; typedef struct tagRtGroupInfo { - int32_t groupId; - uint32_t flag; - uint32_t aicoreNum; - uint32_t aicpuNum; - uint32_t aivectorNum; - uint32_t sdmaNum; - uint32_t activeStreamNum; - void *extrPtr; + int32_t groupId; + uint32_t flag; + uint32_t aicoreNum; + uint32_t aicpuNum; + uint32_t aivectorNum; + uint32_t sdmaNum; + uint32_t activeStreamNum; + void *extrPtr; } rtGroupInfo_t; /** @@ -156,6 +156,7 @@ RTS_API rtError_t rtGetGroupCount(uint32_t *count); * @return RT_ERROR_NONE for ok */ RTS_API rtError_t rtSetCtxINFMode(bool mode); + #if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) } #endif diff --git a/third_party/fwkacllib/inc/runtime/dev.h b/third_party/fwkacllib/inc/runtime/dev.h index ba407803..49f6a3f6 100644 --- a/third_party/fwkacllib/inc/runtime/dev.h +++ b/third_party/fwkacllib/inc/runtime/dev.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_DEVICE_H__ #define __CCE_RUNTIME_DEVICE_H__ @@ -27,44 +27,44 @@ extern "C" { #define RT_CAPABILITY_NOT_SUPPORT (0x0) typedef struct tagRTDeviceInfo { - uint8_t env_type; // 0: FPGA 1: EMU 2: ESL - uint32_t ctrl_cpu_ip; - uint32_t ctrl_cpu_id; - uint32_t ctrl_cpu_core_num; - uint32_t ctrl_cpu_endian_little; - uint32_t ts_cpu_core_num; - uint32_t ai_cpu_core_num; - uint32_t ai_core_num; - uint32_t ai_core_freq; - uint32_t ai_cpu_core_id; - uint32_t ai_core_id; - uint32_t aicpu_occupy_bitmap; - uint32_t hardware_version; - uint32_t ts_num; + uint8_t env_type; // 0: FPGA 1: EMU 2: ESL + uint32_t ctrl_cpu_ip; + uint32_t ctrl_cpu_id; + uint32_t ctrl_cpu_core_num; + uint32_t ctrl_cpu_endian_little; + uint32_t ts_cpu_core_num; + uint32_t ai_cpu_core_num; + uint32_t ai_core_num; + uint32_t ai_core_freq; + uint32_t ai_cpu_core_id; + uint32_t ai_core_id; + uint32_t aicpu_occupy_bitmap; + uint32_t hardware_version; + uint32_t ts_num; } rtDeviceInfo_t; typedef enum tagRtRunMode { - RT_RUN_MODE_OFFLINE = 0, - RT_RUN_MODE_ONLINE = 1, - RT_RUN_MODE_AICPU_SCHED = 2, - RT_RUN_MODE_RESERVED + RT_RUN_MODE_OFFLINE = 0, + RT_RUN_MODE_ONLINE = 1, + RT_RUN_MODE_AICPU_SCHED = 2, + RT_RUN_MODE_RESERVED } rtRunMode; typedef enum tagRtAicpuDeployType { - AICPU_DEPLOY_CROSS_OS = 0x0, - AICPU_DEPLOY_CROSS_PROCESS = 0x1, - AICPU_DEPLOY_CROSS_THREAD = 0x2, - AICPU_DEPLOY_RESERVED + AICPU_DEPLOY_CROSS_OS = 0x0, + AICPU_DEPLOY_CROSS_PROCESS = 0x1, + AICPU_DEPLOY_CROSS_THREAD = 0x2, + AICPU_DEPLOY_RESERVED } rtAicpuDeployType_t; typedef enum tagRtFeatureType { - FEATURE_TYPE_MEMCPY = 0, - FEATURE_TYPE_RSV + FEATURE_TYPE_MEMCPY = 0, + FEATURE_TYPE_RSV } rtFeatureType_t; typedef enum tagMemcpyInfo { - MEMCPY_INFO_SUPPORT_ZEROCOPY = 0, - MEMCPY_INFO_RSV + MEMCPY_INFO_SUPPORT_ZEROCOPY = 0, + MEMCPY_INFO_RSV } rtMemcpyInfo_t; /** @@ -356,6 +356,7 @@ RTS_API rtError_t rtSetDeviceWithoutTsd(int32_t device); * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtDeviceResetWithoutTsd(int32_t device); + #if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) } #endif diff --git a/third_party/fwkacllib/inc/runtime/dvfsprofile.h b/third_party/fwkacllib/inc/runtime/dvfsprofile.h index e27cd832..6e451695 100644 --- a/third_party/fwkacllib/inc/runtime/dvfsprofile.h +++ b/third_party/fwkacllib/inc/runtime/dvfsprofile.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_DVFSPROFILE_H__ #define __CCE_RUNTIME_DVFSPROFILE_H__ diff --git a/third_party/fwkacllib/inc/runtime/event.h b/third_party/fwkacllib/inc/runtime/event.h index f9d2eae2..41e611ea 100644 --- a/third_party/fwkacllib/inc/runtime/event.h +++ b/third_party/fwkacllib/inc/runtime/event.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_EVENT_H__ #define __CCE_RUNTIME_EVENT_H__ diff --git a/third_party/fwkacllib/inc/runtime/kernel.h b/third_party/fwkacllib/inc/runtime/kernel.h index 43c06e67..d3eadd59 100644 --- a/third_party/fwkacllib/inc/runtime/kernel.h +++ b/third_party/fwkacllib/inc/runtime/kernel.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_KERNEL_H__ #define __CCE_RUNTIME_KERNEL_H__ @@ -29,15 +29,15 @@ extern "C" { * @brief shared memory data control */ typedef struct tagRtSmData { - uint64_t L2_mirror_addr; // preload or swap source address - uint32_t L2_data_section_size; // every data size - uint8_t L2_preload; // 1 - preload from mirrorAddr, 0 - no preload - uint8_t modified; // 1 - data will be modified by kernel, 0 - no modified - uint8_t priority; // data priority - int8_t prev_L2_page_offset_base; // remap source section offset - uint8_t L2_page_offset_base; // remap destination section offset - uint8_t L2_load_to_ddr; // 1 - need load out, 0 - no need - uint8_t reserved[2]; // reserved + uint64_t L2_mirror_addr; // preload or swap source address + uint32_t L2_data_section_size; // every data size + uint8_t L2_preload; // 1 - preload from mirrorAddr, 0 - no preload + uint8_t modified; // 1 - data will be modified by kernel, 0 - no modified + uint8_t priority; // data priority + int8_t prev_L2_page_offset_base; // remap source section offset + uint8_t L2_page_offset_base; // remap destination section offset + uint8_t L2_load_to_ddr; // 1 - need load out, 0 - no need + uint8_t reserved[2]; // reserved } rtSmData_t; /** @@ -45,12 +45,12 @@ typedef struct tagRtSmData { * @brief shared memory description */ typedef struct tagRtSmCtrl { - rtSmData_t data[8]; // data description - uint64_t size; // max page Num - uint8_t remap[64]; /* just using for static remap mode, default:0xFF + rtSmData_t data[8]; // data description + uint64_t size; // max page Num + uint8_t remap[64]; /* just using for static remap mode, default:0xFF array index: virtual l2 page id, array value: physic l2 page id */ - uint8_t l2_in_main; // 0-DDR, 1-L2, default:0xFF - uint8_t reserved[3]; + uint8_t l2_in_main; // 0-DDR, 1-L2, default:0xFF + uint8_t reserved[3]; } rtSmDesc_t; typedef rtSmDesc_t rtL2Ctrl_t; @@ -60,10 +60,10 @@ typedef rtSmDesc_t rtL2Ctrl_t; * @brief device binary type */ typedef struct tagRtDevBinary { - uint32_t magic; // magic number - uint32_t version; // version of binary - const void *data; // binary data - uint64_t length; // binary length + uint32_t magic; // magic number + uint32_t version; // version of binary + const void *data; // binary data + uint64_t length; // binary length } rtDevBinary_t; /** @@ -73,15 +73,15 @@ typedef struct tagRtDevBinary { #define ONLINE_PROF_MAX_PMU_NUM (8) typedef struct ProfilefDataInfo { - const void *stubFunc; - uint32_t blockDim; - const void *args; - uint32_t argsSize; - rtSmDesc_t *smDesc; - rtStream_t stream; - uint64_t totalcycle; - uint64_t ovcycle; - uint64_t pmu_cnt[ONLINE_PROF_MAX_PMU_NUM]; + const void *stubFunc; + uint32_t blockDim; + const void *args; + uint32_t argsSize; + rtSmDesc_t *smDesc; + rtStream_t stream; + uint64_t totalcycle; + uint64_t ovcycle; + uint64_t pmu_cnt[ONLINE_PROF_MAX_PMU_NUM]; } rtProfDataInfo_t; /** @@ -89,12 +89,12 @@ typedef struct ProfilefDataInfo { * @brief function mode type */ typedef enum { - FUNC_MODE_NORMAL = 0, - FUNC_MODE_PCTRACE_USERPROFILE_RECORDLOOP, - FUNC_MODE_PCTRACE_USERPROFILE_SKIPLOOP, - FUNC_MODE_PCTRACE_CYCLECNT_RECORDLOOP, - FUNC_MODE_PCTRACE_CYCLECNT_SKIPLOOP, - FUNC_MODE_BUTT + FUNC_MODE_NORMAL = 0, + FUNC_MODE_PCTRACE_USERPROFILE_RECORDLOOP, + FUNC_MODE_PCTRACE_USERPROFILE_SKIPLOOP, + FUNC_MODE_PCTRACE_CYCLECNT_RECORDLOOP, + FUNC_MODE_PCTRACE_CYCLECNT_SKIPLOOP, + FUNC_MODE_BUTT } rtFuncModeType_t; /** @@ -102,23 +102,23 @@ typedef enum { * @brief kernel info */ typedef struct rtKernelInfo { - uint64_t task_offset; // kernel offset in module - /* flowtable */ - void *arg; // launch kernel arg - uint32_t arg_size; - /* module */ - void *module_addr; // module::baseaddr_ - uint32_t module_size; -} * rtKernelInfo_t; + uint64_t task_offset; // kernel offset in module + /* flowtable */ + void *arg; // launch kernel arg + uint32_t arg_size; + /* module */ + void *module_addr; // module::baseaddr_ + uint32_t module_size; +} *rtKernelInfo_t; /** * @ingroup rt_KernelConfigDump * @brief device dump type */ typedef enum tagRtDumpKind { - RT_DATA_DUMP_KIND_INVALID = -1, - RT_DATA_DUMP_KIND_DUMP = 0, - RT_DATA_DUMP_KIND_RESERVED + RT_DATA_DUMP_KIND_INVALID = -1, + RT_DATA_DUMP_KIND_DUMP = 0, + RT_DATA_DUMP_KIND_RESERVED } rtDumpKind_t; /** @@ -414,6 +414,7 @@ RTS_API rtError_t rtDatadumpInfoLoad(const void *dumpInfo, uint32_t length); RTS_API rtError_t rtConfigureCall(uint32_t numBlocks, rtSmDesc_t *smDesc = nullptr, rtStream_t stream = nullptr); #else RTS_API rtError_t rtConfigureCall(uint32_t numBlocks, rtSmDesc_t *smDesc, rtStream_t stream); + #endif #endif // __CLANG_CCE_RUNTIME_H__ diff --git a/third_party/fwkacllib/inc/runtime/mem.h b/third_party/fwkacllib/inc/runtime/mem.h index d5b1b580..30af85d9 100644 --- a/third_party/fwkacllib/inc/runtime/mem.h +++ b/third_party/fwkacllib/inc/runtime/mem.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_MEM_H__ #define __CCE_RUNTIME_MEM_H__ @@ -34,6 +34,7 @@ extern "C" { */ #define RT_MEMORY_DEFAULT ((uint32_t)0x0) // default memory on device #define RT_MEMORY_HBM ((uint32_t)0x2) // HBM memory on device +#define RT_MEMORY_RDMA_HBM ((uint32_t)0x3) // RDMA-HBM memory on device #define RT_MEMORY_DDR ((uint32_t)0x4) // DDR memory on device #define RT_MEMORY_SPM ((uint32_t)0x8) // shared physical memory on device #define RT_MEMORY_P2P_HBM ((uint32_t)0x10) // HBM memory on other 4P device @@ -89,40 +90,40 @@ typedef uint32_t rtMemType_t; * @brief memory copy type */ typedef enum tagRtMemcpyKind { - RT_MEMCPY_HOST_TO_HOST = 0, // host to host - RT_MEMCPY_HOST_TO_DEVICE, // host to device - RT_MEMCPY_DEVICE_TO_HOST, // device to host - RT_MEMCPY_DEVICE_TO_DEVICE, // device to device, 1P && P2P - RT_MEMCPY_MANAGED, // managed memory - RT_MEMCPY_ADDR_DEVICE_TO_DEVICE, - RT_MEMCPY_HOST_TO_DEVICE_EX, // host to device ex (only used for 8 bytes) - RT_MEMCPY_DEVICE_TO_HOST_EX, // device to host ex - RT_MEMCPY_RESERVED, + RT_MEMCPY_HOST_TO_HOST = 0, // host to host + RT_MEMCPY_HOST_TO_DEVICE, // host to device + RT_MEMCPY_DEVICE_TO_HOST, // device to host + RT_MEMCPY_DEVICE_TO_DEVICE, // device to device, 1P && P2P + RT_MEMCPY_MANAGED, // managed memory + RT_MEMCPY_ADDR_DEVICE_TO_DEVICE, + RT_MEMCPY_HOST_TO_DEVICE_EX, // host to device ex (only used for 8 bytes) + RT_MEMCPY_DEVICE_TO_HOST_EX, // device to host ex + RT_MEMCPY_RESERVED, } rtMemcpyKind_t; typedef enum tagRtMemInfoType { - RT_MEMORYINFO_DDR, - RT_MEMORYINFO_HBM, - RT_MEMORYINFO_DDR_HUGE, // Hugepage memory of DDR - RT_MEMORYINFO_DDR_NORMAL, // Normal memory of DDR - RT_MEMORYINFO_HBM_HUGE, // Hugepage memory of HBM - RT_MEMORYINFO_HBM_NORMAL, // Normal memory of HBM - RT_MEMORYINFO_DDR_P2P_HUGE, // Hugepage memory of DDR - RT_MEMORYINFO_DDR_P2P_NORMAL, // Normal memory of DDR - RT_MEMORYINFO_HBM_P2P_HUGE, // Hugepage memory of HBM - RT_MEMORYINFO_HBM_P2P_NORMAL, // Normal memory of HBM + RT_MEMORYINFO_DDR, + RT_MEMORYINFO_HBM, + RT_MEMORYINFO_DDR_HUGE, // Hugepage memory of DDR + RT_MEMORYINFO_DDR_NORMAL, // Normal memory of DDR + RT_MEMORYINFO_HBM_HUGE, // Hugepage memory of HBM + RT_MEMORYINFO_HBM_NORMAL, // Normal memory of HBM + RT_MEMORYINFO_DDR_P2P_HUGE, // Hugepage memory of DDR + RT_MEMORYINFO_DDR_P2P_NORMAL, // Normal memory of DDR + RT_MEMORYINFO_HBM_P2P_HUGE, // Hugepage memory of HBM + RT_MEMORYINFO_HBM_P2P_NORMAL, // Normal memory of HBM } rtMemInfoType_t; typedef enum tagRtRecudeKind { - RT_MEMCPY_SDMA_AUTOMATIC_ADD = 10, // D2D, SDMA inline reduce, include 1P, and P2P - RT_RECUDE_KIND_END + RT_MEMCPY_SDMA_AUTOMATIC_ADD = 10, // D2D, SDMA inline reduce, include 1P, and P2P + RT_RECUDE_KIND_END } rtRecudeKind_t; typedef enum tagRtDataType { - RT_DATA_TYPE_FP32 = 0, // fp32 - RT_DATA_TYPE_FP16 = 1, // fp16 - RT_DATA_TYPE_INT16 = 2, // int16 - RT_DATA_TYPE_END + RT_DATA_TYPE_FP32 = 0, // fp32 + RT_DATA_TYPE_FP16 = 1, // fp16 + RT_DATA_TYPE_INT16 = 2, // int16 + RT_DATA_TYPE_END } rtDataType_t; /** @@ -130,10 +131,10 @@ typedef enum tagRtDataType { * @brief memory copy channel type */ typedef enum tagRtMemcpyChannelType { - RT_MEMCPY_CHANNEL_TYPE_INNER = 0, // 1P - RT_MEMCPY_CHANNEL_TYPE_PCIe, - RT_MEMCPY_CHANNEL_TYPE_HCCs, // not support now - RT_MEMCPY_CHANNEL_TYPE_RESERVED, + RT_MEMCPY_CHANNEL_TYPE_INNER = 0, // 1P + RT_MEMCPY_CHANNEL_TYPE_PCIe, + RT_MEMCPY_CHANNEL_TYPE_HCCs, // not support now + RT_MEMCPY_CHANNEL_TYPE_RESERVED, } rtMemcpyChannelType_t; /** @@ -141,18 +142,18 @@ typedef enum tagRtMemcpyChannelType { * @brief ai core memory size */ typedef struct rtAiCoreMemorySize { - uint32_t l0ASize; - uint32_t l0BSize; - uint32_t l0CSize; - uint32_t l1Size; - uint32_t ubSize; - uint32_t l2Size; - uint32_t l2PageNum; - uint32_t blockSize; - uint64_t bankSize; - uint64_t bankNum; - uint64_t burstInOneBlock; - uint64_t bankGroupNum; + uint32_t l0ASize; + uint32_t l0BSize; + uint32_t l0CSize; + uint32_t l1Size; + uint32_t ubSize; + uint32_t l2Size; + uint32_t l2PageNum; + uint32_t blockSize; + uint64_t bankSize; + uint64_t bankNum; + uint64_t burstInOneBlock; + uint64_t bankGroupNum; } rtAiCoreMemorySize_t; /** @@ -160,10 +161,10 @@ typedef struct rtAiCoreMemorySize { * @brief memory type */ typedef enum tagRtMemoryType { - RT_MEMORY_TYPE_HOST = 1, - RT_MEMORY_TYPE_DEVICE = 2, - RT_MEMORY_TYPE_SVM = 3, - RT_MEMORY_TYPE_DVPP = 4 + RT_MEMORY_TYPE_HOST = 1, + RT_MEMORY_TYPE_DEVICE = 2, + RT_MEMORY_TYPE_SVM = 3, + RT_MEMORY_TYPE_DVPP = 4 } rtMemoryType_t; /** @@ -171,31 +172,31 @@ typedef enum tagRtMemoryType { * @brief memory attribute */ typedef struct tagRtPointerAttributes { - rtMemoryType_t memoryType; // host memory or device memory - rtMemoryType_t locationType; - uint32_t deviceID; // device ID - uint32_t pageSize; + rtMemoryType_t memoryType; // host memory or device memory + rtMemoryType_t locationType; + uint32_t deviceID; // device ID + uint32_t pageSize; } rtPointerAttributes_t; typedef struct rtMallocHostSharedMemoryIn { - const char *name; - const uint64_t size; - uint32_t flag; + const char *name; + const uint64_t size; + uint32_t flag; } rtMallocHostSharedMemoryIn; typedef struct rtMallocHostSharedMemoryOut { - int fd; - void *ptr; - void *devPtr; + int fd; + void *ptr; + void *devPtr; } rtMallocHostSharedMemoryOut; typedef struct rtFreeHostSharedMemoryIn { - const char *name; - const uint64_t size; - int fd; - void *ptr; - void *devPtr; + const char *name; + const uint64_t size; + int fd; + void *ptr; + void *devPtr; } rtFreeHostSharedMemoryIn; diff --git a/third_party/fwkacllib/inc/runtime/rt.h b/third_party/fwkacllib/inc/runtime/rt.h index 0d39389b..83cafa3c 100644 --- a/third_party/fwkacllib/inc/runtime/rt.h +++ b/third_party/fwkacllib/inc/runtime/rt.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_RT_H__ #define __CCE_RUNTIME_RT_H__ diff --git a/third_party/fwkacllib/inc/runtime/rt_model.h b/third_party/fwkacllib/inc/runtime/rt_model.h index c96349a0..b72b142d 100644 --- a/third_party/fwkacllib/inc/runtime/rt_model.h +++ b/third_party/fwkacllib/inc/runtime/rt_model.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_MODEL_H__ #define __CCE_RUNTIME_MODEL_H__ diff --git a/third_party/fwkacllib/inc/runtime/stream.h b/third_party/fwkacllib/inc/runtime/stream.h index b726fbd5..6b9f80ae 100644 --- a/third_party/fwkacllib/inc/runtime/stream.h +++ b/third_party/fwkacllib/inc/runtime/stream.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_STREAM_H__ #define __CCE_RUNTIME_STREAM_H__ diff --git a/third_party/fwkacllib/inc/tdt/index_transform.h b/third_party/fwkacllib/inc/tdt/index_transform.h index a62e0185..a5af2c83 100644 --- a/third_party/fwkacllib/inc/tdt/index_transform.h +++ b/third_party/fwkacllib/inc/tdt/index_transform.h @@ -1,18 +1,10 @@ /** - * Copyright 2019-2020 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. - */ +* @file index_transform.h +* +* Copyright (C) Huawei Technologies Co., Ltd. 2018-2019. All Rights Reserved. +* +* This program is used to get logical device id by phy device id. +*/ #ifndef INC_TDT_INDEX_TRANSFORM_H #define INC_TDT_INDEX_TRANSFORM_H diff --git a/third_party/fwkacllib/inc/tdt/status.h b/third_party/fwkacllib/inc/tdt/status.h index dc9e670f..d5050f35 100644 --- a/third_party/fwkacllib/inc/tdt/status.h +++ b/third_party/fwkacllib/inc/tdt/status.h @@ -1,4 +1,4 @@ -/** +/** * Copyright 2019-2020 Huawei Technologies Co., Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/third_party/fwkacllib/inc/tdt/tdt_host_interface.h b/third_party/fwkacllib/inc/tdt/tdt_host_interface.h index 1cab6fd1..3e7d11ee 100644 --- a/third_party/fwkacllib/inc/tdt/tdt_host_interface.h +++ b/third_party/fwkacllib/inc/tdt/tdt_host_interface.h @@ -61,7 +61,7 @@ int32_t TdtHostInit(uint32_t deviceId); * @li tdt_host_interface.h: Header file where the interface declaration is located. * @li data_common.h: Header file where 'DataItem' defined */ -int32_t TdtHostPushData(const std::string &channelName, const std::vector &item); +int32_t TdtHostPushData(const std::string &channelName, const std::vector &item, uint32_t deviceId = 0); /** * @ingroup TdtHostDestroy @@ -203,25 +203,6 @@ int32_t TdtInFeedDestroy(uint32_t deviceId); * @li tdt_host_interface.h: Header file where the interface declaration is located. */ int32_t TdtOutFeedDestroy(); - -/** -* @ingroup TdtInFeedData -* @brief Blocking queue. When the queue is full, the Push interface will block. -* -* @par Function -* Blocking queue. When the queue is full, the Push interface will block. -* -* @param channelName [IN] type #String. queue channel name -* @param items [IN] type #vector DataItem is defined in data_common.h. input data -* @retval 0 Success -* @retval OtherValues 0 Fail -* -* @par Dependency -* @li libtsdclient.so: Library to which the interface belongs. -* @li tdt_host_interface.h: Header file where the interface declaration is located. -* @li data_common.h: Header file where 'DataItem' defined -*/ -int32_t TdtInFeedData(const std::string &channelName, const std::vector &item, uint32_t deviceId); } // namespace tdt #ifdef __cplusplus } diff --git a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h index 430ed14d..07b32149 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h +++ b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h @@ -17,380 +17,96 @@ #ifndef MSPROFILER_API_PROF_ACL_API_H_ #define MSPROFILER_API_PROF_ACL_API_H_ -#define MSVP_MAX_DEV_NUM 64 +// DataTypeConfig +#define PROF_ACL_API 0x00000001 +#define PROF_TASK_TIME 0x00000002 +#define PROF_AICORE_METRICS 0x00000004 +#define PROF_AICPU_TRACE 0x00000008 +#define PROF_MODEL_EXECUTE 0x00000010 +#define PROF_RUNTIME_API 0x00000020 +#define PROF_RUNTIME_TRACE 0x00000040 +#define PROF_SCHEDULE_TIMELINE 0x00000080 +#define PROF_SCHEDULE_TRACE 0x00000100 +#define PROF_AIVECTORCORE_METRICS 0x00000200 +#define PROF_SUBTASK_TIME 0x00000400 + +#define PROF_TRAINING_TRACE 0x00000800 +#define PROF_HCCL_TRACE 0x00001000 + +#define PROF_TASK_TRACE 0x00001852 + +// system profilinig switch +#define PROF_CPU 0x00010000 +#define PROF_HARDWARE_MEMORY 0x00020000 +#define PROF_IO 0x00040000 +#define PROF_INTER_CONNECTION 0x00080000 +#define PROF_DVPP 0x00100000 +#define PROF_SYS_AICORE_SAMPLE 0x00200000 +#define PROF_AIVECTORCORE_SAMPLE 0x00400000 + +#define PROF_MODEL_LOAD 0x8000000000000000 + +// DataTypeConfig MASK +#define PROF_ACL_API_MASK 0x00000001 +#define PROF_TASK_TIME_MASK 0x00000002 +#define PROF_AICORE_METRICS_MASK 0x00000004 +#define PROF_AICPU_TRACE_MASK 0x00000008 +#define PROF_MODEL_EXECUTE_MASK 0x00000010 +#define PROF_RUNTIME_API_MASK 0x00000020 +#define PROF_RUNTIME_TRACE_MASK 0x00000040 +#define PROF_SCHEDULE_TIMELINE_MASK 0x00000080 +#define PROF_SCHEDULE_TRACE_MASK 0x00000100 +#define PROF_AIVECTORCORE_METRICS_MASK 0x00000200 +#define PROF_SUBTASK_TIME_MASK 0x00000400 + +#define PROF_TRAINING_TRACE_MASK 0x00000800 +#define PROF_HCCL_TRACE_MASK 0x00001000 + +// system profilinig mask +#define PROF_CPU_MASK 0x00010000 +#define PROF_HARDWARE_MEMORY_MASK 0x00020000 +#define PROF_IO_MASK 0x00040000 +#define PROF_INTER_CONNECTION_MASK 0x00080000 +#define PROF_DVPP_MASK 0x00100000 +#define PROF_SYS_AICORE_SAMPLE_MASK 0x00200000 +#define PROF_AIVECTORCORE_SAMPLE_MASK 0x00400000 + +#define PROF_MODEL_LOAD_MASK 0x8000000000000000 + #ifndef OS_TYPE #define OS_TYPE 0 #endif // OS_TYPE - #if (OS_TYPE != LINUX) #define MSVP_PROF_API __declspec(dllexport) #else #define MSVP_PROF_API __attribute__((visibility("default"))) #endif -// DataTypeConfig -#define PROF_ACL_API 0x0001 -#define PROF_TASK_TIME 0x0002 -#define PROF_AICORE_METRICS 0x0004 -#define PROF_AICPU_TRACE 0x0008 -#define PROF_MODEL_EXECUTE 0x0010 -#define PROF_RUNTIME_API 0x0020 -#define PROF_RUNTIME_TRACE 0x0040 -#define PROF_SCHEDULE_TIMELINE 0x0080 -#define PROF_SCHEDULE_TRACE 0x0100 -#define PROF_AIVECTORCORE_METRICS 0x0200 -#define PROF_SUBTASK_TIME 0x0400 - -#define PROF_TRAINING_TRACE 0x0800 -#define PROF_HCCL_TRACE 0x1000 -#define PROF_DATA_PROCESS 0x2000 -#define PROF_TASK_TRACE 0x3842 - -#define PROF_MODEL_LOAD 0x8000000000000000 - -// DataTypeConfig MASK -#define PROF_ACL_API_MASK 0x0001 -#define PROF_TASK_TIME_MASK 0x0002 -#define PROF_AICORE_METRICS_MASK 0x0004 -#define PROF_AICPU_TRACE_MASK 0x0008 -#define PROF_MODEL_EXECUTE_MASK 0x0010 -#define PROF_RUNTIME_API_MASK 0x0020 -#define PROF_RUNTIME_TRACE_MASK 0x0040 -#define PROF_SCHEDULE_TIMELINE_MASK 0x0080 -#define PROF_SCHEDULE_TRACE_MASK 0x0100 -#define PROF_AIVECTORCORE_METRICS_MASK 0x0200 -#define PROF_SUBTASK_TIME_MASK 0x0400 - -#define PROF_TRAINING_TRACE_MASK 0x0800 -#define PROF_HCCL_TRACE_MASK 0x1000 -#define PROF_DATA_PROCESS_MASK 0x2000 - -#define PROF_MODEL_LOAD_MASK 0x8000000000000000 - #include -#include - -/** - * @name ProrErrorCode - * @brief error code enum of prof_acl_apis - */ -enum ProfErrorCode { - PROF_ERROR_NONE = 0, // ok - PROF_ERROR_PARAM_INVALID, // param invalid, for example nullptr - PROF_ERROR_REPEAT_INIT, // profiling has already been inited - PROF_ERROR_CONFIG_INVALID, // config invalid, for example invalid json string - PROF_ERROR_DIR_NO_ACCESS, // dir is not accessable - PROF_ERROR_FAILURE, // failed to init or start profiling - PROF_ERROR_NOT_INITED, // profiling has not been inited - PROF_ERROR_DEVICE_INVALID, // device id invalid - PROF_ERROR_UNSUPPORTED, // unsupported data type or ai core metrics - PROF_ERROR_REPEAT_START, // profiilng has already been started - PROF_ERROR_NOT_STARTED, // profiling has not been started - PROF_ERROR_REPEAT_SUBSCRIBE, // same model id has already been subscribed - PROF_ERROR_MODEL_ID_INVALID, // model id does not exist or has not been subscribed - PROF_ERROR_API_CONFLICT, // prof ctrl api mode conflicts with subscribe mode -}; - -/** - * @brief transfer profiling config in acl.json to sample config - * @param aclCfg [IN] profiling json string from acl.json as {"switch":"on", "result_path":"/home",...} - * @param sampleCfg [OUT] json string for GE as {"startCfg":[{"deviceID":"all","jobID":"1234",...}]} - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfAclCfgToSampleCfg(const std::string &aclCfg, std::string &sampleCfg); - -/** - * @name ProfInit - * @brief init profiling - * @param profInitCfg [IN] config of init profiling of json format - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfInit(const std::string &profInitCfg); - -/** - * @name ProfAicoreMetrics - * @brief aicore metrics enum - */ -enum ProfAicoreMetrics { - PROF_AICORE_ARITHMATIC_THROUGHPUT = 0, - PROF_AICORE_PIPELINE = 1, - PROF_AICORE_SYNCHRONIZATION = 2, - PROF_AICORE_MEMORY = 3, - PROF_AICORE_INTERNAL_MEMORY = 4, - PROF_AICORE_STALL = 5, - PROF_AICORE_METRICS_COUNT, - PROF_AICORE_NONE = 0xff, -}; - -/** - * @name ProfConfig - * @brief struct of ProfStart - */ -struct ProfConfig { - uint32_t devNums; // length of device id list - uint32_t devIdList[MSVP_MAX_DEV_NUM]; // physical device id list - ProfAicoreMetrics aicoreMetrics; // aicore metric - uint64_t dataTypeConfig; // data type to start profiling -}; - -/** - * @name ProfStartProfiling - * @brief start profiling - * @param profStartCfg [IN] config to start profiling - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfStartProfiling(const ProfConfig *profStartCfg); - -/** - * @name ProfStopProfiling - * @brief stop profiling - * @param profStopCfg [IN] config to stop profiling - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfStopProfiling(const ProfConfig *profStopCfg); - -/** - * @name ProfFinalize - * @brief finalize profiling task - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfFinalize(); - -/** - * @name ProfGetDataTypeConfig - * @brief get dataTypeConfig started with of one device - * @param deviceId [IN] deviceId to get dataTypeConfig - * @param dataTypeConfig [OUT] result get - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfGetDataTypeConfig(uint32_t deviceId, uint64_t &dataTypeConfig); namespace Msprofiler { namespace Api { -/** - * @brief transfer profiling config in acl.json to sample config - * @param aclCfg [IN] profiling json string from acl.json as {"switch":"on", "result_path":"/home",...} - * @param sampleCfg [OUT] json string for GE as {"startCfg":[{"deviceID":"all","jobID":"1234",...}]} - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfAclCfgToSampleCfg(const std::string &aclCfg, std::string &sampleCfg); - -/** - * @name ProfInit - * @brief init profiling - * @param profInitCfg [IN] config of init profiling of json format - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfInit(const std::string &profInitCfg); - -/** - * @name ProfStartProfiling - * @brief start profiling - * @param profStartCfg [IN] config to start profiling - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfStartProfiling(const ProfConfig *profStartCfg); - -/** - * @name ProfStopProfiling - * @brief stop profiling - * @param profStopCfg [IN] config to stop profiling - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfStopProfiling(const ProfConfig *profStopCfg); - -/** - * @name ProfFinalize - * @brief finalize profiling task - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfFinalize(); - -/** - * @name ProfGetDataTypeConfig - * @brief get dataTypeConfig started with of one device - * @param deviceId [IN] deviceId to get dataTypeConfig - * @param dataTypeConfig [OUT] result get - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfGetDataTypeConfig(uint32_t deviceId, uint64_t &dataTypeConfig); - -/** - * @name WorkMode - * @brief profiling api work mode - */ -enum WorkMode { - WORK_MODE_OFF, // profiling not at work - WORK_MODE_API_CTRL, // profiling work on api ctrl mode, (ProfInit) - WORK_MODE_SUBSCRIBE, // profiling work on subscribe mode -}; - -/** - * @name ProfGetApiWorkMode - * @brief get profiling api work mode - * @return WorkMode - */ -MSVP_PROF_API WorkMode ProfGetApiWorkMode(); - -/** - * @name ProfSubscribeConfig - * @brief config of subscribe api - */ -struct ProfSubscribeConfig { - bool timeInfo; // subscribe op time - ProfAicoreMetrics aicoreMetrics; // subscribe ai core metrics - void* fd; // pipe fd -}; - -/** - * @name ProfGetDataTypeConfig - * @brief get DataTypeConfig of subscribe - * @param profSubscribeConfig [IN] config to subscribe data - * @return DataTypeConfig - */ -MSVP_PROF_API uint64_t ProfGetDataTypeConfig(const ProfSubscribeConfig *profSubscribeConfig); - -/** - * @name ProfModelSubscribe - * @brief subscribe data of one model id - * @param modelId [IN] model id to subscribe data - * @param devId [IN] device id of model - * @param profSubscribeConfig [IN] config to subscribe data - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfModelSubscribe(uint32_t modelId, uint32_t devId, - const ProfSubscribeConfig *profSubscribeConfig); - -/** - * @name ProfIsModelSubscribed - * @brief check if a model id is subscribed - * @param modeiId [IN] modei id to check - * @return true: subscribed, false: not - */ -MSVP_PROF_API bool ProfIsModelSubscribed(uint32_t modelId); - -/** - * @name ProfModelUnSubscribe - * @brief unsubscribe a model id - * @param modeiId [IN] modei id to unsubscribe - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfModelUnSubscribe(uint32_t modelId); - -/** - * @name ProfGetOpDescSize - * @brief get profiling data struct size - * @param opDescSize [OUT] bytes of profiling subscribe data struct - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfGetOpDescSize(uint32_t *opDescSize); - -/** - * @name ProfGetOpNum - * @brief get how many op data there are in data - * @param data [IN] data read from pipe - * @param len [IN] data length - * @param opNum [OUT] number of op in data - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfGetOpNum(const void *data, uint32_t len, uint32_t *opNum); - -/** - * @name ProfGetModelId - * @brief get model id of specific part of data - * @param data [IN] data read from pipe - * @param len [IN] data length - * @param index [IN] index of part(op) - * @return model id - */ -MSVP_PROF_API uint32_t ProfGetModelId(const void *data, uint32_t len, uint32_t index); - -/** - * @name ProfGetOpType - * @brief get op type of specific part of data - * @param data [IN] data read from pipe - * @param len [IN] data length - * @param opType [OUT] op type buffer - * @param opTypeLen [IN] buffer size of param opType - * @param index [IN] index of part(op) - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfGetOpType(const void *data, uint32_t len, char *opType, uint32_t opTypeLen, uint32_t index); - -/** - * @name ProfGetOpName - * @brief get op name of specific part of data - * @param data [IN] data read from pipe - * @param len [IN] data length - * @param opType [OUT] op name buffer - * @param opTypeLen [IN] buffer size of param opName - * @param index [IN] index of part(op) - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfGetOpName(const void *data, uint32_t len, char *opName, uint32_t opNameLen, uint32_t index); - -/** - * @name ProfGetOpStart - * @brief get op start timestamp of specific part of data - * @param data [IN] data read from pipe - * @param len [IN] data length - * @param index [IN] index of part(op) - * @return op start timestamp (us) - */ -MSVP_PROF_API uint64_t ProfGetOpStart(const void *data, uint32_t len, uint32_t index); - -/** - * @name ProfGetOpEnd - * @brief get op end timestamp of specific part of data - * @param data [IN] data read from pipe - * @param len [IN] data length - * @param index [IN] index of part(op) - * @return op end timestamp (us) - */ -MSVP_PROF_API uint64_t ProfGetOpEnd(const void *data, uint32_t len, uint32_t index); - -/** - * @name ProfGetOpDuration - * @brief get op duration of specific part of data - * @param data [IN] data read from pipe - * @param len [IN] data length - * @param index [IN] index of part(op) - * @return op duration (us) - */ -MSVP_PROF_API uint64_t ProfGetOpDuration(const void *data, uint32_t len, uint32_t index); - /** * @name ProfGetOpExecutionTime * @brief get op execution time of specific part of data - * @param data [IN] data read from pipe - * @param len [IN] data length + * @param data [IN] data read from pipe + * @param len [IN] data length * @param index [IN] index of part(op) * @return op execution time (us) */ MSVP_PROF_API uint64_t ProfGetOpExecutionTime(const void *data, uint32_t len, uint32_t index); +} +} -/** - * @name ProfGetOpCubeOps - * @brief get op cube fops of specific part of data - * @param data [IN] data read from pipe - * @param len [IN] data length - * @param index [IN] index of part(op) - * @return op cube fops - */ -MSVP_PROF_API uint64_t ProfGetOpCubeOps(const void *data, uint32_t len, uint32_t index); +#ifdef __cplusplus +extern "C" { +#endif -/** - * @name ProfGetOpVectorOps - * @brief get op vector fops of specific part of data - * @param data [IN] data read from pipe - * @param len [IN] data length - * @param index [IN] index of part(op) - * @return op vector fops - */ -MSVP_PROF_API uint64_t ProfGetOpVectorOps(const void *data, uint32_t len, uint32_t index); +MSVP_PROF_API uint64_t ProfGetOpExecutionTime(const void *data, uint32_t len, uint32_t index); -} // namespace Api -} // namespace Msprofiler +#ifdef __cplusplus +} +#endif #endif // MSPROFILER_API_PROF_ACL_API_H_ diff --git a/third_party/fwkacllib/inc/toolchain/prof_reporter.h b/third_party/fwkacllib/inc/toolchain/prof_reporter.h index 3ae5f8ef..ff91351b 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_reporter.h +++ b/third_party/fwkacllib/inc/toolchain/prof_reporter.h @@ -26,6 +26,8 @@ #define MSVP_PROF_API __attribute__((visibility("default"))) #endif +#include "prof_callback.h" + /** * @file prof_reporter.h * @defgroup reporter the reporter group diff --git a/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h b/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h index 87fdcbeb..6208f462 100644 --- a/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h +++ b/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h @@ -1,78 +1,72 @@ -/** - * Copyright 2019-2020 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. - */ - -/** @defgroup mstune mstune调优接口 */ -#ifndef TUNE_API_H -#define TUNE_API_H -#include -#include -#include -#include "graph/graph.h" -#include "ge/ge_api.h" - -/** - * @ingroup mstune - * - * mstune status - */ -enum MsTuneStatus { - MSTUNE_SUCCESS, /** tune success */ - MSTUNE_FAILED, /** tune failed */ -}; - -// Option key: for train options sets -const std::string MSTUNE_SELF_KEY = "mstune"; -const std::string MSTUNE_GEINIT_KEY = "initialize"; -const std::string MSTUNE_GESESS_KEY = "session"; - -/** - * @ingroup mstune - * @par 描述: 命令行调优 - * - * @attention 无 - * @param option [IN] 调优参数 - * @param msg [OUT] 调优异常下返回信息 - * @retval #MSTUNE_SUCCESS 执行成功 - * @retval #MSTUNE_FAILED 执行失败 - * @par 依赖: - * @li tune_api.cpp:该接口所属的开发包。 - * @li tune_api.h:该接口声明所在的头文件。 - * @see 无 - * @since - */ -MsTuneStatus MsTuning(const std::map &option, std::string &msg); - -/** - * @ingroup mstune - * @par 描述: 梯度调优 - * - * @attention 无 - * @param tuningGraph [IN] 调优图 - * @param dependGraph [IN] 调优依赖图 - * @param session [IN] ge连接会话 - * @param option [IN] 参数集. 包含调优参数及ge参数 - * @retval #MSTUNE_SUCCESS 执行成功 - * @retval #MSTUNE_FAILED 执行失败 - * @par 依赖: - * @li tune_api.cpp:该接口所属的开发包。 - * @li tune_api.h:该接口声明所在的头文件。 - * @see 无 - * @since - */ -extern "C" MsTuneStatus MsTrainTuning(ge::Graph &tuningGraph, std::vector &dependGraph, - ge::Session *session, const std::map> &option); - -#endif +/** + * @file tune_api.h + * + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.\n + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n + * 描述:mstune调优接口头文件 + */ +/** @defgroup mstune mstune调优接口 */ +#ifndef TUNE_API_H +#define TUNE_API_H +#include +#include +#include +#include "graph/graph.h" +#include "ge/ge_api.h" + +/** + * @ingroup mstune + * + * mstune status + */ +enum MsTuneStatus { + MSTUNE_SUCCESS, /** tune success */ + MSTUNE_FAILED, /** tune failed */ +}; + +// Option key: for train options sets +const std::string MSTUNE_SELF_KEY = "mstune"; +const std::string MSTUNE_GEINIT_KEY = "initialize"; +const std::string MSTUNE_GESESS_KEY = "session"; + +/** + * @ingroup mstune + * @par 描述: 命令行调优 + * + * @attention 无 + * @param option [IN] 调优参数 + * @param msg [OUT] 调优异常下返回信息 + * @retval #MSTUNE_SUCCESS 执行成功 + * @retval #MSTUNE_FAILED 执行失败 + * @par 依赖: + * @li tune_api.cpp:该接口所属的开发包。 + * @li tune_api.h:该接口声明所在的头文件。 + * @see 无 + * @since + */ +MsTuneStatus MsTuning(const std::map &option, std::string &msg); + +/** + * @ingroup mstune + * @par 描述: 梯度调优 + * + * @attention 无 + * @param tuningGraph [IN] 调优图 + * @param dependGraph [IN] 调优依赖图 + * @param session [IN] ge连接会话 + * @param option [IN] 参数集. 包含调优参数及ge参数 + * @retval #MSTUNE_SUCCESS 执行成功 + * @retval #MSTUNE_FAILED 执行失败 + * @par 依赖: + * @li tune_api.cpp:该接口所属的开发包。 + * @li tune_api.h:该接口声明所在的头文件。 + * @see 无 + * @since + */ +extern "C" MsTuneStatus MsTrainTuning(ge::Graph &tuningGraph, std::vector &dependGraph, + ge::Session *session, const std::map> &option); + +#endif From e3b32cd2a098ac4905f23715be833240068c1998 Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Sat, 16 Jan 2021 17:22:20 +0800 Subject: [PATCH 07/59] clang-format --- inc/external/acl/acl_base.h | 84 ++--- inc/external/acl/acl_mdl.h | 356 ++++++++---------- inc/external/acl/acl_op.h | 119 ++---- inc/external/acl/acl_op_compiler.h | 47 +-- inc/external/acl/acl_prof.h | 42 +-- inc/external/acl/acl_rt.h | 140 +++---- inc/external/acl/acl_tdt.h | 31 +- inc/external/acl/error_codes/rt_error_codes.h | 135 ++++--- inc/external/acl/ops/acl_cblas.h | 179 ++------- inc/external/acl/ops/acl_dvpp.h | 348 +++++++---------- inc/external/acl/ops/acl_fv.h | 14 +- inc/external/hccl/hccl.h | 33 +- inc/external/hccl/hccl_types.h | 84 ++--- inc/external/runtime/rt_error_codes.h | 135 ++++--- 14 files changed, 735 insertions(+), 1012 deletions(-) diff --git a/inc/external/acl/acl_base.h b/inc/external/acl/acl_base.h index 12a25119..b3111860 100644 --- a/inc/external/acl/acl_base.h +++ b/inc/external/acl/acl_base.h @@ -134,42 +134,42 @@ static const int ACL_ERROR_PROFILING_FAILURE = 500005; #define ACL_UNKNOWN_RANK 0xFFFFFFFFFFFFFFFE typedef enum { - ACL_DT_UNDEFINED = -1, - ACL_FLOAT = 0, - ACL_FLOAT16 = 1, - ACL_INT8 = 2, - ACL_INT32 = 3, - ACL_UINT8 = 4, - ACL_INT16 = 6, - ACL_UINT16 = 7, - ACL_UINT32 = 8, - ACL_INT64 = 9, - ACL_UINT64 = 10, - ACL_DOUBLE = 11, - ACL_BOOL = 12, - ACL_STRING = 13, + ACL_DT_UNDEFINED = -1, + ACL_FLOAT = 0, + ACL_FLOAT16 = 1, + ACL_INT8 = 2, + ACL_INT32 = 3, + ACL_UINT8 = 4, + ACL_INT16 = 6, + ACL_UINT16 = 7, + ACL_UINT32 = 8, + ACL_INT64 = 9, + ACL_UINT64 = 10, + ACL_DOUBLE = 11, + ACL_BOOL = 12, + ACL_STRING = 13, } aclDataType; typedef enum { - ACL_FORMAT_UNDEFINED = -1, - ACL_FORMAT_NCHW = 0, - ACL_FORMAT_NHWC = 1, - ACL_FORMAT_ND = 2, - ACL_FORMAT_NC1HWC0 = 3, - ACL_FORMAT_FRACTAL_Z = 4, - ACL_FORMAT_NC1HWC0_C04 = 12, - ACL_FORMAT_NDHWC = 27, - ACL_FORMAT_FRACTAL_NZ = 29, - ACL_FORMAT_NCDHW = 30, - ACL_FORMAT_NDC1HWC0 = 32, - ACL_FRACTAL_Z_3D = 33 + ACL_FORMAT_UNDEFINED = -1, + ACL_FORMAT_NCHW = 0, + ACL_FORMAT_NHWC = 1, + ACL_FORMAT_ND = 2, + ACL_FORMAT_NC1HWC0 = 3, + ACL_FORMAT_FRACTAL_Z = 4, + ACL_FORMAT_NC1HWC0_C04 = 12, + ACL_FORMAT_NDHWC = 27, + ACL_FORMAT_FRACTAL_NZ = 29, + ACL_FORMAT_NCDHW = 30, + ACL_FORMAT_NDC1HWC0 = 32, + ACL_FRACTAL_Z_3D = 33 } aclFormat; typedef enum { - ACL_DEBUG = 0, - ACL_INFO = 1, - ACL_WARNING = 2, - ACL_ERROR = 3, + ACL_DEBUG = 0, + ACL_INFO = 1, + ACL_WARNING = 2, + ACL_ERROR = 3, } aclLogLevel; /** @@ -304,9 +304,7 @@ ACL_FUNC_VISIBILITY size_t aclDataTypeSize(aclDataType dataType); * @retval aclTensorDesc pointer. * @retval nullptr if param is invalid or run out of memory */ -ACL_FUNC_VISIBILITY aclTensorDesc *aclCreateTensorDesc(aclDataType dataType, - int numDims, - const int64_t *dims, +ACL_FUNC_VISIBILITY aclTensorDesc *aclCreateTensorDesc(aclDataType dataType, int numDims, const int64_t *dims, aclFormat format); /** @@ -328,8 +326,7 @@ ACL_FUNC_VISIBILITY void aclDestroyTensorDesc(const aclTensorDesc *desc); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclSetTensorShapeRange(aclTensorDesc* desc, - size_t dimsCount, +ACL_FUNC_VISIBILITY aclError aclSetTensorShapeRange(aclTensorDesc *desc, size_t dimsCount, int64_t dimsRange[][ACL_TENSOR_SHAPE_RANGE_NUM]); /** @@ -426,9 +423,7 @@ ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimV2(const aclTensorDesc *desc, si * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimRange(const aclTensorDesc *desc, - size_t index, - size_t dimRangeNum, +ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimRange(const aclTensorDesc *desc, size_t index, size_t dimRangeNum, int64_t *dimRange); /** @@ -465,7 +460,7 @@ ACL_FUNC_VISIBILITY const char *aclGetTensorDescName(aclTensorDesc *desc); * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclTransTensorDescFormat(const aclTensorDesc *srcDesc, aclFormat dstFormat, - aclTensorDesc **dstDesc); + aclTensorDesc **dstDesc); /** * @ingroup AscendCL @@ -553,7 +548,7 @@ ACL_FUNC_VISIBILITY aclError aclSetTensorOriginShape(aclTensorDesc *desc, int nu * * @retval null for failed. * @retval OtherValues success. -*/ + */ ACL_FUNC_VISIBILITY aclTensorDesc *aclGetTensorDescByIndex(aclTensorDesc *desc, size_t index); /** @@ -564,7 +559,7 @@ ACL_FUNC_VISIBILITY aclTensorDesc *aclGetTensorDescByIndex(aclTensorDesc *desc, * * @retval null for failed * @retval OtherValues success -*/ + */ ACL_FUNC_VISIBILITY void *aclGetTensorDescAddress(const aclTensorDesc *desc); /** @@ -604,13 +599,12 @@ ACL_FUNC_VISIBILITY aclError aclSetTensorConst(aclTensorDesc *desc, void *dataBu * @param ... [IN] the value of current log */ ACL_FUNC_VISIBILITY void aclAppLog(aclLogLevel logLevel, const char *func, const char *file, uint32_t line, - const char *fmt, ...); + const char *fmt, ...); -#define ACL_APP_LOG(level, fmt, ...) \ - aclAppLog(level, __FUNCTION__, __FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define ACL_APP_LOG(level, fmt, ...) aclAppLog(level, __FUNCTION__, __FILE__, __LINE__, fmt, ##__VA_ARGS__) #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_BASE_H_ +#endif // INC_EXTERNAL_ACL_ACL_BASE_H_ diff --git a/inc/external/acl/acl_mdl.h b/inc/external/acl/acl_mdl.h index 4f3e257f..5886d857 100644 --- a/inc/external/acl/acl_mdl.h +++ b/inc/external/acl/acl_mdl.h @@ -27,19 +27,19 @@ extern "C" { #endif -#define ACL_MAX_DIM_CNT 128 -#define ACL_MAX_TENSOR_NAME_LEN 128 -#define ACL_MAX_BATCH_NUM 128 -#define ACL_MAX_HW_NUM 128 -#define ACL_MAX_SHAPE_COUNT 128 -#define ACL_INVALID_NODE_INDEX 0xFFFFFFFF - -#define ACL_MDL_LOAD_FROM_FILE 1 -#define ACL_MDL_LOAD_FROM_FILE_WITH_MEM 2 -#define ACL_MDL_LOAD_FROM_MEM 3 -#define ACL_MDL_LOAD_FROM_MEM_WITH_MEM 4 -#define ACL_MDL_LOAD_FROM_FILE_WITH_Q 5 -#define ACL_MDL_LOAD_FROM_MEM_WITH_Q 6 +#define ACL_MAX_DIM_CNT 128 +#define ACL_MAX_TENSOR_NAME_LEN 128 +#define ACL_MAX_BATCH_NUM 128 +#define ACL_MAX_HW_NUM 128 +#define ACL_MAX_SHAPE_COUNT 128 +#define ACL_INVALID_NODE_INDEX 0xFFFFFFFF + +#define ACL_MDL_LOAD_FROM_FILE 1 +#define ACL_MDL_LOAD_FROM_FILE_WITH_MEM 2 +#define ACL_MDL_LOAD_FROM_MEM 3 +#define ACL_MDL_LOAD_FROM_MEM_WITH_MEM 4 +#define ACL_MDL_LOAD_FROM_FILE_WITH_Q 5 +#define ACL_MDL_LOAD_FROM_MEM_WITH_Q 6 #define ACL_DYNAMIC_TENSOR_NAME "ascend_mbatch_shape_data" #define ACL_DYNAMIC_AIPP_NAME "ascend_dynamic_aipp_data" @@ -51,123 +51,123 @@ typedef struct aclAippExtendInfo aclAippExtendInfo; typedef struct aclmdlConfigHandle aclmdlConfigHandle; typedef enum { - ACL_YUV420SP_U8 = 1, - ACL_XRGB8888_U8, - ACL_RGB888_U8, - ACL_YUV400_U8, - ACL_NC1HWC0DI_FP16, - ACL_NC1HWC0DI_S8, - ACL_ARGB8888_U8, - ACL_YUYV_U8, - ACL_YUV422SP_U8, - ACL_AYUV444_U8, - ACL_RAW10, - ACL_RAW12, - ACL_RAW16, - ACL_RAW24, - ACL_AIPP_RESERVED = 0xffff, + ACL_YUV420SP_U8 = 1, + ACL_XRGB8888_U8, + ACL_RGB888_U8, + ACL_YUV400_U8, + ACL_NC1HWC0DI_FP16, + ACL_NC1HWC0DI_S8, + ACL_ARGB8888_U8, + ACL_YUYV_U8, + ACL_YUV422SP_U8, + ACL_AYUV444_U8, + ACL_RAW10, + ACL_RAW12, + ACL_RAW16, + ACL_RAW24, + ACL_AIPP_RESERVED = 0xffff, } aclAippInputFormat; typedef enum { - ACL_MDL_PRIORITY_INT32 = 0, - ACL_MDL_LOAD_TYPE_SIZET, - ACL_MDL_PATH_PTR, /**< pointer to model load path with deep copy */ - ACL_MDL_MEM_ADDR_PTR, /**< pointer to model memory with shallow copy */ - ACL_MDL_MEM_SIZET, - ACL_MDL_WEIGHT_ADDR_PTR, /**< pointer to weight memory of model with shallow copy */ - ACL_MDL_WEIGHT_SIZET, - ACL_MDL_WORKSPACE_ADDR_PTR, /**< pointer to worksapce memory of model with shallow copy */ - ACL_MDL_WORKSPACE_SIZET, - ACL_MDL_INPUTQ_NUM_SIZET, - ACL_MDL_INPUTQ_ADDR_PTR, /**< pointer to inputQ with shallow copy */ - ACL_MDL_OUTPUTQ_NUM_SIZET, - ACL_MDL_OUTPUTQ_ADDR_PTR /**< pointer to outputQ with shallow copy */ + ACL_MDL_PRIORITY_INT32 = 0, + ACL_MDL_LOAD_TYPE_SIZET, + ACL_MDL_PATH_PTR, /**< pointer to model load path with deep copy */ + ACL_MDL_MEM_ADDR_PTR, /**< pointer to model memory with shallow copy */ + ACL_MDL_MEM_SIZET, + ACL_MDL_WEIGHT_ADDR_PTR, /**< pointer to weight memory of model with shallow copy */ + ACL_MDL_WEIGHT_SIZET, + ACL_MDL_WORKSPACE_ADDR_PTR, /**< pointer to worksapce memory of model with shallow copy */ + ACL_MDL_WORKSPACE_SIZET, + ACL_MDL_INPUTQ_NUM_SIZET, + ACL_MDL_INPUTQ_ADDR_PTR, /**< pointer to inputQ with shallow copy */ + ACL_MDL_OUTPUTQ_NUM_SIZET, + ACL_MDL_OUTPUTQ_ADDR_PTR /**< pointer to outputQ with shallow copy */ } aclmdlConfigAttr; typedef enum { - ACL_DATA_WITHOUT_AIPP = 0, - ACL_DATA_WITH_STATIC_AIPP, - ACL_DATA_WITH_DYNAMIC_AIPP, - ACL_DYNAMIC_AIPP_NODE + ACL_DATA_WITHOUT_AIPP = 0, + ACL_DATA_WITH_STATIC_AIPP, + ACL_DATA_WITH_DYNAMIC_AIPP, + ACL_DYNAMIC_AIPP_NODE } aclmdlInputAippType; typedef struct aclmdlIODims { - char name[ACL_MAX_TENSOR_NAME_LEN]; /**< tensor name */ - size_t dimCount; /**< dim array count */ - int64_t dims[ACL_MAX_DIM_CNT]; /**< dim data array */ + char name[ACL_MAX_TENSOR_NAME_LEN]; /**< tensor name */ + size_t dimCount; /**< dim array count */ + int64_t dims[ACL_MAX_DIM_CNT]; /**< dim data array */ } aclmdlIODims; typedef struct aclAippDims { - aclmdlIODims srcDims; /**< input dims before model transform */ - size_t srcSize; /**< input size before model transform */ - aclmdlIODims aippOutdims; /**< aipp output dims */ - size_t aippOutSize; /**< aipp output size */ + aclmdlIODims srcDims; /**< input dims before model transform */ + size_t srcSize; /**< input size before model transform */ + aclmdlIODims aippOutdims; /**< aipp output dims */ + size_t aippOutSize; /**< aipp output size */ } aclAippDims; typedef struct aclmdlBatch { - size_t batchCount; /**< batch array count */ - uint64_t batch[ACL_MAX_BATCH_NUM]; /**< batch data array */ + size_t batchCount; /**< batch array count */ + uint64_t batch[ACL_MAX_BATCH_NUM]; /**< batch data array */ } aclmdlBatch; typedef struct aclmdlHW { - size_t hwCount; /**< height&width array count */ - uint64_t hw[ACL_MAX_HW_NUM][2]; /**< height&width data array */ + size_t hwCount; /**< height&width array count */ + uint64_t hw[ACL_MAX_HW_NUM][2]; /**< height&width data array */ } aclmdlHW; typedef struct aclAippInfo { - aclAippInputFormat inputFormat; - int32_t srcImageSizeW; - int32_t srcImageSizeH; - int8_t cropSwitch; - int32_t loadStartPosW; - int32_t loadStartPosH; - int32_t cropSizeW; - int32_t cropSizeH; - int8_t resizeSwitch; - int32_t resizeOutputW; - int32_t resizeOutputH; - int8_t paddingSwitch; - int32_t leftPaddingSize; - int32_t rightPaddingSize; - int32_t topPaddingSize; - int32_t bottomPaddingSize; - int8_t cscSwitch; - int8_t rbuvSwapSwitch; - int8_t axSwapSwitch; - int8_t singleLineMode; - int32_t matrixR0C0; - int32_t matrixR0C1; - int32_t matrixR0C2; - int32_t matrixR1C0; - int32_t matrixR1C1; - int32_t matrixR1C2; - int32_t matrixR2C0; - int32_t matrixR2C1; - int32_t matrixR2C2; - int32_t outputBias0; - int32_t outputBias1; - int32_t outputBias2; - int32_t inputBias0; - int32_t inputBias1; - int32_t inputBias2; - int32_t meanChn0; - int32_t meanChn1; - int32_t meanChn2; - int32_t meanChn3; - float minChn0; - float minChn1; - float minChn2; - float minChn3; - float varReciChn0; - float varReciChn1; - float varReciChn2; - float varReciChn3; - aclFormat srcFormat; - aclDataType srcDatatype; - size_t srcDimNum; - size_t shapeCount; - aclAippDims outDims[ACL_MAX_SHAPE_COUNT]; - aclAippExtendInfo *aippExtend; /**< reserved parameters, current version needs to be null */ + aclAippInputFormat inputFormat; + int32_t srcImageSizeW; + int32_t srcImageSizeH; + int8_t cropSwitch; + int32_t loadStartPosW; + int32_t loadStartPosH; + int32_t cropSizeW; + int32_t cropSizeH; + int8_t resizeSwitch; + int32_t resizeOutputW; + int32_t resizeOutputH; + int8_t paddingSwitch; + int32_t leftPaddingSize; + int32_t rightPaddingSize; + int32_t topPaddingSize; + int32_t bottomPaddingSize; + int8_t cscSwitch; + int8_t rbuvSwapSwitch; + int8_t axSwapSwitch; + int8_t singleLineMode; + int32_t matrixR0C0; + int32_t matrixR0C1; + int32_t matrixR0C2; + int32_t matrixR1C0; + int32_t matrixR1C1; + int32_t matrixR1C2; + int32_t matrixR2C0; + int32_t matrixR2C1; + int32_t matrixR2C2; + int32_t outputBias0; + int32_t outputBias1; + int32_t outputBias2; + int32_t inputBias0; + int32_t inputBias1; + int32_t inputBias2; + int32_t meanChn0; + int32_t meanChn1; + int32_t meanChn2; + int32_t meanChn3; + float minChn0; + float minChn1; + float minChn2; + float minChn3; + float varReciChn0; + float varReciChn1; + float varReciChn2; + float varReciChn3; + aclFormat srcFormat; + aclDataType srcDatatype; + size_t srcDimNum; + size_t shapeCount; + aclAippDims outDims[ACL_MAX_SHAPE_COUNT]; + aclAippExtendInfo *aippExtend; /**< reserved parameters, current version needs to be null */ } aclAippInfo; /** @@ -339,8 +339,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFile(const char *modelPath, uint32_t * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMem(const void *model, size_t modelSize, - uint32_t *modelId); +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMem(const void *model, size_t modelSize, uint32_t *modelId); /** * @ingroup AscendCL @@ -362,9 +361,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMem(const void *model, size_t modelS * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithMem(const char *modelPath, - uint32_t *modelId, void *workPtr, size_t workSize, - void *weightPtr, size_t weightSize); +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithMem(const char *modelPath, uint32_t *modelId, void *workPtr, + size_t workSize, void *weightPtr, size_t weightSize); /** * @ingroup AscendCL @@ -387,9 +385,9 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithMem(const char *modelPath, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithMem(const void *model, size_t modelSize, - uint32_t *modelId, void *workPtr, size_t workSize, - void *weightPtr, size_t weightSize); +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithMem(const void *model, size_t modelSize, uint32_t *modelId, + void *workPtr, size_t workSize, void *weightPtr, + size_t weightSize); /** * @ingroup AscendCL @@ -424,8 +422,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithQ(const char *modelPath, uint * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithQ(const void *model, size_t modelSize, uint32_t *modelId, - const uint32_t *inputQ, size_t inputQNum, - const uint32_t *outputQ, size_t outputQNum); + const uint32_t *inputQ, size_t inputQNum, const uint32_t *outputQ, + size_t outputQNum); /** * @ingroup AscendCL @@ -455,8 +453,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlExecute(uint32_t modelId, const aclmdlDataset * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem */ -ACL_FUNC_VISIBILITY aclError aclmdlExecuteAsync(uint32_t modelId, const aclmdlDataset *input, - aclmdlDataset *output, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclmdlExecuteAsync(uint32_t modelId, const aclmdlDataset *input, aclmdlDataset *output, + aclrtStream stream); /** * @ingroup AscendCL @@ -831,11 +829,11 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPInputFormat(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, int8_t csc_switch, - int16_t cscMatrixR0C0, int16_t cscMatrixR0C1, int16_t cscMatrixR0C2, - int16_t cscMatrixR1C0, int16_t cscMatrixR1C1, int16_t cscMatrixR1C2, - int16_t cscMatrixR2C0, int16_t cscMatrixR2C1, int16_t cscMatrixR2C2, + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, int8_t csc_switch, int16_t cscMatrixR0C0, + int16_t cscMatrixR0C1, int16_t cscMatrixR0C2, int16_t cscMatrixR1C0, + int16_t cscMatrixR1C1, int16_t cscMatrixR1C2, int16_t cscMatrixR2C0, + int16_t cscMatrixR2C1, int16_t cscMatrixR2C2, uint8_t cscOutputBiasR0, uint8_t cscOutputBiasR1, uint8_t cscOutputBiasR2, uint8_t cscInputBiasR0, uint8_t cscInputBiasR1, uint8_t cscInputBiasR2); @@ -851,7 +849,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, in * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPRbuvSwapSwitch(aclmdlAIPP *aippParmsSet, int8_t rbuvSwapSwitch); /** @@ -865,7 +863,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPRbuvSwapSwitch(aclmdlAIPP *aippParmsSe * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPAxSwapSwitch(aclmdlAIPP *aippParmsSet, int8_t axSwapSwitch); /** @@ -880,7 +878,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPAxSwapSwitch(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPSrcImageSize(aclmdlAIPP *aippParmsSet, int32_t srcImageSizeW, int32_t srcImageSizeH); @@ -900,14 +898,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPSrcImageSize(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPScfParams(aclmdlAIPP *aippParmsSet, - int8_t scfSwitch, - int32_t scfInputSizeW, - int32_t scfInputSizeH, - int32_t scfOutputSizeW, - int32_t scfOutputSizeH, - uint64_t batchIndex); + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPScfParams(aclmdlAIPP *aippParmsSet, int8_t scfSwitch, int32_t scfInputSizeW, + int32_t scfInputSizeH, int32_t scfOutputSizeW, + int32_t scfOutputSizeH, uint64_t batchIndex); /** * @ingroup AscendCL @@ -925,13 +919,9 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPScfParams(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCropParams(aclmdlAIPP *aippParmsSet, - int8_t cropSwitch, - int32_t cropStartPosW, - int32_t cropStartPosH, - int32_t cropSizeW, - int32_t cropSizeH, + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCropParams(aclmdlAIPP *aippParmsSet, int8_t cropSwitch, int32_t cropStartPosW, + int32_t cropStartPosH, int32_t cropSizeW, int32_t cropSizeH, uint64_t batchIndex); /** @@ -950,7 +940,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCropParams(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPaddingParams(aclmdlAIPP *aippParmsSet, int8_t paddingSwitch, int32_t paddingSizeTop, int32_t paddingSizeBottom, int32_t paddingSizeLeft, int32_t paddingSizeRight, @@ -971,13 +961,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPaddingParams(aclmdlAIPP *aippParmsSet * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMean(aclmdlAIPP *aippParmsSet, - int16_t dtcPixelMeanChn0, - int16_t dtcPixelMeanChn1, - int16_t dtcPixelMeanChn2, - int16_t dtcPixelMeanChn3, - uint64_t batchIndex); + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMean(aclmdlAIPP *aippParmsSet, int16_t dtcPixelMeanChn0, + int16_t dtcPixelMeanChn1, int16_t dtcPixelMeanChn2, + int16_t dtcPixelMeanChn3, uint64_t batchIndex); /** * @ingroup AscendCL @@ -994,13 +981,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMean(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMin(aclmdlAIPP *aippParmsSet, - float dtcPixelMinChn0, - float dtcPixelMinChn1, - float dtcPixelMinChn2, - float dtcPixelMinChn3, - uint64_t batchIndex); + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMin(aclmdlAIPP *aippParmsSet, float dtcPixelMinChn0, + float dtcPixelMinChn1, float dtcPixelMinChn2, + float dtcPixelMinChn3, uint64_t batchIndex); /** * @ingroup AscendCL @@ -1017,13 +1001,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMin(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPixelVarReci(aclmdlAIPP *aippParmsSet, - float dtcPixelVarReciChn0, - float dtcPixelVarReciChn1, - float dtcPixelVarReciChn2, - float dtcPixelVarReciChn3, - uint64_t batchIndex); + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPixelVarReci(aclmdlAIPP *aippParmsSet, float dtcPixelVarReciChn0, + float dtcPixelVarReciChn1, float dtcPixelVarReciChn2, + float dtcPixelVarReciChn3, uint64_t batchIndex); /** * @ingroup AscendCL @@ -1039,10 +1020,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPixelVarReci(aclmdlAIPP *aippParmsSet, * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetInputAIPP(uint32_t modelId, - aclmdlDataset *dataset, - size_t index, + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetInputAIPP(uint32_t modelId, aclmdlDataset *dataset, size_t index, const aclmdlAIPP *aippParmsSet); /** @@ -1059,10 +1038,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetInputAIPP(uint32_t modelId, * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPByInputIndex(uint32_t modelId, - aclmdlDataset *dataset, - size_t index, + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPByInputIndex(uint32_t modelId, aclmdlDataset *dataset, size_t index, const aclmdlAIPP *aippParmsSet); /** @@ -1080,10 +1057,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPByInputIndex(uint32_t modelId, * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, - size_t index, - aclmdlInputAippType *type, + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, size_t index, aclmdlInputAippType *type, size_t *dynamicAttachedDataIndex); /** @@ -1100,7 +1075,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlGetFirstAippInfo(uint32_t modelId, size_t index, aclAippInfo *aippinfo); /** @@ -1119,10 +1094,11 @@ ACL_FUNC_VISIBILITY aclError aclmdlGetFirstAippInfo(uint32_t modelId, size_t ind * * @retval ACL_SUCCESS The function is successfully executed * @retval OtherValues Failure -*/ -ACL_FUNC_VISIBILITY aclError aclmdlCreateAndGetOpDesc(uint32_t deviceId, uint32_t streamId, - uint32_t taskId, char *opName, size_t opNameLen, aclTensorDesc **inputDesc, size_t *numInputs, - aclTensorDesc **outputDesc, size_t *numOutputs); + */ +ACL_FUNC_VISIBILITY aclError aclmdlCreateAndGetOpDesc(uint32_t deviceId, uint32_t streamId, uint32_t taskId, + char *opName, size_t opNameLen, aclTensorDesc **inputDesc, + size_t *numInputs, aclTensorDesc **outputDesc, + size_t *numOutputs); /** * @ingroup AscendCL @@ -1130,7 +1106,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlCreateAndGetOpDesc(uint32_t deviceId, uint32_ * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlInitDump(); /** @@ -1141,7 +1117,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlInitDump(); * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlSetDump(const char *dumpCfgPath); /** @@ -1150,7 +1126,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetDump(const char *dumpCfgPath); * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlFinalizeDump(); /** @@ -1162,7 +1138,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlFinalizeDump(); * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlLoadWithConfig(const aclmdlConfigHandle *handle, uint32_t *modelId); /** @@ -1172,7 +1148,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadWithConfig(const aclmdlConfigHandle *hand * @retval the aclmdlConfigHandle pointer * * @see aclmdlDestroyConfigHandle -*/ + */ ACL_FUNC_VISIBILITY aclmdlConfigHandle *aclmdlCreateConfigHandle(); /** @@ -1201,10 +1177,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlDestroyConfigHandle(aclmdlConfigHandle *handl * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclmdlSetConfigOpt(aclmdlConfigHandle *handle, aclmdlConfigAttr attr, - const void *attrValue, size_t valueSize); + const void *attrValue, size_t valueSize); #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_MODEL_H_ +#endif // INC_EXTERNAL_ACL_ACL_MODEL_H_ diff --git a/inc/external/acl/acl_op.h b/inc/external/acl/acl_op.h index b1be0d6e..d2e59bfb 100644 --- a/inc/external/acl/acl_op.h +++ b/inc/external/acl/acl_op.h @@ -33,9 +33,9 @@ typedef void (*aclDataDeallocator)(void *data, size_t length); static const int ACL_COMPILE_FLAG_BIN_SELECTOR = 1; typedef enum aclEngineType { - ACL_ENGINE_SYS, - ACL_ENGINE_AICORE, - ACL_ENGINE_VECTOR, + ACL_ENGINE_SYS, + ACL_ENGINE_AICORE, + ACL_ENGINE_VECTOR, } aclopEngineType; /** @@ -148,7 +148,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrString(aclopAttr *attr, const char *att * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListBool(aclopAttr *attr, const char *attrName, int numValues, - const uint8_t *values); + const uint8_t *values); /** * @ingroup AscendCL @@ -163,7 +163,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListBool(aclopAttr *attr, const char *a * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListInt(aclopAttr *attr, const char *attrName, int numValues, - const int64_t *values); + const int64_t *values); /** * @ingroup AscendCL @@ -178,7 +178,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListInt(aclopAttr *attr, const char *at * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListFloat(aclopAttr *attr, const char *attrName, int numValues, - const float *values); + const float *values); /** * @ingroup AscendCL @@ -193,7 +193,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListFloat(aclopAttr *attr, const char * * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListString(aclopAttr *attr, const char *attrName, int numValues, - const char **values); + const char **values); /** * @ingroup AscendCL @@ -208,11 +208,8 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListString(aclopAttr *attr, const char * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, - const char *attrName, - int numLists, - const int *numValues, - const int64_t *const values[]); +ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, const char *attrName, int numLists, + const int *numValues, const int64_t *const values[]); /** * @ingroup AscendCL @@ -242,15 +239,10 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, * @retval OtherValues Failure */ ACL_DEPRECATED_MESSAGE("aclopExecute is deprecated, use aclopExecuteV2 instead") -ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, - int numInputs, - const aclTensorDesc *const inputDesc[], - const aclDataBuffer *const inputs[], - int numOutputs, - const aclTensorDesc *const outputDesc[], - aclDataBuffer *const outputs[], - const aclopAttr *attr, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], + const aclDataBuffer *const inputs[], int numOutputs, + const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], + const aclopAttr *attr, aclrtStream stream); /** * @ingroup AscendCL @@ -280,15 +272,9 @@ ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, - int numInputs, - aclTensorDesc *inputDesc[], - aclDataBuffer *inputs[], - int numOutputs, - aclTensorDesc *outputDesc[], - aclDataBuffer *outputs[], - aclopAttr *attr, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, int numInputs, aclTensorDesc *inputDesc[], + aclDataBuffer *inputs[], int numOutputs, aclTensorDesc *outputDesc[], + aclDataBuffer *outputs[], aclopAttr *attr, aclrtStream stream); /** * @ingroup AscendCL @@ -306,12 +292,9 @@ ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCreateHandle(const char *opType, - int numInputs, - const aclTensorDesc *const inputDesc[], - int numOutputs, - const aclTensorDesc *const outputDesc[], - const aclopAttr *opAttr, +ACL_FUNC_VISIBILITY aclError aclopCreateHandle(const char *opType, int numInputs, + const aclTensorDesc *const inputDesc[], int numOutputs, + const aclTensorDesc *const outputDesc[], const aclopAttr *opAttr, aclopHandle **handle); /** @@ -343,12 +326,9 @@ ACL_FUNC_VISIBILITY void aclopDestroyHandle(aclopHandle *handle); * * @see aclopCreateHandle | aclCreateDataBuffer */ -ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, - int numInputs, - const aclDataBuffer *const inputs[], - int numOutputs, - aclDataBuffer *const outputs[], - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, int numInputs, + const aclDataBuffer *const inputs[], int numOutputs, + aclDataBuffer *const outputs[], aclrtStream stream); /** * @ingroup AscendCL @@ -364,11 +344,8 @@ ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, - const aclDataBuffer *srcBuffer, - const aclTensorDesc *dstDesc, - aclDataBuffer *dstBuffer, - uint8_t truncate, +ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, const aclDataBuffer *srcBuffer, + const aclTensorDesc *dstDesc, aclDataBuffer *dstBuffer, uint8_t truncate, aclrtStream stream); /** @@ -383,12 +360,9 @@ ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, - aclTensorDesc *dstDesc, - uint8_t truncate, +ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, aclTensorDesc *dstDesc, uint8_t truncate, aclopHandle **handle); - /** * @ingroup AscendCL * @brief create kernel @@ -407,15 +381,10 @@ ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, * * @see aclopCompile */ -ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, - const char *kernelId, - const char *kernelName, - void *binData, - int binSize, - aclopEngineType enginetype, +ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, const char *kernelId, const char *kernelName, + void *binData, int binSize, aclopEngineType enginetype, aclDataDeallocator deallocator); - /** * @ingroup AscendCL * @brief create kernel @@ -430,11 +399,8 @@ ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -typedef aclError (*aclopCompileFunc)(int numInputs, - const aclTensorDesc *const inputDesc[], - int numOutputs, - const aclTensorDesc *const outputDesc[], - const aclopAttr *opAttr, +typedef aclError (*aclopCompileFunc)(int numInputs, const aclTensorDesc *const inputDesc[], int numOutputs, + const aclTensorDesc *const outputDesc[], const aclopAttr *opAttr, aclopKernelDesc *aclopKernelDesc); /** @@ -475,11 +441,8 @@ ACL_FUNC_VISIBILITY aclError aclopUnregisterCompileFunc(const char *opType); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopSetKernelArgs(aclopKernelDesc *kernelDesc, - const char *kernelId, - uint32_t blockDim, - const void *args, - uint32_t argSize); +ACL_FUNC_VISIBILITY aclError aclopSetKernelArgs(aclopKernelDesc *kernelDesc, const char *kernelId, uint32_t blockDim, + const void *args, uint32_t argSize); /** * @ingroup AscendCL @@ -510,12 +473,9 @@ ACL_FUNC_VISIBILITY aclError aclopSetKernelWorkspaceSizes(aclopKernelDesc *kerne * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, - int numInputs, - const aclTensorDesc *const inputDesc[], - int numOutputs, - const aclTensorDesc *const outputDesc[], - const aclopAttr *attr); +ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, int numInputs, + const aclTensorDesc *const inputDesc[], int numOutputs, + const aclTensorDesc *const outputDesc[], const aclopAttr *attr); /** * @ingroup AscendCL @@ -533,17 +493,12 @@ ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopInferShape(const char *opType, - int numInputs, - aclTensorDesc *inputDesc[], - aclDataBuffer *inputs[], - int numOutputs, - aclTensorDesc *outputDesc[], +ACL_FUNC_VISIBILITY aclError aclopInferShape(const char *opType, int numInputs, aclTensorDesc *inputDesc[], + aclDataBuffer *inputs[], int numOutputs, aclTensorDesc *outputDesc[], aclopAttr *attr); - #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_OP_H_ +#endif // INC_EXTERNAL_ACL_ACL_OP_H_ diff --git a/inc/external/acl/acl_op_compiler.h b/inc/external/acl/acl_op_compiler.h index 6bbb855c..adae90c7 100644 --- a/inc/external/acl/acl_op_compiler.h +++ b/inc/external/acl/acl_op_compiler.h @@ -24,21 +24,18 @@ extern "C" { #endif -typedef enum aclCompileType { - ACL_COMPILE_SYS, - ACL_COMPILE_UNREGISTERED -} aclopCompileType; +typedef enum aclCompileType { ACL_COMPILE_SYS, ACL_COMPILE_UNREGISTERED } aclopCompileType; typedef enum { - ACL_PRECISION_MODE, - ACL_AICORE_NUM, - ACL_AUTO_TUNE_MODE, - ACL_OP_SELECT_IMPL_MODE, - ACL_OPTYPELIST_FOR_IMPLMODE, - ACL_OP_DEBUG_LEVEL, - ACL_DEBUG_DIR, - ACL_OP_COMPILER_CACHE_MODE, - ACL_OP_COMPILER_CACHE_DIR + ACL_PRECISION_MODE, + ACL_AICORE_NUM, + ACL_AUTO_TUNE_MODE, + ACL_OP_SELECT_IMPL_MODE, + ACL_OPTYPELIST_FOR_IMPLMODE, + ACL_OP_DEBUG_LEVEL, + ACL_DEBUG_DIR, + ACL_OP_COMPILER_CACHE_MODE, + ACL_OP_COMPILER_CACHE_DIR } aclCompileOpt; /** @@ -59,15 +56,10 @@ typedef enum { * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, - int numInputs, - const aclTensorDesc *const inputDesc[], - int numOutputs, - const aclTensorDesc *const outputDesc[], - const aclopAttr *attr, - aclopEngineType engineType, - aclopCompileType compileFlag, - const char *opPath); +ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], + int numOutputs, const aclTensorDesc *const outputDesc[], + const aclopAttr *attr, aclopEngineType engineType, + aclopCompileType compileFlag, const char *opPath); /** * @ingroup AscendCL @@ -90,11 +82,10 @@ ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCompileAndExecute(const char *opType, - int numInputs, const aclTensorDesc *const inputDesc[], const aclDataBuffer *const inputs[], - int numOutputs, const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], - const aclopAttr *attr, aclopEngineType engineType, aclopCompileType compileFlag, - const char *opPath, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopCompileAndExecute( + const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], const aclDataBuffer *const inputs[], + int numOutputs, const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], const aclopAttr *attr, + aclopEngineType engineType, aclopCompileType compileFlag, const char *opPath, aclrtStream stream); /** * @ingroup AscendCL @@ -112,4 +103,4 @@ ACL_FUNC_VISIBILITY aclError aclSetCompileopt(aclCompileOpt opt, const char *val } #endif -#endif // INC_EXTERNAL_ACL_ACL_OP_COMPILER_H_ +#endif // INC_EXTERNAL_ACL_ACL_OP_COMPILER_H_ diff --git a/inc/external/acl/acl_prof.h b/inc/external/acl/acl_prof.h index d2675124..990c70cf 100644 --- a/inc/external/acl/acl_prof.h +++ b/inc/external/acl/acl_prof.h @@ -23,21 +23,21 @@ extern "C" { #endif -#define ACL_PROF_ACL_API 0x0001 -#define ACL_PROF_TASK_TIME 0x0002 -#define ACL_PROF_AICORE_METRICS 0x0004 -#define ACL_PROF_AICPU 0x0008 +#define ACL_PROF_ACL_API 0x0001 +#define ACL_PROF_TASK_TIME 0x0002 +#define ACL_PROF_AICORE_METRICS 0x0004 +#define ACL_PROF_AICPU 0x0008 -#define ACL_PROF_MAX_OP_NAME_LEN 257 -#define ACL_PROF_MAX_OP_TYPE_LEN 65 +#define ACL_PROF_MAX_OP_NAME_LEN 257 +#define ACL_PROF_MAX_OP_TYPE_LEN 65 typedef enum { - ACL_AICORE_ARITHMETIC_UTILIZATION = 0, - ACL_AICORE_PIPE_UTILIZATION = 1, - ACL_AICORE_MEMORY_BANDWIDTH = 2, - ACL_AICORE_L0B_AND_WIDTH = 3, - ACL_AICORE_RESOURCE_CONFLICT_RATIO = 4, - ACL_AICORE_NONE = 0xFF + ACL_AICORE_ARITHMETIC_UTILIZATION = 0, + ACL_AICORE_PIPE_UTILIZATION = 1, + ACL_AICORE_MEMORY_BANDWIDTH = 2, + ACL_AICORE_L0B_AND_WIDTH = 3, + ACL_AICORE_RESOURCE_CONFLICT_RATIO = 4, + ACL_AICORE_NONE = 0xFF } aclprofAicoreMetrics; typedef struct aclprofConfig aclprofConfig; @@ -98,7 +98,8 @@ ACL_FUNC_VISIBILITY aclError aclprofStart(const aclprofConfig *profilerConfig); * @see aclprofDestroyConfig */ ACL_FUNC_VISIBILITY aclprofConfig *aclprofCreateConfig(uint32_t *deviceIdList, uint32_t deviceNums, - aclprofAicoreMetrics aicoreMetrics, aclprofAicoreEvents *aicoreEvents, uint64_t dataTypeConfig); + aclprofAicoreMetrics aicoreMetrics, + aclprofAicoreEvents *aicoreEvents, uint64_t dataTypeConfig); /** * @ingroup AscendCL @@ -138,8 +139,7 @@ ACL_FUNC_VISIBILITY aclError aclprofStop(const aclprofConfig *profilerConfig); * * @see aclprofModelUnSubscribe */ -ACL_FUNC_VISIBILITY aclError aclprofModelSubscribe(uint32_t modelId, - const aclprofSubscribeConfig *profSubscribeConfig); +ACL_FUNC_VISIBILITY aclError aclprofModelSubscribe(uint32_t modelId, const aclprofSubscribeConfig *profSubscribeConfig); /** * @ingroup AscendCL @@ -167,7 +167,7 @@ ACL_FUNC_VISIBILITY aclError aclprofModelUnSubscribe(uint32_t modelId); * @see aclprofDestroySubscribeConfig */ ACL_FUNC_VISIBILITY aclprofSubscribeConfig *aclprofCreateSubscribeConfig(int8_t timeInfoSwitch, - aclprofAicoreMetrics aicoreMetrics, void *fd); + aclprofAicoreMetrics aicoreMetrics, void *fd); /** * @ingroup AscendCL @@ -219,8 +219,8 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpNum(const void *opInfo, size_t opInfoLe * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoLen, uint32_t index, - char *opType, size_t opTypeLen); +ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoLen, uint32_t index, char *opType, + size_t opTypeLen); /** * @ingroup AscendCL @@ -235,8 +235,8 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoL * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclprofGetOpName(const void *opInfo, size_t opInfoLen, uint32_t index, - char *opName, size_t opNameLen); +ACL_FUNC_VISIBILITY aclError aclprofGetOpName(const void *opInfo, size_t opInfoLen, uint32_t index, char *opName, + size_t opNameLen); /** * @ingroup AscendCL @@ -293,4 +293,4 @@ ACL_FUNC_VISIBILITY size_t aclprofGetModelId(const void *opInfo, size_t opInfoLe } #endif -#endif // INC_EXTERNAL_ACL_PROF_H_ +#endif // INC_EXTERNAL_ACL_PROF_H_ diff --git a/inc/external/acl/acl_rt.h b/inc/external/acl/acl_rt.h index 6fd2da6e..eb6b4240 100644 --- a/inc/external/acl/acl_rt.h +++ b/inc/external/acl/acl_rt.h @@ -26,62 +26,62 @@ extern "C" { #endif typedef enum aclrtRunMode { - ACL_DEVICE, - ACL_HOST, + ACL_DEVICE, + ACL_HOST, } aclrtRunMode; typedef enum aclrtTsId { - ACL_TS_ID_AICORE = 0, - ACL_TS_ID_AIVECTOR = 1, - ACL_TS_ID_RESERVED = 2, + ACL_TS_ID_AICORE = 0, + ACL_TS_ID_AIVECTOR = 1, + ACL_TS_ID_RESERVED = 2, } aclrtTsId; typedef enum aclrtEventStatus { - ACL_EVENT_STATUS_COMPLETE = 0, - ACL_EVENT_STATUS_NOT_READY = 1, - ACL_EVENT_STATUS_RESERVED = 2, + ACL_EVENT_STATUS_COMPLETE = 0, + ACL_EVENT_STATUS_NOT_READY = 1, + ACL_EVENT_STATUS_RESERVED = 2, } aclrtEventStatus; typedef enum aclrtCallbackBlockType { - ACL_CALLBACK_NO_BLOCK, - ACL_CALLBACK_BLOCK, + ACL_CALLBACK_NO_BLOCK, + ACL_CALLBACK_BLOCK, } aclrtCallbackBlockType; typedef enum aclrtMemcpyKind { - ACL_MEMCPY_HOST_TO_HOST, - ACL_MEMCPY_HOST_TO_DEVICE, - ACL_MEMCPY_DEVICE_TO_HOST, - ACL_MEMCPY_DEVICE_TO_DEVICE, + ACL_MEMCPY_HOST_TO_HOST, + ACL_MEMCPY_HOST_TO_DEVICE, + ACL_MEMCPY_DEVICE_TO_HOST, + ACL_MEMCPY_DEVICE_TO_DEVICE, } aclrtMemcpyKind; typedef enum aclrtMemMallocPolicy { - ACL_MEM_MALLOC_HUGE_FIRST, - ACL_MEM_MALLOC_HUGE_ONLY, - ACL_MEM_MALLOC_NORMAL_ONLY, - ACL_MEM_MALLOC_HUGE_FIRST_P2P, - ACL_MEM_MALLOC_HUGE_ONLY_P2P, - ACL_MEM_MALLOC_NORMAL_ONLY_P2P, + ACL_MEM_MALLOC_HUGE_FIRST, + ACL_MEM_MALLOC_HUGE_ONLY, + ACL_MEM_MALLOC_NORMAL_ONLY, + ACL_MEM_MALLOC_HUGE_FIRST_P2P, + ACL_MEM_MALLOC_HUGE_ONLY_P2P, + ACL_MEM_MALLOC_NORMAL_ONLY_P2P, } aclrtMemMallocPolicy; typedef enum aclrtMemAttr { - ACL_DDR_MEM, - ACL_HBM_MEM, - ACL_DDR_MEM_HUGE, - ACL_DDR_MEM_NORMAL, - ACL_HBM_MEM_HUGE, - ACL_HBM_MEM_NORMAL, - ACL_DDR_MEM_P2P_HUGE, - ACL_DDR_MEM_P2P_NORMAL, - ACL_HBM_MEM_P2P_HUGE, - ACL_HBM_MEM_P2P_NORMAL, + ACL_DDR_MEM, + ACL_HBM_MEM, + ACL_DDR_MEM_HUGE, + ACL_DDR_MEM_NORMAL, + ACL_HBM_MEM_HUGE, + ACL_HBM_MEM_NORMAL, + ACL_DDR_MEM_P2P_HUGE, + ACL_DDR_MEM_P2P_NORMAL, + ACL_HBM_MEM_P2P_HUGE, + ACL_HBM_MEM_P2P_NORMAL, } aclrtMemAttr; typedef enum aclrtGroupAttr { - ACL_GROUP_AICORE_INT, - ACL_GROUP_AIV_INT, - ACL_GROUP_AIC_INT, - ACL_GROUP_SDMANUM_INT, - ACL_GROUP_ASQNUM_INT + ACL_GROUP_AICORE_INT, + ACL_GROUP_AIV_INT, + ACL_GROUP_AIC_INT, + ACL_GROUP_SDMANUM_INT, + ACL_GROUP_ASQNUM_INT } aclrtGroupAttr; typedef struct tagRtGroupInfo aclrtGroupInfo; @@ -472,7 +472,7 @@ ACL_FUNC_VISIBILITY aclError aclrtRecordEvent(aclrtEvent event, aclrtStream stre */ ACL_FUNC_VISIBILITY aclError aclrtResetEvent(aclrtEvent event, aclrtStream stream); - /** +/** * @ingroup AscendCL * @brief Queries an event's status * @@ -534,9 +534,7 @@ ACL_FUNC_VISIBILITY aclError aclrtEventElapsedTime(float *ms, aclrtEvent start, * * @see aclrtFree | acldvppMalloc | aclrtMallocCached */ -ACL_FUNC_VISIBILITY aclError aclrtMalloc(void **devPtr, - size_t size, - aclrtMemMallocPolicy policy); +ACL_FUNC_VISIBILITY aclError aclrtMalloc(void **devPtr, size_t size, aclrtMemMallocPolicy policy); /** * @ingroup AscendCL @@ -559,9 +557,7 @@ ACL_FUNC_VISIBILITY aclError aclrtMalloc(void **devPtr, * * @see aclrtFree | aclrtMalloc */ -ACL_FUNC_VISIBILITY aclError aclrtMallocCached(void **devPtr, - size_t size, - aclrtMemMallocPolicy policy); +ACL_FUNC_VISIBILITY aclError aclrtMallocCached(void **devPtr, size_t size, aclrtMemMallocPolicy policy); /** * @ingroup AscendCL @@ -652,10 +648,7 @@ ACL_FUNC_VISIBILITY aclError aclrtFreeHost(void *hostPtr); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclrtMemcpy(void *dst, - size_t destMax, - const void *src, - size_t count, +ACL_FUNC_VISIBILITY aclError aclrtMemcpy(void *dst, size_t destMax, const void *src, size_t count, aclrtMemcpyKind kind); /** @@ -702,38 +695,31 @@ ACL_FUNC_VISIBILITY aclError aclrtMemset(void *devPtr, size_t maxCount, int32_t * * @see aclrtSynchronizeStream */ -ACL_FUNC_VISIBILITY aclError aclrtMemcpyAsync(void *dst, - size_t destMax, - const void *src, - size_t count, - aclrtMemcpyKind kind, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclrtMemcpyAsync(void *dst, size_t destMax, const void *src, size_t count, + aclrtMemcpyKind kind, aclrtStream stream); /** -* @ingroup AscendCL -* @brief Asynchronous initialize memory -* and set contents of memory to specified value async -* -* @par Function + * @ingroup AscendCL + * @brief Asynchronous initialize memory + * and set contents of memory to specified value async + * + * @par Function * The memory to be initialized is on the Host or device side, * and the system determines whether * it is host or device according to the address * -* @param devPtr [IN] destination address pointer -* @param maxCount [IN] Max length of destination address memory -* @param value [IN] set value -* @param count [IN] the number of byte to set -* @param stream [IN] asynchronized task stream -* -* @retval ACL_SUCCESS The function is successfully executed. -* @retval OtherValues Failure -* -* @see aclrtSynchronizeStream -*/ -ACL_FUNC_VISIBILITY aclError aclrtMemsetAsync(void *devPtr, - size_t maxCount, - int32_t value, - size_t count, + * @param devPtr [IN] destination address pointer + * @param maxCount [IN] Max length of destination address memory + * @param value [IN] set value + * @param count [IN] the number of byte to set + * @param stream [IN] asynchronized task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtSynchronizeStream + */ +ACL_FUNC_VISIBILITY aclError aclrtMemsetAsync(void *devPtr, size_t maxCount, int32_t value, size_t count, aclrtStream stream); /** @@ -879,11 +865,8 @@ ACL_FUNC_VISIBILITY aclError aclrtGetAllGroupInfo(aclrtGroupInfo *groupInfo); * * @see aclrtGetGroupCount | aclrtGetAllGroupInfo */ -ACL_FUNC_VISIBILITY aclError aclrtGetGroupInfoDetail(const aclrtGroupInfo *groupInfo, - int32_t groupId, - aclrtGroupAttr attr, - void *attrValue, - size_t valueLen, +ACL_FUNC_VISIBILITY aclError aclrtGetGroupInfoDetail(const aclrtGroupInfo *groupInfo, int32_t groupId, + aclrtGroupAttr attr, void *attrValue, size_t valueLen, size_t *paramRetSize); /** @@ -946,5 +929,4 @@ ACL_FUNC_VISIBILITY aclError aclrtGetMemInfo(aclrtMemAttr attr, size_t *free, si } #endif -#endif // INC_EXTERNAL_ACL_ACL_RT_H_ - +#endif // INC_EXTERNAL_ACL_ACL_RT_H_ diff --git a/inc/external/acl/acl_tdt.h b/inc/external/acl/acl_tdt.h index 61995121..c357518d 100644 --- a/inc/external/acl/acl_tdt.h +++ b/inc/external/acl/acl_tdt.h @@ -24,10 +24,10 @@ extern "C" { #endif enum acltdtTensorType { - ACL_TENSOR_DATA_UNDEFINED = -1, - ACL_TENSOR_DATA_TENSOR, - ACL_TENSOR_DATA_END_OF_SEQUENCE, - ACL_TENSOR_DATA_ABNORMAL + ACL_TENSOR_DATA_UNDEFINED = -1, + ACL_TENSOR_DATA_TENSOR, + ACL_TENSOR_DATA_END_OF_SEQUENCE, + ACL_TENSOR_DATA_ABNORMAL }; typedef struct acltdtDataItem acltdtDataItem; @@ -64,7 +64,7 @@ ACL_FUNC_VISIBILITY aclDataType acltdtGetDataTypeFromItem(const acltdtDataItem * * * @retval null for failed * @retval OtherValues success -*/ + */ ACL_FUNC_VISIBILITY void *acltdtGetDataAddrFromItem(const acltdtDataItem *dataItem); /** @@ -75,7 +75,7 @@ ACL_FUNC_VISIBILITY void *acltdtGetDataAddrFromItem(const acltdtDataItem *dataIt * * @retval 0 for failed * @retval OtherValues success -*/ + */ ACL_FUNC_VISIBILITY size_t acltdtGetDataSizeFromItem(const acltdtDataItem *dataItem); /** @@ -86,7 +86,7 @@ ACL_FUNC_VISIBILITY size_t acltdtGetDataSizeFromItem(const acltdtDataItem *dataI * * @retval 0 for failed * @retval OtherValues success -*/ + */ ACL_FUNC_VISIBILITY size_t acltdtGetDimNumFromItem(const acltdtDataItem *dataItem); /** @@ -118,12 +118,8 @@ ACL_FUNC_VISIBILITY aclError acltdtGetDimsFromItem(const acltdtDataItem *dataIte * * @see acltdtDestroyDataItem */ -ACL_FUNC_VISIBILITY acltdtDataItem *acltdtCreateDataItem(acltdtTensorType tdtType, - const int64_t *dims, - size_t dimNum, - aclDataType dataType, - void *data, - size_t size); +ACL_FUNC_VISIBILITY acltdtDataItem *acltdtCreateDataItem(acltdtTensorType tdtType, const int64_t *dims, size_t dimNum, + aclDataType dataType, void *data, size_t size); /** * @ingroup AscendCL @@ -254,8 +250,7 @@ ACL_FUNC_VISIBILITY aclError acltdtDestroyChannel(acltdtChannelHandle *handle); * * @see acltdtReceiveTensor */ -ACL_FUNC_VISIBILITY aclError acltdtSendTensor(const acltdtChannelHandle *handle, - const acltdtDataset *dataset, +ACL_FUNC_VISIBILITY aclError acltdtSendTensor(const acltdtChannelHandle *handle, const acltdtDataset *dataset, int32_t timeout); /** @@ -271,13 +266,11 @@ ACL_FUNC_VISIBILITY aclError acltdtSendTensor(const acltdtChannelHandle *handle, * * @see acltdtSendTensor */ -ACL_FUNC_VISIBILITY aclError acltdtReceiveTensor(const acltdtChannelHandle *handle, - acltdtDataset *dataset, +ACL_FUNC_VISIBILITY aclError acltdtReceiveTensor(const acltdtChannelHandle *handle, acltdtDataset *dataset, int32_t timeout); #ifdef __cplusplus } #endif -#endif //INC_EXTERNAL_ACL_ACL_TDT_H_ - +#endif // INC_EXTERNAL_ACL_ACL_TDT_H_ diff --git a/inc/external/acl/error_codes/rt_error_codes.h b/inc/external/acl/error_codes/rt_error_codes.h index 73da559d..d2373525 100644 --- a/inc/external/acl/error_codes/rt_error_codes.h +++ b/inc/external/acl/error_codes/rt_error_codes.h @@ -23,80 +23,79 @@ extern "C" { #endif -static const int32_t ACL_RT_SUCCESS = 0; // success +static const int32_t ACL_RT_SUCCESS = 0; // success -static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid -static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id -static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null -static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context -static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context -static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal -static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned -static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed -static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed -static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream -static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread -static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set -static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create -static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream -static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type -static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle -static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type +static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid +static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id +static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null +static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context +static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context +static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal +static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned +static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed +static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed +static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream +static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread +static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set +static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create +static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream +static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type +static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle +static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type -static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support -static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error -static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error -static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow -static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device -static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail -static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission -static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource -static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource -static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource -static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource +static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support +static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error +static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error +static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow +static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device +static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail +static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission +static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource +static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource +static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource +static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource -static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error - -static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error #ifdef __cplusplus } #endif -#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ +#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/inc/external/acl/ops/acl_cblas.h b/inc/external/acl/ops/acl_cblas.h index a2bd8c61..3d81eb2b 100644 --- a/inc/external/acl/ops/acl_cblas.h +++ b/inc/external/acl/ops/acl_cblas.h @@ -23,17 +23,9 @@ extern "C" { #endif -typedef enum aclTransType { - ACL_TRANS_N, - ACL_TRANS_T, - ACL_TRANS_NZ, - ACL_TRANS_NZ_T -} aclTransType; +typedef enum aclTransType { ACL_TRANS_N, ACL_TRANS_T, ACL_TRANS_NZ, ACL_TRANS_NZ_T } aclTransType; -typedef enum aclComputeType { - ACL_COMPUTE_HIGH_PRECISION, - ACL_COMPUTE_LOW_PRECISION -} aclComputeType; +typedef enum aclComputeType { ACL_COMPUTE_HIGH_PRECISION, ACL_COMPUTE_LOW_PRECISION } aclComputeType; /** * @ingroup AscendCL @@ -61,12 +53,11 @@ typedef enum aclComputeType { * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure -*/ -ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, - const void *alpha, const void *a, int lda, aclDataType dataTypeA, - const void *x, int incx, aclDataType dataTypeX, - const void *beta, void *y, int incy, aclDataType dataTypeY, - aclComputeType type, aclrtStream stream); + */ +ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, const void *alpha, const void *a, int lda, + aclDataType dataTypeA, const void *x, int incx, aclDataType dataTypeX, + const void *beta, void *y, int incy, aclDataType dataTypeY, + aclComputeType type, aclrtStream stream); /** * @ingroup AscendCL @@ -83,15 +74,10 @@ ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure -*/ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, - int m, - int n, - aclDataType dataTypeA, - aclDataType dataTypeX, - aclDataType dataTypeY, - aclComputeType type, - aclopHandle **handle); + */ +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, int m, int n, aclDataType dataTypeA, + aclDataType dataTypeX, aclDataType dataTypeY, + aclComputeType type, aclopHandle **handle); /** * @ingroup AscendCL @@ -115,18 +101,9 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, - int m, - int n, - const aclFloat16 *alpha, - const aclFloat16 *a, - int lda, - const aclFloat16 *x, - int incx, - const aclFloat16 *beta, - aclFloat16 *y, - int incy, - aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, int m, int n, const aclFloat16 *alpha, + const aclFloat16 *a, int lda, const aclFloat16 *x, int incx, + const aclFloat16 *beta, aclFloat16 *y, int incy, aclComputeType type, aclrtStream stream); /** @@ -142,10 +119,7 @@ ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, - int m, - int n, - aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, int m, int n, aclComputeType type, aclopHandle **handle); /** @@ -171,19 +145,9 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, - int m, - int n, - const int32_t *alpha, - const int8_t *a, - int lda, - const int8_t *x, - int incx, - const int32_t *beta, - int32_t *y, - int incy, - aclComputeType type, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, int m, int n, const int32_t *alpha, const int8_t *a, + int lda, const int8_t *x, int incx, const int32_t *beta, int32_t *y, + int incy, aclComputeType type, aclrtStream stream); /** * @ingroup AscendCL @@ -198,10 +162,7 @@ ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, - int m, - int n, - aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, int m, int n, aclComputeType type, aclopHandle **handle); /** @@ -233,26 +194,11 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, - aclTransType transB, - aclTransType transC, - int m, - int n, - int k, - const void *alpha, - const void *matrixA, - int lda, - aclDataType dataTypeA, - const void *matrixB, - int ldb, - aclDataType dataTypeB, - const void *beta, - void *matrixC, - int ldc, - aclDataType dataTypeC, - aclComputeType type, - aclrtStream stream); - +ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, + int k, const void *alpha, const void *matrixA, int lda, + aclDataType dataTypeA, const void *matrixB, int ldb, aclDataType dataTypeB, + const void *beta, void *matrixC, int ldc, aclDataType dataTypeC, + aclComputeType type, aclrtStream stream); /** * @ingroup AscendCL @@ -274,18 +220,10 @@ ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, - aclTransType transB, - aclTransType transC, - int m, - int n, - int k, - aclDataType dataTypeA, - aclDataType dataTypeB, - aclDataType dataTypeC, - aclComputeType type, - aclopHandle **handle); - +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, aclTransType transB, aclTransType transC, + int m, int n, int k, aclDataType dataTypeA, + aclDataType dataTypeB, aclDataType dataTypeC, + aclComputeType type, aclopHandle **handle); /** * @ingroup AscendCL @@ -313,22 +251,10 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, - aclTransType transB, - aclTransType transC, - int m, - int n, - int k, - const aclFloat16 *alpha, - const aclFloat16 *matrixA, - int lda, - const aclFloat16 *matrixB, - int ldb, - const aclFloat16 *beta, - aclFloat16 *matrixC, - int ldc, - aclComputeType type, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, + int k, const aclFloat16 *alpha, const aclFloat16 *matrixA, int lda, + const aclFloat16 *matrixB, int ldb, const aclFloat16 *beta, + aclFloat16 *matrixC, int ldc, aclComputeType type, aclrtStream stream); /** * @ingroup AscendCL @@ -346,13 +272,8 @@ ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, - aclTransType transB, - aclTransType transC, - int m, - int n, - int k, - aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, aclTransType transB, aclTransType transC, + int m, int n, int k, aclComputeType type, aclopHandle **handle); /** @@ -381,23 +302,10 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, - aclTransType transB, - aclTransType transC, - int m, - int n, - int k, - const int32_t *alpha, - const int8_t *matrixA, - int lda, - const int8_t *matrixB, - int ldb, - const int32_t *beta, - int32_t *matrixC, - int ldc, - aclComputeType type, - aclrtStream stream); - +ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, + int k, const int32_t *alpha, const int8_t *matrixA, int lda, + const int8_t *matrixB, int ldb, const int32_t *beta, int32_t *matrixC, + int ldc, aclComputeType type, aclrtStream stream); /** * @ingroup AscendCL @@ -415,17 +323,12 @@ ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemm(aclTransType transA, - aclTransType transB, - aclTransType transC, - int m, - int n, - int k, - aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemm(aclTransType transA, aclTransType transB, aclTransType transC, + int m, int n, int k, aclComputeType type, aclopHandle **handle); #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_CBLAS_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_CBLAS_H_ diff --git a/inc/external/acl/ops/acl_dvpp.h b/inc/external/acl/ops/acl_dvpp.h index d2f5f650..1a0f582d 100644 --- a/inc/external/acl/ops/acl_dvpp.h +++ b/inc/external/acl/ops/acl_dvpp.h @@ -53,112 +53,98 @@ typedef void (*aclvencCallback)(acldvppPicDesc *input, acldvppStreamDesc *output // Supported Pixel Format enum acldvppPixelFormat { - PIXEL_FORMAT_YUV_400 = 0, // 0 - PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1, // 1 - PIXEL_FORMAT_YVU_SEMIPLANAR_420 = 2, // 2 - PIXEL_FORMAT_YUV_SEMIPLANAR_422 = 3, // 3 - PIXEL_FORMAT_YVU_SEMIPLANAR_422 = 4, // 4 - PIXEL_FORMAT_YUV_SEMIPLANAR_444 = 5, // 5 - PIXEL_FORMAT_YVU_SEMIPLANAR_444 = 6, // 6 - PIXEL_FORMAT_YUYV_PACKED_422 = 7, // 7 - PIXEL_FORMAT_UYVY_PACKED_422 = 8, // 8 - PIXEL_FORMAT_YVYU_PACKED_422 = 9, // 9 - PIXEL_FORMAT_VYUY_PACKED_422 = 10, // 10 - PIXEL_FORMAT_YUV_PACKED_444 = 11, // 11 - PIXEL_FORMAT_RGB_888 = 12, // 12 - PIXEL_FORMAT_BGR_888 = 13, // 13 - PIXEL_FORMAT_ARGB_8888 = 14, // 14 - PIXEL_FORMAT_ABGR_8888 = 15, // 15 - PIXEL_FORMAT_RGBA_8888 = 16, // 16 - PIXEL_FORMAT_BGRA_8888 = 17, // 17 - PIXEL_FORMAT_YUV_SEMI_PLANNER_420_10BIT = 18, // 18 - PIXEL_FORMAT_YVU_SEMI_PLANNER_420_10BIT = 19, // 19 - PIXEL_FORMAT_YVU_PLANAR_420 = 20, // 20 - PIXEL_FORMAT_YVU_PLANAR_422, - PIXEL_FORMAT_YVU_PLANAR_444, - PIXEL_FORMAT_RGB_444 = 23, - PIXEL_FORMAT_BGR_444, - PIXEL_FORMAT_ARGB_4444, - PIXEL_FORMAT_ABGR_4444, - PIXEL_FORMAT_RGBA_4444, - PIXEL_FORMAT_BGRA_4444, - PIXEL_FORMAT_RGB_555, - PIXEL_FORMAT_BGR_555, - PIXEL_FORMAT_RGB_565, - PIXEL_FORMAT_BGR_565, - PIXEL_FORMAT_ARGB_1555, - PIXEL_FORMAT_ABGR_1555, - PIXEL_FORMAT_RGBA_1555, - PIXEL_FORMAT_BGRA_1555, - PIXEL_FORMAT_ARGB_8565, - PIXEL_FORMAT_ABGR_8565, - PIXEL_FORMAT_RGBA_8565, - PIXEL_FORMAT_BGRA_8565, - PIXEL_FORMAT_RGB_BAYER_8BPP = 50, - PIXEL_FORMAT_RGB_BAYER_10BPP, - PIXEL_FORMAT_RGB_BAYER_12BPP, - PIXEL_FORMAT_RGB_BAYER_14BPP, - PIXEL_FORMAT_RGB_BAYER_16BPP, - PIXEL_FORMAT_BGR_888_PLANAR = 70, - PIXEL_FORMAT_HSV_888_PACKAGE, - PIXEL_FORMAT_HSV_888_PLANAR, - PIXEL_FORMAT_LAB_888_PACKAGE, - PIXEL_FORMAT_LAB_888_PLANAR, - PIXEL_FORMAT_S8C1, - PIXEL_FORMAT_S8C2_PACKAGE, - PIXEL_FORMAT_S8C2_PLANAR, - PIXEL_FORMAT_S16C1, - PIXEL_FORMAT_U8C1, - PIXEL_FORMAT_U16C1, - PIXEL_FORMAT_S32C1, - PIXEL_FORMAT_U32C1, - PIXEL_FORMAT_U64C1, - PIXEL_FORMAT_S64C1, - PIXEL_FORMAT_YUV_SEMIPLANAR_440 = 1000, - PIXEL_FORMAT_YVU_SEMIPLANAR_440, - PIXEL_FORMAT_FLOAT32, - PIXEL_FORMAT_BUTT, - PIXEL_FORMAT_UNKNOWN = 10000 + PIXEL_FORMAT_YUV_400 = 0, // 0 + PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1, // 1 + PIXEL_FORMAT_YVU_SEMIPLANAR_420 = 2, // 2 + PIXEL_FORMAT_YUV_SEMIPLANAR_422 = 3, // 3 + PIXEL_FORMAT_YVU_SEMIPLANAR_422 = 4, // 4 + PIXEL_FORMAT_YUV_SEMIPLANAR_444 = 5, // 5 + PIXEL_FORMAT_YVU_SEMIPLANAR_444 = 6, // 6 + PIXEL_FORMAT_YUYV_PACKED_422 = 7, // 7 + PIXEL_FORMAT_UYVY_PACKED_422 = 8, // 8 + PIXEL_FORMAT_YVYU_PACKED_422 = 9, // 9 + PIXEL_FORMAT_VYUY_PACKED_422 = 10, // 10 + PIXEL_FORMAT_YUV_PACKED_444 = 11, // 11 + PIXEL_FORMAT_RGB_888 = 12, // 12 + PIXEL_FORMAT_BGR_888 = 13, // 13 + PIXEL_FORMAT_ARGB_8888 = 14, // 14 + PIXEL_FORMAT_ABGR_8888 = 15, // 15 + PIXEL_FORMAT_RGBA_8888 = 16, // 16 + PIXEL_FORMAT_BGRA_8888 = 17, // 17 + PIXEL_FORMAT_YUV_SEMI_PLANNER_420_10BIT = 18, // 18 + PIXEL_FORMAT_YVU_SEMI_PLANNER_420_10BIT = 19, // 19 + PIXEL_FORMAT_YVU_PLANAR_420 = 20, // 20 + PIXEL_FORMAT_YVU_PLANAR_422, + PIXEL_FORMAT_YVU_PLANAR_444, + PIXEL_FORMAT_RGB_444 = 23, + PIXEL_FORMAT_BGR_444, + PIXEL_FORMAT_ARGB_4444, + PIXEL_FORMAT_ABGR_4444, + PIXEL_FORMAT_RGBA_4444, + PIXEL_FORMAT_BGRA_4444, + PIXEL_FORMAT_RGB_555, + PIXEL_FORMAT_BGR_555, + PIXEL_FORMAT_RGB_565, + PIXEL_FORMAT_BGR_565, + PIXEL_FORMAT_ARGB_1555, + PIXEL_FORMAT_ABGR_1555, + PIXEL_FORMAT_RGBA_1555, + PIXEL_FORMAT_BGRA_1555, + PIXEL_FORMAT_ARGB_8565, + PIXEL_FORMAT_ABGR_8565, + PIXEL_FORMAT_RGBA_8565, + PIXEL_FORMAT_BGRA_8565, + PIXEL_FORMAT_RGB_BAYER_8BPP = 50, + PIXEL_FORMAT_RGB_BAYER_10BPP, + PIXEL_FORMAT_RGB_BAYER_12BPP, + PIXEL_FORMAT_RGB_BAYER_14BPP, + PIXEL_FORMAT_RGB_BAYER_16BPP, + PIXEL_FORMAT_BGR_888_PLANAR = 70, + PIXEL_FORMAT_HSV_888_PACKAGE, + PIXEL_FORMAT_HSV_888_PLANAR, + PIXEL_FORMAT_LAB_888_PACKAGE, + PIXEL_FORMAT_LAB_888_PLANAR, + PIXEL_FORMAT_S8C1, + PIXEL_FORMAT_S8C2_PACKAGE, + PIXEL_FORMAT_S8C2_PLANAR, + PIXEL_FORMAT_S16C1, + PIXEL_FORMAT_U8C1, + PIXEL_FORMAT_U16C1, + PIXEL_FORMAT_S32C1, + PIXEL_FORMAT_U32C1, + PIXEL_FORMAT_U64C1, + PIXEL_FORMAT_S64C1, + PIXEL_FORMAT_YUV_SEMIPLANAR_440 = 1000, + PIXEL_FORMAT_YVU_SEMIPLANAR_440, + PIXEL_FORMAT_FLOAT32, + PIXEL_FORMAT_BUTT, + PIXEL_FORMAT_UNKNOWN = 10000 }; // Stream Format -enum acldvppStreamFormat { - H265_MAIN_LEVEL = 0, - H264_BASELINE_LEVEL, - H264_MAIN_LEVEL, - H264_HIGH_LEVEL -}; +enum acldvppStreamFormat { H265_MAIN_LEVEL = 0, H264_BASELINE_LEVEL, H264_MAIN_LEVEL, H264_HIGH_LEVEL }; // Supported Channel Mode -enum acldvppChannelMode { - DVPP_CHNMODE_VPC = 1, - DVPP_CHNMODE_JPEGD = 2, - DVPP_CHNMODE_JPEGE = 4 -}; +enum acldvppChannelMode { DVPP_CHNMODE_VPC = 1, DVPP_CHNMODE_JPEGD = 2, DVPP_CHNMODE_JPEGE = 4 }; // Supported Border Type -enum acldvppBorderType { - BORDER_CONSTANT = 0, - BORDER_REPLICATE, - BORDER_REFLECT, - BORDER_REFLECT_101 -}; +enum acldvppBorderType { BORDER_CONSTANT = 0, BORDER_REPLICATE, BORDER_REFLECT, BORDER_REFLECT_101 }; // Venc parameter type enum aclvencChannelDescParamType { - ACL_VENC_THREAD_ID_UINT64 = 0, - ACL_VENC_CALLBACK_PTR, - ACL_VENC_PIXEL_FORMAT_UINT32, - ACL_VENC_ENCODE_TYPE_UINT32, - ACL_VENC_PIC_WIDTH_UINT32, - ACL_VENC_PIC_HEIGHT_UINT32, - ACL_VENC_KEY_FRAME_INTERVAL_UINT32, - ACL_VENC_BUF_ADDR_PTR, - ACL_VENC_BUF_SIZE_UINT32, - ACL_VENC_RC_MODE_UINT32, - ACL_VENC_SRC_RATE_UINT32, - ACL_VENC_MAX_BITRATE_UINT32, - ACL_VENC_MAX_IP_PROP_UINT32 + ACL_VENC_THREAD_ID_UINT64 = 0, + ACL_VENC_CALLBACK_PTR, + ACL_VENC_PIXEL_FORMAT_UINT32, + ACL_VENC_ENCODE_TYPE_UINT32, + ACL_VENC_PIC_WIDTH_UINT32, + ACL_VENC_PIC_HEIGHT_UINT32, + ACL_VENC_KEY_FRAME_INTERVAL_UINT32, + ACL_VENC_BUF_ADDR_PTR, + ACL_VENC_BUF_SIZE_UINT32, + ACL_VENC_RC_MODE_UINT32, + ACL_VENC_SRC_RATE_UINT32, + ACL_VENC_MAX_BITRATE_UINT32, + ACL_VENC_MAX_IP_PROP_UINT32 }; /** @@ -512,9 +498,7 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescRetCode(const acldvppPicDesc *picD * @retval null for failed. * @retval other success */ -ACL_FUNC_VISIBILITY acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, - uint32_t right, - uint32_t top, +ACL_FUNC_VISIBILITY acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, uint32_t right, uint32_t top, uint32_t bottom); /** @@ -593,10 +577,7 @@ ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfigBottom(acldvppRoiConfig *config, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfig(acldvppRoiConfig *config, - uint32_t left, - uint32_t right, - uint32_t top, +ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfig(acldvppRoiConfig *config, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom); /** @@ -1085,7 +1066,8 @@ ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescMaxBitRate(aclvencChannelDesc * @retval ACL_SUCCESS for success, other for failure */ ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescParam(aclvencChannelDesc *channelDesc, - aclvencChannelDescParamType paramType, size_t length, const void *param); + aclvencChannelDescParamType paramType, size_t length, + const void *param); /** * @ingroup AscendCL @@ -1234,7 +1216,8 @@ ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescMaxBitRate(const aclvencChanne * @retval ACL_SUCCESS for success, other for failure */ ACL_FUNC_VISIBILITY aclError aclvencGetChannelDescParam(const aclvencChannelDesc *channelDesc, - aclvencChannelDescParamType paramType, size_t length, size_t *paramRetSize, void *param); + aclvencChannelDescParamType paramType, size_t length, + size_t *paramRetSize, void *param); /** * @ingroup AscendCL @@ -1534,10 +1517,7 @@ ACL_FUNC_VISIBILITY aclError aclvdecDestroyFrameConfig(aclvdecFrameConfig *vdecF * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, - uint32_t size, - uint32_t *width, - uint32_t *height, +ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, uint32_t size, uint32_t *width, uint32_t *height, int32_t *components); /** @@ -1552,8 +1532,7 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictEncSize(const acldvppPicDesc *inputDesc, - const acldvppJpegeConfig *config, - uint32_t *size); + const acldvppJpegeConfig *config, uint32_t *size); /** * @ingroup AscendCL @@ -1567,10 +1546,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictEncSize(const acldvppPicDesc *inp * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, - uint32_t dataSize, - acldvppPixelFormat outputPixelFormat, - uint32_t *decSize); +ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, uint32_t dataSize, + acldvppPixelFormat outputPixelFormat, uint32_t *decSize); /** * @ingroup AscendCL @@ -1585,11 +1562,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, - uint32_t dataSize, - uint32_t *width, - uint32_t *height, - int32_t *components); +ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, uint32_t dataSize, uint32_t *width, + uint32_t *height, int32_t *components); /** * @ingroup AscendCL @@ -1603,10 +1577,8 @@ ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppPngPredictDecSize(const void *data, - uint32_t dataSize, - acldvppPixelFormat outputPixelFormat, - uint32_t *decSize); +ACL_FUNC_VISIBILITY aclError acldvppPngPredictDecSize(const void *data, uint32_t dataSize, + acldvppPixelFormat outputPixelFormat, uint32_t *decSize); /** * @ingroup AscendCL @@ -1670,10 +1642,8 @@ ACL_FUNC_VISIBILITY aclError acldvppDestroyChannel(acldvppChannelDesc *channelDe * @see acldvppCreateChannel | acldvppCreatePicDesc * | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - acldvppResizeConfig *resizeConfig, +ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppResizeConfig *resizeConfig, aclrtStream stream); /** @@ -1709,10 +1679,8 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDe * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - acldvppRoiConfig *cropArea, +ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, aclrtStream stream); /** @@ -1737,12 +1705,9 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, - uint32_t *roiNums, - uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, - acldvppRoiConfig *cropAreas[], - aclrtStream stream); + acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, + uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], aclrtStream stream); /** * @ingroup AscendCL @@ -1765,12 +1730,9 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channe * * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateRoiConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - acldvppRoiConfig *cropArea, - acldvppRoiConfig *pasteArea, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, + acldvppRoiConfig *pasteArea, aclrtStream stream); /** * @ingroup AscendCL @@ -1795,14 +1757,11 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *cha * * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig */ - ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, - uint32_t *roiNums, - uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, - acldvppRoiConfig *cropAreas[], - acldvppRoiConfig *pasteAreas[], - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *channelDesc, + acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, + uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + acldvppRoiConfig *pasteAreas[], aclrtStream stream); /** * @ingroup AscendCL @@ -1830,11 +1789,8 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *cha * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, - const void *data, - uint32_t size, - acldvppPicDesc *outputDesc, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, + acldvppPicDesc *outputDesc, aclrtStream stream); /** * @ingroup AscendCL @@ -1852,11 +1808,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelD * * @see acldvppCreateChannel | acldvppCreateJpegeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - const void *data, - uint32_t *size, - acldvppJpegeConfig *config, +ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + const void *data, uint32_t *size, acldvppJpegeConfig *config, aclrtStream stream); /** @@ -1874,11 +1827,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelD * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppPngDecodeAsync(acldvppChannelDesc *channelDesc, - const void *data, - uint32_t size, - acldvppPicDesc *outputDesc, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppPngDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, + acldvppPicDesc *outputDesc, aclrtStream stream); /** * @ingroup AscendCL @@ -1933,11 +1883,8 @@ ACL_FUNC_VISIBILITY aclError aclvdecDestroyChannel(aclvdecChannelDesc *channelDe * * @see aclvdecCreateChannel | acldvppCreateStreamDesc | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, - acldvppStreamDesc *input, - acldvppPicDesc *output, - aclvdecFrameConfig *config, - void *userData); +ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, acldvppStreamDesc *input, + acldvppPicDesc *output, aclvdecFrameConfig *config, void *userData); /** * @ingroup AscendCL @@ -1956,10 +1903,8 @@ ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, * * @see aclvdecCreateChannel | acldvppCreateStreamDesc | acldvppCreatePicDesc | aclvdecSendFrame */ -ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channelDesc, - acldvppStreamDesc *input, - aclvdecFrameConfig *config, - void *userData); +ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channelDesc, acldvppStreamDesc *input, + aclvdecFrameConfig *config, void *userData); /** * @ingroup AscendCL @@ -1980,10 +1925,8 @@ ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channel * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, aclrtStream stream); /** * @ingroup AscendCL @@ -2005,11 +1948,8 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *cha * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - void *reserve, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, void *reserve, aclrtStream stream); /** * @ingroup AscendCL @@ -2021,8 +1961,7 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelD * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetChannelDescMode(acldvppChannelDesc *channelDesc, - uint32_t mode); +ACL_FUNC_VISIBILITY aclError acldvppSetChannelDescMode(acldvppChannelDesc *channelDesc, uint32_t mode); /** * @ingroup AscendCL @@ -2057,8 +1996,7 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetResizeConfigInterpolation(const acldvppRe * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutMode(aclvdecChannelDesc *channelDesc, - uint32_t outMode); +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutMode(aclvdecChannelDesc *channelDesc, uint32_t outMode); /** * @ingroup AscendCL @@ -2155,9 +2093,7 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetLutMapDims(const acldvppLutMap *lutMap); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, - uint32_t dim, - uint8_t **data, +ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, uint32_t dim, uint8_t **data, uint32_t *len); /** * @ingroup AscendCL @@ -2175,10 +2111,8 @@ ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, * @see acldvppCreateChannel|acldvppCreatePicDesc|acldvppCreateLutMap */ ACL_FUNC_VISIBILITY aclError acldvppVpcEqualizeHistAsync(const acldvppChannelDesc *channelDesc, - const acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - const acldvppLutMap *lutMap, - aclrtStream stream); + const acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, + const acldvppLutMap *lutMap, aclrtStream stream); /** * @ingroup AscendCL @@ -2199,8 +2133,7 @@ ACL_FUNC_VISIBILITY acldvppBorderConfig *acldvppCreateBorderConfig(); * * @retval ACL_SUCCESS for success, other for failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigValue(acldvppBorderConfig *borderConfig, - uint32_t index, +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigValue(acldvppBorderConfig *borderConfig, uint32_t index, double value); /** @@ -2345,10 +2278,8 @@ ACL_FUNC_VISIBILITY aclError acldvppDestroyBorderConfig(acldvppBorderConfig *bor * @see acldvppCreateChannel|acldvppCreatePicDesc|acldvppCreateBorderConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcMakeBorderAsync(const acldvppChannelDesc *channelDesc, - const acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - const acldvppBorderConfig *borderConfig, - aclrtStream stream); + const acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, + const acldvppBorderConfig *borderConfig, aclrtStream stream); /** * @ingroup AscendCL @@ -2365,11 +2296,8 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcMakeBorderAsync(const acldvppChannelDesc * * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateHist */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *srcPicDesc, - acldvppHist *hist, - void *reserve, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *srcPicDesc, + acldvppHist *hist, void *reserve, aclrtStream stream); /** * @ingroup AscendCL @@ -2378,7 +2306,7 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channel * @retval null for failed. * @retval OtherValues success. */ -ACL_FUNC_VISIBILITY acldvppHist* acldvppCreateHist(); +ACL_FUNC_VISIBILITY acldvppHist *acldvppCreateHist(); /** * @ingroup AscendCL @@ -2435,7 +2363,7 @@ ACL_FUNC_VISIBILITY aclError acldvppGetHistData(acldvppHist *hist, uint32_t dim, * * @see acldvppCreateHist | acldvppVpcCalcHistAsync */ -ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist* hist); +ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist *hist); /** * @ingroup AscendCL @@ -2458,4 +2386,4 @@ ACL_FUNC_VISIBILITY aclError acldvppClearHist(acldvppHist *hist); } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ diff --git a/inc/external/acl/ops/acl_fv.h b/inc/external/acl/ops/acl_fv.h index 40cd50cb..27dc367a 100644 --- a/inc/external/acl/ops/acl_fv.h +++ b/inc/external/acl/ops/acl_fv.h @@ -32,8 +32,8 @@ typedef struct aclfvSearchResult aclfvSearchResult; // search operation type enum aclfvSearchType { - SEARCH_1_N, // 1:N operation type - SEARCH_N_M // N:M operation type + SEARCH_1_N, // 1:N operation type + SEARCH_N_M // N:M operation type }; /** @@ -104,7 +104,8 @@ ACL_FUNC_VISIBILITY aclError aclfvSetNMTopNum(aclfvInitPara *initPara, uint32_t * @retval OtherValues success. */ ACL_FUNC_VISIBILITY aclfvFeatureInfo *aclfvCreateFeatureInfo(uint32_t id0, uint32_t id1, uint32_t offset, - uint32_t featureLen, uint32_t featureCount, uint8_t *featureData, uint32_t featureDataLen); + uint32_t featureLen, uint32_t featureCount, + uint8_t *featureData, uint32_t featureDataLen); /** * @ingroup AscendCL @@ -233,8 +234,9 @@ ACL_FUNC_VISIBILITY aclError aclfvDestroySearchInput(aclfvSearchInput *searchInp * @retval null for failed. OtherValues success */ ACL_FUNC_VISIBILITY aclfvSearchResult *aclfvCreateSearchResult(uint32_t queryCnt, uint32_t *resultNum, - uint32_t resultNumDataLen, uint32_t *id0, uint32_t *id1, uint32_t *resultOffset, float *resultDistance, - uint32_t dataLen); + uint32_t resultNumDataLen, uint32_t *id0, uint32_t *id1, + uint32_t *resultOffset, float *resultDistance, + uint32_t dataLen); /** * @ingroup AscendCL @@ -348,4 +350,4 @@ ACL_FUNC_VISIBILITY aclError aclfvSearch(aclfvSearchType type, aclfvSearchInput } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_RETR_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_RETR_H_ diff --git a/inc/external/hccl/hccl.h b/inc/external/hccl/hccl.h index 311e78f2..46d934e6 100644 --- a/inc/external/hccl/hccl.h +++ b/inc/external/hccl/hccl.h @@ -27,7 +27,7 @@ #ifdef __cplusplus extern "C" { -#endif // __cplusplus +#endif // __cplusplus /** * @brief Initialize HCCL. @@ -66,14 +66,15 @@ extern HcclResult HcclCommInitRootInfo(uint32_t nRanks, const HcclRootInfo *root * @param sendBuf A pointer identifying the input data address of the operator. * @param recvBuf A pointer identifying the output data address of the operator. * @param count An integer(u64) identifying the number of the output data. - * @param dataType The data type of the operator, must be one of the following types: int8, int16, int32, float16, float32. + * @param dataType The data type of the operator, must be one of the following types: int8, int16, int32, float16, + * float32. * @param op The reduction type of the operator, must be one of the following types: sum, min, max, prod. * @param comm A pointer identifying the communication resource based on. * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclAllReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType, -HcclReduceOp op, HcclComm comm, aclrtStream stream); +extern HcclResult HcclAllReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType, HcclReduceOp op, + HcclComm comm, aclrtStream stream); /** * @brief Broadcast operator. @@ -84,10 +85,10 @@ HcclReduceOp op, HcclComm comm, aclrtStream stream); * @param root An integer(u32) identifying the the root rank in the operator. * @param comm A pointer identifying the communication resource based on * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclBroadcast(void *buf, uint64_t count, HcclDataType dataType, uint32_t root, HcclComm comm, -aclrtStream stream); +extern HcclResult HcclBroadcast(void *buf, uint64_t count, HcclDataType dataType, uint32_t root, HcclComm comm, + aclrtStream stream); /** * @brief ReduceScatter operator. @@ -99,10 +100,10 @@ aclrtStream stream); * @param op The reduction type of the operator, must be one of the following types: sum, min, max, prod. * @param comm A pointer identifying the communication resource based on. * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclReduceScatter(void *sendBuf, void *recvBuf, uint64_t recvCount, HcclDataType dataType, -HcclReduceOp op, HcclComm comm, aclrtStream stream); +extern HcclResult HcclReduceScatter(void *sendBuf, void *recvBuf, uint64_t recvCount, HcclDataType dataType, + HcclReduceOp op, HcclComm comm, aclrtStream stream); /** * @brief AllGather operator. @@ -113,10 +114,10 @@ HcclReduceOp op, HcclComm comm, aclrtStream stream); * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. * @param comm A pointer identifying the communication resource based on. * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclAllGather(void *sendBuf, void *recvBuf, uint64_t sendCount, HcclDataType dataType, -HcclComm comm, aclrtStream stream); +extern HcclResult HcclAllGather(void *sendBuf, void *recvBuf, uint64_t sendCount, HcclDataType dataType, HcclComm comm, + aclrtStream stream); /** * @brief Destroy HCCL comm @@ -129,5 +130,5 @@ extern HcclResult HcclCommDestroy(HcclComm comm); #ifdef __cplusplus } -#endif // __cplusplus -#endif // HCCL_H_ +#endif // __cplusplus +#endif // HCCL_H_ diff --git a/inc/external/hccl/hccl_types.h b/inc/external/hccl/hccl_types.h index 50a64795..0e832396 100644 --- a/inc/external/hccl/hccl_types.h +++ b/inc/external/hccl/hccl_types.h @@ -16,10 +16,10 @@ /** * @file hccl_types.h - * @brief HCCL data type definition - * + * @brief HCCL data type definition + * */ - + #ifndef HCCL_TYPES_H_ #define HCCL_TYPES_H_ @@ -27,33 +27,33 @@ #ifdef __cplusplus extern "C" { -#endif // __cplusplus +#endif // __cplusplus /** * @brief HCCL functions return value definition */ typedef enum { - HCCL_SUCCESS = 0, /**< success */ - HCCL_E_PARA = 1, /**< parameter error */ - HCCL_E_PTR = 2, /**< empty pointer */ - HCCL_E_MEMORY = 3, /**< memory error */ - HCCL_E_INTERNAL = 4, /**< internal error */ - HCCL_E_NOT_SUPPORT = 5, /**< not support feature */ - HCCL_E_NOT_FOUND = 6, /**< not found specific resource */ - HCCL_E_UNAVAIL = 7, /**< resource unavailable */ - HCCL_E_SYSCALL = 8, /**< call system interface error */ - HCCL_E_TIMEOUT = 9, /**< timeout */ - HCCL_E_OPEN_FILE_FAILURE = 10, /**< open file fail */ - HCCL_E_TCP_CONNECT = 11, /**< tcp connect fail */ - HCCL_E_ROCE_CONNECT = 12, /**< roce connect fail */ - HCCL_E_TCP_TRANSFER = 13, /**< tcp transfer fail */ - HCCL_E_ROCE_TRANSFER = 14, /**< roce transfer fail */ - HCCL_E_RUNTIME = 15, /**< call runtime api fail */ - HCCL_E_DRV = 16, /**< call driver api fail */ - HCCL_E_PROFILING = 17, /**< call profiling api fail */ - HCCL_E_CCE = 18, /**< call cce api fail */ - HCCL_E_NETWORK = 19, /**< call network api fail */ - HCCL_E_RESERVED /**< reserved */ + HCCL_SUCCESS = 0, /**< success */ + HCCL_E_PARA = 1, /**< parameter error */ + HCCL_E_PTR = 2, /**< empty pointer */ + HCCL_E_MEMORY = 3, /**< memory error */ + HCCL_E_INTERNAL = 4, /**< internal error */ + HCCL_E_NOT_SUPPORT = 5, /**< not support feature */ + HCCL_E_NOT_FOUND = 6, /**< not found specific resource */ + HCCL_E_UNAVAIL = 7, /**< resource unavailable */ + HCCL_E_SYSCALL = 8, /**< call system interface error */ + HCCL_E_TIMEOUT = 9, /**< timeout */ + HCCL_E_OPEN_FILE_FAILURE = 10, /**< open file fail */ + HCCL_E_TCP_CONNECT = 11, /**< tcp connect fail */ + HCCL_E_ROCE_CONNECT = 12, /**< roce connect fail */ + HCCL_E_TCP_TRANSFER = 13, /**< tcp transfer fail */ + HCCL_E_ROCE_TRANSFER = 14, /**< roce transfer fail */ + HCCL_E_RUNTIME = 15, /**< call runtime api fail */ + HCCL_E_DRV = 16, /**< call driver api fail */ + HCCL_E_PROFILING = 17, /**< call profiling api fail */ + HCCL_E_CCE = 18, /**< call cce api fail */ + HCCL_E_NETWORK = 19, /**< call network api fail */ + HCCL_E_RESERVED /**< reserved */ } HcclResult; /** @@ -65,37 +65,37 @@ typedef void *HcclComm; * @brief HCCL Reduction opperation */ typedef enum { - HCCL_REDUCE_SUM = 0, /**< sum */ - HCCL_REDUCE_PROD = 1, /**< prod */ - HCCL_REDUCE_MAX = 2, /**< max */ - HCCL_REDUCE_MIN = 3, /**< min */ - HCCL_REDUCE_RESERVED /**< reserved */ + HCCL_REDUCE_SUM = 0, /**< sum */ + HCCL_REDUCE_PROD = 1, /**< prod */ + HCCL_REDUCE_MAX = 2, /**< max */ + HCCL_REDUCE_MIN = 3, /**< min */ + HCCL_REDUCE_RESERVED /**< reserved */ } HcclReduceOp; /** * @brief HCCL data type */ typedef enum { - HCCL_DATA_TYPE_INT8 = 0, /**< int8 */ - HCCL_DATA_TYPE_INT16 = 1, /**< int16 */ - HCCL_DATA_TYPE_INT32 = 2, /**< int32 */ - HCCL_DATA_TYPE_FP16 = 3, /**< fp16 */ - HCCL_DATA_TYPE_FP32 = 4, /**< fp32 */ - HCCL_DATA_TYPE_INT64 = 5, /**< int64 */ - HCCL_DATA_TYPE_UINT64 = 6, /**< uint64 */ - HCCL_DATA_TYPE_RESERVED /**< reserved */ + HCCL_DATA_TYPE_INT8 = 0, /**< int8 */ + HCCL_DATA_TYPE_INT16 = 1, /**< int16 */ + HCCL_DATA_TYPE_INT32 = 2, /**< int32 */ + HCCL_DATA_TYPE_FP16 = 3, /**< fp16 */ + HCCL_DATA_TYPE_FP32 = 4, /**< fp32 */ + HCCL_DATA_TYPE_INT64 = 5, /**< int64 */ + HCCL_DATA_TYPE_UINT64 = 6, /**< uint64 */ + HCCL_DATA_TYPE_RESERVED /**< reserved */ } HcclDataType; -const uint32_t HCCL_ROOT_INFO_BYTES = 4108; // 4108: root info length +const uint32_t HCCL_ROOT_INFO_BYTES = 4108; // 4108: root info length /** * @brief HCCL root info */ typedef struct HcclRootInfoDef { - char internal[HCCL_ROOT_INFO_BYTES]; + char internal[HCCL_ROOT_INFO_BYTES]; } HcclRootInfo; #ifdef __cplusplus } -#endif // __cplusplus -#endif // HCCL_TYPES_H_ +#endif // __cplusplus +#endif // HCCL_TYPES_H_ diff --git a/inc/external/runtime/rt_error_codes.h b/inc/external/runtime/rt_error_codes.h index 73da559d..d2373525 100644 --- a/inc/external/runtime/rt_error_codes.h +++ b/inc/external/runtime/rt_error_codes.h @@ -23,80 +23,79 @@ extern "C" { #endif -static const int32_t ACL_RT_SUCCESS = 0; // success +static const int32_t ACL_RT_SUCCESS = 0; // success -static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid -static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id -static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null -static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context -static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context -static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal -static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned -static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed -static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed -static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream -static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread -static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set -static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create -static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream -static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type -static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle -static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type +static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid +static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id +static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null +static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context +static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context +static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal +static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned +static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed +static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed +static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream +static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread +static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set +static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create +static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream +static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type +static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle +static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type -static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support -static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error -static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error -static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow -static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device -static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail -static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission -static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource -static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource -static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource -static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource +static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support +static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error +static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error +static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow +static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device +static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail +static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission +static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource +static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource +static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource +static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource -static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error - -static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error #ifdef __cplusplus } #endif -#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ +#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ From ed7e35f927d7d9e90a64c07920faf6150d31e30f Mon Sep 17 00:00:00 2001 From: changzherui Date: Tue, 26 Jan 2021 19:53:33 +0800 Subject: [PATCH 08/59] sync code 0125 .h --- inc/external/acl/ops/acl_dvpp.h | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/inc/external/acl/ops/acl_dvpp.h b/inc/external/acl/ops/acl_dvpp.h index 1a0f582d..8f5d3904 100644 --- a/inc/external/acl/ops/acl_dvpp.h +++ b/inc/external/acl/ops/acl_dvpp.h @@ -147,6 +147,17 @@ enum aclvencChannelDescParamType { ACL_VENC_MAX_IP_PROP_UINT32 }; +// Jpeg picture format +enum acldvppJpegFormat { + ACL_JPEG_CSS_444 = 0, + ACL_JPEG_CSS_422, + ACL_JPEG_CSS_420, + ACL_JPEG_CSS_GRAY, + ACL_JPEG_CSS_440, + ACL_JPEG_CSS_411, + ACL_JPEG_CSS_UNKNOWN = 1000 +}; + /** * @ingroup AscendCL * @brief alloc device memory for dvpp. @@ -1520,6 +1531,24 @@ ACL_FUNC_VISIBILITY aclError aclvdecDestroyFrameConfig(aclvdecFrameConfig *vdecF ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, uint32_t size, uint32_t *width, uint32_t *height, int32_t *components); +/** + * @ingroup AscendCL + * @brief Get image width and height of jpeg. + * + * @param data [IN] image data in host memory + * @param size [IN] the size of image data + * @param width [OUT] the width of image from image header + * @param height [OUT] the height of image from image header + * @param components [OUT] the components of image from image header + * @param format [OUT] the format of image from image header + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, uint32_t size, uint32_t *width, + uint32_t *height, int32_t *components, + acldvppJpegFormat *format); + /** * @ingroup AscendCL * @brief Predict encode size of jpeg image. From b4539d54cd66adc0b2014e9bdf1be3f5ea66994b Mon Sep 17 00:00:00 2001 From: changzherui Date: Mon, 1 Feb 2021 20:50:22 +0800 Subject: [PATCH 09/59] modify error_codes.h --- inc/external/acl/error_codes/ge_error_codes.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/inc/external/acl/error_codes/ge_error_codes.h b/inc/external/acl/error_codes/ge_error_codes.h index 20a7e0f9..041fc7ae 100644 --- a/inc/external/acl/error_codes/ge_error_codes.h +++ b/inc/external/acl/error_codes/ge_error_codes.h @@ -38,7 +38,12 @@ static const uint32_t ACL_ERROR_GE_AIPP_NOT_EXIST = 145015; static const uint32_t ACL_ERROR_GE_AIPP_MODE_INVALID = 145016; static const uint32_t ACL_ERROR_GE_OP_TASK_TYPE_INVALID = 145017; static const uint32_t ACL_ERROR_GE_OP_KERNEL_TYPE_INVALID = 145018; +static const uint32_t ACL_ERROR_GE_PLGMGR_PATH_INVALID = 145019; +static const uint32_t ACL_ERROR_GE_TRANSSHAPE_FORMAT_INVALID = 145020; +static const uint32_t ACL_ERROR_GE_TRANSSHAPE_SHAPE_INVALID = 145021; +static const uint32_t ACL_ERROR_GE_TRANSSHAPE_DATATYPE_INVALID = 145022; static const uint32_t ACL_ERROR_GE_MEMORY_ALLOCATION = 245000; +static const uint32_t ACL_ERROR_GE_MEMORY_OPERATE_FAILED = 245001; static const uint32_t ACL_ERROR_GE_INTERNAL_ERROR = 545000; static const uint32_t ACL_ERROR_GE_LOAD_MODEL = 545001; static const uint32_t ACL_ERROR_GE_EXEC_LOAD_MODEL_PARTITION_FAILED = 545002; @@ -49,6 +54,7 @@ static const uint32_t ACL_ERROR_GE_EXEC_RELEASE_MODEL_DATA = 545006; static const uint32_t ACL_ERROR_GE_COMMAND_HANDLE = 545007; static const uint32_t ACL_ERROR_GE_GET_TENSOR_INFO = 545008; static const uint32_t ACL_ERROR_GE_UNLOAD_MODEL = 545009; + #ifdef __cplusplus } // namespace ge #endif From cffc6b2e2e9435c7b3db589303c5e70217c51d0e Mon Sep 17 00:00:00 2001 From: shenwei41 Date: Wed, 3 Feb 2021 23:19:27 +0800 Subject: [PATCH 10/59] update include file --- inc/external/acl/acl_base.h | 1 + inc/external/acl/error_codes/ge_error_codes.h | 14 ++ inc/external/acl/error_codes/rt_error_codes.h | 3 +- inc/external/runtime/rt_error_codes.h | 3 +- third_party/fwkacllib/inc/ops/batch_ops.h | 15 +- third_party/fwkacllib/inc/ops/data_flow_ops.h | 47 +++- .../inc/ops/elewise_calculation_ops.h | 80 +++++++ third_party/fwkacllib/inc/ops/hcom_ops.h | 16 ++ third_party/fwkacllib/inc/ops/image_ops.h | 60 ++++- third_party/fwkacllib/inc/ops/linalg_ops.h | 84 +++---- third_party/fwkacllib/inc/ops/list_ops.h | 2 +- third_party/fwkacllib/inc/ops/math_ops.h | 68 ++++++ .../inc/ops/matrix_calculation_ops.h | 21 ++ .../fwkacllib/inc/ops/nn_batch_norm_ops.h | 104 +++++++++ .../fwkacllib/inc/ops/nn_calculation_ops.h | 16 +- third_party/fwkacllib/inc/ops/nn_detect_ops.h | 47 +++- third_party/fwkacllib/inc/ops/nn_norm_ops.h | 41 ++++ third_party/fwkacllib/inc/ops/nn_ops.h | 29 ++- .../fwkacllib/inc/ops/nonlinear_fuc_ops.h | 44 +++- third_party/fwkacllib/inc/ops/reduce_ops.h | 155 ++++++++++++- third_party/fwkacllib/inc/ops/selection_ops.h | 70 +++++- third_party/fwkacllib/inc/ops/sparse_ops.h | 6 +- third_party/fwkacllib/inc/ops/spectral_ops.h | 96 ++++++++ .../fwkacllib/inc/ops/split_combination_ops.h | 18 +- third_party/fwkacllib/inc/ops/string_ops.h | 2 +- third_party/fwkacllib/inc/runtime/config.h | 19 ++ third_party/fwkacllib/inc/runtime/dev.h | 5 + third_party/fwkacllib/inc/runtime/kernel.h | 35 +++ third_party/fwkacllib/inc/runtime/rt_model.h | 14 ++ third_party/fwkacllib/inc/toolchain/slog.h | 30 +-- .../inc/toolchain/tuning_tool/tune_api.h | 209 ++++++++++++------ 31 files changed, 1188 insertions(+), 166 deletions(-) diff --git a/inc/external/acl/acl_base.h b/inc/external/acl/acl_base.h index b3111860..839bd597 100644 --- a/inc/external/acl/acl_base.h +++ b/inc/external/acl/acl_base.h @@ -111,6 +111,7 @@ static const int ACL_ERROR_DUMP_NOT_RUN = 100045; static const int ACL_ERROR_PROF_REPEAT_SUBSCRIBE = 148046; static const int ACL_ERROR_PROF_API_CONFLICT = 148047; static const int ACL_ERROR_INVALID_MAX_OPQUEUE_NUM_CONFIG = 148048; +static const int ACL_ERROR_INVALID_OPP_PATH = 148049; static const int ACL_ERROR_BAD_ALLOC = 200000; static const int ACL_ERROR_API_NOT_SUPPORT = 200001; diff --git a/inc/external/acl/error_codes/ge_error_codes.h b/inc/external/acl/error_codes/ge_error_codes.h index 041fc7ae..b477a18c 100644 --- a/inc/external/acl/error_codes/ge_error_codes.h +++ b/inc/external/acl/error_codes/ge_error_codes.h @@ -17,6 +17,20 @@ #ifndef INC_EXTERNAL_GE_GE_ERROR_CODES_H_ #define INC_EXTERNAL_GE_GE_ERROR_CODES_H_ +#if defined(_MSC_VER) +#ifdef FUNC_VISIBILITY +#define GE_FUNC_VISIBILITY _declspec(dllexport) +#else +#define GE_FUNC_VISIBILITY +#endif +#else +#ifdef FUNC_VISIBILITY +#define GE_FUNC_VISIBILITY __attribute__((visibility("default"))) +#else +#define GE_FUNC_VISIBILITY +#endif +#endif + #include #ifdef __cplusplus diff --git a/inc/external/acl/error_codes/rt_error_codes.h b/inc/external/acl/error_codes/rt_error_codes.h index d2373525..2109fb79 100644 --- a/inc/external/acl/error_codes/rt_error_codes.h +++ b/inc/external/acl/error_codes/rt_error_codes.h @@ -92,7 +92,8 @@ static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error -static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error +static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error +static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error #ifdef __cplusplus } diff --git a/inc/external/runtime/rt_error_codes.h b/inc/external/runtime/rt_error_codes.h index d2373525..2109fb79 100644 --- a/inc/external/runtime/rt_error_codes.h +++ b/inc/external/runtime/rt_error_codes.h @@ -92,7 +92,8 @@ static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error -static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error +static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error +static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error #ifdef __cplusplus } diff --git a/third_party/fwkacllib/inc/ops/batch_ops.h b/third_party/fwkacllib/inc/ops/batch_ops.h index a4786cd3..181bf694 100644 --- a/third_party/fwkacllib/inc/ops/batch_ops.h +++ b/third_party/fwkacllib/inc/ops/batch_ops.h @@ -107,11 +107,13 @@ across multiple sessions . \n REG_OP(Unbatch) .INPUT(x_tensor, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, \ - DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE})) + DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ + DT_COMPLEX64, DT_COMPLEX128})) .INPUT(index, TensorType({DT_INT64})) .INPUT(id, TensorType({DT_INT64})) .OUTPUT(y_tensor, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, \ - DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE})) + DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ + DT_COMPLEX64, DT_COMPLEX128})) .REQUIRED_ATTR(timeout_micros, Int) .ATTR(container, String, "") .ATTR(shared_name, String, "") @@ -146,13 +148,16 @@ across multiple sessions . \n REG_OP(UnbatchGrad) .INPUT(x_input, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, \ - DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE})) + DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ + DT_COMPLEX64, DT_COMPLEX128})) .INPUT(index, TensorType({DT_INT64})) .INPUT(grad, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, \ - DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE})) + DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ + DT_COMPLEX64, DT_COMPLEX128})) .INPUT(id, TensorType({DT_INT64})) .OUTPUT(y_grad, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, \ - DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE})) + DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ + DT_COMPLEX64, DT_COMPLEX128})) .ATTR(container, String, "") .ATTR(shared_name, String, "") .OP_END_FACTORY_REG(UnbatchGrad) diff --git a/third_party/fwkacllib/inc/ops/data_flow_ops.h b/third_party/fwkacllib/inc/ops/data_flow_ops.h index 45303828..0043c027 100644 --- a/third_party/fwkacllib/inc/ops/data_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/data_flow_ops.h @@ -1430,6 +1430,24 @@ REG_OP(OrderedMapClear) .ATTR(shared_name, String, "") .OP_END_FACTORY_REG(OrderedMapClear) +/** +*@brief FakeQueue, support tf api FixedLengthRecordReader. \n + +*@par Inputs: +*Including: +* @li resource: A Tensor of type DT_RESOURCE. + +*@par Outputs: +*handle: A Tensor of type DT_STRING ref. \n + +*@par Third-party framework compatibility +*Compatible with the TensorFlow operator FakeQueue. +*/ +REG_OP(FakeQueue) + .INPUT(resource, TensorType({DT_RESOURCE})) + .OUTPUT(handle, TensorType({DT_STRING})) + .OP_END_FACTORY_REG(FakeQueue) + /** *@brief Returns the number of incomplete elements in the underlying container. \n @@ -2258,6 +2276,7 @@ REG_OP(LruCache) .ATTR(shared_name, String, "LruCache") .ATTR(cache_size, Int, 100000) .ATTR(load_factor, Float, 1) + .REQUIRED_ATTR(dtype, Type) .OP_END_FACTORY_REG(LruCache) /** @@ -2277,9 +2296,9 @@ REG_OP(CacheAdd) .INPUT(cache, TensorType({DT_RESOURCE})) .INPUT(ids, TensorType({DT_INT64, DT_INT32, DT_UINT64, DT_UINT32})) .OUTPUT(swap_in_id, TensorType({DT_INT64, DT_INT32, DT_UINT64, DT_UINT32})) - .OUTPUT(swap_in_idx, TensorType({DT_INT64})) + .OUTPUT(swap_in_idx, TensorType({DT_INT64, DT_INT32, DT_UINT64, DT_UINT32})) .OUTPUT(swap_out_id, TensorType({DT_INT64, DT_INT32, DT_UINT64, DT_UINT32})) - .OUTPUT(swap_out_idx, TensorType({DT_INT64})) + .OUTPUT(swap_out_idx, TensorType({DT_INT64, DT_INT32, DT_UINT64, DT_UINT32})) .OP_END_FACTORY_REG(CacheAdd) /** @@ -2295,9 +2314,31 @@ REG_OP(CacheAdd) REG_OP(CacheRemoteIndexToLocal) .INPUT(cache, TensorType({DT_RESOURCE})) .INPUT(ids, TensorType({DT_INT64, DT_INT32, DT_UINT64, DT_UINT32})) - .OUTPUT(local_idx, TensorType({DT_INT64})) + .OUTPUT(local_idx, TensorType({DT_INT64, DT_INT32, DT_UINT64, DT_UINT32})) .OP_END_FACTORY_REG(CacheRemoteIndexToLocal) +/** +*@brief CacheAllToLocalIndex, get id in cache +*@par Inputs: +*cache: resource data +*local_idx: id in cache. +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(CacheAllIndexToLocal) + .INPUT(cache, TensorType({DT_RESOURCE})) + .OUTPUT(local_idx, TensorType({DT_INT64, DT_INT32, DT_UINT64, DT_UINT32})) + .REQUIRED_ATTR(dtype, Type) + .OP_END_FACTORY_REG(CacheAllIndexToLocal) + +REG_OP(DynamicGetNext) + .INPUT(x, TensorType::ALL()) + .DYNAMIC_OUTPUT(y, TensorType::ALL()) + .ATTR(output_types, ListType, {}) + .ATTR(output_shapes, ListListInt, {{}, {}}) + .ATTR(_dynamic_graph_execute_mode, String, "lazy_recompile") + .ATTR(_getnext_inputs_shape_range, String, "") + .OP_END_FACTORY_REG(DynamicGetNext) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_DATA_FLOW_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index e65c7027..9f981d12 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -3627,6 +3627,35 @@ REG_OP(Lerp) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(Lerp) +/** +*@brief Returns the num value of abs(x1-x2) > atol+rtol*abs(x2) element-wise. \n + +* +*@par Inputs: +*@li x1: A tensor. Must be one of the following types: float32, int32, uint8, int8, float16 +*@li x2: A tensor of the same type as "x1". +* +*@par Attributes: +* atol: Defaults to "1e-05". +* rtol: Defaults to "1e-03". +* +*@par Outputs: +* num: A tensor of type int32. +* diff: A tensor of type float16. +* +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* +*/ +REG_OP(DataCompare) + .INPUT(x1, TensorType({ DT_FLOAT16, DT_FLOAT,DT_INT8, DT_UINT8, DT_INT32 })) + .INPUT(x2, TensorType({ DT_FLOAT16, DT_FLOAT,DT_INT8, DT_UINT8, DT_INT32 })) + .OUTPUT(num, TensorType({DT_FLOAT})) + .OUTPUT(diff, TensorType({DT_FLOAT16})) + .ATTR(atol, Float, 1e-5) + .ATTR(rtol, Float, 1e-3) + .OP_END_FACTORY_REG(DataCompare) + /** *@brief Hardmax(element in input, axis) = 1 if the element is the first maximum value along the specified axis, 0 *otherwise The input does not need to explicitly be a 2D vector.The "axis" attribute indicates the dimension along @@ -3650,6 +3679,57 @@ REG_OP(HardMax) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(axis, Int, -1) .OP_END_FACTORY_REG(HardMax) + +/** +* @brief Computes the dot product (inner product) of two tensors. This function does not broadcast. + +* @par Inputs: +* Two inputs, including: +* @li input_x: A Tensor. the first tensor must be 1d. \n +* @li input_y: A Tensor. the second tensor must be 1d. \n + +* @par Outputs: +* @li output: A Tensor. Result of the two inputs, must be 1d. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch dot operator. \n +*/ +REG_OP(Dot) + .INPUT(input_x, TensorType({DT_FLOAT, DT_FLOAT16, DT_UINT8, DT_INT8, DT_INT32})) + .INPUT(input_y, TensorType({DT_FLOAT, DT_FLOAT16, DT_UINT8, DT_INT8, DT_INT32})) + .OUTPUT(output, TensorType({DT_FLOAT, DT_FLOAT16, DT_UINT8, DT_INT8, DT_INT32})) + .OP_END_FACTORY_REG(Dot) + +/** +*@brief Returns a new tensor with boolean elements representing \n +*if each element of input is “close” to the corresponding element of other \n + +*@par Inputs: +*Two inputs, including: +* @li x1: A tensor. Must be one of the following types: +* float16, float32, int32. \n +* @li x2: A tensor with the same type and shape of x1's. \n + +*@par Attributes: +*@li rtol: An optional float.Defaults to 1e-05. \n +*@li atol: An optional float.Defaults to 1e-08. \n +*@li equal_nan: An optional bool.Defaults to false. \n + +*@par Outputs: +*y: A Tensor bool with the same shape of x1's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator isclose. \n +*/ +REG_OP(IsClose) + .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OUTPUT(y, TensorType({DT_BOOL})) + .ATTR(rtol, Float, 1e-05) + .ATTR(atol, Float, 1e-08) + .ATTR(equal_nan, Bool, false) + .OP_END_FACTORY_REG(IsClose) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_ELEWISE_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/hcom_ops.h b/third_party/fwkacllib/inc/ops/hcom_ops.h index cb9fbe22..f4ded0cd 100644 --- a/third_party/fwkacllib/inc/ops/hcom_ops.h +++ b/third_party/fwkacllib/inc/ops/hcom_ops.h @@ -238,6 +238,15 @@ REG_OP(HcomRemoteRead) .REQUIRED_ATTR(dtype, Type) .OP_END_FACTORY_REG(HcomRemoteRead) +/** + * @brief Performs Remote Ref Read of input tensors + * @par Inputs: + * remote: A tensor. describing the remote memory address to read: u64 remoteId, u64 addrRemote, u64 length + * cache_var: The local base address + * local_offset: Skip step length + * @par Outputs: + * cache_var: The local base address + */ REG_OP(HcomRemoteRefRead) .INPUT(remote, TensorType({DT_UINT64})) .INPUT(cache_var, TensorType({DT_UINT64})) @@ -258,6 +267,13 @@ REG_OP(HcomRemoteWrite) .INPUT(local, TensorType::ALL()) .OP_END_FACTORY_REG(HcomRemoteWrite) +/** + * @brief Performs Remote Write of input tensors + * @par Inputs: + * remote: A tensor. describing the remote memory address to write: u64 remoteId, u64 addrRemote, u64 length + * @par Inputs: + * local: A Tensor. whose value is length / size_of(Type) + */ REG_OP(HcomRemoteScatterWrite) .INPUT(remote, TensorType({DT_INT64, DT_UINT64})) .INPUT(local, TensorType::ALL()) diff --git a/third_party/fwkacllib/inc/ops/image_ops.h b/third_party/fwkacllib/inc/ops/image_ops.h index d7f60346..4703705b 100644 --- a/third_party/fwkacllib/inc/ops/image_ops.h +++ b/third_party/fwkacllib/inc/ops/image_ops.h @@ -652,6 +652,62 @@ REG_OP(RGBToHSV) /** *@brief Generate a single randomly distorted bounding box for an image . \n +*@par Inputs: +*Input images must be a 4-D tensor. Inputs include: +*@li image_size: 1-D, containing [height, width, channels]. +*@li bounding_boxes: 3-D with shape [batch, N, 4] describing the N bounding +boxes associated with the image. \n + +*@par Attributes: +*@li seed: If either seed or seed2 are set to non-zero, the random number +generator is seeded by the given seed. Otherwise, it is seeded by a random seed. +*@li seed2: A second seed to avoid seed collision. +*@li min_object_covered: The cropped area of the image must contain at least +this fraction of any bounding box supplied. The value of this parameter should +be non-negative. In the case of 0, the cropped area does not need to overlap +any of the bounding boxes supplied . +*@li aspect_ratio_range: The cropped area of the image must have an aspect +ratio = width / height within this range. +*@li max_attempts: Number of attempts at generating a cropped region of the +image of the specified constraints. After max_attempts failures, return the +entire image. +*@li use_image_if_no_bounding_boxes: Controls behavior if no bounding boxes +supplied. If true, assume an implicit bounding box covering the whole input. +If false, raise an error . \n + +*@par Outputs: +*@li begin: 1-D, containing [offset_height, offset_width, 0]. +*@li size: 1-D, containing [target_height, target_width, -1]. +*@li bboxes: 3-D with shape [1, 1, 4] containing the distorted bounding box . \n + +*@attention Constraints: +*Input images can be of different types but output images are always float . \n + +*@par Third-party framework compatibility +*Compatible with tensorflow SampleDistortedBoundingBox operator. +*/ + +REG_OP(SampleDistortedBoundingBox) + .INPUT(image_size, TensorType({ DT_UINT8, DT_INT8, DT_INT16, \ + DT_INT32, DT_INT64 })) + .INPUT(bounding_boxes, TensorType({ DT_FLOAT })) + .OUTPUT(begin, TensorType({ DT_UINT8, DT_INT8, DT_INT16, \ + DT_INT32, DT_INT64 })) + .OUTPUT(size, TensorType({ DT_UINT8, DT_INT8, DT_INT16, \ + DT_INT32, DT_INT64 })) + .OUTPUT(bboxes, TensorType({ DT_FLOAT })) + .ATTR(seed, Int, 0) + .ATTR(seed2, Int, 0) + .ATTR(min_object_covered, Float, 0.1f) + .ATTR(aspect_ratio_range, ListFloat, { 0.75f, 1.33f }) + .ATTR(area_range, ListFloat, { 0.05f, 1.0f }) + .ATTR(max_attempts, Int, 100) + .ATTR(use_image_if_no_bounding_boxes, Bool, false) + .OP_END_FACTORY_REG(SampleDistortedBoundingBox) + +/** +*@brief Generate a single randomly distorted bounding box for an image . \n + *@par Inputs: *Input images must be a 4-D tensor. Inputs include: *@li image_size: 1-D, containing [height, width, channels]. @@ -1424,11 +1480,11 @@ REG_OP(Resize) *@par Attributes: *@li channels: An optional int. Defaults to 0. Number of color channels for the decoded image. -*@li ratio: An optional int. Defaults to 1. Downscaling ratio. +*@li ratio: An optional int. Defaults to 1. Downscaling ratio. *@li fancy_upscaling: An optional bool. Defaults to True. If true use a slower but nicer upscaling of the chroma planes *@li try_recover_truncated: An optional bool. Defaults to False. If true try to recover an image from truncated input. *@li acceptable_fraction: An optional float. Defaults to 1. The minimum required fraction of lines before a truncated input is accepted. -*@li dct_method: An optional string. Defaults to "". string specifying a hint about the algorithm used for decompression. \n +*@li dct_method: An optional string. Defaults to "". string specifying a hint about the algorithm used for decompression. \n *@par Outputs: *image: A Tensor dtype of uint8. diff --git a/third_party/fwkacllib/inc/ops/linalg_ops.h b/third_party/fwkacllib/inc/ops/linalg_ops.h index d8f45c5d..330fef2e 100644 --- a/third_party/fwkacllib/inc/ops/linalg_ops.h +++ b/third_party/fwkacllib/inc/ops/linalg_ops.h @@ -61,8 +61,8 @@ REG_OP(CholeskyGrad) *@par Inputs: *The input x has to be symmetric and positive definite.Inputs include: -*x:A Tensor. Must be one of the following types: double, float32. Shape -is [..., M, M] . \n +*x:A Tensor. Must be one of the following types: double, float32, float16, +complex64, complex128. Shape is [..., M, M] . \n *@par Outputs: *y:A Tensor. Has the same type as x . \n @@ -76,8 +76,10 @@ form square matrices. */ REG_OP(Cholesky) - .INPUT(x, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(x, TensorType({DT_FLOAT, DT_DOUBLE, \ + DT_FLOAT16, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, \ + DT_FLOAT16, DT_COMPLEX64, DT_COMPLEX128})) .OP_END_FACTORY_REG(Cholesky) /** @@ -87,8 +89,8 @@ of one or more square matrices . \n *@par Inputs: *The input x is a tensor of shape [N, M, M] whose inner-most 2 dimensions form square matrices. Inputs include: -*x:A Tensor. Must be one of the following types: double, float32. Shape is -[..., M, M] . \n +*x:A Tensor. Must be one of the following types: double, float32, +complex64, complex128. Shape is [..., M, M] . \n *@par Outputs: *@li y:A Tensor. Has the same type as x. @@ -103,9 +105,9 @@ form square matrices. \n */ REG_OP(LogMatrixDeterminant) - .INPUT(x, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(sign, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(x, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(sign, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .OP_END_FACTORY_REG(LogMatrixDeterminant) /** @@ -114,8 +116,8 @@ REG_OP(LogMatrixDeterminant) *@par Inputs: *The input x is a tensor of shape [N, M, M] whose inner-most 2 dimensions form square matrices. Inputs include: -*x:A Tensor. Must be one of the following types: double, float32. Shape is -[..., M, M] . \n +*x:A Tensor. Must be one of the following types: double, float32, complex64, +complex128. Shape is [..., M, M] . \n *@par Outputs: *y:A Tensor. Has the same type as x . \n @@ -129,8 +131,8 @@ form square matrices. */ REG_OP(MatrixDeterminant) - .INPUT(x, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(x, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .OP_END_FACTORY_REG(MatrixDeterminant) /** @@ -140,8 +142,7 @@ their adjoints (conjugate transposes) . \n *@par Inputs: *The input x is a tensor of shape [..., M, M] whose inner-most 2 dimensions form square matrices. Inputs include: -*x:A Tensor. Must be one of the following types: double, float. Shape is -[..., M, M] . \n +*x:A Tensor of input. Shape is [..., M, M] . \n *@par Attributes: *adjoint:An optional bool. Defaults to False.Boolean indicating whether to @@ -159,8 +160,10 @@ form square matrices. \n */ REG_OP(MatrixInverse) - .INPUT(x, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(x, TensorType({DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ + DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ + DT_COMPLEX64, DT_COMPLEX128})) .ATTR(adjoint, Bool, false) .OP_END_FACTORY_REG(MatrixInverse) @@ -169,8 +172,7 @@ REG_OP(MatrixInverse) *@par Inputs: *The input rhs must have the same type as matrix. Inputs include: -*@li matrix:A Tensor. Must be one of the following types: double, float. -Shape is [..., M, M]. +*@li matrix:A Tensor of input. Shape is [..., M, M]. *@li rhs:A Tensor. Must have the same type as matrix. Shape is [..., M, K] . \n *@par Attributes: @@ -189,9 +191,9 @@ dimensions form square matrices. \n */ REG_OP(MatrixSolve) - .INPUT(matrix, TensorType({DT_FLOAT, DT_DOUBLE})) - .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(matrix, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .ATTR(adjoint, Bool, false) .OP_END_FACTORY_REG(MatrixSolve) @@ -221,8 +223,10 @@ dimensions form square matrices. \n */ REG_OP(MatrixSolveLs) - .INPUT(matrix, TensorType({DT_FLOAT, DT_DOUBLE})) - .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(matrix, TensorType({DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ + DT_COMPLEX64, DT_COMPLEX128})) + .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ + DT_COMPLEX64, DT_COMPLEX128})) .INPUT(l2, TensorType({DT_DOUBLE})) .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) .ATTR(fast, Bool, true) @@ -234,8 +238,7 @@ matrices by backsubstitution . \n *@par Inputs: *The input rhs must have the same type as matrix. Inputs include: -*@li matrix: A Tensor. Must be one of the following types: double, float. -Shape is [..., M, M]. +*@li matrix: A Tensor. Shape is [..., M, M]. *@li rhs:A Tensor. Must have the same type as matrix. Shape is [..., M, K] . \n *@par Attributes: @@ -256,9 +259,12 @@ dimensions form square matrices. \n */ REG_OP(MatrixTriangularSolve) - .INPUT(matrix, TensorType({DT_FLOAT, DT_DOUBLE})) - .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(matrix, TensorType({DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ + DT_COMPLEX64, DT_COMPLEX128})) + .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ + DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ + DT_COMPLEX64, DT_COMPLEX128})) .ATTR(lower, Bool, true) .ATTR(adjoint, Bool, false) .OP_END_FACTORY_REG(MatrixTriangularSolve) @@ -268,8 +274,7 @@ REG_OP(MatrixTriangularSolve) *@par Inputs: *The input shape of x must be [..., M, N]. Inputs include: -*x:A Tensor whose shape is [..., M, N]. Must be one of the following types: -double, float . \n +*x:A Tensor whose shape is [..., M, N]. \n *@par Attributes: *full_matrices: An optional bool. Defaults to False. If true, compute @@ -289,9 +294,12 @@ dimensions form matrices of size [M, N]. \n */ REG_OP(Qr) - .INPUT(x, TensorType({ DT_FLOAT16, DT_FLOAT, DT_DOUBLE })) - .OUTPUT(q, TensorType({ DT_FLOAT16, DT_FLOAT, DT_DOUBLE })) - .OUTPUT(r, TensorType({ DT_FLOAT16, DT_FLOAT, DT_DOUBLE })) + .INPUT(x, TensorType({ DT_FLOAT16, DT_FLOAT, DT_DOUBLE, \ + DT_COMPLEX64, DT_COMPLEX128 })) + .OUTPUT(q, TensorType({ DT_FLOAT16, DT_FLOAT, DT_DOUBLE, \ + DT_COMPLEX64, DT_COMPLEX128 })) + .OUTPUT(r, TensorType({ DT_FLOAT16, DT_FLOAT, DT_DOUBLE, \ + DT_COMPLEX64, DT_COMPLEX128 })) .ATTR(full_matrices, Bool, false) .OP_END_FACTORY_REG(Qr) @@ -384,8 +392,8 @@ of the rows encoded as a list of indices in `0..M-1`. Shape is `[..., M]` . \n */ REG_OP(Lu) - .INPUT(input, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(lu, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(input, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(lu, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .OUTPUT(p, TensorType({DT_INT32, DT_INT64})) .REQUIRED_ATTR(output_idx_type, Type) .OP_END_FACTORY_REG(Lu) @@ -404,8 +412,8 @@ y: Shape is `[..., M, M]` . \n */ REG_OP(MatrixSquareRoot) - .INPUT(input, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(input, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .OP_END_FACTORY_REG(MatrixSquareRoot) /** diff --git a/third_party/fwkacllib/inc/ops/list_ops.h b/third_party/fwkacllib/inc/ops/list_ops.h index 292b1dbe..33270ea8 100644 --- a/third_party/fwkacllib/inc/ops/list_ops.h +++ b/third_party/fwkacllib/inc/ops/list_ops.h @@ -192,7 +192,7 @@ REG_OP(TensorListGetItem) .INPUT(element_shape, TensorType({DT_INT32})) .OUTPUT(item, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, - DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL,DT_RESOURCE, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL, DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) .ATTR(element_dtype, Type, DT_INT32) .OP_END_FACTORY_REG(TensorListGetItem) diff --git a/third_party/fwkacllib/inc/ops/math_ops.h b/third_party/fwkacllib/inc/ops/math_ops.h index 4cbcc027..50d058ba 100644 --- a/third_party/fwkacllib/inc/ops/math_ops.h +++ b/third_party/fwkacllib/inc/ops/math_ops.h @@ -222,6 +222,24 @@ REG_OP(Bucketize) .REQUIRED_ATTR(boundaries, ListFloat) .OP_END_FACTORY_REG(Bucketize) +/** +*@brief Returns a new tensor with the truncated integer values of the elements of input. \n + +*@par Inputs: +*One inputs, including: +* @li input_x: A tensor. Must be one of the following types: float16, float32, int8, uint8, int32. \n + +*@par Outputs: +*y: A tensor with the same type and shape of input_x \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator Trunc. \n +*/ +REG_OP(Trunc) + .INPUT(input_x, TensorType({DT_FLOAT16,DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8})) + .OUTPUT(output_y, TensorType({DT_FLOAT16,DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8})) + .OP_END_FACTORY_REG(Trunc) + /** *@brief Computes the sum along sparse segments of a tensor . \n @@ -645,6 +663,7 @@ REG_OP(NLLLoss) .OUTPUT(y, TensorType({DT_FLOAT})) .OUTPUT(total_weight, TensorType({DT_FLOAT})) .ATTR(reduction, String, "mean") + .ATTR(ignore_index, Int, -100) .OP_END_FACTORY_REG(NLLLoss) /** @@ -674,6 +693,7 @@ REG_OP(NLLLossGrad) .INPUT(total_weight, TensorType({DT_FLOAT})) .OUTPUT(x_grad, TensorType({DT_FLOAT})) .ATTR(reduction, String, "mean") + .ATTR(ignore_index, Int, -100) .OP_END_FACTORY_REG(NLLLossGrad) /** @@ -884,6 +904,54 @@ REG_OP(LpNorm) .ATTR(keepdim, Bool, false) .ATTR(epsilon, Float, 1e-12) .OP_END_FACTORY_REG(LpNorm) + +/** +* @brief get complex. + +* @par Inputs: +* @li real: An ND tensor of type float32. double +* @li imag: An ND tensor of type float32. double \n +* +* @par Outputs: +* @li out: An ND tensor of type complex64, complex128 \n +*/ +REG_OP(Complex) + .INPUT(real, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(imag, TensorType({DT_FLOAT, DT_DOUBLE})) + .OUTPUT(out, TensorType({DT_COMPLEX64, DT_COMPLEX128})) + .ATTR(Tout, Type, DT_COMPLEX64) + .OP_END_FACTORY_REG(Complex) + +/** +* @brief deal complex. + +* @par Inputs: +* @li input: An ND tensor of type complex64, complex128 \n +* +* @par Outputs: +* @li output: An ND tensor of type float32. double \n +*/ +REG_OP(Imag) + .INPUT(input, TensorType({DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(output, TensorType({DT_FLOAT, DT_DOUBLE})) + .ATTR(Tout, Type, DT_FLOAT) + .OP_END_FACTORY_REG(Imag) + +/** +* @brief deal complex. + +* @par Inputs: +* @li input: An ND tensor of type complex64, complex128 \n +* +* @par Outputs: +* @li output: An ND tensor of type float32. double \n +*/ +REG_OP(Angle) + .INPUT(input, TensorType({DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(output, TensorType({DT_FLOAT, DT_DOUBLE})) + .ATTR(Tout, Type, DT_FLOAT) + .OP_END_FACTORY_REG(Angle) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATH_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index 33b596d8..6bff7f82 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -1022,6 +1022,27 @@ REG_OP(IndexAdd) .ATTR(axis, Int, 0) .OP_END_FACTORY_REG(IndexAdd) +/** +*@brief: Returns the upper triangular part of a matrix (2-D tensor) or batch of matrices input \n + +*@par Inputs: +* Two inputs, including: +*@li x: A Tensor. Must be one of the following types: +* float16, float32, double, int32, uint8, int16, int8, complex64, int64, +* qint8, quint8, qint32, uint16, complex128, uint32, uint64. +*@li diagonal:(int, optional) – the diagonal to consider。\n + +*@par Outputs: +*y: A Tensor. Has the same type as "x" . \n + +*@par Third-party framework compatibility +* Compatible with the Pytorch operator Triu. +*/ +REG_OP(Triu) + .INPUT(x, TensorType::BasicType()) + .ATTR(diagonal, Int, 0) + .OUTPUT(y, TensorType::BasicType()) + .OP_END_FACTORY_REG(Triu) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATRIX_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h index a35cee03..ddd70bc8 100644 --- a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h @@ -144,6 +144,64 @@ REG_OP(BatchNorm) /** *@brief Performs batch normalization . \n +*@par Inputs: +* Five inputs, including: (NHWC, NCHW, or NC1HWC0 supported) +*@li x: A 3D or 6D Tensor of type float16 or float32, with format NDHWC or NCDHW for 4D or NDC1HWC0 for 6D. +*@li scale: A Tensor of type float32. Must be 1D if input "x" is with format NDHWC or NCDHW. Must be 6D +if input "x" is with format NDC1HWC0. Specifies the scaling factor. +*@li offset: A Tensor of type float32. Must be 3D if input "x" is with format NDHWC or NCDHW. Must be 6D +if input "x" is with format NC1HWC0. Specifies the offset. +*@li mean: A Tensor of type float32. Must be 3D if input "x" is with format NDHWC or NCDHW. Must be 6D +if input "x" is with format NC1HWC0. Specifies the mean used for inference. Must be "None" if the +operation is used for training. +*@li variance: A Tensor of type float32. Must be 3D if input "x" is with format NHWC or NCHW. Must be +5D if input "x" is with format NC1HWC0. Specifies the variance used for inference. Must be "None" +if the operation is used for training . \n + +*@par Attributes: +*@li epsilon: An optional float32, specifying the small value added to variance to avoid dividing by zero. Defaults to "0.0001". +*@li data_format: An optional string, specifying the format of "x". Defaults to "NHWC". +*@li is_training: An optional bool, specifying if the operation is used for training or inference. Defaults to "True" . \n + +*@par Outputs: +* Five outputs, including: (NHWC, NCHW, or NC1HWC0 supported) +*@li y: A 3D or 6D Tensor of type float16 or float32 for the normalized "x", with format NDHWC or NCDHW for 4D or NDC1HWC0 for 6D. +*@li batch_mean: A Tensor of type float32. Must be 3D if input "x" is with format NDHWC or NCDHW. Must be 6D +if input "x" is with format NDC1HWC0. Specifies the mean of "x". +*@li batch_variance: A Tensor of type float32. Must be 1D if input "x" is with format NDHWC or NCDHW. +Must be 6D if input "x" is with format NDC1HWC0. Specifies the variance of "x". +*@li reserve_space_1: An optional Tensor of type float32. Must be 1D if input "x" is with format NDHWC or NCDHW. +Must be 6D if input "x" is with format NDC1HWC0. Specifies the mean of "x" for gradient computation. Pass "None" to skip this output. +*@li reserve_space_2: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. +Must be 6D if input "x" is with format NDC1HWC0. Specifies the variance of "x" for gradient computation. Pass "None" to skip this output . \n + +*@attention Constraints: +*@li If the operation is used for inference and outputs "reserve_space_1" and "reserve_space_2" are available, +then "reserve_space_1" has the same value as "mean" and "reserve_space_2" has the same value as "variance". +*@li For Ascend 310, the result accuracy fails to reach 1‰ due to the square root instruction . \n + +*@par Third-party framework compatibility +*@li Compatible with the TensorFlow operator fused_batch_norm. +*@li Compatible with the TensorFlow operator fused_batch_norm_v2. +*/ +REG_OP(BatchNorm3D) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(scale, TensorType({DT_FLOAT})) + .INPUT(offset, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(mean, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(variance, TensorType({DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(batch_mean, TensorType({DT_FLOAT})) + .OUTPUT(batch_variance, TensorType({DT_FLOAT})) + .OUTPUT(reserve_space_1, TensorType({DT_FLOAT})) + .OUTPUT(reserve_space_2, TensorType({DT_FLOAT})) + .ATTR(epsilon, Float, 0.0001) + .ATTR(data_format, String, "NCDHW") + .ATTR(is_training, Bool, true) + .OP_END_FACTORY_REG(BatchNorm3D) +/** +*@brief Performs batch normalization . \n + *@par Inputs: * Five inputs, including: (NHWC or NCHW supported) *@li x: A 4D Tensor of type float16 or float32. @@ -242,6 +300,52 @@ REG_OP(BatchNormGrad) /** *@brief Performs the backpropagation of BatchNorm . \n +*@par Inputs: +* Five inputs, including: +*@li y_backprop: A 3D or 6D Tensor of type float16 or float32, with format NDHWC, NCDHW, or NDC1HWC0, for the gradient. +*@li x: A 3D or 6D Tensor of type float16 or float32, with format NDHWC, NCDHW, or NDC1HWC0. +*@li scale: A 3D or 6D Tensor of type float32, with format NDHWC, NCDHW, or NDC1HWC0. +*@li reserve_space_1: A 3D or 6D Tensor of type float32, with format NDHWC, NCDHW, or NC1HWC0. It is an output of BatchNorm. +*@li reserve_space_2: A 3D or 6D Tensor of type float32, with format NDHWC, NCDHW, or NC1HWC0. It is an output of BatchNorm . \n + +*@par Attributes: +*@li epsilon: An optional float32. Defaults to "0.0001". A small float number added to the variance of "x". +*@li data_format: An optional string. Defaults to "NCDHW". +*@li is_training: An optional bool. Defaults to "true". Specifies the operation is for training (default) or inference . \n + +*@par Outputs: +*@li x_backprop: A Tensor of type float16 or float32, with format NHWC, NCHW, or NC1HWC0, for the offset of "x". +*@li scale_backprop: A Tensor of type float32, with format NDHWC, NCDHW, or NDC1HWC0, for the offset of "scale". +*@li *offset_backprop: A Tensor of type float32, with format NDHWC, NCDHW, or NDC1HWC0, for the offset of "offset". +*@li *reserve_space_4: A Tensor of type float32, with shape NDHWC, NCDHW, or NDC1HWC0. Pass "None" to skip this output. +*@li *reserve_space_5: A Tensor of type float32, with shape NDHWC, NCDHW, or NDC1HWC0. Pass "None" to skip this output . \n + +*@attention Constraints: +* The preceding layer of this operator must be operator BatchNorm . \n + +*@see BatchNorm +*@par Third-party framework compatibility +* Compatible with the TensorFlow operators FusedBatchNormGradV2 and FusedBatchNorm3DGrad. +*/ +REG_OP(BatchNorm3DGrad) + .INPUT(y_backprop, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(scale, TensorType({DT_FLOAT})) + .INPUT(reserve_space_1, TensorType({DT_FLOAT})) + .INPUT(reserve_space_2, TensorType({DT_FLOAT})) + .OUTPUT(x_backprop, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(scale_backprop, TensorType({DT_FLOAT})) + .OUTPUT(offset_backprop, TensorType({DT_FLOAT})) + .OUTPUT(reserve_space_4, TensorType({DT_FLOAT})) + .OUTPUT(reserve_space_5, TensorType({DT_FLOAT})) + .ATTR(epsilon, Float, 0.0001) + .ATTR(data_format, String, "NCDHW") + .ATTR(is_training, Bool, true) + .OP_END_FACTORY_REG(BatchNorm3DGrad) + +/** +*@brief Performs the backpropagation of BatchNorm . \n + *@par Inputs: * Five inputs, including: *@li y_backprop: A 4D Tensor of type float16 or float32, with format NHWC or NCHW, for the gradient. diff --git a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h index c848668f..53922ee6 100644 --- a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h @@ -1059,7 +1059,7 @@ REG_OP(DeformableConv2D) *@par Attributes: * @li groups: Number of blocked connections from input channels to output - * channels. Reserved. + * channels. * @li data_format: An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. * @li dilations: A list of 5 integers. Specifies the dilation factor for each @@ -1119,7 +1119,7 @@ REG_OP(Conv3D) *@par Attributes: * Three attributes: * @li groups: Number of blocked connections from input channels to output - * channels. Reserved. + * channels. * @li data_format: An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. * @li dilations: A tuple/list of 5 integers, The dilation factor for each @@ -1167,7 +1167,7 @@ REG_OP(Conv3DBackpropInput) *@par Attributes: * Three attributes: * @li groups: Number of blocked connections from input channels to output - * channels. Reserved. + * channels. * @li data_format: An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. * @li dilations: A tuple/list of 5 integers, The dilation factor for each @@ -1267,7 +1267,7 @@ REG_OP(LSTM) * dimension of input. * The N, C and D dimensions must be 1. Has the same format as "x". * @li groups: Number of blocked connections from input channels to output - * channels. Reserved. + * channels. * @li data_format: An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. @@ -1319,7 +1319,7 @@ REG_OP(Conv3DBackpropFilter) * dimension of input. * The N, C and D dimensions must be 1. Has the same format as "x". * @li groups: Number of blocked connections from input channels to output - * channels. Reserved. + * channels. * @li data_format: An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. @@ -1369,7 +1369,7 @@ REG_OP(Conv3DBackpropFilterD) *@par Attributes: * Five attributes: * @li groups: Number of blocked connections from input channels to output - * channels. Reserved. + * channels. * @li dilations: A tuple/list of 5 integers, * The dilation factor for each dimension of input. * The N, C and D dimensions must be 1. Has the same format as "x". @@ -1422,7 +1422,7 @@ REG_OP(Conv3DTranspose) * dimension of input. * The N, C and D dimensions must be 1. Has the same format as "x". * @li groups: Number of blocked connections from input channels to output - * channels. Reserved. + * channels. * @li data_format: An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. * @li output_padding: The size will be added in the output shape. @@ -1624,7 +1624,7 @@ REG_OP(Conv2DTransposeD) * of the input. * @li ksize: A tuple/list of 2 integers.kernel size. *@par Attributes: - * Three attributes: + * Four attributes: * @li dilations: A tuple/list of 4 integers, The dilation factor for each dimension * of input. Defaults to [1, 1, 1, 1] * @li data_format: An optional string from: "NCHW", "NHWC". Defaults to "NCHW". Specify the data format of the input x. diff --git a/third_party/fwkacllib/inc/ops/nn_detect_ops.h b/third_party/fwkacllib/inc/ops/nn_detect_ops.h index 39b4b227..af59b4e2 100644 --- a/third_party/fwkacllib/inc/ops/nn_detect_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_detect_ops.h @@ -968,8 +968,9 @@ REG_OP(SPP) * Three inputs, including: *@li x: An NC1HWC0 tensor of type float16 or float32, describing the feature * map. -*@li rois: A tensor of type float16 or float32, with shape +*@li rois: A tensor of type float16 or float32, with 3D shape * [batch, 5, roi_max_num], describing the RIOs. +* roi_max_num must be less than or equal to 6000 and must be divided by 16. *@li roi_actual_num: A optional tensor of type int32, with shape [batch, 8], specifying * the number of ROIs per batch . \n @@ -1604,6 +1605,50 @@ REG_OP(NonMaxSuppressionV7) .ATTR(max_boxes_size, Int, 0) .OP_END_FACTORY_REG(NonMaxSuppressionV7) +/** +*@brief Obtains the ROI feature matrix from the feature map list. It is a customized fused operator for mmdetection. \n + +*@par Inputs: +* Three inputs, including: +*@li features: A 5HD Tensor list of type float32 or float16. +*@li rois: ROI position. A 2D Tensor of float32 or float16 with shape (N, 5). "N" indicates the number of ROIs, +* the value "5" indicates the indexes of images where the ROIs are located, "x0", "y0", "x1", and "y1". + +*@par Attributes: +*@li finest_scale: A optional attribute of type int, specifying the scale of calculate levels of "rois". +*@li roi_scale_factor: A optional attribute of type float32, specifying the rescaling of "rois" coordinates. +*@li spatial_scale: A optional attribute of type list float32, specifying the scaling ratio of "features" +* to the original image. +*@li pooled_height: A optional attribute of type int32, specifying the H dimension. +*@li pooled_width: A optional attribute of type int32, specifying the W dimension. +*@li sample_num: An optional attribute of type int32, specifying the horizontal and vertical sampling frequency +* of each output. If this attribute is set to "0", the sampling frequency is equal to the rounded up value of "rois", +* which is a floating point number. Defaults to "0". +*@li pool_mode: An optional attribute of type string to indicate pooling mode. Defaults to "avg" . \n +*@li aligned: An optional attribute of type bool, specifying the align to corner. Defaults to true . \n + +*@par Outputs: +* output: Outputs the feature sample of each ROI position. The format is 5HD Tensor of type float32 or float16. +* The axis N is the number of input ROIs. Axes H, W, and C are consistent with the values of "pooled_height", +* "pooled_width", and "features", respectively. + +*@par Third-party framework compatibility +*Compatible with mmdetection SingleRoIExtractor operator. +*/ +REG_OP(RoiExtractor) + .DYNAMIC_INPUT(features, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(rois, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(finest_scale, Int, 56) + .ATTR(roi_scale_factor, Float, 0) + .ATTR(spatial_scale, ListFloat, { 1.f/4, 1.f/8, 1.f/16, 1.f/32 }) + .ATTR(pooled_height, Int, 7) + .ATTR(pooled_width, Int, 7) + .ATTR(sample_num, Int, 0) + .ATTR(pool_mode, String, "avg") + .ATTR(aligned, Bool, true) + .OP_END_FACTORY_REG(RoiExtractor) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_DETECT_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index af223552..00e2020f 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -1233,6 +1233,47 @@ REG_OP(SigmoidCrossEntropyWithLogitsGradV2) .OUTPUT(gradient, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(reduction, String, "mean") .OP_END_FACTORY_REG(SigmoidCrossEntropyWithLogitsGradV2) +/** + * @brief Calculate the PoissonNllLoss function. + * target∼Poisson(input)loss(input,target)=input−target∗log(input)+log(target!) \n + + * @par Inputs: + * Two inputs, including: + * @li input_x: A tensor. Must be one of the following types: + * float16, float32. \n + * + * @par Inputs: + * @li target: A tensor. Must be one of the following types: + * float16, float32. \n + + * @par Attributes: + * four Attributes, including: + * @li log_input: An optional bool. Defaults to "True" \n + * + * @par Attributes: + * @li full: An optional bool. Defaults to "False" \n + * + * @par Attributes: + * @li eps: An optional float. Defaults to "1e-8" \n + * + * @par Attributes: + * @li reduction: An optional string. Defaults to "mean" \n + + * @par Outputs: + * loss: A Tensor has same element type as two inputs. \n + + * @par Third-party framework compatibility + * Compatible with the Pytorch operator PoissonNllLoss. \n + */ +REG_OP(PoissonNllLoss) + .INPUT(input_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(target, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(loss, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(log_input, Bool, true) + .ATTR(full, Bool, false) + .ATTR(eps, Float, 1e-8) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(PoissonNllLoss) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_NORM_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_ops.h b/third_party/fwkacllib/inc/ops/nn_ops.h index 16552eee..820aa00d 100644 --- a/third_party/fwkacllib/inc/ops/nn_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_ops.h @@ -20,7 +20,34 @@ */ #ifndef OPS_BUILT_IN_OP_PROTO_INC_NN_OPS_H_ #define OPS_BUILT_IN_OP_PROTO_INC_NN_OPS_H_ - +#include "graph/operator_reg.h" #include "nn_pooling_ops.h" +namespace ge { +/** +* @brief Says whether the targets are in the top "k" predictions . \n + +* @par Inputs: +* Three inputs, including: +* @li predictions: A 2D Tensor of type float32. A "batch_size * classes" tensor. +* @li targets: A 1D Tensor of type IndexNumberType. A batch_size tensor of class ids. +* @li k: A 1D Tensor of the same type as "targets". +* Specifies the number of top elements to look at for computing precision . \n + +* @par Outputs: +* precision: A Tensor of type bool . \n + +* @attention Constraints: +* @li targets must be non-negative tensor. + +* @par Third-party framework compatibility +* @li Compatible with the TensorFlow operator InTopKV2. +*/ +REG_OP(InTopKV2) + .INPUT(predictions, TensorType({DT_FLOAT})) + .INPUT(targets, TensorType(IndexNumberType)) + .INPUT(k, TensorType({IndexNumberType})) + .OUTPUT(precision, TensorType({DT_BOOL})) + .OP_END_FACTORY_REG(InTopKV2) +}// namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h index e0897280..a225bb5f 100644 --- a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h +++ b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h @@ -223,7 +223,29 @@ REG_OP(Relu6Grad) .INPUT(features, TensorType::RealNumberType()) .OUTPUT(backprops, TensorType::RealNumberType()) .OP_END_FACTORY_REG(Relu6Grad) - +/** +*@brief Calculate the elu_grad_v2 function. +*Applies the element-wise function: +* Computes the backward for the elu: if x>0, 1; otherwise elu() + alpha . +*@par Inputs: +*One inputs, including: +* @li grads: A tensor. Must be one of the following types: +* float16, float32. +* @li activations: A tensor. Must be one of the following types: +* float16, float32. +* +*@par Outputs: +*y: A Tensor with the same type and shape of grads's. +* +*@par Attributes: +*@li alpha: scalar parameter, default value = 1.0 +*/ +REG_OP(EluGradV2) + .INPUT(grads, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(activations, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .ATTR(alpha, Float, 1.0) + .OP_END_FACTORY_REG(EluGradV2) /** * @brief Compute sigmoid of "x" element-wise . \n @@ -842,6 +864,26 @@ REG_OP(SoftShrinkGrad) .OUTPUT(output_y, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(lambd, Float, 0.5) .OP_END_FACTORY_REG(SoftShrinkGrad) + +/** +*@brief Calculate -ln(1+e^(-x)). \n + +*@par Inputs: +*One inputs, including: +* @li x: A tensor. Must be one of the following types: +* float16, float32. \n + +*@par Outputs: +*One outputs, including: +* @li y: A tensor with the same type and shape of x's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator LogSigmoid. \n +*/ +REG_OP(LogSigmoid) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) /* "input:x" */ + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) /* "output:y" */ + .OP_END_FACTORY_REG(LogSigmoid) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NONLINEAR_FUC_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/reduce_ops.h b/third_party/fwkacllib/inc/ops/reduce_ops.h index 0b114134..5b97d226 100644 --- a/third_party/fwkacllib/inc/ops/reduce_ops.h +++ b/third_party/fwkacllib/inc/ops/reduce_ops.h @@ -37,7 +37,7 @@ namespace ge { *@attention Constraints: * This operator is a BatchNorm fusion operator for updating the moving * averages for training. -* This operator is used in conjunction with BNTrainingUpdate. +* This operator is used in conjunction with BNTrainingReduce. */ REG_OP(BNTrainingReduce) .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -45,6 +45,27 @@ REG_OP(BNTrainingReduce) .OUTPUT(square_sum, TensorType({DT_FLOAT})) .OP_END_FACTORY_REG(BNTrainingReduce) +/** +*@brief Performs reduced batch normalization . \n + +*@par Inputs: +*x: A 6D Tensor of type float16 or float32, with format NDC1HWC0 . \n + +*@par Outputs: +*@li sum: A 3D Tensor of type float32 for SUM reduced "x". +*@li square_sum: A 3D Tensor of type float32 for SUMSQ reduced "x" . \n + +*@attention Constraints: +* This operator is a BatchNorm fusion operator for updating the moving +* averages for training. +* This operator is used in conjunction with BN3DTrainingReduce. +*/ +REG_OP(BN3DTrainingReduce) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(sum, TensorType({DT_FLOAT})) + .OUTPUT(square_sum, TensorType({DT_FLOAT})) + .OP_END_FACTORY_REG(BN3DTrainingReduce) + /** *@brief Performs the backpropagation of BatchNorm . \n @@ -88,6 +109,49 @@ REG_OP(BNTrainingReduceGrad) .ATTR(epsilon, Float, 0.0001) .OP_END_FACTORY_REG(BNTrainingReduceGrad) +/** +*@brief Performs the backpropagation of BatchNorm . \n + +*@par Inputs: +* Seven inputs, including: +*@li grads: A 6D Tensor of type float16 or float32, with format NDC1HWC0, for +* the gradient. +*@li x: A 6D Tensor of type float16 or float32, with format NDC1HWC0. +*@li diff_scale: A 6D Tensor of type float32, with format NDC1HWC0, +* for the mean of "x". +*@li diff_offset: A 6D Tensor of type float32, with format NDC1HWC0, +* for the variance of "x". +*@li scale: A 6D Tensor of type float32, with format NDC1HWC0. +*@li batch_mean: A 6D Tensor of type float32, with format NDC1HWC0, +* for the mean of "x". +*@li batch_variance: A 6D Tensor of type float32, with format NDC1HWC0, +* for the variance of "x" . \n + +*@par Attributes: +*epsilon: An optional float32. Defaults to "0.0001". A small float number +* added to the variance of "x" . \n + +*@par Outputs: +*y: A Tensor of type float16 or float32, with format NDC1HWC0, for the offset +* of "x" . \n + +*@attention Constraints: +* The preceding layer of this operator must be BN3DTrainingReduceGrad . \n + +*@see BN3DTrainingReduceGrad +*/ +REG_OP(BN3DTrainingReduceGrad) + .INPUT(grads, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(diff_scale, TensorType({DT_FLOAT})) + .INPUT(diff_offset, TensorType({DT_FLOAT})) + .INPUT(scale, TensorType({DT_FLOAT})) + .INPUT(batch_mean, TensorType({DT_FLOAT})) + .INPUT(batch_variance, TensorType({DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT})) + .ATTR(epsilon, Float, 0.0001) + .OP_END_FACTORY_REG(BN3DTrainingReduceGrad) + /** *@brief Performs reduced batch normalization . \n @@ -120,7 +184,7 @@ REG_OP(BNTrainingReduceGrad) *@attention Constraints: *@li This operator is a BatchNorm fusion operator for updating the moving averages for training. -*This operator is used in conjunction with BNTrainingReduce. +*This operator is used in conjunction with BNTrainingUpdate. *@li For Ascend 310, the result accuracy fails to reach 1‰ due to the square * root instruction. */ @@ -141,6 +205,59 @@ REG_OP(BNTrainingUpdate) .OUTPUT(batch_variance, TensorType({DT_FLOAT})) .OP_END_FACTORY_REG(BNTrainingUpdate) +/** +*@brief Performs reduced batch normalization . \n + +*@par Inputs: +* Seven inputs, including: (NDC1HWC0 supported) +*@li x: A 6D Tensor of type float16 or float32. +*@li sum: A 6D Tensor of type float32 for the output of operator +* BN3DTrainingUpdate. +*@li square_sum: A 6D Tensor of type float32 for the output of operator +* BN3DTrainingUpdate. +*@li scale: A 6D Tensor of type float32, for the scaling factor. +*@li offset: A 6D Tensor of type float32, for the scaling offset. +*@li mean: A 6D Tensor of type float32, for the updated mean. +*@li variance: A 6D Tensor of type float32, for the updated variance . \n + +*@par Attributes: +*@li epsilon: A required float32, specifying the small value added to variance +* to avoid dividing by zero. +*@li factor: A required float32, specifying the weight for updating the mean +* and variance . \n + +*@par Outputs: +* Five outputs, including: (NDC1HWC0 supported) +*@li y: A 6D Tensor of type float16 or float32, for normalized "x". +*@li mean: A 6D Tensor of type float32, for the updated mean. +*@li variance: A 6D Tensor of type float32, for the updated variance. +*@li batch_mean: A 6D Tensor of type float32, for the mean of "x". +*@li batch_variance: A 6D Tensor of type float32, for the variance of "x" . \n + +*@attention Constraints: +*@li This operator is a BatchNorm fusion operator for updating the moving +averages for training. +*This operator is used in conjunction with BN3DTrainingUpdate. +*@li For Ascend 310, the result accuracy fails to reach 1‰ due to the square +* root instruction. +*/ +REG_OP(BN3DTrainingUpdate) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(sum, TensorType({DT_FLOAT})) + .INPUT(square_sum, TensorType({DT_FLOAT})) + .INPUT(scale, TensorType({DT_FLOAT})) + .INPUT(offset, TensorType({DT_FLOAT})) + .INPUT(mean, TensorType({DT_FLOAT})) + .INPUT(variance, TensorType({DT_FLOAT})) + .REQUIRED_ATTR(factor, Float) + .REQUIRED_ATTR(epsilon, Float) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(mean, TensorType({DT_FLOAT})) + .OUTPUT(variance, TensorType({DT_FLOAT})) + .OUTPUT(batch_mean, TensorType({DT_FLOAT})) + .OUTPUT(batch_variance, TensorType({DT_FLOAT})) + .OP_END_FACTORY_REG(BN3DTrainingUpdate) + /** *@brief Performs batch normalization for inference . \n @@ -284,6 +401,40 @@ REG_OP(BNTrainingUpdateGrad) .OUTPUT(diff_offset, TensorType({DT_FLOAT})) .OP_END_FACTORY_REG(BNTrainingUpdateGrad) +/** +*@brief Performs the backpropagation of BatchNorm . \n + +*@par Inputs: +* Four inputs, including: +*@li grads: A 6D Tensor of type float16 or float32, with format NDC1HWC0, +* for the gradient. +*@li x: A 6D Tensor of type float16 or float32, with format NDC1HWC0. +*@li batch_mean: A 6D Tensor of type float32, with format NDC1HWC0, +* for the mean of "x". +*@li batch_variance: A 6D Tensor of type float32, with format NDC1HWC0, +* for the variance of "x" . \n + +*@par Attributes: +*epsilon: An optional float32. Defaults to "0.0001". A small float number +* added to the variance of "x" . \n + +*@par Outputs: +*@li diff_scale: A Tensor of type float32, with format NDC1HWC0, +* for the offset of "scale". +*@li diff_offset: A Tensor of type float32, with format NDC1HWC0, +* for the offset of "offset" . \n + +*/ +REG_OP(BN3DTrainingUpdateGrad) + .INPUT(grads, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(batch_mean, TensorType({DT_FLOAT})) + .INPUT(batch_variance, TensorType({DT_FLOAT})) + .ATTR(epsilon, Float, 0.0001) + .OUTPUT(diff_scale, TensorType({DT_FLOAT})) + .OUTPUT(diff_offset, TensorType({DT_FLOAT})) + .OP_END_FACTORY_REG(BN3DTrainingUpdateGrad) + /** *@brief Performs the backpropagation of BatchNorm for inference . \n diff --git a/third_party/fwkacllib/inc/ops/selection_ops.h b/third_party/fwkacllib/inc/ops/selection_ops.h index dee9e0f7..33980d43 100644 --- a/third_party/fwkacllib/inc/ops/selection_ops.h +++ b/third_party/fwkacllib/inc/ops/selection_ops.h @@ -857,8 +857,8 @@ REG_OP(SliceDV2) * @li sorted = true * @li It's unstable sorted indices on the platform of Ascend310 -* @par Third-party framework compatibility -* @li Compatible with the TensorFlow operator TopK. +* @par Restrictions: +* Warning: THIS FUNCTION IS DEPRECATED. Please use TopKV2 instead. */ REG_OP(TopKD) .INPUT(x, TensorType::RealNumberType()) @@ -883,6 +883,44 @@ REG_OP(TopKD) * Number of top elements to look for along the last dimension (along each row * for matrices) . \n +* @par Attributes: +* @li sorted: An optional bool. Defaults to true. +* If true, the resulting "k" elements will be sorted by the values in descending +* order. +* @li dim: An optional int. Defaults to -1. For reserved use. +* @li largest: An optional bool. Defaults to true. For reserved use. \n + +* @par Outputs: +* @li values: A Tensor, specifying the sorted data. Has the same type as +* "input". +* @li indices: A Tensor of type int32, specifying the indices of sorted data . \n + +* @see TopK() +* @par Third-party framework compatibility +* @li Compatible with the TensorFlow operator TopKV2. +*/ +REG_OP(TopKV2) + .INPUT(x, TensorType::RealNumberType()) + .INPUT(k, TensorType({DT_INT32})) + .OUTPUT(values, TensorType::RealNumberType()) + .OUTPUT(indices, TensorType({DT_INT32})) + .ATTR(sorted, Bool, true) + .ATTR(dim, Int, -1) + .ATTR(largest, Bool, true) + .OP_END_FACTORY_REG(TopKV2) + +/** +* @brief Finds values and indices of the "k" largest elements for the last +* dimension . \n + +* @par Inputs: +* Two inputs, including: +* @li x: A 1D or higher tensor of type BasicType, with the last dimension +* at least "k". +* @li k: A 0D Tensor of type int32. +* Number of top elements to look for along the last dimension (along each row +* for matrices) . \n + * @par Attributes: * @li sorted: An optional bool. Defaults to true. * If true, the resulting "k" elements will be sorted by the values in descending @@ -2103,6 +2141,34 @@ REG_OP(StridedSliceV2) .OUTPUT(y, TensorType::BasicType()) .OP_END_FACTORY_REG(StridedSliceV2) +/** +*@brief Fills the elements of the input tensor with value val by selecting the indices in the order given in index. \n + +*@par Inputs: +*Three inputs, including: +* @li x: A tensor. Must be one of the following types: +* float16, float32, int32. \n +*@li assist1: A tensor. Must be one of the following types: +* float16, float32, int32. \n +*@li assist2: A tensor. Must be one of the following types: +* float16, float32, int32. \n + +* @par Attributes: +* @li dim: A required int. Used to select the dimension of this tensor. \n + +*@par Outputs: +*y: A Tensor with the same type and shape of input_x's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator IndexFill. \n +*/ +REG_OP(IndexFillD) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .INPUT(assist1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .INPUT(assist2, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .REQUIRED_ATTR(dim, Int) + .OP_END_FACTORY_REG(IndexFillD) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_SELECTION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/sparse_ops.h b/third_party/fwkacllib/inc/ops/sparse_ops.h index 09d8ced9..a1fc9ee6 100644 --- a/third_party/fwkacllib/inc/ops/sparse_ops.h +++ b/third_party/fwkacllib/inc/ops/sparse_ops.h @@ -383,11 +383,11 @@ REG_OP(SparseFillEmptyRowsGrad) REG_OP(SparseTensorDenseMatMul) .INPUT(x1_indices, TensorType({DT_INT32, DT_INT64})) .INPUT(x1_values, TensorType({DT_FLOAT, DT_DOUBLE, DT_INT32, \ - DT_COMPLEXT64, DT_COMPLEX128, DT_FLOAT16})) + DT_COMPLEXT64, DT_COMPLEX128, DT_FLOAT16, DT_INT64})) .INPUT(x1_shape, TensorType({DT_INT64})) - .INPUT(x2, TensorType({DT_FLOAT, DT_DOUBLE, DT_INT32, DT_COMPLEXT64, \ + .INPUT(x2, TensorType({DT_FLOAT, DT_DOUBLE, DT_INT64, DT_INT32, DT_COMPLEXT64, \ DT_COMPLEX128, DT_FLOAT16})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_INT32, DT_COMPLEXT64, \ + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_INT64, DT_INT32, DT_COMPLEXT64, \ DT_COMPLEX128, DT_FLOAT16})) .ATTR(adjoint_a, Bool, false) .ATTR(adjoint_b, Bool, false) diff --git a/third_party/fwkacllib/inc/ops/spectral_ops.h b/third_party/fwkacllib/inc/ops/spectral_ops.h index be3d7d00..82accc73 100644 --- a/third_party/fwkacllib/inc/ops/spectral_ops.h +++ b/third_party/fwkacllib/inc/ops/spectral_ops.h @@ -26,6 +26,24 @@ namespace ge { +/** +*@brief Computes the inverse 1-dimensional discrete Fourier transform over the +inner-most dimension of `x`. \n + +*@par Inputs: +*@li x: A Tensor. Must be the following types: complex64, complex128. \n + +*@par Outputs: +*@li y: A complex tensor of the same rank as `x`. \n + +*@par Third-party framework compatibility +* Compatible with TensorFlow IFFT operator. +*/ +REG_OP(IFFT) + .INPUT(x, TensorType({DT_COMPLEX64,DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_COMPLEX64,DT_COMPLEX128})) + .OP_END_FACTORY_REG(IFFT) + /** *@brief Real-valued fast Fourier transform . \n @@ -47,6 +65,84 @@ REG_OP(RFFT) .OUTPUT(y, TensorType({DT_COMPLEX64})) .OP_END_FACTORY_REG(RFFT) +/** +*@brief Inverse real-valued fast Fourier transform . \n + +*@par Inputs: +*@li x: A complex64 tensor. +*@li fft_length: An int32 tensor of shape [1]. The FFT length . \n + +*@par Outputs: +*@li y: A float32 tensor of the same rank as `input`. The inner-most + dimension of `input` is replaced with the `fft_length` samples of its inverse + 1D Fourier transform . \n + +*@par Third-party framework compatibility +* Compatible with TensorFlow IRFFT operator. +*/ +REG_OP(IRFFT) + .INPUT(x, TensorType({DT_COMPLEX64})) + .INPUT(fft_length, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT})) + .OP_END_FACTORY_REG(IRFFT) + + +/** +*@brief 2D fast Fourier transform. \n + +*@par Inputs: +*@li x: A complex64 tensor.. + +*@par Outputs: +*@li y: A complex64 tensor of the same shape as `input`. The inner-most 2 + dimensions of `input` are replaced with their 2D Fourier transform.\n + +*@par Third-party framework compatibility +* Compatible with TensorFlow FFT2D operator. +*/ +REG_OP(FFT2D) + .INPUT(x, TensorType({DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_COMPLEX64, DT_COMPLEX128})) + .OP_END_FACTORY_REG(FFT2D) + +/** +*@brief Calculate the one-dimensional discrete Fourier transform on the +innermost dimension of the input. \n + +*@par Inputs: +*@li x: A Tensor. Must be the following types: complex64, complex128. \n + +*@par Outputs: +*@li y: A complex tensor with the same shape as input. The innermost dimension +of the input is replaced by its 1-dimensional Fourier transform. \n + +*@par Third-party framework compatibility +* Compatible with TensorFlow FFT operator. +*/ +REG_OP(FFT) + .INPUT(x, TensorType({DT_COMPLEX64,DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_COMPLEX64,DT_COMPLEX128})) + .OP_END_FACTORY_REG(FFT) + +/** +*@brief Calculate the inverse 1-dimensional discrete Fourier transform on the +innermost dimension of the input. \n + +*@par Inputs: +*@li x: A Tensor. Must be the following types: complex64, complex128. \n + +*@par Outputs: +*@li y: A complex tensor with the same shape as input. The innermost dimension +of the input is replaced by its inverse two-dimensional Fourier transform. \n + +*@par Third-party framework compatibility +* Compatible with TensorFlow IFFT2D operator. +*/ +REG_OP(IFFT2D) + .INPUT(x, TensorType({DT_COMPLEX64,DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_COMPLEX64,DT_COMPLEX128})) + .OP_END_FACTORY_REG(IFFT2D) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_SPECTRAL_OPS_H_ \ No newline at end of file diff --git a/third_party/fwkacllib/inc/ops/split_combination_ops.h b/third_party/fwkacllib/inc/ops/split_combination_ops.h index f1a93fa6..af2c37bc 100644 --- a/third_party/fwkacllib/inc/ops/split_combination_ops.h +++ b/third_party/fwkacllib/inc/ops/split_combination_ops.h @@ -62,8 +62,8 @@ REG_OP(Split) *Must be one of the following types: float16, float32, int32, int8, int16, int64, uint8, uint16, uint32, uint64 *@par Attributes: -*@li split_dim: A required int8, int16, int32, or int64. Specifies the dimension along which to split. No default value. -*@li num_split: A required int8, int16, int32, or int64. Specifies the number of output tensors. No default value . \n +*@li split_dim: A required int32. Specifies the dimension along which to split. No default value. +*@li num_split: A required int32. Specifies the number of output tensors. No default value . \n *@par Outputs: *y:Dynamic output. A list of output tensors. Has the same type and format as "x" . \n @@ -94,12 +94,12 @@ REG_OP(SplitD) *@par Inputs: * Three inputs, including: *@li x: An ND Tensor. -*Must be one of the following types: -*@li size_splits: A list of int8, int16, int32, or int64. Specifies a list containing the sizes of each output tensor along the split dimension. -*@li split_dim: An int8, int16, int32, or int64. Specifies the dimension along which to split . \n +*Must be one of the types:float16, float32, double, int64, int32, uint8, uint16, uint32, uint64, int8, int16, complex64, complex128, qint8, quint8, qint16, quint16, qint32. +*@li size_splits: Must be one of the types:int32, int64. Specifies a list containing the sizes of each output tensor along the split dimension. +*@li split_dim: Must be the following type:int32. Specifies the dimension along which to split . \n *@par Attributes: -*num_split: A required int8, int16, int32, or int64. Specifies the number of output tensors. No default value . \n +*num_split: A required int32. Specifies the number of output tensors. No default value . \n *@par Outputs: *y: Dynamic output.A list of output tensors. Has the same type and format as "x" . \n @@ -129,9 +129,9 @@ REG_OP(SplitV) *Must be one of the following types: float16, float32, int32, int8, int16, int64, uint8, uint16, uint32, uint64 *@par Attributes: -*@li size_splits: A required list of int8, int16, int32, or int64. Specifies a list containing the sizes of each output tensor along the split dimension. -*@li split_dim: A required int8, int16, int32, or int64. Specifies the dimension along which to split. No default value. -*@li num_split: A required int8, int16, int32, or int64. Specifies the number of output tensors. No default value . \n +*@li size_splits: A required list of int32. Specifies a list containing the sizes of each output tensor along the split dimension. +*@li split_dim: A required int32. Specifies the dimension along which to split. No default value. +*@li num_split: A required int32. Specifies the number of output tensors. No default value . \n *@par Outputs: *y: Dynamic output.A list of output tensors. Has the same type and format as "x" . \n diff --git a/third_party/fwkacllib/inc/ops/string_ops.h b/third_party/fwkacllib/inc/ops/string_ops.h index ec84cc83..29aec302 100644 --- a/third_party/fwkacllib/inc/ops/string_ops.h +++ b/third_party/fwkacllib/inc/ops/string_ops.h @@ -488,7 +488,7 @@ include: */ REG_OP(AsString) .INPUT(x, TensorType({DT_INT8, DT_INT16, DT_INT32, DT_INT64, DT_FLOAT, \ - DT_DOUBLE, DT_BOOL})) + DT_DOUBLE, DT_BOOL, DT_COMPLEX64, DT_COMPLEX128})) .OUTPUT(y, TensorType({DT_STRING})) .ATTR(precision, Int, -1) .ATTR(scientific, Bool, false) diff --git a/third_party/fwkacllib/inc/runtime/config.h b/third_party/fwkacllib/inc/runtime/config.h index ee104693..fed7341a 100644 --- a/third_party/fwkacllib/inc/runtime/config.h +++ b/third_party/fwkacllib/inc/runtime/config.h @@ -46,6 +46,12 @@ typedef enum tagRtChipType { CHIP_END, } rtChipType_t; +typedef enum tagRtAicpuScheType { + SCHEDULE_SOFTWARE = 0, /* Software Schedule */ + SCHEDULE_SOFTWARE_OPT, + SCHEDULE_HARDWARE, /* HWTS Schedule */ +} rtAicpuScheType; + typedef enum tagRtVersion { VER_BEGIN = 0, VER_NA = VER_BEGIN, @@ -184,6 +190,19 @@ RTS_API rtError_t rtMemGetL2Info(rtStream_t stream, void **ptr, uint32_t *size); */ RTS_API rtError_t rtGetRuntimeVersion(uint32_t *runtimeVersion); + +/** + * @ingroup + * @brief get device feature ability by device id, such as task schedule ability. + * @param [in] deviceId + * @param [in] moduleType + * @param [in] featureType + * @param [out] value + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtGetDeviceCapability(int32_t deviceId, int32_t moduleType, int32_t featureType, int32_t *value); + #if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) } #endif diff --git a/third_party/fwkacllib/inc/runtime/dev.h b/third_party/fwkacllib/inc/runtime/dev.h index 49f6a3f6..018f4e6c 100644 --- a/third_party/fwkacllib/inc/runtime/dev.h +++ b/third_party/fwkacllib/inc/runtime/dev.h @@ -62,6 +62,11 @@ typedef enum tagRtFeatureType { FEATURE_TYPE_RSV } rtFeatureType_t; +typedef enum tagRtDeviceFeatureType { + FEATURE_TYPE_SCHE, + FEATURE_TYPE_END, +} rtDeviceFeatureType_t; + typedef enum tagMemcpyInfo { MEMCPY_INFO_SUPPORT_ZEROCOPY = 0, MEMCPY_INFO_RSV diff --git a/third_party/fwkacllib/inc/runtime/kernel.h b/third_party/fwkacllib/inc/runtime/kernel.h index dc16ca58..0ec1a163 100644 --- a/third_party/fwkacllib/inc/runtime/kernel.h +++ b/third_party/fwkacllib/inc/runtime/kernel.h @@ -191,6 +191,14 @@ typedef void (*rtCallback_t)(void *fnData); #define RT_FUSION_KERNEL_DUMPFLAG (0x04) #define RT_KERNEL_CUSTOM_AICPU (0x08) +/** + * @ingroup rt_kernel + * @brief kernel mode +**/ +#define RT_DEFAULT_KERNEL_MODE (0x00) +#define RT_NORMAL_KERNEL_MODE (0x01) +#define RT_ALL_KERNEL_MODE (0x02) + /** * @ingroup rt_kernel * @brief kernel L1 Fusion Dump bit flags @@ -207,6 +215,16 @@ typedef void (*rtCallback_t)(void *fnData); */ RTS_API rtError_t rtDevBinaryRegister(const rtDevBinary_t *bin, void **handle); +/** + * @ingroup rt_kernel + * @brief register device binary with all kernel + * @param [in] bin device binary description + * @param [out] handle device binary handle + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtRegisterAllKernel(const rtDevBinary_t *bin, void **handle); + /** * @ingroup rt_kernel * @brief register fast memeory device binary @@ -314,6 +332,23 @@ RTS_API rtError_t rtKernelConfigDump(uint32_t kind, uint32_t dumpSizePerBlock, u RTS_API rtError_t rtKernelLaunch(const void *stubFunc, uint32_t blockDim, void *args, uint32_t argsSize, rtSmDesc_t *smDesc, rtStream_t stream); +/** + * @ingroup rt_kernel + * @brief launch kernel with handle to device + * @param [in] handle program + * @param [in] devFunc device function description. + * @param [in] blockDim block dimentions + * @param [in] args argments address for kernel function + * @param [in] argsSize argements size + * @param [in] smDesc shared memory description + * @param [in] stream associated stream + * @param [in] kernelInfo kernel info + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtKernelLaunchWithHandle(void *handle, const void *devFunc, uint32_t blockDim, void *args, uint32_t argsSize, + rtSmDesc_t *smDesc, rtStream_t stream_, const void *kernelInfo); + /** * @ingroup rt_kernel * @brief launch kernel to device diff --git a/third_party/fwkacllib/inc/runtime/rt_model.h b/third_party/fwkacllib/inc/runtime/rt_model.h index 482486a8..e6d849c8 100644 --- a/third_party/fwkacllib/inc/runtime/rt_model.h +++ b/third_party/fwkacllib/inc/runtime/rt_model.h @@ -50,6 +50,7 @@ typedef enum tagModelTaskType { RT_MODEL_TASK_STREAM_LABEL_SWITCH_BY_INDEX, RT_MODEL_TASK_STREAM_LABEL_GOTO, RT_MODEL_TASK_MODEL_EXIT, + RT_MODEL_TASK_ALL_KERNEL, } rtModelTaskType_t; typedef enum tagModelStreamType { @@ -127,6 +128,18 @@ typedef struct tagKernelTaskInfo { uint16_t *argsOffset; } rtKernelTaskInfo_t; +typedef struct tagAllKernelTaskInfo { + uint16_t blockDim; + uint16_t argsCount; + uint16_t argsSize; + uint16_t reserved; + void *devfunc; + void *handle; + uint8_t *smDesc; + uint8_t *args; + uint16_t *argsOffset; +} rtAllKernelTaskInfo_t; + typedef struct tagKernelTaskInfoEx { uint32_t flags; uint32_t argsSize; @@ -251,6 +264,7 @@ typedef struct tagTaskInfo { union { rtKernelTaskInfoEx_t kernelTaskEx; rtKernelTaskInfo_t kernelTask; + rtAllKernelTaskInfo_t allKernelTask; rtEventTaskInfo_t eventTask; rtStreamSwitchTaskInfo_t streamSwitchTask; rtStreamActiveTaskInfo_t streamActiveTask; diff --git a/third_party/fwkacllib/inc/toolchain/slog.h b/third_party/fwkacllib/inc/toolchain/slog.h index ba286d02..7c4f7be2 100644 --- a/third_party/fwkacllib/inc/toolchain/slog.h +++ b/third_party/fwkacllib/inc/toolchain/slog.h @@ -120,15 +120,15 @@ typedef struct tagKV { } KeyValue; typedef enum { - APPLICATION = 0, - SYSTEM + APPLICATION = 0, + SYSTEM } ProcessType; typedef struct { - ProcessType type; - unsigned int pid; - unsigned int deviceId; - char reserved[RESERVERD_LENGTH]; + ProcessType type; + unsigned int pid; + unsigned int deviceId; + char reserved[RESERVERD_LENGTH]; } LogAttr; /** @@ -381,13 +381,13 @@ DLL_EXPORT void DlogFlush(void); * @ingroup slog * @brief Internal log interface, other modules are not allowed to call this interface */ -void DlogErrorInner(int moduleId, const char *fmt, ...) __attribute__((format(printf, 2, 3))); -void DlogWarnInner(int moduleId, const char *fmt, ...) __attribute__((format(printf, 2, 3))); -void DlogInfoInner(int moduleId, const char *fmt, ...) __attribute__((format(printf, 2, 3))); -void DlogDebugInner(int moduleId, const char *fmt, ...) __attribute__((format(printf, 2, 3))); -void DlogEventInner(int moduleId, const char *fmt, ...) __attribute__((format(printf, 2, 3))); -void DlogInner(int moduleId, int level, const char *fmt, ...) __attribute__((format(printf, 3, 4))); -void DlogWithKVInner(int moduleId, int level, KeyValue *pstKVArray, int kvNum, const char *fmt, ...) __attribute__((format(printf, 5, 6))); +void DlogErrorInner(int moduleId, const char *fmt, ...); +void DlogWarnInner(int moduleId, const char *fmt, ...); +void DlogInfoInner(int moduleId, const char *fmt, ...); +void DlogDebugInner(int moduleId, const char *fmt, ...); +void DlogEventInner(int moduleId, const char *fmt, ...); +void DlogInner(int moduleId, int level, const char *fmt, ...); +void DlogWithKVInner(int moduleId, int level, KeyValue *pstKVArray, int kvNum, const char *fmt, ...); #ifdef __cplusplus #ifndef LOG_CPP @@ -500,8 +500,8 @@ DLL_EXPORT void DlogFlushForC(void); * @ingroup slog * @brief Internal log interface, other modules are not allowed to call this interface */ -void DlogInnerForC(int moduleId, int level, const char *fmt, ...) __attribute__((format(printf, 3, 4))); -void DlogWithKVInnerForC(int moduleId, int level, KeyValue *pstKVArray, int kvNum, const char *fmt, ...) __attribute__((format(printf, 5, 6))); +void DlogInnerForC(int moduleId, int level, const char *fmt, ...); +void DlogWithKVInnerForC(int moduleId, int level, KeyValue *pstKVArray, int kvNum, const char *fmt, ...); #ifdef __cplusplus } diff --git a/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h b/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h index 6208f462..e436dafd 100644 --- a/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h +++ b/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h @@ -1,72 +1,137 @@ -/** - * @file tune_api.h - * - * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.\n - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n - * 描述:mstune调优接口头文件 - */ -/** @defgroup mstune mstune调优接口 */ -#ifndef TUNE_API_H -#define TUNE_API_H -#include -#include -#include -#include "graph/graph.h" -#include "ge/ge_api.h" - -/** - * @ingroup mstune - * - * mstune status - */ -enum MsTuneStatus { - MSTUNE_SUCCESS, /** tune success */ - MSTUNE_FAILED, /** tune failed */ -}; - -// Option key: for train options sets -const std::string MSTUNE_SELF_KEY = "mstune"; -const std::string MSTUNE_GEINIT_KEY = "initialize"; -const std::string MSTUNE_GESESS_KEY = "session"; - -/** - * @ingroup mstune - * @par 描述: 命令行调优 - * - * @attention 无 - * @param option [IN] 调优参数 - * @param msg [OUT] 调优异常下返回信息 - * @retval #MSTUNE_SUCCESS 执行成功 - * @retval #MSTUNE_FAILED 执行失败 - * @par 依赖: - * @li tune_api.cpp:该接口所属的开发包。 - * @li tune_api.h:该接口声明所在的头文件。 - * @see 无 - * @since - */ -MsTuneStatus MsTuning(const std::map &option, std::string &msg); - -/** - * @ingroup mstune - * @par 描述: 梯度调优 - * - * @attention 无 - * @param tuningGraph [IN] 调优图 - * @param dependGraph [IN] 调优依赖图 - * @param session [IN] ge连接会话 - * @param option [IN] 参数集. 包含调优参数及ge参数 - * @retval #MSTUNE_SUCCESS 执行成功 - * @retval #MSTUNE_FAILED 执行失败 - * @par 依赖: - * @li tune_api.cpp:该接口所属的开发包。 - * @li tune_api.h:该接口声明所在的头文件。 - * @see 无 - * @since - */ -extern "C" MsTuneStatus MsTrainTuning(ge::Graph &tuningGraph, std::vector &dependGraph, - ge::Session *session, const std::map> &option); - -#endif +/** + * @file tune_api.h + * + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.\n + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n + * 描述:mstune调优接口头文件 + */ +/** @defgroup mstune mstune调优接口 */ +#ifndef TUNE_API_H +#define TUNE_API_H +#include +#include +#include +#include "graph/graph.h" +#include "ge/ge_api.h" + +/** + * @ingroup mstune + * + * mstune status + */ +enum MsTuneStatus { + MSTUNE_SUCCESS, /** tune success */ + MSTUNE_FAILED, /** tune failed */ +}; + +// Option key: for train options sets +const std::string MSTUNE_SELF_KEY = "mstune"; +const std::string MSTUNE_GEINIT_KEY = "initialize"; +const std::string MSTUNE_GESESS_KEY = "session"; + +#ifdef __cplusplus +extern "C" { +#endif + +struct RunnerInitConfig { + // onilne online + std::string profPath; + std::string parserPath; + // ncs only + std::vector devList; +}; + +struct RunnerOpInfo { + std::string opName; + uint64_t opCostTime; + uint64_t aicoreCostTime; + // gradient_split only + std::string modelName; + std::string opType; + std::vector start; + std::vector end; +}; + +struct RunnerModelInfo { + uint64_t totalCostTime; +}; + +struct RunnerRunResult { + std::vector modelInfo; + std::vector opInfo; +}; + +struct RunnerResult { + uint64_t totalCostTime; + std::map opCostTime; + std::map aicoreCostTime; +}; + +struct RunnerDataBuf { + void *ptr = nullptr; + size_t size = 0; +}; + +struct AOEBufferData { + std::shared_ptr data = nullptr; + uint64_t length; +}; + +struct RunnerConfig { + bool isProf; + uint32_t loop; + // offline only + std::vector input; + std::vector output; + std::string modelPath; + RunnerDataBuf modelData; + // online only + uint32_t devId; + std::vector> inputs; + std::vector dependGraph; // run graph (for training) +}; +#ifdef __cplusplus +} +#endif + +/** + * @ingroup mstune + * @par 描述: 命令行调优 + * + * @attention 无 + * @param option [IN] 调优参数 + * @param msg [OUT] 调优异常下返回信息 + * @retval #MSTUNE_SUCCESS 执行成功 + * @retval #MSTUNE_FAILED 执行失败 + * @par 依赖: + * @li tune_api.cpp:该接口所属的开发包。 + * @li tune_api.h:该接口声明所在的头文件。 + * @see 无 + * @since + */ +MsTuneStatus MsTuning(const std::map &option, std::string &msg); + +/** + * @ingroup mstune + * @par 描述: 梯度调优 + * + * @attention 无 + * @param tuningGraph [IN] 调优图 + * @param dependGraph [IN] 调优依赖图 + * @param session [IN] ge连接会话 + * @param option [IN] 参数集. 包含调优参数及ge参数 + * @retval #MSTUNE_SUCCESS 执行成功 + * @retval #MSTUNE_FAILED 执行失败 + * @par 依赖: + * @li tune_api.cpp:该接口所属的开发包。 + * @li tune_api.h:该接口声明所在的头文件。 + * @see 无 + * @since + */ +extern "C" MsTuneStatus MsTrainTuning(ge::Graph &tuningGraph, std::vector &dependGraph, + ge::Session *session, const std::map> &option); + +#endif From 29e380abf63e2a956752f73090c064750ef4493f Mon Sep 17 00:00:00 2001 From: shenwei41 Date: Fri, 5 Feb 2021 16:03:35 +0800 Subject: [PATCH 11/59] update prebuild --- third_party/prebuild/aarch64/libalog.so | Bin 223920 -> 225280 bytes .../prebuild/aarch64/liberror_manager.so | Bin 888880 -> 1080976 bytes third_party/prebuild/aarch64/libmmpa.a | Bin 63182 -> 62550 bytes third_party/prebuild/x86_64/libalog.so | Bin 164208 -> 173984 bytes .../prebuild/x86_64/liberror_manager.so | Bin 852544 -> 1133320 bytes third_party/prebuild/x86_64/libmmpa.a | Bin 57270 -> 56998 bytes 6 files changed, 0 insertions(+), 0 deletions(-) diff --git a/third_party/prebuild/aarch64/libalog.so b/third_party/prebuild/aarch64/libalog.so index e041ad7e1e1f697da1328537689b7b300ae292dd..65aefa59a84fb99b46d0674ef6870f62e282ec82 100755 GIT binary patch literal 225280 zcmeEvd3;nw_HT7}fB*sk0z_a;C!mJ71!M`L(CHuq1&m45xQy912}#Jps?r2UaT!f3 zN<>GRfS8VsMp;a7Mq+Sb+$Q3N&WwhDh|6dM!32T4@2Puk=g_9-ectEu=KcP8cjj{M z_j{{OojP^u)N*gfl~>N4Wwlt8dDzs;icrX-2IJrdjshFsDdkYHst^7hrAF$sy?jr8 zdlNFns!8*zbPnU+-gvU_C*%3PpA7ltH8s?bWuI=!G<2lYlusQo@~I=N7hg-5Hm|{) zJqTAi_i$DHuVXo#d8M>;Bz{$%t@9l=GVbxahW0bknO8I4waBOSG#>wN{|(_3NnBna zyF?8%5}H@8j;w)kiEtInlGAzT@jVaw z-EvbD^;@LB2tlO#vD32O9y)t-BVvx%*b3(|q>iP4mt7FI(bSyV6 z>P}o&^1Tb!)j03Mc@NGtIRA*#JRanmhjCqt^D&&&IM?HR5~q3miEli(Zo>IA&S!Ae z;xvzEaq}F57jS(M=Qf->a5mtS$14DTVPY4quijyYL!ubi# zPjP;Z^Itf>#JL}58_okb58|ZbE1X~BJdE>OoZsX80q2i6+i@Pjc@*a{oOJwRTvP|H zoqYc*Ur+H>UQRRUqN@e}$7#iB!%0VPT*+ViGVYJ-Ae;b-(xnx{ZaHitCnYmkVO~aYNI1ATY zocW9w;9A7@B(s?B%W$pW`^Dn9S?&^WOPOEB*X6jbzlx7{@SL6CP&hx*- zcE`gX^}Wt>_~W@Z{`%cbG4l?eGopWc=lqY~Tk_Z!=Z^noRMMD@{avbjhmS{VpC^ zSy}bvC%?aM`to~j{qf-ohpl}#b$iyAyJ9=H+%kJ=((I435?Z%gPaj`>@9`yj${u!( zeRaXH`!9L1^~VbiPB}UA*-vh|eM4#S)M?|cu6X9X>kqz~@I(4p$FIMvCgYB@u9;82 z{b=7+FYWwk_RcL&#~gU_>W?G39)3Riz4tG%jDFz8TZb&Z|H8J=8)kpJ=lr5)UklaUszG&I}O~<~UaM=?dqdxZ~rvKfIRx#LC_` z-q1Fz;qhr7-czwI?_mAGCnhZG+PdvnbM)@RKc-%Ge%^%r6P~`{i{vW?uDxn_cE2z0 z`S&@G?$7&nA2~KJKQ=YT{qpe=>C1g#GV- z^7Pw(zw@?N?-^ZrYwVZRbAH$@LMFFKU+_|(_8CRvjE z2Twh6;N-&5cRb#4WADaaM!fjSN7?6m-q-o)kr&Uq>Ec6cs?Kt!cNANSDhoGcg@-lY zeD#Yvx6PQ-?~5A;E`0s$roxDO{&mrv51+T7`RQKQ<=$yMe8CInfA)3Gv&}~~uh}=^ zPxozXxc{7}-1y*$x9{%k{i+(0cGtB2UuC}7_XYRJm;UH|F{AO`_0?;#YsXKmUjFpv|?D7u+2hkrr`(;r$N|>H47kj_V`Rtv?)EF>dCt`;&I-tVGp_ZttoFM08r z%N|&@Vvg7Q=WpspA0PVs3wK#9&z|@67h6UwyYJKmJ2Ur;E_5Gp_Zxim$_3Sy;Hha{ zg;}rsJ@$?rFKs=MbaETo?4MWlKb?`#fAu8;u036U`&VnWygYy9$IVgUcgMIlZEZgI zsO$YHJ8#TP`%~qD)E!^^Vf;4BJFCXta>2?Ew|@Oo+uCREEsWW9+w~vRzjx%$ii=mh z^zqKWdl&UtwffDsVmzs%D%!sp92Iug%ZDy4f9m+VpZ|3IoIe$Pb5Z!?eY$dQtlc%| z;TJ5kn!ngTbZfz1_if&`VcJDwD$qx1)ep;`EpMUz|C+kC||GTQ+C+jYqmEATe`NsF2 zy!)NFr`~FL`Bl%YWp_-PRBU}~(=~s5{M*4}+IFm~cf%oaj;`Kw{(>8hmE~=`Z=7ez z=$%`G7R)>Q-n+(DEqH3jU&b$9IPZ$!#w$i?DKOjZW!C|kKcY^>ALcb%^&Pr z)#on{Hg0`wci*os`E}Y`E9bT(w{~88aR0n-l7n8EH0`gJaqnF?Zo<5<$1Z67u-yA* z`0{ISnexk>eLijfRwHpw>6Zl1Cp190WtjK( zB*%vJPEY(<0r<86usAb%Dt z9Qhk7WBwPQKi&~QPI`cH??k0~s@Kv0et0)@=_!5QsGj|yC4gV;4B!uM1hD720R9kv zR?qrW2e88{*l_4c|MUR*j78#}{QRi^`g|Rr+;0Qets_9YToj;v*95TV!~pFz5c>C2 z-}V6UBqe}7lLN@<6F{FN=--pwHUzNGzXHg4D?op@2B`0>0PXl}0Nxv*+|L8}Nk{%lbT><1T31Ejs0pej}0DfKoIne>y_oV=GrUj_itN{8i2oT>&1IQT=K+j15(mxTv z{&Ns#B6^62w+4{EG=Tgu0qnCUK)Fu@=%@1n*azw;dk=d48bF`10puJDFisT&h_|KS zd+P5$28dT52C&;IjHgiPH^++s(oYPa|6KvnW0>vHKF^zY3;J92~UYNXOVP zgRi0uAsn=SLdW^IQu?ST3=H?sM~3##{;K`BfyXlcGMC#@V-P1<&U$1VjCp<-YiR0u zvF@kPC&@^d&gq-E+;%RviTPF9Kl>{eZyJ8j<&Ib0wAqOx26mxiD%&%PH`k!HK5o}>9y{kD zM!7*;uRpW=!;1_en0ea6C4Ka!Fz(U)^|4KlJFo-SD~kE!T;JeMgGdFY<0`gWeyAZB z>gmIx{jI-hqK!`+rarrLe?s0<+<>P4bg&#xogu)(sn+1DS^hutxDWjwGYHzBqvJT+)5CsF z^JY5YVL&Q3l{dIAH)s{X{mA9lk4o7;UDp``%stlqLs@_7AUI-K{ubPm{Q3a~Vb+)S z8;P%Ff1apwDV4+N_xYuNt&fqu>2F5DLQWrzjze-B&lv=oLm%VWo_pAyrvKM-zo@3o zZ5(F5`yszPt6f z*O85K>ZejH~a5A?(g{=pG|%N>z~N_CmPw*qg>xqdQpR84fD|> zjdB|n8+KxBj^Xrq+%ENR8HDL4 z-?ID;_Cszqbv;ZxSPfGxBaD>jZu*$Oc1UD9gfj18zJbTP7}lqX%Z=S*BsA@CrO8u6 z;8@D(pX2uGpchg&9Qt3p!(%(Q{L>&z`|M>q9KOUzZ^n~@JPwBV^+#pu&o7=#ed4)Y zLRgV}F83M~MC}smH_m1Rb9-_8G2_*xJYMhn!VvHz*DGq6k-nAv!5n|*@i-ei*hqMi z%dKEPOsqACvCN;x{i5|7gJ@y?S8m68*1v_zeTv7&cE9m)2iv)t$6vF*{J{Fxe`^Rf z`QNjBma_a@pN-XMNsc`KeZe_$TwHcpN?_N#ppjCwV|FX`CJt%LTlKB-*FqtpRH`q zHOzm(cIYTD(ubPu%l;7awvlimr%!_8k)APr@uUOKi4SADz02v#xF4q$B+90x+KG4u&yo+?7}tM$hic+YPnS5w$e)Mz8UIqu|gxd~jZgVWdZcoEC% zuWIH;aXjhZej3aCa*hwJ^lxvQBsk3YHjsHW#^4Wg z`tzAT%=}v8u^P*Imhgu%?VSD=Jg0h{*q(>|;-@{>&_CfF zqg7ne`yORPsFs+qt2>XE{a4NAjznSTKJNPfviBR%;y9dlq$ z-Ch@Sdl|G^Z_Xb$K2$OPgBj=j+OeJIrC~gd*g5@Y+>Qwxe_(cf+`{^|KWAWWMrGyr zoVwfK&361J$2~jGTM~@NDxLdF0{0g){U%Od>o@NIjrED~)926Z&xif|nWiOVw`#xf zD}noCezIZ6P;QsMvmJu{#?xKgE{W{tPqO|&<~+e~+ zdF&7Q;|)1`SWXTyl6|6%8icvOH|lJI-^c5wrJQ~U+b!R3zoI|;RrO0oLep<^SWge@ znZR$WHZY_4Ci~*gpBa z4f&}o{~#2m^r?RHsLM^B`{PD(`_;dZR`i&w)qzOAV+ z((|-QJ;C#(1dhYOEdS5!pDNo(AI$Pg*lrzcw^ZY?3gU6$@S|ty{|t{`F8Z(&M>?nP z!~HQP%zS|MxZ3cRLAaQIisid_ zyfgdnH*C*(Ubjx<^e?hMtG^qB>9>DmyE**qmd5SAbd;gb8kQ5w?GoiTKY5Dh4}1Lf zXOg*I)qeAq$Jh@YmmBiOviwUp4yO(>_|43Rv0v5xXb>lj$Ld_R|5CQUxsQ>aR=k!jNzpt;Mpy|(}m=FHW zNNC!BINXNhgmJr=4!2hm?=v`~<83YP?~P^oA>6*MG(&)?|1!3Z{G#bh9ai^L!mE~YyaFxSk3ys&33Ee@j9E^ z@d{4A=eUvH)c;y;m+B>k{BkZ=rKRO9EG|kbE6*q`PfJs2b5iD|W#^RUzs!b&5SQ33EuZ52H6*()LhzYStu*AIL z?25u12%ej>IHzz{Y4JiRnp=>!SS`$1Se8?+U~wbOoTA*~GG^1t$oN?$%Z!`CoFYm` zIiYVwj&s>u_<@>JHXl_g%_y8-u`s#3l(Li;7b@tX3v(`G!P%tE1k$D_J;)y5np<>3z%&I6XyrC3EEGtO7 zdhx=70^NX`!SgA|NR6DBb(`771h2`RnX!zj2v5o=Bv(jMWkn^W1x4k#FahLFoKvP{ zzy@W-g*l5=UQT&V(PC|;g>a3V#!sa-x^i(&ky-mIixz7ioI(%Gnmd`c zVJ2M)RNxk)=7N$CJUKC=v@B-JMCuLMH7dmuhLII$)Dy z(x?_iSw=M`URRQxQSS4Y#p;@poTB9Xc{vLewIJG=oG3Yep~@}I(XBJV6h`&bHJ*&{ zP(~u=6d_um`x|{#v$~qe1$l`DB{>NhMcIWprG{Sd`8in&Oi^eys<}2fxRhd}Gf^e* zsH`9_XJJYCGV)*CXJnNZ6c_0XGmHJzhnQHyONz@2a+lqZQJ$5bQ;Jvslig5Ux}dBi zBP%B{qdZ@g`Pw@!J9~c45}g!MFP(s{TUu^JmRZH6T3UR5Mp0f4OVeH6KUHy_jy+s; zM5S^B%(4YH6qM)B%s~{&hv-;cX+#-qwn^k%<)sx_4j0gU>Y0w+{a`$mfp`*EUS2w7ZgC!6(N&F+ zIzFSYFcTx5u6;HV(ok1Ov85ofz~@6}MC$RE>U3xdBOOdiCBVHjMhA%31d8k?&S(#r zgtYNtT~Qy>7V#nK7i=ZX<)zVpPeV>Y9{d_zH)S^BvRa556=&&KWCS9LOynMMSy}LB zRZyh+xprG0$jHu4TS7hG$CNH)0v1C}jB+RpAk-kX>7GEhB;AM$s-&X4jCuep(Vg53 zhG&o}FD*+ePOh$F%Pho7BNItCx}PC@PMMF#tc6BZI5H)Qr;x#Eipp|Ib)kCPHKglX z9n1{@&WhZGoWhbEJq~B(>r0U_gqx-7EWT;i%p3%p;$;}dorM`i3(RX_K~WCwNo_qj zaV|6D(;$KW%SV~ZU=ElktGtjJq>%DxPtXlwGI|7w&&?xako}T!N(vEkXXfN)R1}sw zm(46FRk_6&WmHOO0Zk+dit^N%71Kr`HO{O7nM&oB<>V|-x$x^Um5b?I8MFtF0=cmg zON+@fj9Tc{FuIaY9w$fCO3o?Fg@!s2v1a?hBl(fiw#?1*OH3@Mpgh`7NC1Sz$wwBb*(A3wY^yG!6GeTWzZ6BYc;^9(gL)}Pz zMI;p$lRjG5yam|>rE_xU7nd78xwy=jexs)(p>=dil4P12P{&0F%~84Nmk2azMpQ4= zLyQr)^A{FptI`}jorCIHM7ByqL!0$fOK8f5%!Nj7{cKLgLer*X|I)?qZ6hquL~>R( z00d)tOR<}b1~nKtm(eKb3viTxspMrvS+h%vD@sy|uPMh&fYMxt?xi`*A@g#|D=?bj zQnG|@=9FX^V?74sYnEUfPz%fQ$l(o^%w^DpS^33Fipb~UsKt%PY*1|ygnEnt_1{{jt2D2u@H?UPj4$!p(=8Eh#Q6$XXWQSw?BbLbN$n4OBd|_zy*4 zwv)A>jF!UwN@VK^AJ4*zcPz1`=67;m;J6rL*{;u7R`;+}Dsw{+oxn9F;>p ztpl%dpInqpPs?!Or%70gfhom>8DkPp0D~0TRh8v0G{s@G!h8;dIjhTGI8)63zV&$KEoKuQJ=yR^e&wadj{ma@BzAH>42hj$ifl=?pMZF!BI%o zdFSc@qEP=!&u5vlVU_E<)A?Y2s*p}ohA@GlMgMEeR}KHxPn`v@P$vCDX=zNt;8kc` zh@sAjDJ)e4mn@#Q(i3exV_vKC8n?+g5LHJ1P#S|v%7M*G=^xF->3&*K!YIBlC!+|c zqD=2hP!h~koEfF11&B~-Y1lU@Do#T$%Fs(AG!QLni*vKF%q3Q@annk*w5y5>ifCox z^PSs3=qIqoHK+h`(~O)7F_?_fyfOs}S5!MQ3;ihT;<92M+>0?)F{hn*X|(f#sR?Z? z7?TlT9UzUx2F7L(3XvhPkfsJ%iw$pA&=HENnWc-7TYCp?lQE7X0w(34`WWZW5M=}x zEllUp@+pa)b^0{os0g0MXP*cH^ym!25UHmVrW_hxv5?WzZ#@mhYz7sk>;=X)7u1}E z)fU;kOcwzHW=ky0D9q12gA zeDX}o2zzSBAv?1144t~|os7m6HJN2@*ZJ#oT~PrU41#=WGSzKT-RGdDF#?j0URQF4 zRkhz}+84H|W;Q>gePXm6TIamUBif zYVz-arPlPD}qX|&2NG^Y94g=NcV@TK`E zb^uf|IwE-yO*iIJkfYAZYa*o5PKie}MWL9DS+X%<)Z1UQ$B6+aKcfs%NT}h%x_@Fb zh%)iK!gyk=;fVGno{6x8?pjfbhSjC`p6L0so~&WTQ!qDU8MMVrEE^FVmon@vn+58W zm`xR;uVb#ICvWC6>bdhWmTFZh7W!3;9?~2uU;^Dt{<)1=s?iRZ%O~8*oyBVEwlcKDJ9Qm&Bmi;-7FfGQG81A%mNHstmiekIy>bd zt0k9U)^>)Lx?EZn%rA~FURY9!j_4aBw0Mmum9HAVHR>6Ux^3;F$;xLo!x@iy$iX4e zmkiY*0lCmauXcrBJDSeyr-X3w4Dj8B_z z@%SnH7SF2u|3`lj&*bncADzy`R{WaExW`LnU#jk>J>4nQOQe+dX6kN9bY~Ogn<@VH zS3^d(Br}KPE%+qo|Nrm*Tj2k-1&ppnrCLYfXRv^Foa@|=;Y*8NYCAYO==oj0c^-7e z^Yy=ZZad@o41P}X4Ea{ybMxqr~C0P=1cteHO#yG_$ubB{P=3- zJ$}50`FcOTmiZ<>zJd7`Kfa0iRzJRl`F1~kAM=VG*7Vy}=0p7W!_3?L_zvb{{P^Hn z!%rN3d3+PO`4T@qig}kGAH#f=A0NxS$B%a~U+>2!FyG|ICoc^)u-|olfGmk&$tD_=6Rwc}b`0-1bxBKxf=41T$HOxEw_-f`8{df=a>3)1I^Cf`FcOTh505wzLohFKmIWDt$utv^X-0o2lFAl&a}UJ%kW#f zA0Nhij2|Dvyu*)AU_Q~0PiH>ek6+4si639ZyvvWTWxmRfZ(!cz$M0dj-jCnMe3KvF z&U}j>AH2t~Ppcmv#eBOT?_gf_KGV*r%!l~#CCuCXco*}nJg=b768WcRy8j#&{Cdq8 z|8xj`r{Kf7j1LrPSgJCrq@UUa|B*-^CHPB4`WV6EQ(xZ^D|r6YQ$KSEo~LM)f8P-zcsbsM37&saq4U@UUn}HC2_8Su@EtLNf6m9k z{{{b;kmC^iNRd84@S_EvDEJg1Cspvj6Y0|h&p*Y|PxA%OKef<&iQw-L@|Oz!93kH& z_)UUeBlvK^R|&pE$gdXsJi&Vee^kh+6}(;W^@5KOe1qWk3BF12k%HeN_&WvPBKUg+ zzfbUE1m7z7v4TG=_;Ur{F8KMv4jqCwfAgoa{nG9KuM0WBftgcss-;6={Rews<*dRXvl1>Y`shmg}D_@_mB)!FU;mkT~v@DB<(A%f>WS)+4> z37+;W%)>7DD@+pCD8U~Ve2n0~6nw1UrwiU8_!)vv5PY5B69s>f&@)x=KZ*3|f_Df$ zU+@t^PKn^-MEa$IKS!i@3EnBvuMs@|Necb6O7QgG6f%!$!N;2Hc3I4F)9~Sc41wTvh9fJQt@ajaj z|0f7OSn%hIazg~qKT+4Y!UVrsq_+$HVD$+Xy|GnT71m91{ zNfi7>kv>)Ma(^jZ@K=fS`GQ|0&M(|gQa;pSCSMb$>?=R$d z1Rp8*TEX8e_K|k6j_-o9>xV8#DQSgTa zf34u#1^a%u&CM5M15{JkQ5gW&m3#_3#5f`35B*(3Pt1m7a~ ze+zz};0r{#t%AQ^q(3b98wB4j_*B7n2)>t)uTFORKY!Apa|H|jMj2UoH5}g7*lX|74JUS}XWtB7ME!R|>vC z@HYs3ngsu>;P(hVL&#|ne7)fJ2|iQst%AQo$UiLjERnul@Y#az5d2GmSEsuDzfJJL zf^QXkh~RSsA13%3!P^C&EBGkEn}2hK9>)lNfT(Y*;ExMA4#EFZ@CkzFKZ&ECCJKIx zke@2}bitYsG`so_Mza->T3H~!7r&{nAi1Z%8 z-yzc13jT!P>jnR^;2Q*=FZd?Gzb5!Sf-ew!i{Nh){64`yA^29ohlqL|7JQ*d-!6Fm zQ$qS_hv0XK^y+lC{~r>3u;4d|azg~aP^1qN{I7zy3;v|wqXgd~_!z+#2|iZvTLteB ze2L%_1iw(|pD6f6B7LghO9h`U_z6NzzTjsIzC`e4Le5gbFBa)tf-e{8*9iUvk-kds ze-!Df1^xl2zDe-ag5M+fnSyT-yjAe~1iwU-+bZ}D z!5xyq2kaF1LEub*9|o=z_%Yxbf!6~!3;Yyto4_@|)?wY{Zvl=JxDMDU@bkc# z0>1=YDew;98i98LHw*kKaGSu*z}Dg2<-Z9WDe&9CPJ!PC&J=hraHYVX0M`ioIdHSU zUjVlW+y-nN(Ov!_;7EbL1$GMj18}CmM}R8@J`P+X@Co2%flmXs32co=`C;AV_Xds> zxF4`n;DNxI0uKSM6nHprjld&;n*}}xxJ}?lVC&i4<(~%}DR4BfQ{an%GXxyK4eS*7ec()i_X1Z6{0VT4z@Gy*3;YFeo4{?r*6{A~4*^FC z{4KCk;2(f91wH~?De!UN8i7v$Hw%0kxJ_W|Oq6f$F26T$q`>`vodOR8&J=hEaHYV* zfolXF3EV93IlyfKM*>?Ty30QgI8xwfV5h(r17`|60k~4&$-p%NUk2PP@O0odft|qC z$nNrI0Y?ga6|hs_`M{Y1CjnOqd_8cDz&8Om3w$eZo4}dC)-m1X=K@Cxd>gP+;3D8m zflGla1zrqXBk*$IW`XYnZWFi?*gCem{JVi81-=j1De!~9nF2oyTq*Elz%>G|2W}Sl zDd0ANYk;lic9*{eI8xv`V5h*(17`~S5^$x!JAi8h-U-|+@TG&0B#oeG;o{1)+qvcZWGuEY>nNP%wyb_!esoGEZAaHYVDfolX_4%{s8 zoxp7ZR{~ov>@NRq;7Eb*19l4hAaJI@4+B>U{1|YJ!0UmV1%3*+P2d_}>qXt=Zvl=J zxDMDU@bkc#0>1=YDew;98i98LHw*kKaGSu*z}Abq%YPF%QsB3NodUlPoGI{L;7Wl% z0j?4FbKquyzW{C%xDD8PNq6~&fFlL|7T78955SoM9|5iu_&9Klz$bv41wIYjCa`rD z%8%(Tzc+BC!2N)o0uKbv6nF@5rNG01YXlw%+$``pz-A-CQJAthe%<@|X&jOAV_$pwh!1IAK1x^C46!?1J8i8*D zZWj1f;5LCXfvuNzm!At9De!H;PJxSnGX*XMt`vANaE-vrftv-s6Sz&_N?_~6?(**j zjuiMlV5h(j0%r>RFmR>7j{(;RydJn&;HQAw1g-(LPURWJ+XQX~wodLY|4raXf!_vp3j98BroelFD+T@pxJKa5ftv;X0=P}! zHelXh-VC!s@AKP7iZ{SFQ`vE%z z9tfN%@DSiifrkUv2s{$FS>SVk+XRjTwodIX|2*JGfun()0$&WADewf~N`WT>*9d$W zaI?VEf!hRj0$VTZE`Jtqq`+4JI|ZH(oGEY;aHYW41J?+A6L7P@w*t2boC$25)?I!s zaHPPu0XqdQ0?rh;6u460#lSTJF9&WG_)g$9fh&Qnmv@(cH*lnZPp$Z?x5=XFBa|zN z_EnE2TfF%0w&mE(R_{mHN42;nPwjgy{pZzP_-wmv0Lx&ZiGA+WE9}}L7R$x8f8(Q-6LE{BqyS2ik9^T zp0{>&ji9~WQ!8H8`@{(-%VSfM@ZXW_oP+Z5Zf%kW^{c_Do}At3+&8;(zs*{A+cdTI zC}ca3)(#zRLcTjrbghFe+K-;>T33estYygmF7DG0smAHJ-%j_DmPWEg#&p%VwZEhD z)QV=UGhOi>wHg!I2 z{0DvY`m3%NwG*|^v7t)a<~Hc+3PwFqFKQ1DY-aDHwq@hqrq=E~VDTKWLe730v{8=E z^+->4(CxZscIRZYmEEQ$u7zF6wyXQOk}9=r$LR8lU|Z6Io{c%ne0H8YAH3P-jv%!y z5psqp*AQy=R@<=XV?!OC)ShNrQkmL!I%apCO=SkDN#q}vU{@0PMhQ6lR3T(f z4yU6scAIr}jn!q0$MfBIZgZ^K>$4r!!B@j}l}Jx{HbF0^2R>*&Pq*z@v#dVM`3&FJCqM)Obmx_=R%h0+v(uRuQPBS z2;siq32}dhbPCU8IrM%<%D1DBga@hd&@+YPo9}#jBkw$vf%dICFvOMQ5@qPV<{IpN z4QXT^(x1vB+nieQiZ>nl;J>n>>p}5uJM2jPYBBhYHM2V-VUwEkRVUhh?|kTC?~VR- zK)JWUj{9vx(T`k7YY`WAb=kZ-po_N?X%GWj@vI+wBz&~(rvX7K#Wm8=*#tYEOMMjg z4%{m>y@iB`txx&$#{8uxyfPTY>nAG9ny9+*Fqe$lil=KSB@P z1|_o^O+P{#EW-D%Db%0Lw%mmNqHWzYROioupOatPOM3hAX*t1;##Wm>THPL=Y|7Jo zdAEFxmv-YG%NuxRd5Gsmc}u&?)8z*%U-@0}Lq0gQLg|?K%P7_PGTQj(Pc7cJ5%cNy%7_n_@G&P-iB$Q`yi)V+1J#l2&M>U`w_)oFt~Glr1N%V1;tBr1AL zkmQHfO$3im#iA?Gt` zMxP8Htx6TzjOyjI7Z8b_3R8)L)vpFgEI?(qIH$^pAMI$>M4*`9}>$Je%z(d0*8*+xYlv<;6wFwB+I zW;?rXzb&lp3+O{-HT}}H{VVvG3uE|r>JL;tI2yOfj$}X6X7iwHSNvdK`%&LS-_vuG ztz#^17j)EZcfQef)V?i{iJ#ht_8VIF0_3ElZOC42u+u8oLbVQa{}nn>8+epq(?*Il zu-V37m4aB%?uk@x)7QVUjnH-K9pq@-G?M+$K3x0#Gmvv;`wp#Z?l5G#&|b3a3@Y1x zw)-i+ve$Fjmfk44hjMq1b|r0r&2)cDKUA^A%7;Oa``r4@h z<#fRw6q^sBPG>Fdt*?O|wX6r(z&}qG zY-7aykwzY*--+~pMH_VORv*y#NbxShHOhTzg~fX+Ub&s^voSBR>bWk>?J$pXr=UM? zu&SRXsvm=8s?{!Z5k?bI^HZq&0s>UV(c5yx_d2sxBb%Ar0vCLD8A$RIfpo>6YHS0{Xd z^d|jH-7T;`>9z87kay+hs_`V+??39N>^}XnA`JZwK<+E7Ust^41H|Nd^nn(o?Qiv- zTCLm>+WzS8u;)bB{n!}QS%G#S`-j5*HJ>{gYkH}PdR_#3+hMzK*n1w@AOq=+jiGsE zyqD^BYK7AqVYj$ZmK*U+&r>Lds30}ij=E6%MnA9n8|qSX&RlKZ%>%CakW1A0t9Fh&#EkJwCR-MfQ)wY+jY+n52 zDjIs!Z$;c}ToB|vYO~ZS*d560A>N!iLIR4>iR9IWMRyrOjv#R^URp@t7h>=rmqx-M5s_&ZmpkK^D8`?snM@=S|6+0o`8{%%?_(a6X zoDVnNXBo8->zEmk{iN;jkz29$*p9X2%USWT!AviWZLPM^(I;oqS}h)aZ`FO)Q>+@# zhRr?2j>Z*z)Zmqa)S|c(T`A_gH}e;aRiggmI=WI$+RlzP<71r>@9SdF)?cH3nZ4(Z zI|P5qhM(<+k8NDwfS-+yZX2Z!r0YGeUtiXgzG$a z2y|MBdcKSPG#dFnz*Qj*Z#4VYYHEL@PaRFx{fYjBNFDX3bc_whY?kO&Q(ROI-Nv)kv z?X3;R8vnMx9KpB0EuQiZk7T(naJ#||9;xY*Fizd!cmi{b#%D&&8K+Lpeng#I^G++q zb<5!uAGV>M5m>|2^j6nCJ@l$^D%f(r8lc{39i*@h9~Mn(z^h?v)FB$<#(0JCkow&~ z_#(|`gQ3$kur>Np-B%d1$cALA_!&F~G>y~!r5WicUm1;$@Xd4{A07CUjntQ@A5s76 zT5YtyDQEX|mg5+w=ic>@^CN8iE$TkLhjMqD<$9uZxtqD%Hg2DPBHtL~GsfF)eGj6q ztah4ZU8wUu%6Vygq_!9UJJ5Pa$49F2?|k-RL+=LrmmOh zb?$Ay8gW*R_g6q)8teCML1R`o&t-4Upy2Q^ok!l~+PH z4|F9xlUPp+<`Fa|Tnha#7m2=<<2&u4nCnQhoU8;cr)j({=L(cV^A}U+!O)jvQ~b$? z&Lo${i~cC9CwZG@n|jA+dE+2YjmCebGwQXGh>t^5kh+#+;d^6ao`5mSoF6Nz+U8q} zBOX(^G?!hAIS|$nQ};p_S8vsrZgouk8s)n%PcrsRjQu2^92?2`t2grYxc<)DEkkJy z{xkYc3i=BE6UiwQ*B`sn@d&jq_EG8(^P|&_cdh#paT@J`=T1G(r#Ak15XHdVwMyto zyu=y3)p*a_<+0SB=(j^Ce?-cvn<#HY`8mmyzw4K-5!lE0DJaZwVim8`O?^+TXw+-3 z<6m06$1(nNgsV=^rK&R*I<+D`#^Q>YS2qjw_e@bVW-Pi0V@IQr62Gi z`&_^DQ*Ii|MxyO$oWVX%QZJ4RVSSXl%Nq7w6ULDyYuNpr7;98}T5S0DYEeX2S4!GZ zwP-HJ70(n$=f};H?mvmO%Fvd}?(fa{pG3?rb1L_SU(_PBRZ2PH1;wHe=!dvehdCL> zuh6;<((`oJB+sP|#H&%!ClJ%mNB={-i%!Sf^d!=gE;NQ5!}vftt@;)H0ppM!f6A`( zZpWV3@h_cT#POsK#L-hL-tw*2XYH>H-U!_Mk|b!t5GMjf4ZO( z_4iFTu&=9$?qZ#GShNSaI?x|)Kpkn_LH&>RAXdRvvYqW?!DDW93!Q=}W}P z6r?|jbf*5K`+@5@t>aRib_UXZ#POKwJR5mPp9ROKaKU;_nlovT|*s> zE3Ik)_E}Qa()<%K)wMjML1Dh>S{~6r<^CPAPp#PE>#vxz*3&*B#a)_v{R}&HU{B+? z&5EBKV~^?Y#{8<&W{ci}`qKP-7v{)!jdU!34Q*lix?zLiut8{a)@`OQPtm^k0P3#i zG=J}&)7blUulYN$k8^6p=e~Hd^T#0XPFs-MHne-6>1FJbwAx12y}ZfduKpQ&7vfo~ zZA9H8;4l`}w_YsZxRNYjS=9_$H3K_A+0q4qt9cy|DEG6nyx zguN(k#z0m&@~pF}i93Is>3tb<$rjk{F~o#_L8j67M)~}E_X4i3Csx-t5%SG^w67kD zJfEKGnuNWyz57`Qn$Ox#bxmFcnecbrXE68n$@~gq!R|tq>zb@OZgAA%25kq=~`{dK&)#;W&^ zI}z`&M_5ns#*RJm^Khk@g?LrJy3~~vi9N#z$26_mQ0PW|dRG_b=Uu(MJF+a;W5(WN zSFqP(>o@L~qh0H6gPt_cUprY1J_@|Qk8AG%VEpE;9)47Rm*aA*BQM8$x8Zep9Dg^! zpB?DeQ-JS;ohW}0^q{>v(u4L5C=MPdV|_fA>pAd`NKZZoo%YsTefcSZB<2e;R;#Y{Ob~gLT+<-(WulV?bRWjO7kX;*^Ymj>ZUwa+g^x_ph{u ze%FS%U3zavqrEG9ayw*npuMF|uRy1!lUU_9D>+*njpqXnl?GlGM5+&Hi&2>q+$@zk$9jV_arm!TbR+xfr@`!+h@>=t}v&hQImd zvWAZJv{qjPSs9UWjhG8A@SxB9f!Z490`T;nRE~pP@iyPO_1CgK-kZld#@!O+=oVx4uphel$juYwU8spSa>{nnC_v=vuDB%kV3z?<8R7pg3LMnIjzDnnC@% zHQ1-w6mNBJ9?{oJb@zyRw}z<{+7lt2sSc#KSr1cps)yA7z#z5FyIM8A2_3zw9gRJ< zr6=eNJrBYM&f{_);QnfZ4ZJHHgNfFl;2Ti@ji3U zY%kU$u>ZVq*mr5%vc%CydXVk2S}ktVM}I;-^3fYa`Q@T~`(eNGM+_Xd1$E9s8tM-f zT;App^Nn&)Zz|^*s<+4H#(besw)e+e-ZW8OswmHO%qY+M$bfNFU$X7fPYfKF$Mw6B z%kw^B)a&Ud=8vQDHd1-%R@6&%Qh8s)US=H|xXg1znbSm>o*%i)p#yc9PosWY&<@kh zvW6OUdz$OE1#OdM4?3f6R37>7pSUa=%7R}Gq4~u{xW5@Oum)vP-;9D>V}57!N9vpS zooam<-otKs)ObJTf=^Q%jzB*RLI0$8R;wR3IC>Ug@9pl_L%$uu<%Zxo9cBK3%k0l( z_7o4|pX6At`nXTxeJagUF>jfgR%ls7F+8o@vdDpb1B+6fG)6@RIi^MgDL3&hJdYgh zh^712u*N3dOh@Cx3|?!{I7W5H-ycO>8(KFFc0&BFr!}+QkExHxx^l)Rw1-9Sh~zi{ znb%qpGGb>$VV#0F7f0`*ItEQeU0P_q<4g~BTQEOZj5<;*v|z07Lj0SBx>Ic0w86KA z&|{miehPN)gncl6Cegb{8t;AM8Rl@%HJaw`Qz5fSsfl)^JF3?i#$F7i{}#{oV}4F+ z;55`n>)r>t`=#qzJp$w0Z|8^Gv--GmFrFW`1=an6d4rxq)42YlRgdeP*!$>!4p=MH zoxpfUdww(zqIbJ1P~NtzUhWzj>W=Rz$oID2tUA+9PV%OmoQ!h{&RCpNabAXV8qUkT z7U=wP)`)T2vQ+1r=QzBZ*In&(^l^AS_nhTz9vFvs+sEta)7N_d?`$`Z2=><4tnMx0 zy}ht6t?BAEueP{7DBIItO*--uY|~dwq&*53#(ql-#(lIm{5C~lY;D4R@)c+U%==)Y z5z+l{Z^zhi3-ZICCQ%-p4)K^|?|?kRABNSvfV6n8PTy%&sTP`dIyz^ez4X2`>b(7C z2lhh-U_Lw$=OAzR$rzmDaZbQ_Db9)B`H*o!``56#4UpXlU-%MxOMgB`rI7z&uWeFI zmJKmuc=WIBhVOVVHhaFqyNNf^v%&6qq^5`zhF+-iT4!r zo*lm98+T3F@tas?dOy8Z2!_n>;ll@EXUq}sEdaf5r#Z;*=nqh@8GY1G1t+^wwp-7> z-*W`}VdzJ#*pD*Pufq3f5!k!Ndn@?X@aWf(X9INnl>3FQ|7G3vFBl~1f0?CmEb702 z>rZty^)%)gA#Sq8rr*1g(&4|f-djU$3)!!tO*~i=j-@O1L9WL$&u**xIh0?C=j0RP z@$3NVMSg*}4nG=J_Yulk0vRu`eu~!PXopg8G?#9{b82_250m1s2S$Cj7=BN_L-D~L zf>;*hG2U^#pc?PO^G#bZHsczB^JkQ)&gz)b2;bN}pnJ{S3cJ1s-DnN0`WoK|dbV1Y zJ%Dm)Z*UdT+WTWK7x~F|n+MRh8E5Num;w&#u8FJQOU(tY>9%U^PgzlB+Yiufe=lrCZ8jWZ&2i*wg&mFeTf?Kz!!xS8!u1*0 zWhb6ne%nsx9dm-z4OqvMH`Po9g~6KW<~!7T4ARki%?7mL638e26Y{GNx9a21W!+SN-CxJEZh^*! z7a-ue`;l*-$Ybl}_N?yhZSCb6vN1jg_n6xb!ae4f zn|CX>=N{Eq^Uy4e5jKn$voTHtVVnqse-De^b&2Y%p*@N$dROF1ipO_IR4%;(BfV~h z4gQ<;jYF9`{)g&IW%u!`Z}@+?z7Z&M`TtOTsqA;~{fTVf13&(E+t-3Jr~ePtm&$&~ zufEUxx9e-gT7{uf7Xp#US zC&w#_RrH>lzCXdc!RR*-PhA|deDCf>+;aV=xE1t&7Pn~LXT~myTNJ;Bq25$3`8It& zPO*#hyP${qn{}r-ya%y)BVuz6V)GW*V9PbCvo~z832}Ne;`Gyq(_0XypPB8t!rBY5 z8hdCfvDWz+?*ZmvACtAiZ|ry87X}^x@avb%b@#`SU!rV-cbGBx43?8b-Ihs#V`tOj|OmpBhPU9M)(-a}i z0X#Rxi9X&|E9|`*%2cDd9;n%5 zantvfR2Q>e@0d2nyJFhgd+!H~uUK=M<8M0jSNt8rbl3#*9p85hR{_&^44BXQzGI-g z=DU7cXAVO5Cl57XbI(Hx2L_d;HhOY&w!j2?IXH>&XvWd0uZjm0Ttrz4H2 z7ve(F>UYgLg}Og8^cX_lSjlt;p}!6C^%}xH%>8#xNAGaYT&G*GPFHo;z^=)7r?RrQ zvHm1`gif?|F2p!Yy2!biX{*q+_~xmrYa5McmKaN8W)Eo%zccI&zoOq+R5|euGg85x zXftX@{??<4-Z@Hp(l;7u=Kcrv6zH7?y>q2^t5JB@M|#lvPAk5RSvds$0K0F%w-(s1 zPriYtg6d+9yyt}d(b?G45x>?`d32;=ldypMCC|2CkHVr@UkbC1)T z`NZ9OSNC>wHXq-4#M$zXBN58>PG;8OBdf9QioD(V1peFT@1)}!Nchq(*3+0?gYhr}>FIkK^j-a%9`oHDm507sPjPsRjciN5eLUNJ4{Qcq zA8to~SEvic2Nf2Stgy!r9*Xx`6E}=B$5C~b)!^|hwdCo&Bdt@%);dm@?;dIYYbIp$ zQk6*?PR>}AS#{;|J@~$Arn2?lpn5IH$32bHsn~;|xf0&XMeo4aP4gQ1){EwM_~y56 z1pEqfnmRkaUBiA(9qrA~``~5Y>%DF4TZLke2k(Xv>spO5Qt#EY(mP(vdGI|@61Cr_ zR{S;u^B;<5#`@KGr%CmtZ-!2w{)wFbPL%luY(aYv6xU3<9SCN-IgH;5P(Iq9k^Vv7 z^iGEyirIybv(+aj)SN?AY1^w&?lJfc6t&BFkU{UaLy%U=`WUiEzcjqF9*ghe=o>k- zUy2=hs7=h6N#738Jea;6p!(9DFxe2lDXOAx2grWQaDNQ@M_~s>xu>oUa}UKk!#3=f zn=*i_Z6*H{jJV;7j%6M_t@JVzaL|hg1uU;s<8>D7x`$foc7g#F>Zy{Sy#D| z{(;y|wzK!{m~s^9kS7U!Mt{$E4BrpxJda5Q>pgPto0f@E)y-_F1jg%A|Bpj5`$VoCEzy z2JHpXd_&_JiepF{nr?h5acJm+)Wp)>j32dFzeYaP1bCLK$${xM_e zeqSs#ep605Qe745dI9PQA02YktS9uI1zm~z0o=2=$9$nht(~pkfstQS`sOQKA7dY{ z1?wR>8rNQz*-<5-`=l0IcO2Z zdHT-cG1$QTZv2z?@m}U$*IxQY<5Sf2DfD0RT}OYl%?93x@wPgJa_If#ete&V_+A$a zynm%@FU5^Ew3)|habF59!-{=Nd=s=4e))2wwUgeR!v0AgBj(dPeRB-_U+leme3aF- z|Nl%TT&j41go~HT41rdnRjZ)ljY$F`7Q6(!w6vlqa%xYR zBv55)Pw5dX>E#fOwYF$QY;CLUw?WiiY)>h8Au8qj{_M-llOfple1E_5&-eH$P4YZz zuf6tKYp=c5+H3Deacq|7e(t@zGFzWXF!!nTOm?3cJ_bMJVDj>GnKAOGc)lKZU$;H#wOMD+0;YyJ-X3rkM0<$D=h`O_-CoXy z@6@wRV@zpsRDL{Ox3k34>euKR_D;Op360XT06fpKCsW!+e2^WNPV5@pM}O$aY4n$% zz5Ed0m)b>Xi)-IN`j9qu{4F136VEo& ze(mX;Cq=(rE8+V<=(?2gO7C0FE76a{1;!`u0!DkH8s9tMt8?&~b1i%gXF;t#4L0!K z0p8aMdwZywg>+$Vl;w4%PB!rg_Ukk!WEbB+=P$xWTDuwKWeYi+v%8zI?4eJyPO;x; z){ZBq^i;r;dxBu|<@jw)qiTEhVrT8SxXS!t(3w7PVEkYP z!~Pr%-g|4$2)(>zLuEgbsfl4r%Ia_n;}H$dBEP$6Cpr>GnA!{DH%pi0M@Q{rBtN)D zHnnA9(WXkLh|j-t20vwg`trX^?Q0e7)lO|RhsE!Yi7srO^tjZ2Z|B@q6uw{+v9-$Y zl=i9dHDL#4y748c({ASXC(yI@8r!FIMEx56INdl8Tz>pNMMrertIvLO7la>t7kbsd z{Pc0Y|JM)9Y~c3?=s!;X{vMi-@~oX_qD5!L#EVk>8%{r}0lOU7FFV-wl&SYwBl(&$ zf1EQKiJdGTG4&SJ$Q0r^J-< zd2ZW}$Y1H6%TK`vs>kQu>nY&V*@ z+#Q69_tcj?1805P_P$`L4gPK)u*M$Zd&-~IS%_z1MTut%ic#!XHx(fY^N?wpn&65v3d@2}m9jCCe~`MfcprfyUq-@1Za$h}_~if*QeE2JMk0S+2iXDjl5 z!A>dn-mNns*cLsr^V|B`8mF}nW$aA{8_SrJ$|-bROumvjL5-ccwBriKD%+qu#@*2O zbMRU_SBTfFtf`Bun`U`-5pC3;+J6vu(?9M17wvz@-)5cokmarHfYB9vBlS6fwt`n) z8DA`4%eqj2>FyU+O}BlV8tG$%>*GhX(YSn@IAbxmgW`CSwEKaB^Ks8>#>bB3-(U@) zCM7R|eJcQuHw z;z^BPW8t;p6}8j5QvAwGcpe)5<@$$p+~*+JXK1JXzvt)_4TqwWa|^xkbPfpX-fQt} zHF$>RH#j_Lhev0+I+^dpRuh_aW*j@JTAtC^Sa>$`7}n_k-?fGsN4?YYX4Yt8(pLlQ zKuvk@jP8X{U1Kf2uJL2}J>Yr4zf~0hcA9!g&s7pc4mpU+Q`G`E)~UOdWRhg+i3UG-x*!14i4k|cU8><<@uVa ziJ!<=67(xx$j-gT)vfC};|>jvc;4`d^x5cQbq)Ly-v0n!j{6*9*rVAOH=JEFI=DQ^ z+BFe>f6^V(Z+XPz5@VsqcPKdIG;`#F#M#2R0i2zj#q|24`x}znmsa-yI~TL?B8BXg zkJEVVnZ+1q7HbP<7Lz4sSl%RFir$xUQ|a(sq~RLywJyf;A&hu*(L2i{R=-O+og;__Uu5*xMx&ns_}ST zl#b!oZ&Xh5JDkyJM;GN6C}+7Tqy1s(RzKHYc4UV?vn0Og%o6MVcAZ;l!e4rdJ|50g zg=Kg6yOk>QPw=ex_ptn9{GC2M)v@&?>W!(blAPbhz62Gv&MHk@pxkk;E*Aco^+-JL zK7#!FNh#&#>!Ewcw-~3MCyt_yk2>0`nOB@KTGNqspRcH7eWNF6r)`4+PLR*ECt@KT2 z-lQ+e9kiU4t-ph@M#u6Fw0HI#*erf9mikV{buNAB>@mEo*4<&$aTV?jd*nSf7x+5< zm-4c46dL;eH0sp%a_&9W0_@fQ{ zHNfW_{Jp@x06ckJYW<43OMPm-GCdM<3w({FG9@Pr2rv0`^d-0|?cShth z<2;Td!t-hS5I&Q5lY8^Prq_{?&xb4pPg8&96u9IwWKJ*Qu|9*P;bd_9o9VxN!+P3l zU03dOHve=6!RIz*yKA{yE>^Z`$30)>(i_m z$DWbICpD|&fF>finO|5-fOIzBPz_v(YZkF(|{xtnA*?Ir2pYoBWv8aP{MV7rg=JBP2KN%S4~c&o_EC!}7rR`OZhuoJuB!gkNAB9-sI1 z)h?h9!H-8CS@gxfQ-1?_mS8Vi&%EAeu5db^s0=%4yYi3Pe|Y49H2nnJA^5qM^|!5S zcmVn79roYMUmrKhPd!5VsXImSOR?j+SEjn@MSH(1^2T4)S+UA$`F1{T3+88c90$%c zdJ=H|Xq>-w=cvY|m{U2D6)$sVEIH$`z-jFAxst)qaMvjDa%jE_dEdZ$`40(T^!~Zo z<)PtI%EJxIcR0AsHFmWeq{z~Z8 zcw|$=S3TF?%Ad;DkN&N8+SAc{{jOYEGyF09?Ho!TdJ1=Cq;6w*Rv8%eTYw9O7vVYw9t2mYgK@I)a)E|Te}TUm&tB+LeUtjP_e8mSf{=ma z`8vLgcx=vI11cLV9p!#egcRI`UpXdg=Pqt@9*cusC>+$Q9&J&4vw ztzN1;*sMEt_QJo{@i7bcEb)6QYq!p?=5__)5@ZuFr*x-KE9dxhr;zRw(p^ILANQfL ziCa_mt*@9iw*7GK3Nm*IHE%;7%>8KWcU5;Ye%W8GQ1=R*%lJjp3&=$@>u=`d zUnjBm8W5x2&NzR_UA3R2eyWPS?3F?P1+~~f*~*>q{?*=wqwjgy?Y;4G_Oi?H_4;w{ zy)r)leE9$PCYAYt{GLIlbO&Pt_kSe0+Xxxl`L~ze-G0O4A${3(J(s-v{G0@Ty5YTI zlva5CBsM$EeE$eP6Ylv=Y{KKRjws9BpdJzdmyChTKSM9;>K%r0%nw z`p0$DKdx8(BQ=lrQ}Z|*p0u51>m}M+f-rw-8TCK$4bvD;>siIR#cW{r!S=7%Vf1vn z_{Kcgzv9~)G>45WoQ^AIz5zW;ezmrzwJGR%gg#ntw0mr6&STnr49`5C`@yB3^MQMe_ursx2lG<75ar;^ zT)wd=qrlbO+SvVRBPYe-sx1|stH9F=d?)fqa91e$y4mJ|hUbM>IAx1``yaie+FIL} z;w06MNH*gAWzcEm|L>|tF*Os?0nJ1FmNm9cf;bpGP^?kLTy9%z^-Omq_umT4WOD4^whocJl6M&XUzX{^|&b)~jUAD5cZ=cwz?=Omeros>#rs)@w{!o2v$)d;pIB$L zD$M@WM|PQcj!hYs-^=gc!IthU3l2X}7JKz#&TmZ&j$Kfet$FK3&TgsSx2z2FYmlGv z!;kX!d!SSLlESYDxWjWf{Rx&hV90;+UUd60$Y0WP`O@Ntcq4x7rf>28K;1EgbBhne zM|eB2rtFBa4dp}Q8@^r@@45f|@t(ro{nIud(FSZP_{w=T!F}h|246j|F8J5;CIw$R zZ*s8qybFWu`BTcX=O>9t+NobrzwHxEZA`kujm{7W~xvqcVEXt@Xxs0QZ9xHii zjzncrH~e?nhp07r5jawO*=M{*uApf*GCr)>6pj8S%6=SMl) zxI=iK1E=O`7N2o3a1Zmh{Ej+!Ngvf|>T8qmQ+g{NnmO`x@eE%#c?88y(sOuMh@XUe zCH<}Y(uEty8PvCZZpwya5PV2=(egpp4KLqdb2G#8InKBLUi`D=8&c9d48AtK7lSM?$#P6ozQ$}t11gMCs-5e{k({tqudG3 z9QvNS&z*rhF?D^4^R(ib`o4nq;!*CM180e*sYRNwf0fl8^r@fn*F9|y8`@&*xhBo{R*$O-EgKb2+ANPlf1_^Q*vzB3;tKdM?- zd#7b({#G+)&frOBc&Gf0XgEP~H0zlC4uQ8@${lEJv^=HO0)Opr@CVqJrrO}!N%9EL zxx>bL#q-9@V`4Y$LEC5Ofw3F2cC#l5tu5Hb1ai&%jCkGivldSB;vu1WH2lKMj0hd&1nKoQs=j?k)lWM19Ddqob`1Oj-;t>N)t>f&yY}Qqe|pDBL2l2* zpI^6UefD!Zs;BPQGbono`ON4)>}mY?H}|}>EB5cnV9>V7=WW|F=GZ^%89g}MGvy7f zcLS=cZmqlT)7;}ako?NX1b0ciGyR?nHLweh4#EYi55KSZwu|p;ylpafxz_NFgS)m> z@4oHX_3vDK&&9FWw$^v<+!h-cbd2HIU9rQqtq)?`25c-FJEpSVoxkIr*v7&Aw$0<7 z*w$Mo-N)Std>>&lIBwsDFW52qPq#kX4E*|mG1Z=Q`1@8eJS*dl-aiq~PcP>lOmu0| zt@q#e$Op1JR&$^1=uej)SB}43!?WZ&^PY`;I(8g>m)W~aZt6E!Hk{aD@JjOfd2D43 zdXfxAhwM92x7bzDKYFrnVUU^mp`Wo`{}R$VK$5qh`_4)A(!+ z^t6(P6iuR2bcm*(;D?L`@9)r4@DEYV?9QDOz9~VDq4n?! z$0|mYec!_v#FH%kj$#?zZKd|R(ap2^9$&tS{Y0yOmZlBj3vK0d32)Nq{}1r*Y`(5^ z%qCXBH-Nq!%h3H+Xw0>+K2`-C6QT2R@ZtMi-&~%pzZN@`MrYuUSzA=o(1w4};9`x2 zl6uzG!zYc^xE6w=mG)`ItG2q&?CoyN%U*T2^1JYLnRnXBOJDU@p#|E`%z;C?@-zO{d*y9Q*1G%z-f0Xuvkw&OwSL9U zmu^?&&jW_{qWx?6z{2jKov#cl6c&G2jcZ{W}dT_|XmG zgYnUIRJiByTx)ac0QZ;j`~B#F{B*^39+o&_dz$*dqshH$yuRO=z~2YFheQ9j%YRK# z^ViShX`TOw{mhY1RX$5|D8W9e&XSERPhI~2`R&=@`7wH{KGU2}DLdNwm>*>fqOF2+ zJ#MdkJM(pWmG%=gzdA24IpQ~HFZ;-N3N(wx*}zJ#YP+c)aJW>*qWve)DqO1Ns5{x= z*{rf zT*W5w`bBu7HAlQmcTWr-|E=Kzbu8q=`=_qIgZcH4(+Q1p4?f<6h}=@xv>*|L>*#|v zLj?Oe^zeLpK&{=^-1FT$lRUkhQ!JyL(nI)^x{uDtiW-kA!LRi%%e!ce#}?>{!9VFy zBRJFKk9PL6x_vwHOaLEHFRS<|&U(&WcGOK*G@7@ z2PX!DM+QR|+<}h3OJdn!`P$BMQ)~HW-pdAdq8nOA71t8ine&F;ralPWIs>=|oK~lY zR~z1RmW3aKUeP^+cfP&nhvIAHX9cVFK{g&<4!nnZ#qx4@kc)*2phGaim2$YWMtzpP zWgir$`*^E>j~bx!BluLm$-9lFFY5QN1m{ycyVcSED0s}gGIEWDr?|GN0WssDhHGks zjuRXm-{-xRueG0Pb<@c*T^Q?=f-{zZBn!U)S<`C--2A*MX@&C?|G&EFRG=FB`~{wn_@dZ25F4;s!xc(Zm;t6;SX$c zu$xL?>O2fK;!$8^&qPnYH{9+jPjh$wa0_tJv91O7FU-3$q4{_4_!W5N@BNI>v%8)3 z#oDcb;r)&t(XDac4Gy2XOd$(zo8%8D{+CT)?a7l!@au$;)lT}PoxKAMTv0!jahUkK zfD7B!jSnH4@;mUb7Voz6q#~c_Bu73lyCVrc=~=f~KYQDC+2^;RQ@Z>R<9!P~5nWl@ z;1im&36i(dk=?3kwX(AJPO1HT$7A_U_$s>t`t|FY`Fm5z-**-NF8!`k6YcSdb{Bj@ z>YG^mcgUW8;ZgHF!wKZr%shCw3Lh`)YeJUpBXeJScIwCAWg zyVtFq%y)9mA!>uKf`7KoQD+c`d}g|=2? zqq#N)K8j!6*wap)u{O#t&bM6Tc$Yge)O^r9lsrw&fLf#m=hL;iS`6h3US}Re>yTK} zb_;hV7!<0mz|*t^dHojtt3NNRmPxL^?!&^s>Sp1dyKIE6DoUX2*ms-Lnf${xpq>a|aI`H(RPlYpf=#qSH=@NUuyK{G& z^9d8M%j4L;b^bMHn4*jgpr0Z{1tzA1cc$?76d!ePMi>!g{ zxdhxt)dt5!WU^DOJ;Zcg?`mudFM{n zEy?h^@K)=P`n!sDZ_Yj{)Y#SEOZ1UJ2VaB^(eT?y`x^Et)(+7eQGZ%-FZ}a zIXn>Vb>RLYFu!py%CC!OL2ht(5ilBq_SMhlz2LtL{AYlFrWej(;2aX3=Wu=wm}X#} zDB{c;oWbDmj0nyX9nKcumjkbUzQ?nIZ;(AYe80na3ow%PHy9r|AM#@gJw@M&o6w0~rTJa$ zqU%ieudUoP*W;XRPUb3%&+&2TBHyO$B5un@Y>iz5E5cXcWncK9!>n6=T}ZKJX>VJ$ zUAf0e@ZPL>j4!%RopAIA4qmWh96!Vh58D^qv;QF6BYwT@3!kIAmz?3B$!8HWn|PW0 zg|{pCSotjXjw^oe#@}n^zHyCR@p9VjT}02|*0|h{?0i(7N!mzPhDje-M?B7*%5e`# znQzXW$Q%{SdU!|NIzCHZ>USqP)l3b7c#^~yop?v=`iq#4@*N*0*U$pbp_dxOxY4

7v>wQ>c6wI-G`};ZA@Zx$$2QFmaPOi`G`}Do$<~S|KK|^+ z2gwezbSA_fd#3#Q0Gjb*P0V3+(bl*%ADimvJg{}hMD7yTnTwsoQlhUCJxrj7@;{V6 z(6b7sL*nILWGQ@6TxS5QJf+65f5mrt?JMgX8-B<3H<;&|r&(mHIc)NJ)WS$lvD-6q ztkHbOArEf~btLi+#7o5h;;ZVY<&)RJ5B+?Kp8+zoaau(_37yyl6Q{KunWEN2bANdL zFFc1=jIScU5xH+AAES8l4aQ^?KOpV!!jd;{CKf5nf@zL(mz(pK&E zGS)L0vvNPW8&c2ylix+>O_HzS!wC-<*-!i?GJr5WFA zPQKDhja#&Q44i=*zxGo!{zZykCAYx>;(MWFO#N{S7YfwC2~g-^bn0fxoqX-{O8szmm|gjeaut zXA^_?Cq@rU-BQEf>a&b9Wa_V4<6vzFaz$Gxet3GLcp43!eg!f6*Bl9kFMdAL{ z;p~fk$!I(>n8jJC@+VSnjn+CJ;nDNRRy?)m^&ctdpXXDG9QJRJssB66-{gBI;5Uz3 z`{$c-{^12%7udviUG!ZH?KMBd`Y#)5*P*Tlx}Dzp^;&Yhjyds3r=QUAdGpRa zmtFo{ALGdu^dN>mV{4d1Z@LdzMfDawjPv?7mHDgw`;wRV_%UepeDQ5^&-bl2@XO5a z7<22S2(OQKypHw}rAPgv*S8!IX)~jbHlB{?d>Pw^?t8c>J+H!FPyagF@SW_6Qaf_O z0c$55J#UG>v!JcviQ;&?Eo$;S=q%a>-|s)tzP*pR=i3L&6UpEIyu;bCPVH6P#vbqc z!unAIb4xiRwLoJEZjBu$xd&_3e&qajk*C);&xcEl?JnM_hF%or`)|=>jUy^EPoKUw z$Gg9(PxK%H?8C6`<=WYc;ai!7Z)2Vj^gISH za^%x&DL5#2sN8BpK$V|1&m zeE8{|cYL~@ob!(EKRmGXtMJmte&8Z!8FVNnmd`*=!_{^d>rfOgy#?Lx1J`x5)!bHY zAeH7mKc14ix&As*jD4~?`8d!T~hz*`!>l@=MT_-^(&p)OZ#X%B0eckrJr_u z#`c-HY-9}1@)0%XbRtXDj>&hEPpbPX)UW#2IsIyQslMs&+uiuj0d{m3c2BV<^lwy7 zB}kol=N#lM-vR%!{#U;umM5ofYMJmmc<%N_isvvGzp1ao9&HcOL&Gn_1IbtZsr+ZP z6+fOwpY<#eY?H9aT$+w|)A^-N;Gsz{Jy&c07<+Vl{o(#=@ z0XRSJUYLu+hPmEznur};apcmwVoxZ>C-o*R1cC(CGPwrGDOeD z-wRI3S8>@HLB-+s97cTuG|QKb#(k>i+KFGOTqWaL69m=aHyO)%+G%gc<=?g|uSWi- zzBWfaVwSol^mG8@8;+jlpgkVkyJJ@@w?}%f*kmjHjbz-)RcZ_x-wt>o8bp`m^BewF zo<+aw`LFm}zuWm{>-D5hPmcdEuWR+ih5K;Ftde>gX(XKTgKv0EPsI{HCp4%^IkmGc2LNII9eg?b8o zo9%loWnqo%4F8g;-O-(;pJm|q8S*!J#u-)htLN%F$v3qY^1cTCrpRk1;V*XR z`g{A|d+f)dSNQVci z`j%{kr-l7t!_&kGhK_0Ac#!tX;LGi_c@o~KPn)N%tX7-$YS*UI-tjk)HsY^p(Kpc6 z)H%y-&OaobtSB2%;?}2c%%3}hpoLDn%6?Ja@<;Xpm(F0%c(@z#r-?t zbp`aw?(PS_=*B-c>yBh-zwcPQH}!SCk74&WxO01M5RRjb$zxD|#kW3g7CxD? z+dWzKjAsYozS*&{2ZjV4A9b{`UXP!>G#G5p4IGod5IRM3!2XG7c^gOs6qODAi;v#~{$GLDx)#lMv7T*g z!p=7^-&)Cy%*M`2f7{HyTV=0Y)MoNx_*uJU-^YWm5m@or_a}PeRgOogQDG-|J_p>- zS^v^~*!Pv#_xpcg_b}m0uf9a*W^!WCV(wVBbpHqEymYt6`^{NZ`H2e{KaTLm03THA zo_?3Fw4CSW95jA`)`eBFn$W6r3? zRX){tWEOkrOU!G#hRz4C@MsRiX)j#K?h_5K>lw59)LpQmTYc+q4`-d@H#$Z~Fz!-Lg}{Y}-W#?*~z9CYj2H?)2xR;b(N+P9UFb+rSA+ z;Z>UaR*vsAHzAKs)_&d1sJv_gb)l_-<80#Zc}E^?{7?DWEtx`F@TVy~{|0Yl|I)lW z7hGN+s)jgS2tHuOHVD4_5}wG%y%N4{hIYv}cWh11dzs6R+I3=M7wwXK8$M0H2f(Mb z-tWt)t$42X8O}u{JF5+x+P(&?>UE+p@xik7Clz2`1?ELyB#S6qm*5g77vOdR=V|>2 z*Z(VPLh6cCk{0~$<%4#$Nz?2V2fk?E!{9@`~O$+zTiR5 z-F{-+zN$3$17Sll+@p8ZaY0Aj0QR<1mv1?!`{R~!|wMG5? zz{qTPb=3z8dpO1Qr~9-}^Ii1JKoy)|McYJr^Hx%vtgHQTDEq_>KMGG4UUAvaz4uRgHHt zf)5(s>5NBf+)lg{nuwxYyNIXF*quz@=iq~?4|i)WYmPTPI@Id(BsPLI_k>pH-Lwl z`!pU#&$UNVx^Cp+v9J)Q5|79x=^om*e(wBL?6tS^%vW*sQ-22S|K0p=riU9$W-asdDMyXbc>dLj8qZY|VFCsSt`ncdD9 zghM$3y^HfsaLLXyjht@dz3}(aV`{dIEZrKQwM6;Dp8_Wu|3rV%+e?0K^&$NW`?Hi! z@_p0H-7@BGo8!}K%A3JI;ZZ$i9KDJSuM~yb<>5Nd3C95^ z7{Q8tx+2PRXlsMY(j`HY3hM$Gg8i5C-^eHz2u=fBgGa~@JF;!g!3i74?H+Ki1;48-FgH2$j@JOi_YVz{#N*Gd|td) zS~m1`=!LI^@6Vg~9C^qO8xN1y{*Cie2`*Sw!hBl|wsx7wsGA-^*b=dR8h2$w2eN=Uuy9&h_!1 z**+O#{XNKEzN^n`{sO%?p`f!Bz82H0#X7%Yc*Omap&Pr}Dt{$ zag^*ZIl4mrTRP!u7FPTGH*2fxSPnf!(0t0)MvE&V~ABuLJmz z4bCTiq;USCn15ruLzMsYHbyiXJB5F5Wj`^z#?h-iSq}%yc02AMtl}EmsM?0wJ+f>ONnY!EcMD$+s z!rCjlXQjDu6?!LIm6m^x-uw=I>cqeI^F#Kcz@LcCYL=g3>TB#=m!3HK*N7)w_}+HR zW#KSKzwTN$_7?tsfqqNunr(-lZQ7;cq1H?BMl^^&;%6Pcf3zRZSLG8#{|n&tHtyLX zPYv#NPg779{uOxPR@@N9*WzK)vGDf}<`H1Tw=}%B^P!lNMhDF~U#$rJ@OK?~-?hX{Pq3EKcl~Pi1&r;9=v_@=EjU>3qI7n##+$Ksmxur1=(J}S zjBQ$zcDmW_;S%Mc@{EFYvoVd%}f%5#_FW(D?>< zzmN5xd|T?RBxe8! z&wcL;!nf$_JlYeKv2SrKdEDbT*B`I`x|_3s;&AZj9QP_;BVmfZhp_wrir}~>WF9lwya{or>Un>ZclxFl`*KV zdl*x+|4+HTQ|}xY_fh(42N&|pW4G-5#m_c+$z6q6`X7!wMWb?1%z;g((&qc8rh05H zxHA7Xe0&Hyq8vRw;F=h6R8Fvs+;I|lDnF4tBG|0lpk0rP`;9x#)R~c3{;TMU=B4@x z_8-_R-0DMXhMs$Uldjcie?fjz!q$3=Uy9>P;krB=-%HgvUItEnV<}u+!r{wVxEFv^ zjHB^B$xrH0@{m7m;H0&mXn z2|sr)ie};e4)9+G?yu;&{yqzNS-V@LD?Zwf!P1piA5JFs(bm(i_{`F8Wh;DZfxR1; zhwv9wPbz(uE)PYn`&Vo(tk?1@b^_G3 z%2>A^;Abn}PS$>j@M>Ody(j3#G?$3BbhOw_k>bLR#Zkv{pV60b71=U2i41`z0M8ekb2GudaQ6fZsbH|224`eKnxRH6i!!GLFoNx>vCe+hM&I_*3aR>a`dxGmzgZWv< z-$w>BhlBIigX~?Qnuo=CJ-oW@s^YwErVd>>cI&ThE7TEONZ+5OKhc{}Ufa$eOS8*Y z$DrBgBXs|y#(h7we->j8@bx@T@5hd8K|f39?Jo9z3=iB~`7?cLz6$Pr{C*w%@1pOA zjBeX8Yy4gO?dQWw@#Cwthhy>BI}~4_?YA5r4`|xi|x#I3ip}zp4rG@7n#lZu?HYi{`5G zYTkyFqx+IaY5s*czCJyd^ET*d-}?fbg&1{i$ei97P@8}8GtBG$_;0K~KDYc_+0o%H za%P?2Qm#byHc5^C0>+Z#J7?za)R6E^+NS3Y;Qpszli=Ekr`5*1&sK!oJ|{ok-0{8_ znfY^WjB}%4TIi!TI2xNj*yJgcgQ%yCeAH(cv+uhOyh&>Q)8H1&RKYMew4bQ>i#fDg zxv}6{)wRbq;6QF%g08#RZ=CvS=Z?=+j4PR{H1qmwaOm${JkNTXgQ4N+hGt(!T&#b= zHglc<8!=}}&nkFp`8O0kj(jeFrf589-gOTx?6Xjdw0rkLgP|e2hbowy+>79{B23l%U+*6nuUV!^g;IuE$i_Z&-d>&T9=N9r9s~A@@ zuzRrooA&y<%jGwWZm>W5OP(t~Y4xJW=Q)gd^pfOR(i_QHG#WhY zOFs@C@!!|YiD$`sYo()`623iog)BVotNp_z?M?sOGuNyC!w=nF{^mjbuPf=_)+g)cLmrC@9+|Hre4=ZWU_}3)=R6;*->Y>{A@2mZ5 zCGCm34%Pk*`2@Y^&zj^rCGCkp57qvalJUz&VeEmbU zSH3Mu|6KU@cx7GBh3Idm)8Adk9=iR*CGCAaPy6FJw=YioYQBAS4eOoqy$SQ&*xG#5 z)@nUwecGWq$zNlytAMxhg!#sV;+!?@+*47@{(dr5W!9lD(!cDm)_AoKTs^4tbS3S{ z>Gi62)mXLG_?W*OKR0LgiHiB)nL3YdVhU(wk5F~6%w5yJ;)lx1#@%^lXH|F=bj-$w zRUJ4vvivG|b|&jo8XD601l&tz>czFMLce|HvD>lDK8M{2%xuP^x<^l^_{kUw_c?0M z5B|+Oo_<)L^I7^*zF{vs@N1U%K+Pnv`N7Y-ini2@$MBM|Orqbu;5!XJi+5>MOta@z zzWlVQ6*ReyX3;|b0sCs628~yIJ`f-LOsqU-zOCTz#g~sUgEd{cz*@gXcZUV1)!%IH z4jXCj4pTn9d05b~c^5UtO~K73=6N*;52G)&v1gXKtH<0a#`nOWKWFMjhUOI?ntSKT zE3M}2l$Txn!{|=p9QJkWof!jYqa0c5$l`s3)EI2GYpOfH8Xs)#Afta*k1;g=3}cUR z_oeC?pQ7e+=o7hm-4*dC#kY8{|my;d%gl+!dLcqhgN6Op0D;h#Ge#j zffZj5{M7Qb2AS!c@;|MwM;^@Ak6XTO^!jS}nkx$zM)*2E%2&=pdcL;IakO&JgY@W{ zKKL3OLSKvb;|js6X*?wafRPS||dE6}L1X%9kt^8B^%*nxRo7B=tpJn&xtUivyiymf0s zVDkQ{o=(;vC@kz31Ey>h3(>Nj^z=GFw+-?>rxQ>-RRipFUE`D^pLZx}Y3+w;Xal zADf=#PM80iyUg+TH)_u-lRCoOWj+wzDBfdC_2kz+s64dlNqk=JF?@r=(INPq*LiKv z7xBZc5r>B>p;v7Z;4phB)GRl!-kaKB=3QU+v`6uD5i=TGiNnK%;1V9yN=VM@=>Jt{ zRR8UL^`9LS&WiN!_2Y}Q`wi`^UsUP$K(&@{+(n#aX+I*o%=IVwl?#w8e)N>`rVkhH zk@ah^=G|8A#!E|{jU(qGYKhtEA4N+j%;*KGV|2D-^e(&UKrc=7UP%yGzj<{_d6;t zLI3r-`&#!d8@^u};d_N&pMPRH<4T< zd!j3j2*xRwJc4gNsb>G?0m0=pBU7K}Jn;@{x$9fWBTm?R+q3@r8PAQP_9i}JK^gif z9A($uux}Lkpln;J=h&-n-S<5H*A>iR?OFJ{$z{)(@8-^fq`70|*!*emPjj=AdGyr* z+~FP{_G*%v2i0y1@6Pyf)%OAORcfi3YnO}9hR5t@@XVaWQoc}kOh`YYe9d^ib{-ji z7e0zVUvY5XYnr^_9)4FpUJfr)Tdh1`o%UOezh%ES@(t;(Z+B9vNBO)LnfqhmqrFe@ zINA-%NBi#5o~dwjA06K3`i|0mlf$4=#XTTv^zehXylvl!& zfS*yE8Qw`&%GqvaT{3s9E4Sa&Z^Ii;+VyPz3R{n9@@43UeDP*8kNRy$XdW?lz{~d_ zu!~)>3G!#p;I92SUrdc%8}wW78FK5ZgMNoMAm`P@8=4!+PktENti6sc*vIUkA0B%Z z^Lj$nIpLeNm0|gse#f2j%Q^dW=YBx$?*MurndjJ(o7+Fz0pF=#;T#V0QF-e!bVK?P z+%$LJW6-TL^qQ01e4n@hc)zQ_HEphclJ!M% z!sLyam-c);duixabD6b?F}H7T_tNZHbIDV+mDnfZ{h?un4=6;{b<7?4= zn6Vu;zZrllI$rI&8M!EjjI5Rw^uWeO?9G_GWQ_Vo>B67rC&9kFVyesOk9B#x^h~j; zkCDuHfYTi{3F`Jn^84HZZ58#u|P{{z?rZ9L8USKPm0Rkb~vFCW6ia@!Tl zX&o^>+mAR~i0(`0H+Lys9Gd?s{2B+3K8gPSR{BrP$nDbo`XG!W``O^kP~X(dPr$l66L7S&p-!klapW_vGSAWjYei(akz2W*-*Nyh_ z9ueN|;LKX{qsUs*t5)k*h4sew*HY!>a%8y7;qY}R4>C9RT3Yj}&5HIP_cUfJ!?~`V z)|%gL)B60~4Y7nh_o-aNRh%7DE=Bx(5&kCNYaRBboi#?a6Q86FXH<;tN$;ea@`J9X z?;LBE)>qxVCp-2qHsuQDnC5$H*>T}7n0w?YHp%WBgAA_b-Gr9&!Vy)+g+tu_rTi0f z*2~>lB)$1IeM%;s#1r~^Ib)Taz%^cYg}+m{*%OHcsR<3-@7ciJIj#E-jPtt5o?_nL zgCrbZbvT<@vpxpCpCQ+F#-RSIm{a0;QngN+2X1e1IJ}cRLVqgtliX3gaP1dQsA+hc zpR((kbFu|*!awEr+gRszI-7+*vspPPyHEIdVV_X=G{???mS#sshJ7V3#{woPy8Yhonlb0sAP=n-S?afyqfT{S(h<{LHzVTL|AD!s_^_LM zvs2wicI*ds67)+}y2lUw%@4pn`mt1<%^n%Nwz4=b+{{?eOY^OF-9M@R^|$gr8sneA zXY_-uqiS_ z$Dwb%qtD~$qMgN&2z{M*S4|(Z;|mONxINBYeZggqH~E87n$^EzhJbN++Wfx#+0eBT zx~%=GtoF3Ezz0j4J!iQGxE6G5|BC#Ec4D3A8mSydWv)DA9-2C1#Z%I&a_srKZ`n1| z)Th8R>d1^f{O!luXU*%Z(cE~MHYZ1TndP15XWd1PpTVebt!t;4VT5Q!KKoZZ zVB*)eS=+9`zKLHtx7pB64wsEN;W+es8NRdR=I4(1^smUEhO>CViMjd)&J9vy*Rk5tk3BlZ*o0lIH$MLT z1MuDk1lW?IOh)8C!Z_e@^$z58WWMzi2To^_^=&TRwL-Q zBL5b4GJ*f!&HAc&|6FaqP&Q!|{+0S!N%UG-}bNgWnsPaw!*j59QrGA`vkK7HZ+vZo32M) z|LM`jryWiIvgscOe!bz1zH3^XXS#d0?lIRUJI1t8yr()`=>_(zI43<^=lcxY5y0uZ zs$}lhSLr|te8nEC_VX?61EtA};#*Bo~L;`1tC_(o>F3%ISUAFpFay}k2w6v^{~iZcF9BzDud{5Lfvmsx|T zr6S&#b$oDr4L`Fy^X-(UEy>Rs-@Z_T%>E4aWyjC(8^uel3s*8XzS!U9XMK)WdD_k7 z_LQsD{7IqXJ_jBvV=m=R48H*nv-t3t=dgt`3(1r+m4`t2-m2`sv##Z{Ec>P0iX7j1A||F2OV3PVuJr z`}`Bu?!muJALuE559ptg6Z$7PHGsbv`=va((i%) zt64*&pS8Ku!&oA_qlxvz$3-h>qj|6yTq$Az)iwzx*g{;%Gy1Adk+V=dqA{}exmu`V zo&6iEd!q9^bVWX7-O_@MH1e?e{K0S|d=ehv5H7`7-bR`E0G^Y;;o?ErZmUCPYG%8mQjyHTBV7Q6g9KCHb5)ZPC% z&z@7!y`TDyobGP+-?#7UJCna*toTWrbho%<;e9Xh+++Bdpr! z$0Z}yk5=OO?s%elVk+_KAd@Sq$iK}y$tZyT=8my>#av}G_Y&wXp*P5B?i(rHe9HJT zl79p3s8y`i?-$db){-py7~-#38w|0eK~%US#``s5qEXwJFB^3vZ=m1jF-gFcDhLp;1&eryK&Q$y^% zni%@=o968sOA$ICa&7V-s9`6ojMb+55He`dFf1#&0Dhf_@>p*ty82!mHFk+_Eqd^2RW82j%M$L zdig9mCf`BdZ`8d)`tIoc(AwG0evb;>t8RO<7$4OPE5=9r$Q`{yj%ojj-xmC1=--j8 z>NkP>3w<7+A3>i{{A<9?e5%$NTaC}#!PS<6FCJ;%J0QoQwfZ{l1ygM`a@(Fj2a@P)Kz{RWc=(kWK{$f(AHzGH zp=xDsWPr;r3eTJPz9Xu125R_%BZzNW$N_sBAo-mC_<=9o-mW`Lj?Gt*pVYlmHcwoc zUw`dQ`##Hi=~fQE&gySvevovAeB;INRrz)0$EWc7-SAyDQ2Q3jO-RqWPLYpbbL(Za zdjXz#{&#u4rq3$yl?y?>w9@f4cVp1;LH@qU;aztl-^K=CEBkelgZlY1@BO}nYVKpq zi&clGIwXTx@UUik^Rdl*oBJNd5!H#qY4;ssE$M~!q$I~|)#M4?e5dIv?(ecej~tuI z#*UL*be@K>71mOd57$`)XFo*GPaMumU3<}R4E;(DI%^{tN>|PkPwDSKU5t1jwqbuA zxqkeSfLycolFivz<&}A+dG;uG^3Nfkw{}{;>-7y6;mA~H>(46Z3@&y>YgvN)uyR;t z?Yl#EhI~HsXkRKjXy2J>Y7YZ)gRz15nJzatm9rlc(XTV0eJAp5_jmTM`1%IP-urJe@QJkM$R|*&tb5OD(#s}jUyE<+O<*6Sr}b&O?&JoyA-*?Cdssst1TN{m>P__XX?{vx`aMRwZRUB;4^&9i{9twwIqbwBgUyl6-x9RRMpsK1r^(gWJbXf}ca2s=H-G zBYIZsqca}9*Yy#FudD0>HW3ep6zH*MVtjlZXn&rZ8@itt|9osMKVv*~%gV!7Jw|Qa zg=J^QiHY@G&*Xo+m*@DkYs%20O!}x$cizT;(Yvo>J0zRcjEy;D_WQ>(4?C%I)AJpA zu9%wmOfjsFfqRdUobxSqJTJok1bquuZ9IJY&ArCE-OKbj2k+t3=fBXW$KP_RlRq`2 z%AM$a7=6FO+qizA@~^u8;bm->v1|DJ*tIpf$7eM5i*MMPef>6kZMc5uoal)!DzcsT6BY6qu0(EcuC2Q~$qX&NdAUGmeI+p2xr02P}Gi zwSz6zW#l*beFncK5vQ+_{b)gcrY_@K#XTmi4YL1dBCEa3jRtai+V@CP*Dc-GndqBF z9TqAFx%|;1!!wc5b1%Lpj2*6f2jcml!hZMUN_ZtdPH~_4J`%j}`ylu8j+~X*3k~oY zG|?Z9q-g|*1XiR@>%J*naOuh2%mqWpRJ8FsHj-xuSK1Lhj@c)W6?s?#$u{kMuS zeXCm^-(y#94E z2W7`(TO|+4S#sO+Xy3Lf4ewVl?=}BF44o-wt4>#+SCo<;Ubsb*jM~92t zxV@f5;I?Nx9QruN!M%L2o!VXH;izlbH7Nj)`@{ieO>g!Ca`FAMuT zPPHKHeVV)lKOrD{Y&>I-WrUp#otS&`cc!Bn!xwY7c2y4z&qbg{#MlwiZYa3jLfkKN%%0z zjnDgW@@HE1+4}Xm&O@}repi;X^YcW!AWyz&G;4euKiI~u-0Knq6IyPKAJ@VfwwIVt z`uIKgl4ZPt=dKd+Bo$^(y%#=ft-lj~bOIld;qIy*IazlP4)>y;icPZcGmSi6pxs*V zDK1m&DLwJFW!Dc~JI-zk-%GR=oZ3T+yDz_Zu2=nkL;V}SqB5TVUUst6&Ruh_u$7Z- zlL5c*3ZLuK&P90qW7?MX5jff}qz`OVKJ$2y*D+*cWJC_~yN=G%_M&eAb|wBqp+7q} zv$pP5bbQ0Lm0c73EZ{vqx@c$nuyvn;U+duYE!o1oRL&`LeTBU)eHW!|^{#LIMOxCGi0jG?c2zw5^i4!xc0;QE^PagVRNBK)X>)4VUWH&q^v zd|SPPQw&xLSGUdccvyImgZmM1k36Craj@wgVu|8Bb#<-ivHTjXGZo}=H79<^JUNsf zul+>PQL#wA6Z~`6tcPaG01JpD2cHY~@*& z+K*e{g?tayZEV3u@;;UPk5_p|J)HL2j1TiW@X3dHjJ372X5(65z3-Dl=d2&2nvKf* zXVLpk{22W{N^3DTMZe!Kd(N2Kca+Yd1=^F=! z;XC&mJmuONea2sEa6UP4cd@32^A_G`lHMri_%^iF(uaJam*OLQ4XcUG+P8cBBf`xN zzt-te|EA8b$Z2xMfzwJ-=r62DNzwB`Nbt2On zu3+o#E`e+54QF*TeSE0+&FY)|M%973lb#{3ZN7O?QV+4_4RV-1&qE%R`T}x0^ZFS* z>O^mRPIMIcQQ4q%*l2TRroDeyhR=q+)o;mI|NBb#u=PVhM;Un{J(r$c&a-HYFF$?L zrPMB-6!hHE$va@>^J&c${BoWNW*6<`AKM(ibZvP4le|-X&?sQ-KGlePTTA~5tASM> zNbTQ)jCB@7F=y#I75|x&b9$s%r_O;-f>Yi}`h?zAx6PYe(5dFgdBiuUrGt+qcd8m_ z^m7gNV0-(s4rizR-h*(B2JfGcxrZ^jn?54!`ni?AV2*Qri&oW3OMg6km&cj2b$Eh5 z%E3Pu!Q1kj>pOc~s5>+z7s)FNpR7LS3;Rmr+_?_zaYk*$8SGUmzjot`T0`?^GWNsh=ebdd@HO}^8!DTocP4hCuGz;< zR|DtmM>lcM=3cgFX#NS_yLf6NI5zejPYumq2%P)`*|c0Co>DGwcz%Ih>rJd$?&2!t z>Pq9PW*1jQ?St%;UJhUSr9_x?y9AGBjtTxH~6h^x|xF!L)b-*v8? z`j5s{&(l76Q2UDNy60V=sicXkBJ^zUD!dyN-VI*i6ivdbIxxjll3yI&>|!62J9hE) z?7fv2yL{S+x2=A8KQh2JX$_QL{T}EET>Nwa^x^CEikYNGRlhFSEi-1L&zD-1)qj`2pX2}xpjA=S&%$#!) z%NH$NoLP_%aN@e<%NlP=%x##zuyM}GiKUHA%NH&?e+<7iEnC{Sbm{qHnoc>)w==B- z8hLw|=xYGeg$tKAU8_I%&-K&PxGb^k+NF&Rb7n1SxUTWU0@&C>hfC(qp*OmSwwr0% zM8U6LK7ZNCi2|_4zpP=|@}|Um{w{+O_V?2xzn@`#FA!kK4dyLeJiB4xtc8s?G;(aa(9b-^9eq{kBf?&b z>g2@orp5%cFK>*n!SgSQgV$!D3l}!dYd`@1Nc+Ng{TL(t7sTsPNd}FJ8fGtSoP0y$ zqGeHeXgmyY(XvF-jq{gfuKll$CxZT;8cuM@;zf-S{z`8%ix(|hx_Dt?&f*&vC6+Bt z7#W;@RZaaRQ!km~$7FsQ-9wL0PN?0&#Z66WJZJv0`HL5wlR(sqm(E(W{JQhUEI&DM zW5d!#g+Jymn!C90$DGF5%jdbjyt;Zh9h#o0mt1)1e*-aYK4ca)HY_!x^xU!X`fs4X zsEg-^=6#eWPHPHMnp|IhY5ji(QI0QBT9z*J;<<@A4L27?)~9WW%wM%*EooS2TYKwt$Y#Nq)5gvDz?jockNn>``qTX1 zDPvAMW8ob8|5gnPdbr5&crI4nkm);mHy)eu)y$}ye95F)Gp1cSW!7c&Q!kl0Yv!f1 zX3U&)=@q2Q`0s#yYD1ZmOQHttm5Hrp5LHs^c{{>)SOEfH+V`xO!u#RPt zIg2fso0yA#P%wKQZy)p-6RYJgLS129T)d=lQKIQumZgHK_~}=WeRTZt91>Q`6LXg? zzOK)6;4N?772LxwX;{kY>l!!@hylzpeh;(C5=RFPe}=`QG0}wY1VgbxW4rEFt=_^ffUe^fcboaNYbxjYdoGITy|2SK(R2Om4_%JuP55h$|;MK|-N0 z+W)4B4VNrlHh=ETS2f^RG%mHz9i1XA>OUR~eh5d>uy@uXgIE~HG@Ux8$^10_Z)Wk5 zn-fbK;9z9nhIM_A?VQoR`j%H}2IJ^$m@@|t!i=MUxwkHzocKr3d3`hb>=D8$mWzLY z;MvQU8SiNRqUC!|r#m!asere;p`AvkCiMflHE-;At_E)^x zc)Ue^h!yfpi>lm6nJ(_3SwJs*nj#A&n9zvxoR%UK4Qf-_!57Z@*R_#(|~Shft^bql?b^705O#PDwL za~f}$pJ|**x}u~}asEmVeLqg_#FWc!USgeeFqq~C$=kIvs}}PPpBpEv5Q#G&L#2)U zP2=8lM%$U+4{C9!Av9%zW)jv4}s72`(Hum z=qp)w3l3XBeh!Wo|HvLlp;;-tWaSeJl@M?|vPl}Je3FN6>G`&J`7)DGbRY)_q7=?7 zf=d=RnOuEh$zrpq<$D9UgLmlArRz-mvS@Ll>E`QZFJ5@!`MvUKeZWO1DdK}Ki!5Uz zuM2L>p^_v;{c!thTD2n%LeVd{ri2d%DO#y~92pia;tce)SEu>o`RMYuhK)E^3r)@= zqR@T78IV47PtOaMV7U|QDNH=|cZvwqPi>j#CsshuPradGso9srr#)3L#SKc|L|~=# zUb~nHI%ob;g000Q$BP7)&|3uQgW$r;BGrd7XTE=vC-rRdY!>s32YK)`^6jFmbvu#r z^DMvZ4yqZZhwq~wW%bmPmrwzX>)tZlrN=xTlTS6mEg{y4$HNuoc`rR8wd)*r-};c6 z?fA~T>V=_Uu95-Et|j2~)9qvj;dd!4C9Zw1#z@uVANy)ifG1zktI^+~)U`8yw`!{)OKR@sf{AI4Ic zhf)45B;)gUP2U(LSNX3O9X1@F1g6em7jldWJ7wG!XSAY! zJAhM{UAF|AmRTTR{_ADeiZvIdXo9Hu>jTVpe@J{K-InZwB??<$k$o^jUojCh{}!JI zN<@|-Zy%72Tj>7o{+MYp^^z-VrcIp`OqyJK#T0td_O?27VhfC0$lpo>==se0nmTQT zU3wYYO#C!EWc<{|8b5-mlO|7^B60oqWlZsh7C@v`JT9 zcA1{nUvbIIsnaJ1bp|_dlj`(1m{fnI`8j=3-Gx`on0o0Y=C2^&?`fCT)y(uy`1`WS z^>vdkb58_6W4eK>yL9^WXgmIxI`h(ciwL;d8CP8-qlPs-38Me+{{UK02ey`PM0wF zZ+fl!>7GxW4w3vfRY>@6N&#Mct_kXDrcc&|OLia9%204KCr>sbnL5L^n=#dmOU&lK zNi*!j-+V^{A&fLBCvMaf7^7N1QbJt$ZopaBeIdkUBnKS3kT?KoCE#iP>)(BSi+aibB zgjmn}v~|*9I~kDiQxpo(2qAVzS@#dnldP6jJPx*Whl0igI{MRwO%ona>*Ok0R8QtC z;k)X;(z9jXxS|_YdO?t3>nKs;Kw#$l7wZe+$TWea;k4KpPt)pgDphOI_o;dmoX*ol zqCMithE8Ki>1`!~trXyH4fX|5kMnZX^gxut<-?(F!$w-kMYqsL^P>ccpAl~&cV~KN zV^X=1zmm;h4kC9)7NzJa4S7g_VNqxi1u=kf6GRma`lVRhn1E3HNgh8P5LWV-YG^`yehUgeK60o`w4Dy<~yTTy#N;m9=>IXf?d=WIHQQ+dloffRDIYAg4Jf=bi$b0TR=MO9?K*%2H2Mpd%TY37$9A+?!KrCSuG z5gi&Lm$Fi^*_<@mkQ-wf7nv!@Aivmwx7@H7%m@4oq=Tz zG=eYGcPPSvRD(K44s~+m0ajNB5q&=0|hQp zrE1UgTmwXYmH2QOT1Gxt(SszQNHT2Gb-E_J?9tfSRcTo4(>DdVq&Ss!3QWw-B#m= z6Trsv0en8f5)+W%+&&V*M}++$Z|ORG)YTbCA1;vA$1P-{=VT+Q3ab|DpAz`~`|tl4 zatJN;jn&V$VAEbxxu>P-05-MH?mw^>Cwjdtps>gh#8KI_9I|1Pp5%cMA+K6aOhTsl z)nQ7BzRAOmu3#T>c2I*-$W8RN(gauz;m-p8xL6IX?Z13G(kn|%1l$k$E>XDWa>-h3{G!=_bRWho>e!Sjfa0D#BetykJFNMrhOYeus zhhi{pCYG{O8c$KD9e-n;L7e7*^Wa9Q3oK8XPM$EaP^o-M3!TwcR#|tj(bq!BFFK3P ze1!Y9o-fZ{YJIWCpbX7WuZlBhDbxz%A^XBkFCPvdQz=lWSo2pG*YqR^3|;|-A~w)2p2`T(SWU>G_aM6GV`O`bQnWCT9KwL zRs0^}f?yw>^+6JPoZAwJ9x=uRJTI|=n&%~y7d^6vULv)u=`4?-Li!o6L9d319t}!U zF)$>@LdW6K{!~~3y-P)m#nBVmLZt5-@m-Vk0Z69!@6tAsI~CAP3ten^J5!pi;Fs)pj})AxD}BYzX6?%!hA_Ht~^a&X)X zLFt}u#8#`(^(f^?zk-m>Zm4~tvW%L}2QO~Xc?=O&s=+Wd%JR{BFnqKCaiZd?YUo{8 zqpkBN${5Af*+`jxG)QkvzjwZ54~m-Q%G?6;mvYF(7P=7A)vyv|lpConinP<~1yLFJ z$#q}GLO2sHFH}TprBl*nTj9f@!+1f2m~4rO^ER1&AHck?Gx={-xs9AHKHPq|2k+bQ zJ>=64NBtOWDT`?yWTX=h*7=2zX#7C1!z)(nMp|wwIrNgP-K0Id`C@p7Lo|Ft`4qiD z0H&9I*4iOn+%xp+hV%yZ8rDG373jzxYlFq&Esd}o3W5L6tf&4+Xlo!E!fMolOZf=F z*k5@s<8YY9%|d4s_eON>N_`phA;#IlSEn~NVA8jxLI!m!d8EEG(;L|<`bs2w#p90< zd<5Kxi-aKq!L={YRw?!bmEswKv@|2$D_3xFL*g6d0*oXzz1BlF%y@d+)5xb$#0)F> zOMF)TZn0t;+I3Ubqdo=`lI>L?3=~B!A0YQ;xbF@GQ1XbEER6D02jdy>jlno~?SNX` zWi{fDN)5c_s*#8Fa8JsCTa~;{F+HprdIg^Ox$y!G-IDl57``NwW!eMC@_VrVm^``5 zUIv*ae?WhHrp8;?A7!phiwv4zdqZf9wL%%NJcDNPS5g}LudM-F1GWZi4g91uAVa%) ze;++{X~Z6c8UH8zKC%e$9`Vu!+&=qrJZzUKRUp+&ak#CkKraFKDv;{*c_Y>g^IeLhr1DoH+V+*p^N-U~kIfaqVE8#t}P&XcQ zlA3NeA$|^yvET zdck6qdQI_*XX)Q*y78}B=={_;sQD(&DH+GYGF~P+K6eFjJu@p&2G7p*4SqrBNVKDR zuj^;!wpQ6`Hv5;4U!|?-zjpCb+P$j!>bQ?GQ~4_!N&sDny1UC(FKZ2Yr2m+hS7j|U zbjrTy_hrQ6{!Ta@!{Zh7`9|}d{4##VL(DB2ag)A`;#$Xt-c2%&pA4iPgFFxPl3+|v z{5i&2DOjdiPyT~=P~YgYk`I~23Q=Vn;;A1z;SC0w`H3fSv|zGuWGwP!;*2j{tr#z5 z&#~Uabv+$*s3hhEU5KAJ?L90`M5Q(46)9Ou@RjZ#i6RV^eeRDPdvQOld~X(Y7+nxT z?DrIRunH|r@!XXC*5mJe9CoU4<+{e0^(UnPVLmr+=f~EFshyj|PcwHal??k&|@1Ta$&_|9-t>bT$hp0t6Mwv3mt<&9TeN+a-^_6@k zMXG@|oa3;*-|WJ#4|me<2nOXEXby~UuJ}F10rDIp9!&}*t^lXKx)J=A+C&XhM&wbXGUj0`m8?ewXR?BGw_X zZVM4jCxFD#twId$&rRsXiYlrY#yibkOa`TN!QPrzvD%?LlVmVND_>nBCf-<|rAOhJ zowjoloH7_FflqBO{3irp+^ica-U=!9gahtkGChWTZt z6O$UsDAUcu$~V?Sr^(b0j|s*&sV;uO+SD&YT!gjnKcz%DqvgW+SPxvf_&g93;h>Vo z%>TWGUd%`MJ#&4MZ$-$ZyoTj~kuHzmqmN&Dq0cmuhLDX_%i|#Gr|YgXl+1KuGFeT) z+COD4Y4#baS?qynGg*%8_)X|nSP;`QUyglXV){-;-qH6Qnfw7)Ua1_2ltDikda2XV zxLfp+kzDar^Mn+_FTWXQlg?Mst;n!g^z~x22ftXreWv&4;FPTz5CJwCtP1-(^c|pu z537X4O3QC>V@iI5om0xtOs_m;7H=jdqHO3fRHj{--d_vf_dWr+AC~$g*NO=!e@4+T zb#AbJS?8h3k6K--f!hjyWw8sz0(mEFdZezh`^DbF7UdcTBds@OC)D8;wqnq)qT_K^ zV`uc{WF}ZM*g`VfhpM--DGR;PE=6*g1mvHW6rHBC^HRRY9tgk{8^)1NpS#|x1z784 z9Qhl#Uaqf?w`iQEz)eQlaZm1tieb@iytLwb?RskQaZPjm#`V#6+pkoylI4`AOnucwXy4g!t? zmcD_00G0tR0}g!adg@RS`t$AUsk4CnfHQzI-?^SDyA^x@y@36Hay=CXoB})r*gOON z(B~LnCt$;0Tu&_kjsq6n4!v9eJ>V4JIN-zr`T;oh=Jiy0G32>;J=G7`f9ZN^8ZdJC zda7sx;9J*I0l>w#!4Gf=@EyYc)%Db-JJ3(SLj^k^e6A1?U1C0Brst`b|GZ@vmt2UQH_k+yprBZ=eJ8{X51Fa0ajtKUUFv4SWFy zQW*dDW1O{AssgaYkxKOgE&}4;cGfC#QmF;NWDUcmCzsZ@l@fTsxNr&4A3$DdjYQmHY($--31g_oVi*MdL2^t3LO zN&uDujsrFTo(1d!qqVlha3-}-QrZL4=}kQm6`x7yCapl3^)Ur{~+4GGnFa_Tm?;!@myANmhC2G|TZ0T>3H0_+DY`amjm4KQ+lDiwGb{oREA z0*(V-2Alv~0-OZQe+2CVZU!uRAeCwWEC-AOwgM&rI{{w<9DES^q5BU(ACIEnrJy7D zFvbVa2e<&(0Qe4I1W?}X3#gCw$k3-%H=m)Ub4SNENcwh&+&_BSPfc=0zz(^&=5is8ixdE2}mjMU&K#nIM zcNOdv&{Yk20LOf=8^F$*R4T6=`mV+N0i3Q+r534t0Q!3puo3Ni5bXgT0vrR3P`L^6 z0A2x{0dyUNo&j3{OFjfTz}_z*%xDPma1pX3m8gLx2 zwGZR72l4`z0QLiJ1{?&e0L*_0c0+i;S-|q2f_+y(uAhco0!{;t1D5?a$W;ybkD*<_ zflq^v5Au8l{R12TOaP7njsso+oB_=LEa(9{0gGxdPXHSLU7rITVCm;U2Ur1k6>tG? zQ!V=Y3dRj^>E|IA;LI<;t^s|&h<5j4JOCR27XjmdlfMMJ11uRrJ9Xd-xCw9)FaS6> zjD8Y+1pXAzmBjefL;e#OU%*npHvr237XX(5%l2X1@F|i&bG&pw%jYv_+G`g0yvig7w&Zprwh)kp>~E>kF4?x9Nq>D*|0{^s zWuMBt!f*=jb$Nzz5{@QR;Nj>}mu_bh>P?{D&n zJPrCeuInCg9GtIKWuhXY;T)>-oI=CS!8bn_c7lD;HOY6v;XYk-W<9F(J3OaWd6H{J z3n~+9ht|1I+;TkMJK`KJtUkFqHVe(pxfd?DFTUx%zTTZS%wTc*q&d<)xUs!na;w8^Y5}HGUkmJyAA}*G4j2Yx`Qw{HMVcm$cecm(T ztedaV`|5W3fGC*vIP2+_rn$iDGI%XvFGu5rF;erUmZys*>^M);3bCIXmo#GjVs2Cp zV;ye23Od?rCM8`N4Ij;4jQ5CRI0qwNg;6+P`Sx2>qgo&4 z5r?2W@0p+T%6ph^;PEc_^;5f~^9&bw z63(H*Zj3WV`0^z;F{Az%|Cr;8Uwuw{B;Rezjlsm89nx)ZLAJG`c80t@wKt zxH90HrHs1%hI71$+@ZXuXU}^{OmxcQtd7x4rJUPRr z3+_u7J#^DOx<&ZjaqvI&RpbFguVkBNfg1;|PWqs+HI=6mjx$5j2Ytbj_$5d6@StPl z7ahl6alC}7qS|#k-AOpTUvSi%_&G=H!oo!^x>0mrtX;T(Hb|EnZ$V6r9E8#(jdvMv zuK>sMrQ&q{nOi)touSo@`iQs_tM<)$600_Wz7_O&zXv~wYx7uQ)#CN>b=(>N-A2$Q zF;?VHG4Jmz)HBYR4 zHr+s_`Hs|4MZTt8Lq3M)6@94BO~92QC-WL1*nWkMa_V&*d2#Dy&<&h`%^2ulGVnbg zW#5DTOY0YY2Q!;Jk@8J)eSZUdB51G4%m=PXdJj0WYk*_(tqhEC-f7elU{B_5P-*M#hlO0{Wu%Mf8&cTzv?KpC2 z5B}DPzwMXy;@W*l%GSCD{swubh8xR;y zGx1~cq4Br|KF#00p3749CnAN(TtHel_|o4%gv zTgmh3!~@=u`zw<&;=2IcHOSFV2%dxHb)Dvxd0nS^MTM{(@EUjz z_3C(*l3(&Wk?K2aq=n8`=>jjyYSW=B(RUtLB9Z zbg!Y#80wIm=#y##G-v`JT03Vz^Ezl|3E^HR);i&P5cqk9a~i-}MTaDtzBZE{3)f=& z{xq#e!nuI+T5vmoD>vX=pz{H@88{JZdE_1g{XrNbWg}i;(D)4X8i4BuZZ~j0DI1J~ z=PYKC`jpUBzBpv$; zc;>jB4SXf`FxS94`CaIq;)iN|%-pmk^wQ>VG%uN3c|7L`n7(On`JfhYyk)5fzAbIX*HMyNcmj?!upbM{{Q!$Olc?$P7 zQ$v4wJ@u}+ztD8`NbYc+XK1x|G^YvC#f3`57sB%4WGWJ?sMoc#GR7rcti%vSjirXq zP(x~uhLb4k3oamtp{a!R9PWpX3wo6|eS+e=AYFPri>WsFAp!#8p(;{RDZ z7s0i0OsM7Bp}alk$@$4$x^o;PW1v4ZhqzGo$zWqJ{yihPUNHeaAr})pD1fz*@sqCh z&d*_E#KD5V6Sj_oP9p`OM9_$twcQ|@59igIE2#-al|{T_c(zqceZz;$r4_hW zfGZIglmX+w4Fb2*Y)6%eRj?poNlC|OPAl{$<5V^!ryjVbZA%CajTKTJs8&GuY_vho z-2!;N_A0Km=jB@AU3)K9Tae;IvRwnsB52e+sv|s}$6W>Pl$1@`kb4N5!JIvb+>g%9 zrqzk@mNu|=4x7>8oc#q*m2PafjcJc zY9`-f&EI&Cxv7ykoR20y<>*uGlc#gNL;oW;@hiEZ6DM>8IzYrpzO{osB)q zXR|P>4Cq17?8b9gTKgcIh;b0V(7Fa9kCQK|opKI{{ni_((~3G`-lgLr zJ*Pmd4&h7Bj2l2#E^SfwC5cs)L#wM){zN$dnp!@ZjqcH$KmmN_1l>h8c=hG)kvY7ifqW39mL1di4j`VcM-oX>!xdjr570*-Wmej9Qgw1`Um zcyVh2bOF$DyhM4r+s@nynFk&2p(4-ly1K;rs@WP!?xB*v4;3ZW53eJ#k6~AiHE}2S zEQ8O+tJhN#)L!k1IFS}U6(=I)BQGh&DZ3N#2G{Vc$LaT-xmN_P8$Ba;`G)VVO5Ec~-Z@%Q zbNr5-6MBVEjOIeJ;Qg8mL%^yen&L|qc=fIj>JGq1S5A5 ziL62FJi~VK6oouhXoHykfMaXWDcAk{;(UaILP9_|yjzl`?i zjKSppg6*?UDs-Rz6UUkF(4O2gH0?Mz`i5iVTaG=$f9yzn+tDdjB_Hy{q<8qELXZHD zyC4FotlLb^7|p?O#f8V|mr!zXOP3SA zz;5LB<^r&-Lb?^MR6J*>L;Z?>)aS0jh7%5v`H*=CT0iJY%!Pi`37`(y3w>yQB!KG! z&NyerfqTV5cNVxY;0i@eS$77wQ@{yd!2GTUN?|;Cq>LLsLgi1yT&@h5DTY z{VPN-Z9(K!F&%P#R!ua}kdK@K-PwQA_j^j`o&=)3oV^I|#Jq$bz+N}upe#0pV{)T`si7y?ZHuN4mvXEg-g>*y!MrAninG z^KfClii$oWB|5DiZ8zPEKRB~gCT&;6kRCj*5Mks#1h%|CqWwksnbe*U$J6tB=V(VG zkt2>eT*IJbv3?FAaBU(N_9_wBdl+buj0dfpKMRoIHJq2CIih)u>nZXpY&v32zYqIF z(6Nmf#>Ox&6OINN3-V26p!ee3RUz@khj3otDlE8W;C35uG$vu-%7JT8G3SbBhSi8B zy?AI?kJ$5>3;X74)k8XR@TP!MhMK*?R&!`oQC5T$^JdQ$Cv>lI!cpH0r#8I{8!wAM*8=ftv&_PhjL97r?u~ zj{{F_Vg9Qa6Eha`03R2=CHV6?XvDh2H1H=Tn%$rw{x_m&1lK%t-FO`I?bjng2t*SAV3(Tx#x#34|S-2+G-Sn(}`QXp_$J z72(Wao@{f_K{2Cv(1`faGqQHHaQ{%z!Sir+^YTHuA-tr!g8Y0X!qD@cA#|(`JX^u@ z4e-2%Ym8;TgPsBlo_Ib?4{?XqHJwMyG_Rh_r=J}YrRThNXq^}Akg5`MZ36t_|0g}B zq`x$Kn&fI9@73-{^c!uK7fD<{MrIqnbz4p5Fe@hZ9x&t*{0IKMXm*Jt5h4qVuR zs{^jpf@=k?$$)dAjW}>V;C#5&e3|Vp$@~RPt)#Kq-&xQMg3pcY?+R!Vpb>rcW^OAF z$@}q}(3FDa>`mIL1I^S8Xh^>i(7XW}W$P~BjsZ8R+UIdG_Lb_<`OtHqp=A?Bb^KP=nN^*l@T55z{sE0fqVpAv!DqRjVHYy61lUXy!u(%9@09A54Bwm z`r_;6w(Ec^G2mRFYXxp2a22>#ZDX%(@*~GUQx2MJ<4Em|gJw5q=$bw*e9v+{EcM2{ zn2Gll(CkD#qs<%pPJHt4z|04lZ2BRZQqVNrKt`ge15LBylO9LY{EC1k0Gd3|)5nGH zF|JpEYviFb`r~oX#8EFB4e8|^Xa+%}Y>RMLfIDWvy$f8QMFu+m8&>?QbQ!QXrN?|T zXa+3xDu8<#IAMe7{jlC=7i0*4CIXsl<4gDf&`|$g$2I(ePW(Gu7dknB4kMPA$mAp491q>dwFQw$=a=IyW6Bc^oM4b1Bdxj>D=X zl7V=H;Wj+KsG@`-@=Dlb;)c`5u$qcsLH2wWJn2mP1g{il*(HdrUPlpAytm% zJafT|$P}3(3Y#gUKJP{YvvbhRD`0sH{HGl_BbkGOdtG{;Mf)kw&>c0Sx1CyBeY~hL zvB8(T)pK&)iSNIeYaJX0W&`qC=h2>FFgop&G?VLypkcA-mk9-En=bOXs z2joA<5hYAvYWaby#FTZlSKau?&B zBr-VUCmnR~je-d}5Vsen=x~7Ul(U}B(s@s;J-!YH>~i*9q9@81->hA5Uxwtc1u1#< zlXTCVpQR;*4#mj>c6&%TItYv>k>XwrczNi4`UoDp%6YkRxi1ScT9&LtB#BtvK$Bd5 z3f>HiKrO+(h0AUd-Fn=a6u1zrB#c-I5hYCns;MU{$KT|i#} z&8C~svCfU;R*mLR5=$*ycp8;nC{cy>2=rd}>lWEWERdse{S@k`9Sc04cmgAH$Qv<< zmr=I@eAFIC#4b4q4VjMSxfg$m@GfYx^gB~{9yH)M^I7>k=rfMQr*V$pnB%Y^w<`U^ z%cxg|cSQfQ^Fb@FXFmUdzFxLMSr4!D|lLdQEt??W$^uI~(PJjiL?aSb)2u>E9T0<{994{1CZ|=S9F2KUJ zPZ4_*>G8r7P9mwp`w?Ds*U%E(^UymlSm)d$>xYZnB)$8D^LU~A)S8nxf~yVCcNgL% zyw{s2_gv}NpI&;Y9WL~pxJAVIp3wrl{(`<>fiyj9PUlV4J2#X+traiZG^Jm}@!A1z9l1kN)%$)NRW|pVkGr@Te%1%6wLj>em-g+CcoZ)%Z zAv{y3BO#QasGOUnacsauJB9a|`8kVWah#rn+_+vP2%!{lt}=)0@vcN=hDjB=K`z%2pCd-^H7+h_6TJ~&CZ%ID_i=l}+r;#B^SaQ4!N$}08q*p~{Qx);yI zE1h&2QPxE}Mfmokt&Q|vIIihK{xtzy32--PpBm57Ha9HVg)w=ZwR2vOgDb#0NuTvdU9x~ye)ts6% zW^m}GS%KUm9`Vy{aW*U;8|C81v0s%oKjS!k_nEuM<`Z`g-{DE#?j6}MT6|!rq=_DX z;SD(PxC(P}#xYbvBy>A@J5_rAeEm>KJ^JW`=NT%2Sf%)Og8$iFY?qv~g?psr3q(l2 z!%H!L0<__5_sRUDolYUX9ZlOP94>M0;Ja;2zlQt^f!xKJFy@yAq zLG<9J8t>j+z&mzsoTzr<+&12}leSp$Va$`K^qhzOu7w;gWX9CM@hV96TZcO1sKfTF z>QH!zF@`f&7hH$tUO(!*gF3~yrq3pP6TmG2hvCs}S`2>$KH=;B0YSQm%#ycFSJ z_F-LQ+j4=V#0|dqoe)|Nwf!sOeWKY7nr6_H6HVnxnh4OXpb3L!#@uH-C-Np7cszh3 z#3KzL zsI84&^b34dY({wdV{5?HfUN;r1GWZi4cHp6HDGJN)_|=6TLZQRYz^2Nur*+7z}A4R z0b2vM25b%38n88BYrxiktpQsDwgzks*cz}kU~9nEfUN;r1GWZi4cHp6HDGJN)_|=6 zTLZQRYz^2Nur*+7z}A4R0b2vM25b%38n88BYrxiktpQsDwgzks*cz}kU~9nEfUN;r z1GWZi4cHp6HDGJN)_|=6TLZQRYz^2Nur*+7z}A4R0b2vM25b%38n88BYrxiktpQsD zwgzks*cz}kU~9nEfUN;r1GWZi4cHp6HDGJN)_|=6TLZQRYz^2Nur*+7z}A4R0b2vM z25b%38n88BYrxiktpQsDwgzks*cz}kU~9nEfUN;r1GWZi4cHp6HDGJN)_|=6TLZQR zYz^2Nur*+7z}A4R0b2vM25b%38n88BYrxiktpQsDwgzks*cz}kU~9nEfUN;r1GWZi z4cHp6HDGJN)_|=6TLZQRYz^2Nur*+7z}A4R0b2vM25b%38n89+e@6r5$20R?N}BNw zE*(A&Pd_Test>Ln2PeDd&KT65|sByf`<#Ohi z;&L8WSmN?@gGBs0m!DG%|BK)i9$yU-|Gpp4 zexM?FX>b4k|0{O_*cYT|&!E0kroKnMq;?Wg6MbA(bp2eWeGYvGxJ+84?;w|{75XN* zO#3YQj&YgxS!%C^OO4v64_(tomj3I@<18QT7wJ2}Ws-^HpX4&>gUVA}CS6c@n#-gM zD$j74bV20>F4HxA7r9Kjpz;!zXHZ*> zH*h)0Ciq(k-OlDK78g@-&y9;PMQY%ej1o%TIE7k;@XDJU_%Hx*uq@_GmNzKHw*EgseGO^zM@ZCYoN5SsQf!%Q?&obx%y zFcXc+^UZR;??yC=HX{wUF?)lyR2!GME!l(Ye{<1ci+TicE>=R7Pc+uf#fqr%h-Q4A zrt*zu{3=c5<;?iin#$*y@waFyZ)nEnYbw8J#;?)T7?|+|dfvf|cWOn$MvT19)e1GG zd*j_)ZLM}CgD!Kmb=vfz*-oimuC`vg@`FtHB2DFY&HQiGR9@GN$LfP&cAomPHwwL7)tt!8@aO`i7sl$H7;0^!u>iMsE>MUIxnlVtRf z^ee|p;#cZ_Kk8&}ca5gzoM5i=FVxf=Q23v}As<8)8_nZ&67(d0iA&-)Qy_$o>hIKu zEUUj?5f??;BIoB7{x@(ze3~DYe5Uz^;$yW#$>&yW*}_NS*J}A+HOndS8?^qr&ExfL zwBx|IE4+&n?(>WvyPxR`q(FbG@Q+EnYULfqzsh*k$}9+o|G0(zM@&D#c=BQN$!GdW z#-p=&Z7dsy+3T)Q3hvfG1GtFSyTQhHvr%y-#tk#@zRXEFmCugKSBgKyAc zj*p}-#u}kCAn`S#UunF$dyw&kOt0`SFuurw{~5*?Tkx{o4O+Qn{(eEwr}1I|gGgUw zd?(W@{hwuggz-wAKWBX0g8wVV_gV1oGQOYjV!cGW4h$37!yx1PrFyj68DDgZY*Dpa z%J^an{wc}7njh5jJpTN$tV8)AH?h5lz4AGYAX!1#y-|7FI7@Tq^$g$xQs=huMBqtxpO)r15J0{xst!ve;YxsZ9LW zYb7~m`Cqw-{I2gQNhDPAm;Y)e{>69>ZMG{lE;Dy#!mrgTGV)okP3N2COx{G!$iG_T z1ikRjjBn=KQl4VXWs&m_gg(>wBJQ5*Zzty=R4Wn>dnh!^`KLFLQ(IOXBz%kIRQL&# zoXArAS|&Yj&=#`jv+OrA(XZEv)|%z~_nXMszt+shiQyxCmeInBPpL`H_1esBX8!kq z{zmieN{N}j(sRl0X2K&*zRS#i%T4%~KbnaT?CpPM!mrmB-)H7ueiQx+AI!vOgEmcq z89r4glK)hAweI*CKg0A2uk^6=%}o5)YvcEsYvuQwi{zi7cIoE5;mT|leJ~#3wQ(W}X;3LexD1`;W@R9qYm3flSfc`eD3q`ldaa4Bl1%Wp(;L9&(!GApq{v7k4`5%(O zH8z*OVZ8DWFEjt|Gv4)k65(U~8az;-9KH3kQQ(n(U_ZIQ1Unc%FeMR7jNi-n<^L`P zd4utX7++E>@ydU8FuwT~iC6mXWBd{&5b&Aeew`3_i8KEFb*7)TtiQht{HLg1Om0DhI}OV>$0D2mV5 z7~ju&C}sS21fB~9a5)S9@0d^Lhs|>Si1CA#`LYUm7t-gIEi8`&+6I9)G{~1*vf$m! zr{Yf~q0;98#xMP{#PhPDbuhk}5)1gK?cz@>Jljv4KmZJ|AHE`~wov%J>g4 ze(Da1s1VeeR?B!54=8+-z%!8n#IoRD&Vv6%=3kyC+b!c|=1YuM`_OaT#&0oxz+xxA z$M_kJpNp7&TH!ZK{>uIr7+-Ox#KZi==kFOGVgAZ5{R`t;uS+^*4{MS7B>VJP_}nA# z%+vrjWx;RFg0Ex#YQI@7#nsw?r}3TSeQptVIL`EC+a=+v-1g_P@c-p3_-W=d#`(ZQ z%x8}Aed7}0W&A%WJjab{-AOTipjXPn!=M#Iv65KMDdGc7EuQ6WV2g%#oImVZNiy1Ti zuNc4ln#8NP`d=77c245^nEn=QeKYCpZh=QU^BqYa=4KwvLjM%gH*>oQrf+1tkN1gc zzO*U+ypAjWu`K*Qmj!={`80IP4h?X-Ut_#)LL%x|pEFtbECMg=pW|mXf9(g%rg3-uH$?sQx}F@JwU?wOR1bXTe99|F~t{{BMjed0Og0wVPo4 z#Fu2FySeT0Ed0Nb1^->qvGro`WDvJL;#+O>+gm!`F&KN)+(~rAlgB5)5GmIbj z9f?R{zeJy}GQRH*Wm)O}&lo=$k$lQn{)@ohCrM3zf5`MjUED6y-%^x$p1x1uo!a6@ zn4Y`Pq$@R{uM8q=4tpH%ckP%Pt6BJeL-AQJ`M=8i|B~?yzbO&3 z^0xL*3eWAbRcOmu_}{ic>a96PGPulq9$|dLxa7Zy+x-aR^Esd3V)~~Uug+tr^{Y+b zxv~NL9MdQ1K|DUqd@qrO{>w~XG$#q)<#xZy_z5=fO^kno@tu}&oM-&<21%&w`L6_? zg)o36rZ1h4$c=n&^&O478`LQhgyP1A~ z^H(Y_{VB#zO)~@Le=-Z7-(va+j(&QQqJ2^k^E}I zzsY-WBjWQA-?rzWLWA!pr>)GJc%DezBWh*(c$R(K7}IxJ^1#2v_~eU{ah&;li}C&EC1R5CZ!z9y$?Lw$ z_|89)giB2CyeqSvyRzV`1Ri-Fj_Z^^f0prMJTH`g{siOuACU4Z|MOFfZ{~b;Im`2D zf#-q&j4^#H`^gHv_Zs8NXC*?7;W53~JKJ$!U;(7Wq@#Ftn z;;+eOw68F})Utp41I6Eh|1*WJkPIrgnZIScI+w`9qy2#K<(vRh`pms2v)(ocJoLcv zjN-qU@nvieFmLhM#rWiJ%d)c1LyY&eNjYC<`WG0l&NGxT{wU+89+UJ5#($piFcW1#jGXJC{p7}WAr?|l+xA7w5eHQ!wbQb={ zv*2H2KFO1kvGSka%tAlU^kY1~lpcP-_!3^1OIglU@5?-|@63XKMBtI1d`6C=%5PUQ zeu?Ar1$kS0E(@P9(=V`oFs$P9BI6g?4in7h^I7{DwMT zmoM3Ajf(zXB|@#&9gI&}*7sh<=UOjL&bEc;)B!Grswol5mOX zI~ZT_rbJw3e4O!1QOQTmi&q#w#s(5*`UK+t z@;^z&6U=|Vz;nR>4l{ix?;o4_UN{T=PiMh@midgayDbbyH3qu_2ZEpM4aVa2 zu?}rhKx^uZ2K~T=gZ@}>OIuHOERHIXE!(w@mIx|Ug~GwQP%O?xNsdA&wx=&d*!FO5 ztg|W973}F%M3v!Cu$u~j;E~3-KOWR#qWMTfYk98j$!DXXc+d+>DAcfR+uq>OXZ+#b zpgY>pu(z!-{$xwb5r0dVngsC^9VB^GfUdXg>S*Z*_Z;?z>v}rsf=7a3f!)#3672RL z4hQ!fp;n1-r>IpKkA~A^+d5iEiu&Gouul*@3HgXO$zKVDANIGspcq0A-NCkaRoLGl zP-WENnr_G~C3&36f>jz>jz;~lc+(M4V>?PDVr5S+3xzspj)ZD_F%)m>6l6fYNa|>a zhPvbXdbpNMI5m-Vc8zHW0SQFc>Bz z2)lX$>DFO_v3PHLJ4_`2ZjxzBysM=x+|wP5X)P^*9v*|1K)fd!Yw`EOTzk4A;UILg zrMzr=d1j)P_E2}I#UG9Ok7Bsu(W6>>)ZZ0s3G{Y#9YqyGsRfjA6DbWGdeqg`(+$bm z+R+u5WlO{#C7Xqzp||aFWO3at2bo3&<`2EH@e>mB+A73=~DRSHCp@KqGng1LlJM@ux0Vf6-&gxZ2)7U|;- z2}6f{{_a3Hs0E^-Bf)5kKN1pkz^SUYyN!CKfhg*a9!2l{0cIcX5t>7(4i?sdfk1y~ ziZ_N{Vg>9n-r65C-+aP&(;bP>U0AJDU3rF^X}(YDcWGdJJ@7#OKCbTzh9kkKg{QPsa44haxN3dtiTBN9yXPGBEj@b;_2!! z(6@DB3RUTdNL+Z-7Jt0GC;Gyco<K6iahB`BKeD|H6uCbX97y8Rw^UCaKes>VG{ElqAu-JTX1@l>{K-?Hrqtt-~i5j3OXFU2gFmglyWRrQ9$!e_@q4SSDtg+dr1 zEE&>Ly|Tw+iPNSU8N=Uh(-%CqJqeZZvjw zsljdR7P4Z}`vPr{1>^03_XgKWSW|~k%l;RkO)b(JkD2&U&l`hr*{<+)R9|S0N}i)N z0kV*oMPcw+Fp-uRsYo{4h_S#J3NI(*f_&b%=8Yba9i-8Uz!CGb_(V^r+aw6wB7CC> zMV0_*gs+C8VE)f-dmIhY+UX6p;VRU2L?0y6#MZH>PtL`Qp>1#L?0M1LD7Apz(;6!p z05uQH{%}ATlakjDk`{D1*47yeV1@8^nM5VYYGRGT(5nInWI}->)ORp!2n!d`C44c= zOAb52qXdpnO=y+1ClAo%`B+#l_TrH8N*7KtEEn2Z}s zQ8eBg5hd809Cy_tX?7@)4q;8IQYFI6Zd4*U{bW9|?g*{S?YL}dfop1ep{1=8;jTXv zHtClJmo!8C#GDbc2eXw{{E&!F#c)C8aPBn$i0?VdCaL+u5yVD4QL~e?j%=vA6YfS1 zu&M2q=gJ$y@FGw)#dOQ zJGx>*?GiQx?ls*o{ce9)%qY33Fq&c;7R*qT9HVwbx2HHFD419bj8$y^tL8cth1}bA_v$@xs~5m?aDQo2ACw=SrZeh zI0TIKz_*IY*lAwRFh2vm5mSR=)=O3ErX{^lZ}$p6BxZB9x6pAR4i0Ziw0arPsD6BAe8+%5bTWw zA(a@LgOLD?7Wc$R9)UK<2Z;6L@KK;m8Z#TN44yS8tRYOUzU_!y)WLWAHpy4)j0I=U z(LLQqjvx;pO~!LnF8NsOX`G>ZIDd^sg$7X=t6xN0D@@{GH-#wF#&(Lil;p-}3qIKz z1u5Sv4Jd?mOpMV!%Y*%kj0zh=9SxyKQ0{i3ArTyz>R_CoG;5FhD0~#J>T->MdeZI* zh7qJ_)6A@ec3&@HuWLdZM#FPdnm4VEFmdWTVmpyzfeuJ>`cR=ard^Fm zny3iiO(;xoYZ!`l3=5zZ>K49I>{d)wsae`yl6RI<8G&?q8>j1t?iNnb zth-!ju7RUE4lFoZreSI$P|DbE@X_79l0diyDZ>63kYd1U5f3-{V=o}2c@evrMtwH} z0+Zk4I64qsxvXL?X5Ll_m4$=Bh(>x=TMzUP0f|~DE#e~_hjXBc(u=rd8fx1vAw7g@ z>XFedf}appexgKYp&<=|A&l#g=5Aq2@jOoxsc|;aZ98#8&UxXV+CD+S9 z3o!m7f<+vs#|@?lLXH+obs*9c4z-!*Nh2ze528tkESgEEnr`H6(tZw&KonmOMa3dS zm)b{ur>Bj)GJ%( zEQCqto2VNZ))O*q>sEN%Hd@Rulr(@(P|Gxs!f$k~T;N6Si~?PKV#-}Hbs8dZ)P-#d zLJUjaWjeP3Ens=2`Q!1<zF&(;LZPm-JS+ZS=^7;8|-FTLaR)*eWxbCUgax>#PrU zY3;G2-R7;L+z5z;ie#07(tM(5)GJ&9Ivqf6+9bBf*_bdb&piR*Xj4SpARDZqIZCRf zP>%dOt!+{cj#c0tgP6BnV%IEFZj|LCZ{K2GSHL>Gu*r0zFes?pAEri;1fm#HI&9-g z4fGBXRY4emrzCk9(nyF_F}k!t5rZcMm65odEL9w)5NR3Fk(;2c41^)43Wj150t%}X zd$fZQ>7d9CK$o7Yvh!WKec&diM%Yuz=!vvoh@Lty?OyD)OuQA7m$rW~Ye2>38>Wqx zWsgpVDny5@D&`T}QlV2}G5Ye*7NxzbX{gCiKu)Po(nY$DT5pV;wpLcxiPP(w&x9;00?FVc3x#Q6wP#i(GyVSeIik=b?-Xz;p2V~iLSVM})p z4y@=V>meBsqgBRbvRODpL)1XAh|o!uifS-TR%X0u zD`VM>39lQocu}!6j#(T5?Q|^m$qx^OM`fSQUOu3`NKf@ledvmHL@kkn8YQzO@F+o{ z`trc2c5>h*rb02o5_MBWJ(}F~FtKZ8ZdD&;T0CUx_COFB<6w7Nkj79nNh{a^ouLQ? zXwK9lc^InmABDvkB`0T)wlP|6w&S)?2zBg;CPO3gvtl-gR-{#%rVcMa#E#|{C(1>% z3SkAmrXIv&QpY0aB;rJ|I+!yL216ICqjEPeKWo~IG$?j)kXw52nDXEVZ(CZzEA0rT zuv5inLM(SX5>?dKU;uUGqXfCEKvv|EnyR5t3f_X<=Fm~?pZtM9h804L1&tF$w}wea zBGYytCOjFM2qIsw&mZrN`okD@L{j?lCpX%ewvfa`=;mNI+IayFaYf$BWL;{MF=EoG zNf#tWQMd$)=Mdh8V`bj2s12#mmqsfoe4JQ(NMC3`3?YR;h|$E(U8B2X7>yCc^D=cs z!GJe-xL5AqWgb%aOJ!3^Qd1Cvyel;V$D!M+A@oKS;WN-V@z|-7^eAk-rX49jxgTt) zX{yID2K6W$PvPi6coQ8r(0PJ^m~iyKSjnMljP3}1VR6#4AtaTNRH~I`EU1uGkReQ^ zKTbp05sX_SC{m+T{bB4#OhXpa^Xf_zYD|ruVVctTi$p7ITy>8hTACQ{>#4-!{U{k5 zxiq=-#5xXO3r;N1Q5wAc?Os0~<6~lwy$Xkf2_O@p6l?Xy5SsF75PcU12?OHMm3&ep z7a6ffu|C6~@t098^(G|JZ$wibQ)lR&0b~GDT{t50A1N;lffctb>L!(Dhs~R1Qi<fDBxZX^3{HAOR$qq?sNuFSCwQ9 zd4xySP}gAW?+Ue{)gJJYJPzYwK2Dx>bs=9U#Swkj;z!0JbQsZnjL+5mnBX4NzXe}) zOmCXcEh>oPnx>CBzo?K~aPhDBH(OPG^`3=-8w(_5E?3A`6&ccbV<*0)xfRlg57(#dLk>7)KV4h7ZuS$S9XL0uChGc?w}^0V@;f@OGr-uO}HN)`MW+%(o# z?=LEN_MeTl)AB3qF-v{*?|>+%+EMg02FB0lQK0sf{?+foE4WAlWcVokE7TWoVXUwI zT@eN8_wbA#Yx`rkX{@jQ{SgJryvEuq`~MZ(UWc!;5B2YqEYJ_dQB{E@Q+ZJY)94Ce+Tskvi%4vR`pxeQ+(<8IrU%FSO0ExaGoW}*>RQu}pTFX{T%=E*GQbKF}OF&cmWo9z` zKEJGQeRqIp>7(FPT$BG*ANB9Ic)9+9y1`KCQK5+st5~4~blt-8e^8?F`n2{(_$v98 sUEt@0^u9|<`FGJR>wgsIxs4wsx582XB&EVg=`|?yLv@w^oU^`e4{1PZY5C;6{~vS-=S)VPTS3Q z=eIwKhubu1U6qlp|Lu-Du4CrD>zI*mT^suwSus;AnMOxSP5CM~Uj^s0uEj>2vaTVV zJs4Ly_i|PJuOm5~b)~d)Bz{$vMZZ%&HW~e|W#{N*%DP(lZbClN^Z)M=$_bOWyg+vG zo@)|XSFVn(+W_1mE6%v#X7$+fImbR*+rRh4nfFdBDO)o4rx&;XlXCVzh6T7r;OvDn zxZk77nc#5YSCGxV!nQZm+3V2gzdahE9!PMHa_o)Rvn-@>Ymf>Kc2tBu8qrJbn%EL_ zeADg0VQPi_+PJC^Tcuk)s4^bh?CiI!R)uYgv@N$g`b6Z7O1(LB%K5Qd)D=oS=e7lp z=ouOl>Pnmzx#52AnvtrH@&N>kIncOqVJc>aQnQrm z^M_F7bPWnR%vfX&o#1$HTZ*;`HEr4CmuGSL3vfHT>ggT%X11#aV@O z15WFB4nHi4!od3Z2IZkqtf8nI#-#EX-*@Uwh=V6>jaDI*RD9&$jeuwjWoOJwXE~*9B zpZNE2zMkM~SC^Aap2D>iXB*=)xSqw?&X~efH=NyZk{^fQ?1__(-ngEN^E{lP%=P8# zK)zDCLE<;z!N5b98_w5oTqAHsGLFLaLY$*;j>Z{{(>gBU-{lNhJqdMnP`82=8}JNY-s zOyl2~xMuV39C6<&Hy2zU^Z9(e3)eX~3vkY5j?x$M?_$2r!?grwDdRG}-p$uVxGuqY z56=5=F2zZQ8`ow0yByc$I9K5O19Oz-e*XOct`#^R#Q6|&EBX3IT>pgg5yl=|AH%r{ z=i|(+#&r$Or*J-lb1hCUPU~2Q-&Hu{51qK#ImP~Ks$;~8e|GeXoXCCZzZp@-(=bqj( zYu2&yznocg(|zXzUGVdW0XaX6h&gv~@n2s#c;=7qlq81tcx2X(K@TQ=9=+!5+48SG zed3P(e|+;mW69@VE_g1v^4tqvfAgOkzx~r)Z@hP5MdV*Dxoz;B&n@lO^!$A#dpR;LaZ(y>#HJ z_pV=DI(b)Y+on5aOir4yKQp0eo9)+=%O5;>_ukS+og?3vb7JM?FHJf#?fFk{zh`Yp z(c~*fUpN1`_is7;M#2xS-Y0LFQk8yhTKlw(?>v6avX^)MG-KzcjWLIwdGy7s_dmEi zXxJZbyR+Ydm6tXTxOK+bCEX`@`<6ry(Gb1o=#QyWF3ufy zaNNdAzDT~h&#GC2vU+~`!1u!+KbZ4-k6L$O!ZX+0K7U5@_8C_VKO0i9ciyro*K9m? zB&g)O*Y3z3_-(KClVUu7n|13CchrTyb@16g9c(RqAoZI3uyM^8ycl(s8_}vH3 z47hUK!4E#&_|Av--Sx%;!^-cB{c_FBpSJw<{mP&2*f)5{*0+y*m9XFT-u`O}kEA>~ z`EOg2f|7fMOg?t#%-mu3KG}L(_qtPqUwZYEtl^)Z<9z(sOBdZf=14_lZ;z|BD5$W! zU~Oi2Si|qGduiv^sWW?iaa*6ce>=Z^ZsY_1zB%VUTf?yp6$b|Y`Jr_?Rt_JP6CX1E zo;_{d-%$P1R$STZtBjY<`KxEh%YUkVDZTE&r`A+dFZizT9|g(tGv8kO;){PM3*NAK z;+*>jM5aZqELiz)zxIz>?!6__W&7dClF`!!u1wms>xrjNzn=E_vInvc%_-S-@W|QO z-F__}Kklj3A76F#k3+B9+4jYOK~>$a>Umj~=go&bm%nu5ls_(8GPAn+FW=M*JK6um zzpk(aJ%7>0FE$Nc^w8N$c4q7yR^U12>Dl+XrE}H6IIn?r#_set(Q-{g#HqkGnsZwDY!%v_F^6N!|X% zAI5GCdUx5#J1$xJ@s_WDYF_pHg9RVezJKh#`D2#7ynpA1)$@8RTmIJDG2Yan^IN{@ zJ1T6&D@U#_Uh{or&rerhF+Hn!Lh^0zKXd=PanHWp_{tmJJ4^4KFrmoy_WB$D z^yIgFM>KC=UF$)kXCGg__u@IXo+!;-_t0qX-NSZn={9Hf`E#D#{@U0Db7x-_Qg`)p z&kcHiNc!4w?I%7TK4!*$76RvzcX!QG+jvhBV?1@X7J}#?%D}3=ycT75UUysjPPW|Dp&T%wk2R!WR996sc zx3}$zW{$y~ZoG?0eZNkO0k@skHUDsc^f{qjr++H|pM?2zSLOD>ytgYp2^0LT_`3t> zxdCy#tMmzdyXI>H@LPL#oxZY9*ZhwG^#4l$eYOYS!vn~97wev`>UBDRoR}h?*c8AHe}db0Ww(#9km`zmIDni# z2hjhQ0RB0AP}lNp0qnmafc)vOaMW+CjCp$iJA4>G&c6cq)jtCG|F!`Be?N5T%5L@{ zUHd~+0QnOG=xGb!54Q#I2R9bEUFq{}0Qs#wx=#PE0PV5>`gi5$lLPdZ+XM8|vH~LIh@XAHcNO2N1H{7%1C(nIz~3K$|1^O8F+6r@hbIHn>-GTlxio;BZvy!3bphJ( zIjw&$mDiUv>zL)ft@~*&AyF4B=h%ixs}ftg61o9d$DYtl-DX@k4F`Pb+)4Q1eK(`~5;?2ew*oBVcY|q%)Mvi5-R^1=bF1+Cv z%=OA;`EE7L-A($~-6kR2RUctG zp1>cTGuY}Eg>26QY){LdZF>Cer4srXJ+1U#>NwU*g>buD@~=YsQojrBW>Q9&Z0cfe z-)h_Ke(gS$`(2aOF0B94Y|jI<(8EDH z2z0#2{!nqL;S&t4?qfS2?QQs2<_B@V3;D_rwah=wcCa3Pq%i-JmHr1qtYCgG`@ed` z5Vfr5CoHFe?K6ziFJt>e@PiY}J~wl{7WOv+tahp6c64()7O#C+>IE)0beGA$knNenb}k-g zi193c9FIq}9~;7|?-yLJig1&jo?Fo2Vt=k@f41ti)6(+}lhCsBS=MtiKX7T%Qj|J} z(+RjH!Ld#DcU_Gq|Wmfzz=D3vlvPr+0B{zld_G1Ty*nD51WF^_9jysF|jA7agCIQ>y>-xltVmOp>S z<+}XJ4dZrCXfXn;_DyFytU0%{oVHD=*5VuY_OH@kjQbib;l_#(WF6 zZ^&Vj&gvH#tY_-woy*N-`EHI&FpECu`J(o7zxlwUT(20v`M^Z(ry+?(eu25DMD9m> z-!yX3&GqpS+c|;lVA=Bu_BSub&wDt19M>zR*$}ZTe=*l9)URH@A{psl!TrMW!~0pE z#400a8q4`N%db6Tc&ooxS@z_I?3SF}a6FP9%6?K|vZ*y}hssnVcmTIcH*VjA-6r99 zPVYd)Nlp{n!D@G!pAsL#c3Z>gf8_MVFBrm$enLkP+cS*yOhkSi$T&^{qe#ZUcz)&OK(sM5Nug%==Vp-03?(Z#kne>)D zPjWlPjxl@!r=Q2^^X7Jz|0M2{efF+03Gd+aZ$cpPo4H<=J_oqnV>gpNod(;GxyWY^b!aThqdYt>0e!&JDs-utBSkF9;8xhP0Tl1?rLnJc4lKmm|GefN5a(6Mm@E?X>!S+1F z?GnOq*uipEbNao%7$Sz#mvFn(RvZ2kmVb?vp8e38KVOS{SV zP@WGYu$+b5FOG7*u+oQfddH6@;V4c&l=W%y)5pbro9E}Zl#I$(^+j_t6+Z{B-`?H}`{QKX6Wd4=ui^&7uZ*$oT;re3R?DQwdPU$f}o4boyPrc6m8Jqh%?#LeQdWzzkc^E z%Xjm{>*ZG%Z@tbzS8_P2#R{~yJ2p67L6 zNKaGl2Ig;Ozuj@f5NFJ7mBDr{W;~FPx@!@9NC;Q~BG6`LreyKH22r>m)ew)gCShGoJ+5d0cF0I@ycd(xI><g8p5(Oz3WMQ>-UDY;=>3Ye_cFpX<<2sVISJ>jR`UmnxG#Y z7Z2q6jx`EecD{}MP`^NpbXI$%aJwu#pEconRk1(p*rUa&h0H&|e&z7s_`_t)G2Hv3*kiZUk8RzsLPIW*{rV_5Byyr?TFpx9W91*SD4h zSbp1$<6GqqCjAO?Q5RT#`;{S5n0K-rQvLeHR+is#z$C2T^k-OpUYjAT`0zT^ruJ1I z8Ga4Nu@&t9qi#0!%Hn!`&FS6j50?ICxIf15zFZlXtJ2bP=N1*Fm6oNKl%=Jqw3#Wh z)3UNlvUBrG%d$&SX2%y46=tWTXB1?cdtKj2%UqbAmXlwYUXZ^S32z@8lUz`gdvjqy zQRbWlDy68XVD|j7?1eWMUJpX!8QEpmmXs8g#1~~{tJ1QPYy#@~qTJ*~rN{~yu_S`h z3jsPi#7~-8nv6TyW${IYh1r>9*;xyaW8C=U>@q(-xh%bGerZ1GG{MR=J?j=Is(OFrX6X&6Z%KN=4fE$Fmz7YKvZ4Y7CAB8bMJzb0lOj3k`30o= zIMTgKtzkXz@nt0i)3P)1D?byhl0P?lT7FKBwk_YCS!mtOq_$7X%`PiLGE&uvgs)iPk9(xQUw1qzyE7cS5?oLfvOCQ<8Jm31zQ;tC3kskAVZ#7#==30;tXVq$tpY4(hQqKxzcU9H6HGD#)D5WIFlcA+tTM4Q)+cmYg?N<&32HjMs6r69Tl35Ere&j}S7HKrL|MuFOltetrMd8|$>vvFNiNyFY;s!K zg7mZk>Q1nhv7+U%AWY-=e0YJ+?;x}=6AEM*51g2kJ-28<_U!D^()3(tm7AED32i3p z$|s^o@@e3#f}-5Cd~M^h#Z>j&?6P761N6r$*hS+Cv;56iT9#EbzfAXu>G=o-Md;8u z3lUokXY8sVt`yy{s90BpjZLjiAsL3C*hvMA?<77h2hB@GXJ?rP8$S&?>To?1SxV4R zGZ!P<*ei&?HNB*;3z}kAXIe{{mYp#l{v)Lr>C{a+@smloVSEKn&;_D#ue-&%GodU! z_qtoG6gt!Ng88L+y0OPndIZ0?va*s%*B9l|75&8wZt>{_1sRCNx+YmjNYSc*I(U9! zzOU(J$V82GI+)d@gL$X~c!kFB&3H|q$PS{DZDkVD#)q}iKBQ~sL*&j}W6kBJ(HKdw zKR*}lhz_1I12Is|MU9FwbwDuDfWiYcb#g&=cCr2ymzfENRQZKEE@;2=f%L4bw7V%% z_?VKpOu%-ilPQtH26`?+jdo@FN#&S0qKfC2mC`s4n{*_%VpAtl<)&roDv$%~STr4> z%VZ+yrvDh>GfRE^wF~t?2lu2z@zm!zO<`$vi7r$Rg+{vmsbi}V;GCb6kX=xmt%t_U zJbfuNqpDT9&f=T1Ov^^JC|ZP()me~UILEpcs^B6V63OKE-VOU*5`C1arVV znPmmkGzFAL`-E-~i_rl+J|~xqLH0|^E-pZfo|c`HKEI&MxoBE`iOMNL&{ruX`82lY z7v`$Y6;sq_NsZ1mAXep+W@pb)Iq>jOm4mUl6xvhjoLp|K#F8TN3{wl;8fL`t$>ZdR zMakI(InYoiBGzg@_$J>{+Lk%Feu;_Y6qHB%2?>C(xLovqEfLObxm(0w$ zp{UIGXQx`^8%~m<+p$Iu?CRUf|F~Wr7ytzeLswBG*V-3|! zi^x)mXlSdR>Ta4SA#;Jrt?$iDpKIBa>|e3~zHI^oP35L%0YEUOqZE-zFw|h=Ttved zao1DWqXbMPFDlHOQBpL&IHl;uGRzz(&CTdun#0U3H@j>;#wc8h@1`F!i!;rDj1l$5 zyAj>h+|pcfc*Byp3|)|!S9EtF`CJ^exVg;+)%GES#dn=%I?bzLK_f!1i;D-llOb7wA+{M|o4jnUb@ZbY`8mc0No_?gp62_zJi5|N*o zJ#(6_76Kn={yEzk^7H0Sv$(nOFnw{Eo-n1&rKOjN^qnc~iJhtWddcROHH$+aSroN5 z^Dyl>y3c@0&dkfsGQ1vQEurZc;n1DS@(bZZ`DLY)%qQHssoCP9g8a-y0q&)jq|b%R zV5(2WLyP~SD80NYrDdqU5?OjeNK>S2)8T07@J$y3iOffP`9x*vEIz1fAgu%M*8>uU z;?mq)ZX)UuI&MR8{7x>!La#Kp6c_EnrMXF1Oo1t(HI+$Yrqrc*b4dm+Xkz@ErT?W~ zMag_JF@iv%?g{B;bcdD&#prT69aiDw(r8(_Wa=nG`I9p-O-DB<<*VQ*PV2na>rtaX z|4a9$TXS5Mi1zNb3!sN8ANM z-+?u5L?b>W z0h+EXTbcxucO#m&(fKm#hm~H@1l$zTDiUL}s1p zw=||1`c6`I4t4+wGxa>wREqClGN_k~MwWlWqeK{SW)^toBF@oa7qHCfA;PB)`1o`T zp7~{qIugf`nlAfCe+mHjW*UKad>qLtASp}twXy~HJAQsgs89kh`(6D|z1rwTx@`41Z z^qdH{XzEC@5mQt%Thm)XwC9Jwo|j$eW6xm z{#?I`(M_7m1Wce?%Rjf7BAVVgGizpHGB(7l;@DJ}D*02%Gy@RHZY*V;eoOi%jVmth zA}zE2i76$|?5xJ4HI*I&QG80#w0sN?tmln6Iy>bdt0fm>&eKUtT`o<@Zzzf{np<3g z{%B&mRTGUUm9HAVHEO3@9k%w-WaZAy(CJneIXFW4lA$^zAP0KrrKY7F_}_4(pD&|U zpRyu{kL(nGZ`6xI%ao?oP1|)UiKJRLyHHr(_LZXxw=ziupthmOumOtcq7bs9$p_!) z;=WHTyG{VfxZ9PAprwvfBO0|tIha0V6=3c#W*p5VO3LWxSo)cpiD`uoVW%+jl1m6q zq?>bnzi8e8E-j5l-o<##gP+#poish3&rtKD@xPGQHK5g8Xv6J`-lMSzwb^agy^)8E1_(g|>ZTSAn{Kf-P!FJsL?JuRe{g){_ zDE+sxx@L@o4ml>3WP|YH$N&4^|FghhrGN0(juVLQh$9tJC_Tx7*@Al(snUCQ2BP>04FmJs# zVe$3MJN(k`Wj@i5Z)D!(#~)z6*pF{w-tEU9WxmpnZ)M)=$6J3Ctk#bYp%+MS)cf(F z%s2Y+VazxA@e$0o`0+8!EBfFYhh;Yh^PzrxBJ&Y`d@A!XetaJD4nKY&^ND`En|YTX zU&(y2AHRlqw;%6izS581%)Hl+uVud0kKe(3y&u1q`9?p!k@+S+zKQu3KmI85mf)$Hy}7_TwGQSNib@%zOR# zMCNP#_*CZW{dgDijedL{^G$wyG4m~c{6gmOhebR2znl3`KfZ$b2tU4(`4~Tb4f75^ zelzoleta$SEfYJU9n6RN@u|#5 z`0;tn=kdIPUb8GTMe6n~7CgT~t$DZLw`s=w6VYy7jH6*`sgN^D@b8KAF@on$Q1snc z!Q<6C-{BBEe`=-gB?x|~FE##-so)0+eNqJj( zZo%^>G&)y>;HL;Vm4Yu8a@Gi*Kbg?EynM_$0)(yYmvCd2%i50fW8|m_^X9I9fHRK!*?VI{)~@>KMVeC!KVtIU%A$I zU4rLN*)^Xhc)U96JBkJG@v%xR6nu!_-Gaxfw!Wi6@DGXlRtmna;MWKquXg(mui#hu zSo}?E!Q*XR-%%@g>m6pgxkK=`igN1(f45Hx{+_$w@#?kjXcRnNt@j-V1i!(@;(JEH z_Y>tF6+FL!taG&p9-qeej#j}x>SOWaWQRY~TGTp11kayn>RX|LPZ9cr34W<11lI_` zA__8l>+n6g*y`_Z@D*%kii}@QFgtO2K3K?>p8AezT8N$}9Lk2sxVt z&s!2YSFPZO2{}6if31*HFZc^Y`n`hZPe=6KM#2A0q(30|xk7%E;D?L!M+N_^;9CSA zF8Ef#yM%mos>A>3TQBPf5&U-+iEF6fBLp8N_(;J=2)s3jQC0-z<3k#7^I>75slh`W=F&ztLbF^@1O5k+|*^{B)7N zQSjC`FO=N$~v1lP=|`!yI${JrPVljU_gaZ@bqM}S z!6yj*ULhw@@Z$xaD)>`Ej!W=Y2|iEoO@c2L{AYq+DEO-d?-u+ug0B$#Cc#$0+TLiyc@U4QMCU|wa!~e&K`i2O8sNh2d|FDn~CirUwA0hZp1wTsgGXx(a zc>dFk`fjY?+eLbZ;7f&`34(uLq)!xlg5XmHzf8z+3BFRK&lCJ%!50f2kNAAYLcu@d zW0i6XUhb1r2!5tWUn%%>A%BhFs|4>A{4l|97W^zBzgFIFYY@OuS+ zz2F-qZwbNmfZ%Hc-z50ifTf02-rDEK~tPZfNUkna+FoJgN1 z_*B6c3x0;+7Ye>i@NU6BCCaT3e5OcWDfmf(Un6+A|Lhg~Eh7D9!B>cKYXzSy_#J{T z7jo(a|E);BSMb(1^>n*Y@Fzt21A>20@J)hG5&TiXe9vQcy*@3|8Et1 zh~R$_e5l}kuMXgTnBY@I`Ut__Ciqc;cM5yP2>y1FK34EQ3Em<2-w8fJ@OKD4QSf=9 z+*H9oBGS7A|9ipb34Xiaiv@pB@CyZhr{LX!&lmbs2>y>EeWl>zMfx>@|5Bv)3VyBN zHw)e-u1ZHwoS)_@jd7KiQ-2wg^65 zq;C~`hTzrN4*!2q@F9YKSm+-r_|HZ9Fu@-Xe1zaL1wTsge-?a<;IjlDEBHl%cL?4t z^h^-^4Y7fui!5b={F00u}EJl_+x_KA^4XCUoZF^!S5CPYl3eSe6HXR2tH5nO@e!2vPZ0cE!6yp-_d@?v!5513F2NTGK2Pu?g`8r+#|nO-;ERPE zx8V6tz396Yf}bbSR|@{mLjD@TKP1w71^=VqHw*q*A*WXG3k1JI@FhY{z2H}g^m_&W zfZ!ViKT+@p1m7y;HwnH>@J9vTBKQ`;&lh~F;44JAil6h+^V~m)^dW+ORq&yLUn}IC zU9zhhUCcA7yIOU2$?nbd_B6TNRV}#R7^Euu-tTM+jT+#Iu!Vmb9%0{ao%-HGxaTzY zG=3O3L*Pe&%LRS{xJuxsfExsU7Pwj9Dq!0{UAC6L2{=mN8epfuF9K%>{4#L4z}tbV z1l|eUAn+T&%>p+7+Xi)%{}ynR!0!M%1^xgyL*RYDny z;AVlHz_uYB22HA@Iw<@>JGNVW9+060V7eZb`ce+pbB@aMn{0)GMAEO0ZhEnJtcBH$>2qk)|Qj{(jQcpPxKz!QP11fBxiAn-N7%>p}tZBZTN zPX~??cowiz;2VH51Wp1j7x)(7DuHhYZV>oR;AVj{fNdi>%Fh9g68J7)r@)2483LC8 zmkYcAxJux~zzqW52iz=hIk0VHNBQ>yM+y88uv6fNfinbt6u4aACxEL2ehRoj;AerG z1+D_NUD#3nCg3Q6Yk-{szX+Tm@XNsE0&fSd5_l(YgTQY9Hw)YVY`dtV{I`Ik1bzqD zDewot83OMEE*JPy;3|PX2W}Af3*csfn}KZ?ca(nwI7;Aeft>>X0GuK4G2n86PXbp7 zd>Xhx;9r581-4y_@<(-)-yJwg;GV!vf%^bw2;2|2T;M^#RRRwIZV-4laI?Tsz_!sH zQ3B5bb_#q0aE8E1 zz~utp0$e5V?Z6EJ-wE6-a0amLl8*9ofTIMy3)m@eA#jGkCBWqZF95C*crkE;!1n<+ z3tSFtyR@VH`+=hbehAnp@Wa3v0zV2|F7Ok;RRTW++#v9?z|8_z0oyL?D1Q@hl)yE> zPJv$p&Jg%z;BtYt16K*W6SzU(H-MW3ZUDB8=_vm#;3$FL0d@-f0dR)E`+&;@{uH=M z;Lm{@1pWfJS>R@1+vOeQ9|4XM_*-D7z&`+I2z(5oa;AVks(@}m* zNBP}>qXg~=>=d{UaE8GBfXf9Q1Y9NX5a0%ZhXXeY90hC}+fn{Sz)=E613LvC1Dql7 zIN)-DCjwUqJO#Kx;A?=J1$F}4#&wiG9XLwhS-?(#Zvf5^I0?91;9G#J1il@(LEt-q zn+47Qwq4OtehzSyz;^*V1ug{65V!=mT;K)3RRS*tZV>oB;AVl#fo1&=EN}y`ZDL3HZvjUM{0^{F;17T^1l|W+F7T(oRRVtw+#v85z|8_T1KTEb zlz#*`O5ksSodW*=oFVWr;BtXa0#^xq8n{8=UxAwiw#`8Ku^r`i2aXcBC$LlCKEN3Q z_X92$co1-vz(ar=1Rf6DEN~RCZE{EX7Xe2J91ZLgcnolcz~g|+1)d08CGZsB27#{u zZWh=HY@5=d{VI78qP;BtW%09OgT7`Q>;`+%DTE(f+<)lvTaz)=D}1ne~U?2fBc;n#=nnD&^tjr)wZ9{bF`ft>}Wf?DJfZC_1kPXRaC2iJIh z#XVe?gO5U4_P*{UlwVtqaw1((o^9>zt6#~CudbUjt$Ir@N87gkj<#1XakTAiZy)?E z^4^T{kJwesSN4I?hwWj}_H*4y&GsQR2kk>^+>o&m`9DWmk{KWBPNFg*n<70f+_fI9TabOOM%~UXc|*6?aq#Cu zC)j@io=-L6U7SYcozdp}*NnDbo=TpXyX~kSBm|* zYO)XN6p8z;AwhNN6IER;ue&5`(b8X zZA*BP@ht~@t5o~efat1lM_W4k*6u!P+wtVM>a$D!ruC!xtM_KKO`x{#p(fbXvV8~b z_8RzY(kIvpUxoH}V}0yF8BO*9HEFokBVAC4JBjdeB(*A4fl{AjYRu>%sxQvHUjq_M_Wfm4A-`)vi0>0MH;$lKj{VE zb42KS1JM2haF6`10Wt{J<0^e-d5_LMLuq;-&vvAx-F`;8e{_*9{v4#M??^}e;X|a8vi49K_XR##2a)EjE@Ul-O(N?%?C}}W zy~eUuplx(}{yd}2fqq}{Yx`h&#sRKH)rWc3;TnnSRHeT2DwP7<7QYSksUwC0g zn;Us_8Sv-x;1>tb2Gq}74Ple5{z0;+&y!q|r_(oudFc5K^J5&x&@Sj1jm8pQ?#R{Bw&k zbRTy0@svWo%;U3X-t;=lJ{0@$K6(oIrlq4D?XP7t_3@D0bhI6{S43WSUp}p4h@-B_ z9uckX2~W1C{lw_6mI9 z=g)$ww~erQnhkM3I9y?WQu9@V?- zw#mDI5f|_}p`)$7yV|_INw|~vCRwLVu z_L60%Q`wFIo~QiEeu~Qu>W;FzD0jqAchV-<%#6DObh&?k44R9ryV%+0=5}(0n6dK2 z@0`B2f(?D`w3W(%jVR_EL7lAnQG2bo>gDRM<&x&AA@}HydEwa-( z=o=BN>UJTmOh@$~f2O{iU{fhggVzr6_EdE=UQ)jGxG&=g**FLGHF2q*v2B<;={o4K zne`wW_~+R(gxkYAQ0JM7^gEIMd$d9O9tHmisy-W!7>sd{Vmr-+T(%(3N4Ou}Tm6LZ zFjCO&KjAx#6di{mlqaaSqi$-5nimwTQqC@kt3Hk~8nS$L48K(UWTkzf8~PZfM?Jlm zmqwxw1oc*R*TT-EYwnQiMrXtSGJDP%-E3ENhkB{Hbl{ENL7qr;zSf!AVfk=VkMp4a zA+B#6%Ni$SQ6H1CNcQpzFdv0Hl1s88>j!zrj%U!`q&w9?>K_CU}szP+2ycvGWs#>Tn0P4_c`iZ-PCwJj>E1Iuv0kf zN;XfY`>4zDg%ooSp_>DTwj^= zxHHI;esxXB6TRI@<)1q0)-PVP!-;k)|5Vjw;<|qEU%TAVhWHYFd<6Mxd^K$2>u=s7Rd*Te=`C{9J<~(= zU3;FI7kRop<=@;-YEB`>i~3f#wx=9NJo%dMH>0n&!G~OE%db(#^6uA-K7z4H`_Twh zcMyI=ZP+|i)kVT@4qrlk)gQJ|nESbtTH$NduP9F1FEzeT=_9?7o)OS%E$aIY%Ic4_ zG*4EDl^bw1?c1qeG}7GR1lpR`NGI$;(Yuz~tMxcG)vS{yLC0N7gE8Oeh7@ns#xW3N5Pvm5P4>zt;xXZLN!`pI?IYsc_zXrs66<71iL zi#+bI!^f(6B#c(~I-W+o>Yf`qbF?}$<1uxn;@u{UyFo{neB6wBMq=(<)m`1RvHz^m zDkNy7I#<2hg#Chp@EKY^JqBCTx(IQ7tipIjbA~?bf5V{D1F$vv3f9eoeB;adt2stD zjnsYqQ>3GOwBB1c6}s~H<>*G^S3JfpXY~pAf#n0%I5onO;~J^g9e;zIA7STTQTO~V z${leHms@|KE_Vl)+l)NaUs{mwcgSbPL#=Nu+O_tueL(af2j_KNtn*fLUK+osEpCP# zXdaI7y;iwK>3RMt$U_??)nmOtaw6+TdHRD3S8CotjDJmNZ)AlF0zF0%@XigG@@srj*rI1a1-_H7`^) zwbi$_!u*ZOr8(RxjQyBDPaY53ySuA8m(4NxLfF@h`GHyMo4p9196QN*y*lcixL(eC zg8I{%iuSNl;DdNiIAt5=gioOV)BKUfisP{JM`7P;3`&4I_?Aa{! z^w&GRyBh0#r!000_C+G`pWfSs`BY@evfC+dWZCd!%70sH`(Ug~e+mwBoL%ullIBFaeoWzp*-!ju9Pd!PT0?nCY=zUQnp~&n2xxj9der#yEv>=-<$p=aRK< z=#-BBIwHl27ngeeqSFqH_Ci+&`s16hiP`(?A6OZbSZEi2Edu@Joc@7xT}ykKYMhFn09gxeUck-Ip_Ow)*mAItEoh zr!NtIUPSuidS6nn$4%N~POC1}Y41haPdLs|o!21`>9YmxHXOex=3(CCD{Flc=XYG9 z^Up>8zajrn=-Ixf-$&57RyoFCo@Un5v>w}nwxab|I@(IN)2%k$PUP=c57+jF4I;4D zQI7J+)?{OQA=(LRJkrcI-o*(|K)0J`B6)Im# zAdgv(55l^4aLuKtKaG`GmrbC49fo?-egO6hYB85rgAymD_i@xkI+Ul>7PNAy zZOC^Gi1F#&!L^4^bp6xpwPLR>WiDi%VE-VUNneUh?XXeAnf3`*+GWUZr5g!bK7xD{ z$IoS3Vx9y$4yoBwO!LVw$T?rn#WA1OdxlhRvJcg}0&Ulh{N(4<26~*e?C%<@?f)V2 zy@EN-TIja$RL6drwU73rDL?ujkmbhOUG9tNIF9|MF_6)Od*oMX_)Tf>8}t2!&6r;e zruF&nA;-*9`uqBTUVAoO;o0+hvsd;4@{)`jSO(=MIT!K#{h1S%ei)kusGHKT1|&Tx zPE{kGPIX}3jP|1VJ+-%*N4`K~Qw6xoQ2yFu7&ozgw8kHb?cu8boIiro<0P-4>bt24 z6iX-IK72g-gpM_PbgZHHsq=@LwmqTe8J*Kqp)8V3c0Yo-4b2;tr~CE;b^OqE_m20_ z`rayo%A~Q*8rM|g_?0wn(s*Bu`S(8dpFru|SZAO58F4yB{nQ)jwVneUbxYAVA8Kn) zSw-syjN9(T={pqG3+}~{JE+V?mV0)|Cf~SV#TpvlY3__QQgkcUNGI(!{MV(ihxehG zAGcwxl!N-xv!h)$_0x(Wj>Wst7FJ9(HW&mO42a&7!!gf0LC2yP)LqX>KkS&3M&Q}j zap**QDy>+noL%y{&mOck+i4H>*!y?vaes zK4n2)iu=vR7S!f7mLKeyZ;f}8b=-LgI&a1N?i=V!`F{^xeREgLE1_c}?HzpxS?NRK z>M-}4gZPv3F?4zd96eK$v54x~9&h*Ui?m*@+D@ab&rDTqw<||oY8d9pqt#Zj%OuR9 z+kZW8Ue+4N>81-!ys*kU13#xaID+wv5@YR2`>>kyM;(~w+G^@BpJ=lO*G$8H&U$-D z_1Z8skK%0818aw@MeI=n)()XL;7rVsBKoND%Ldc4)!^u7Q8$X=h+nJM&2Y5Qm`H2g zC5XufAs_3;+T8VnJYQkHh*(jRS$`$QH5wlV)bvMQeD)Z+vY$ z1objqcXJrmMpjDp}^ekV*bdx}68zNk-EN%po%Dp3=`9b);Xn zHIC66hn_o{{O?!f!#)iBX-M>QSE{z*z+~T6pcN+UWB+mw$lE-}v?tUl?C?I9TmSQK%iS>e+|ip#RUOs;%VVbQbzJs_ z!Lvuh?vM0T==b&q45nu`k=|=`zfJ((6SAqC zb8&T}3~FC0BcID4`G^sfB+H5qdmgmn!&EJ2BIL9}Uz#^y-7-0?AZVT!u{^CTXr2T6 z1wl%+(VQnL*fBXWSb2!2SRXaa5lg>!V{J{mm5#=VsXX_iJsi?!Gvv^|%U{vHc=k*& zB3kdmyb#~!P*XppJt2A~BF7BKyeTLlJ$C9S%o`E^sQ=M;o7tp1%}eo266=92kVkPL z67zBg>QC{6(v0|%Z$3wLuhsK8>}~&oG&E;D0(<$!GqV?iaV02vCG1wO)c6Rbp?Qw= z9tid4@rVgne~{kMA5poaa}Vh3m#%&JV2pE})`gX{F5H&c!;_8i{G>g&<`mv>(Q_FZ z*MGF>alH*|gI4H(Ia|$XjAud6fz~{_%8 zJ!6DUEcAIBYc=u}9mgd$q8?cV+2b(rwo{?47qx*0k+!uI|uen&c*t< z56<(d!_UOv9E)=t&MR<^uYMLXupf@{2h{X{Y^;}SFjt;8cbH093+%wYa#f}s334 zwGHKwk6L!=ewx-In9tsB&B4ymbFf6zqZitb_Rh)w=)Eh<5%7$g*3ZiY>f2^_%TIoK9Qqf-=z*c(re@i5uvqoX=NO@)<&k5-8Fw31qw#IX*t>E2wXY6I@ z=-p%UBmmbSjjvvpcGPQTA5pJM@%|L@yazc{FRF`GH`DJzJXA+J>gR$_4?(^5qx?e1 zruM8sIfqa;YE#5?w8Oxf3Aq0r&TOPX9Oz57+Y6iyJPudH=xEH#lj5+)MSXP}>_qz< z6bm9k5wn85Ni_Fc_g7W70{7Q%v3Z(tjl_8u^i;iDC)J@%_nh0YR%t>Xm;qgA?Lp5D zNUnEF(4sF;9_{@tL)wU5%Ci`0Xb+w%Y7g>Fzo9-htzb5(ge%w{`8|!#8cN-L4 z08Bbg$JGP7C|u|G+MpxukGPm+VlD4R`khEeGU!=>wk_Ik9_mPA$&aw(?T|rhr6XeO zIE;PH5f@sznP=jgA?Fq3L7V&9o9b}LN>?AO%X=2-@P6T7MQd8rpXP4+QI6xcy4Efq zY3XX$c^^UECv+KlZ>}SjNA&Om4egw-`cHPHl zKaJiEqyE*^c+dlKF&=1N@Q?G>Sa1W%>uM}GyW|D4UdI@?1@WosyuQ^N2KTGp6yCp@ z)^+iSRqJQqeHiph@5Sz`*InYiy6STG)$6ZtU%g?H`|6EXy06|e)qVAI@$RdGf;ygs zQfx~{JI11pI!5Bzp^nKkPvkYA3-73yvGfz)`rK>p=J77?UftBq-EUodFn(jsbsm0W zuDM~4@^~Lmbybf{$CzNp_%H+GLNLY!6K8f|y;hZpy~s>@Ht0^G_bBO^B|ST$XSDlU zXnpuUSKm04N$a8ijrvmAz5MF?<{tYg>2v7{}0zU2xYGLU#c&a z{g_{UBmbxCYjY-iBZU0^WSl{Z6Pxq^SZY|b4h*uP&vJkU2AZ7(4 zX8l+3%E|GHVii3f{u%RGJo}68g*v-wUPtdcSkJsg+`{}LaNG+1KZ{!jF>ca)hhi7S zEs9^~qux|5m4A?97wNaLi~3u2r#ZV9v3VV0a}{FqCfH!pjjF9XY_J}2dIRG0M#Sk& zh||x_a9?ffhFFbt;!@1}e#ZXmZ0v7S88q+D!ZToczn$j(^gNU1`?PoUCdMiU=9$_q z^d3k!zYlO@M@)Bg?`#{|pQE~*C0qDOU;4fbA+apEx^C(!O2>_HyyYE@^A4^@vOV7%y7jc1T;*pIE*igmm- zm#DdaTtt|rYBsGNuw?D`oB$+vV}hUb`7xaY*PhbX1$T4`R;@h(6mJu8s< z(lh)tYn_ZWC_N9MXC?GZWEA%3y^uxEDQuy5H?1GuF@z1);#oZQcT*11o(I;V@4|lM z~$yqq$;!UvqYedA2=jB-Wtu%5%}MxayGuoYhgi z@{)I&(~-yNqOgT4Q&ICX)x zd&hS@WOsTFf!MK+p7-x+x0!b{5Yw&N)3-g8H-q=?M%ZB|?|Jy9D%3;kb(H&P3;OP<@9{eK z1Mr+9X4w#mORBdmS#x;D6j4-jW}Wj|HLX`hZg!luo;hLtpE3>kyQ%V|wP&Wz%c#6| z@m{<~GfmlhtySITr|}aXuf|OafRN&r16d3>7jAH3D3L#i9U<5ttJBRC}B;n zzeA#T-seG2>|J92VgT0p^z39{^j6pfdxLt--h|jjzE1B9QagNR!#e~R2PrPeXIZ2_ zy&G~Gb&uivPWa?s&_3q*o_>B^sbd|!@6k4MnRnAE-!Dij+nL_!9u7Gadt-3#X`h?{ z)>vApWkmGz*zxTSwaK?gN6#*Ukygsu4_TyN8s1A7iT9xBT`1_05`jEsoalJ3hvq}H zCrI_By+E=d-Vv#68-aJ6V82E9eFFOkVfOx>$@qSvKb{*kV-E?>j^-TtZ0(RzeE%1( z?9rKcpM=`td+1{J5NKa{K+OpKeV+N=fOLKxI;(pzuSYuC=Q{Ww^Ioe9&o`TF`dRr{ zH+0>N-`Kkydk|xcg1wq-_=0=pvJb$owOG1O}2~Z-a6?x(jiaMC%DpB zM9+xzejuJVon6uq#~w+Hi+*p49M{&aUJ`l$S7rv9BxgY8I9om8Ri4F#p zC(&LJ&2#AeRr=_6qd-TlBp9J?N-yk3BnjpN!%O%?Uci6q--# z{b}>PAk~weU(jBg%~qb|s=wGn-_eamJxB)a3Au1z;T_C{(2Y2nBM?XF@Y#*0gn6>L zk9S<`DF9Elq`G~C-!#9`@da}mD_;8cJun}peGl~etr4hyGwL6%Y;!i#ya#&`RR3bs zpX#pg?7(|5*Bv^O?`=fg>0VR+wYTdyinyAN_)71f9rVRfGZ!Kqsjdoj{Sh)1>T%qv zC-lAsx)Mio!1efzalb{anW3L~kiBm3%{#b0*w3N*U|#H@vZ>s4s1MeW`{G$=iu1$= zL7#QX%-cy<>-~`jrF~c)y~nZZV!UUM^@SzxZN$xb^l>WdDEbYRXVtq()|tz&O+F9X!T6w28f@^*bHoYYyUlG{pCs7?gVu&uJ)bG^5SDc>m=R zaOpPeUtxcB3;gnxC|esnBZK{u_9N!gGivL-1zOLz!CQUrD}1vw0^b-oUD5bfWQ?Z* zwx+p41kzY}sGii`hcSo#3g3$c)nDq_6VdT3i1IEDkS|`OONR_yj{6c%A=1k-GP_C_ zaj7ROfLx4A^sKKVhLHYvKW`7d&!GCYA!G3ltY;t6QQRfDR$9^{1biv#Y0Yz_Uh$*2UpU5l z8j!AD_`xprgHGx7a|Y^1S9rD~y;r2);^#N?jp!=G12_K8;CYBg6o0&k6OZE^ATPxR z#H%K(eaUC~M>yNwKpeoBSOYoRw%|P^%184v%I88XUj8wpw;t&!zED3Iag{H9qfU=+d#V0QkluPv&x(ii zjN0Yv8@8GT_&LSIy?AazeS+fRN%(vMVx)Z;HwE%@6q%{jCwpCj;@cSGOMD+mKIM z{;GXT#d;ou{irPS4Uw7KW_Fd2-S#2Ppg@4HYM#J!YmNP~Ux$-7kWoCu6(B$M827@_qu zGO0Y;C)_i=qdqh@_W3OIr2b2JNe{VCh`D-AQ;<6;;@i&SImNC2kG=Pgv%0GG|KBqQ z5EWB?H1a{7?J_EBW4nqbZ6 zATuMJ5XiS4NlxRgPanY^rHCt}ACCYB4aD~&b3f*}&S3SaCL7zLXLhdk&pS$|%bAnP zDRjPzykqah#s)K&_MOUDWgC>kfLWjVH}G0JH#%1!Yii083oXxv(MJ8L{Y2nR|FoY) z`!Dld^R8w=k*?qyNq>$2BY2$wQQcKRAHk*J0oTVt;Cvs$Tp!=1jpXOs?7o~n{Q<3&aal+{XT#^Gm{;Xa4q7Xg^GtG(-xh!V zU*ORkCT~Mc41N%Bnxo=*MejSq(dvgaHH*yk{HOeWKWlLSFU0qk@S9)3cZvHK!t;ds z14gjLFuw)oV#jBl!53dWPYgfcbq{<{JN;ISUwMfF_})vy#G5UiPddJT#nCAm2BK5v zn+x#ty)#U3UR-^48a$(OpLKZZ9Uh(C>1DnXTg})=oyJV;=zjQjCN{Q#IeaSXbb#+# zO--AA)ANn2(ZrKg0lTnI`6A-L^)}z8 zI)CyF#8=sK*q0}7)X13eCvrXH4>-eO=IiOmtbw&NL%h{Z9!7UXC?=Dvv14I3?H>KD z(WR>31kTS^R?kqLZzJ{5GZ{;ge#Hyfx#QuH=7F9w?$Gdv=MC?#zX)Bds)k>}`vCZ| z)Dx9qkCtBEa8dP{!MiJ1(`MrD&%S-(jSrh#Vp-_%4FrdrmW*GSyhu2^z}d^0JINh+ z5#NoW4l)Q6lkHs0z>7i1UimnU*Pcx)<80cj=xkcW>)Z!%!>nnWl*4=gp4DHz?xKg_ zO%h!ZzjT&IIlm3iA-*FYa~GHT^L~GlcAJoavtw0WM{77EU6Gk-Y`y6G8E_Bt`Qw;f z$&aZlteKJ@(-Xj!F&_1!y|d%^-WK&S()6LWiSy}$x;o86_3WK@KJI>aWg*)(-#PhzBsP&_ENoyE#*r#|%&yy!p&qe*@d(n>@;m6K&SvW3T z6~3=#XxI(>Gau5rIx6=n_%qnVY`S)a){(J%*LtQiV43%~U$k4i;d=u$`_g&#;&OWa zZ?Wf^)3=t7+yqYM(U{yTzp*p~#GTLLPpgi9KXIn34a;@YRy5M@G<)v~b<6y&db3X< zOEa!N9-S(G@=w4@f9%<@)6Cg1lk>bNQ@en%#>et)Xzx9IbcgsM|FoBJO`*Ncn8M4d z9mtM)p2J-(FZOWk%%1YHwnlSmRPVor{(tWJSD(_Wn(6i&TSan+(JRGQUvhfe2>cU8 z@Vg`U;|%t?Z`XKKGjY zp6BhsxLoBlk7ICHM%(-GnZ%pyt4Fv04jK7;$c5l(AHr|oGO^+Xc|3L}$mOUcbmX}$d<<}lGdE2~SrFM&f?fdi5sq3t-JwkATkHfww7+^2s zGsAh>jnGsN%|Yt;@GFc-@anI)5AV0g2FPF0oR=-gGM|S-t76MOY&YZGmT_@^7Jo%C z|HF(=eJbX^i{CUa?!o^!3mT-~!to`|HE=N3@wM64VSF!}e4icTUVeWE@RCXT9g%;r zx0-t!tX!srimytwl|AdF{W-3E;$kCHwcTdg`uLyrd!0UJoIhavVdOEhmpdI?E7-mui#VQ2~xwtTYjzm3jh7YaD(}7-?LK>KlR((-}<=2 z?tjX!eHpx2YGCEZV)wUcAEN!&=oz+#e(`Um!=tL?3;H-OXwK|=5#kl$LeI`zrfuKoDMpYy#$x?r`Zki#jOoaMArOy1V5Ir@w1b z@}|_?_l{gJspmxQW-)iSY}|uBm^-CZtKY}?Wv{jFr~6J0b&tzgj9)bU9Jz>QeP<5- zVK#fU0Ws|d8RvHf1>66TI;2YWzHbSJtel0-lWlw^F{H}deDpmhJAW`Sh`sM}e8a)4 z*`sm?pEGtIUuIP9CH_t`W}PQ*;9iJ|AlQQpHvK2h>2qyg;-2>v+iuAj9*-F4x%9=? z8x4a$eehl}O&7erO>>L6K7!Ard;Sb(Sw6sb-=DV?zMuH_BOCtJ?AP5#&DYl533C=z zx^Q35psl~9W_atA;P8Fa(fyX1;ro^cJ9A%|P0h~9TkreA9O`vWF*V4aA3uC+c09Fm zmDI{nFW5uf+!pHQ?p56!wQ^seR&FUg@ptQXcLrf@N;!2uiLIwFp04TndbdpA>)rO< zr*VH%e1ktnHhguf=CF~4({aVv*P&+>TdEItwFieErjM@c?Vemc=SJ+lN09pjILgT1 zC>HqvXEUS&qmsdJ<;MP*bHwuhbI_qZ_+D}=s$q~1DjS7D9G*%0hdLAHZiNTW;ojhD zf}J<=i~tQC7?-=AzqyN{Y72Vo&i~^FaGn7f^lHxw+ft6NQ%!BcV?2}H430ZA{bBHD z=(nDI^yq%YTe$b(mgD*F1pYgb|Az73Nn7WFqq|eNV^e=pdj;)!%MMNNdKWhLmV5T~ z9iM#>+wuH)tWomK{|OzRrg2kS{~&$3`itC|;L-2<^c%jC>~$Tu^jQJi?fm{B+UmTh zawp2!nYny@UPi>sre4#=`cD`+?ZCfKO``Ce44y9Fd)?eeUw7EN(OAywVne|xTjbk+ zivWgT0h`^6M9sHR2n_1Dh|4v#}7r@gXkgydCmyWvmn8pb1kCP*B* z@CMe`}%ywI}_sxyuQE2i_dn@I%9=INmu9Z|{+#)4A)0 zyCYP)G1Ba3QQTn8Uun(y6@NcSz3emP!HGx9%bvgdwWIhUr>!i{RR3{5cg(2YuUQ%9 zmLNanlW*kvbMQ|3l49NjnNz~^=ufc34I@6!?_Y;*KL+_ndM@8v{19)%k6+NY_nGcoP*vg{^LJqnAbU7(ZqbN`Um9hY0;f<{_mghx8!#rI;(l0xgwp=-7?*k<)P+;{6{}8;^*f6 z1)N#*J$tu1^LBP>ZHhCOTIbaFXnq%uxKn$&XquL%3Hvvy>Sp@X=ZP^sJz!`ngJSo<9=6u+`T4#v1jn)Pl2zhJ~(vY1LRXx z1FPJdbT4JbJf`Z0;LvZ%_lSlQBuC_cyv+Qrdx5=1aCTzDlJGzM6Ygc+J7H5b^|)I1 z6>6_}}Znt-sNqZ2|cF z^SHlAzH7VI{Pv%@x)$oywMI%7gIxZvfxBxf@Gm6$dl+NJ<^AMW#r;Zb$UZ&8&bU1S zdyko(7e5pI#dI)^y%%J-7vvP#(PPsg{rYRs5$9uY(@l4Z_sJFYhdjT~m3`)K?w1&J z`;|97Y7eM-zOjmqtW zpUQ)!$cxRwH;_-SKJTX=Y>+vttz7oie2>dbYa{E2>RqSaQoiBE`trBDedH;3o>pHz z{_VGv-}IvWJK*n|UkrF2*B7lv@$W~d75_(S)3wGwvc;X3V;xd1Jj2}&xAWV9st@j~ z{Qk}tPdxu4`-cA4yu*o6KYg)h=z$k=XMT9!IYIWt%kS9o;=P$q?5mo;@5Nzdsly*R z^LH;c{lk}EeD*-u*D8Wxd*)oS=f#Pq{qDsxhlelDdqwN+aaEN!)!hAI?(iJ?cJ3ca za(Cxz3-3(7wsB9(DM7gMwiEB(c=P3VH{CpkdpxVTQ~jfRs$RJH$$MYB{LahE%Jy`< zwrNkhMgO4?lSlnY%4px`}E9C-p#xA zS#lS*ut##+nqc^r@xjhb#7g(3nX||!;q1kh8yX%;2jzQig^s!)@%)+4Qo;VgLh`6- z{!VNznRPM0 zuW2Kn_nUcR?OEmM;#}2vVMQdcWDt6f7yk8(9T66`sV7f@`gd_XmHC~najZ|;VV$1c}!uOIl$I%)c!H>s<0 zD0df+&Y>qJ?pVd|$~Pprze)KNjp=dxtm)Vnn=iI^RCzvhau>GYL-PDk{P`g5)lR*zXh?j*&k zvb9;pAf9CKyA)IDE+)1AN5=ODXt#VR7+po*}jLdxx zdj);d;_IjSJIZsd$*H49ryk<(GtPV`MR z^Hj0zdWZ9Q;J*faZ)Tj@cZ;{}JkPZYE{xi(bnO&Z`92PuxMtuIdmZn*-2IF0Cr7vmX35o$q@7W$EwP!EoJK zdpkN}b!!Z=ywuc&?&NpbzFu@g>!;#s;!3mEEiW4jqCKuAvT>)~1QTZ|1x51W~-_@ue;e z|2>9J^`_w4X8Pj1!31#rfM=tC(X$VL$IL4u*BRlXuB~cT3>}$^!_hH1e$C&aRqqY5 z^0oEd^~l4{L0jML{TbQ)6myb1wV9K@#Yd}WEgOHRY;6`hYU`*+D^AbVfLn7i>FV>P zlUhIGbwa#j%fS8~x|7t5D5m8+l98MErTAL>n#$k3+|4Rp2c}+*`={A2Q-A6!#qW}F zJ@1rKe5~^%x`Q`EpMGv>{-(8;C!dG;y9wTi9_Sh&9%x*?db4$#^C3Dyx#=-kEU(vo#ATNR{g3^)l(F}diwAK(hgSl+r?ojJq$KN z`5M_X(UU8JOL&@-Gs7!^i;wjlU_S)SFT%Iqz~f)TD|_GUC{rikc=kf4YNa)9?z@`l z=n>r-_s7BEbEhd};cb)r0M$CkCb0hGzVoZd-WXYZ3_j7$-q8iF`1-^+OkN?vg>CD@ zcaTlFA3VhIo9#RqnM*!Kj(%un-!B=1^sLXUoB6d!c3t-QPtYk{ei!3?09esA6&mn) z%vlP_+mH7^%FC)e6wlSZ%<))0Q-=Nn`t|FY`TotK@0;`Ai{G;&U*s}fC0h$X1uW?$?wuPeuenh%P!!{R;l8KmAUhd(*RBf5}An&-ACheEn3trE9O~N}GlA%md~L1G>_NYf zy~CWRn1NlM%KowQt2xsblSTC@J|-)a1#;M?K2;Nle%7WlSFBfUU=KBe+tJIvhZc0v zz59tZP`a2oF1#4Jsn?q(Jyd)kJq(KUaN~c(^>9?~WpHKKTa-Vkci5D1-|2PGe_*`T z%d#XnvTw~hd;mD+ZdE<_C5!2Nf12mgt)@N48IOUKGNvme&`SlUyQY{X0K#A^mapo zd@1#*y|DV^(C~LW7w#?Kp3L9>;$W2D7tey=gs_k28iV%r2lKn&{~7oRJeR)YagG7! ziQ!WY=O=(UmA`Mxxa*mQ;n%zpUZO#Xe(LEe$40ZKJ$K@k*e`kD-A?Q(tnyB5xYZ>&uU~VUeg&%-trSL(A zS-1SU;OTjZbq9Yn$_EAP|IGkL`Jl0H@4fxQwfMyQ`hIs`+xf`G>t;QER6Thi%~|>5 z*j!ipVsk{|hvfN3#6!z-@|FI zInk#WoPITygRz*w^Iz*|p5OnrRl0(n+~{!*8drUBFaEdo)}$Zu<#ZlU{i=VRd-@@K zSKsva)jsB+;+O+Q7e*O7Dw`jqF5L7iG|BH{{jI&3HYt35v-iZB!gCk9yX-tAD6=~J=>1XX)YL^Q3LZD&pn)SdnvwazDF>bH-!gdFj|Ym z7te#h%$58ZWna6Z`JyxR8oO%lKh9XnsPo2G&2d)btG6>h$PLY?Wfj?=d_Xotpui=1bvRvAmFc@^d85pSaw-yfjaA7C2fzTs~wX<1{uB zeaLcFT5F2dfSJsV6m!?)rQm73%S&aHn=$&5@9za*uZi=InwcK(DnE0rtZzPb!GjX5L=5_A=Hh&Bq7G!F9U% zsCqfsXQ-Yb*C6_|z9q5K zn#-EkdUl-CA%g=wGIqk)eT(Y?VEuc`j%;|apzcHGQpr)i@Cxgo*0Bt-l?`KVQg3GS zwpr$Q7P;|W1oOTSU*{$NS-ez?EIX%j5wczL;De>I{Z_#;^JX&+;r&BEW==bj6n?12A$ zA-elqVi0#wslJvou)xYT9Y_q$jmAzF+YxU==k~e&eqlc!b)UcZ5BvS{U)fLQ-XAJh zTldh9;;NZJ;{9h1P2E_{clBA$`BU{*rE#zp1liJdGmfXp;29j@sT*`^8+O&;6Rxo( zaQSfu?6vq>K{iw(+fY1C(Q+nt0i_(?{j7b${kUs$3_44;`&J2>ynKt-g_*~oi*cIu zMzs8k!x>*|{5a9?+T)Qy9cLd0J(l|8neu~UJj%&eLN@mPjeH%nZ;$`6{YS{uf6wrp zeUKUW8B=fhW&XL~J`sZxPW2U+N2l$pK(-!l%H;8l4;H-_M|SqVpjA0p+5J&T-T}h1 zyRN9%r1eI*m4Yljg?)&TrGL7`S$TOM5Tl!Ka*F&zLB0VDV9pCAwO{C7)SxKCmZ!N_~*4;YyaVN-K$S<>hQrLB%EDUa#efS^XWs+QN79UCU>r7@j z`)U=b(IL4a^RBMG;r1PQJ3Grmz5nv-iSm&3VCOZ!Yd@!+TH5#Ucb56Es|Nj7{pNAQ zC+*^{)|rdm{E*(SDg0Lfqjx*(m~blf=%?kLhbI|)xo_6+4xsB(J6}T=e$M+ARCoW# zAmx(J$l+goD#<-0-4{@2%y-fLjZMMMMtG*Znk;SWvEj49rM^X%YNgem`r37Uuv2~Q z<@es#j!u=_A1NOmYOH#n@NRc@d>p*xJ(@m;;S(6wi#YHy{`4VAYSskNJhNK=WDXaUGy?ci|`#^7o^T<@gtG2jFvSmicF zdpk195aY*v0oeo1*{5e!h4KkB{;PTRYWdkAYoOU5d`3J)Zhh>>g0Hqz-u^lEnVpV z^1g`l2>21In?W8XkFBvt?^Gwa`*-4_JsvJNCv0?ZeZUPrrX0>4 zP!4r5IVh)A>_ds}VmTz>yXcx7lfzXdZeMy~_d&uC7Tu%Dt={=9Tr zG8N5|{{imKHRGbj_Wv?|!6^sj;RIvHJtgeqK3TPU4mjoee*>=sFCEZxuPf%>SO9DY;Ju%#eqM+N()Z~66mtT5w2%G$?W6G5bT{4E=)LBJwO6io4Bnhh|MJJ{ z;fHM126)p;9@Ebc*^7ujF`Ko~y|+6)KOFs=8Smyw&PdrYzb(u;`gK>V^l?9ZER1v{ zs==}ChP!s$m-rdiPBe%=;%5)P$NTYo4S^N?cY@d3xF_>GHMkR=ChGq_=x}?#3BDT` z-P3Du)}J5VrychlP{5Lwd&94u}9-)7-M^m*vuDuOctCO1(9xi!7c)5d9 zz0|8u+x&geJYo#xIq8q)Q4MyrhjB=U`k=R)aeS6>^s@eTF%Hp>PV}R{EIJ=jNWZ5| z-QUUk#96ztw+x%~Dsw}zVv;eWxGP5c7y=k1knBT+k;;@% zrH$U%doVG!O1|*jZwqj#B$!VLZIfFAX!n79{R z{}F8zQz#~oUHcyVQ#`Kv1bobGWyp)%V^ueCV+C?E=QV}}JM>OyyUynGCc>LJa&(7} zFJw!l7haE~Lp`3J4WYvFDN?lJIbe0%xS zyY4+NYKXxsPFv?In6DRUsuPj^ zN_U_CciD>_(Yot$MY*NOl>P2pS1adduo<(E@3+0}xZ2td`Hsm`x%Y(i=eN9vw`+HK zsN99l25Sx}_n`Sa^P_J$)QrCA9esVLpyR~ZT_drdHRYl1kjO4B4@Fm&m~$#)&vx1z zht7EGy|-_2=Z3QQ(<$-{Rq!SYj&HKAKZ%}yfbYVcVea!jl(oX2#8zx!pN)HmYh~xk z%d+^j<8oRL1RQTN^roy)m9;8pCy1ag78|LK{;aXG!q z_iFf%Vm^CZdUtOoF?JJqlB%U=1^Bhc<*opR99>oB(9x+UqYpPSzM8YR(>^v|js9>K zqU8I1V3enM78*2`dU*64m&+cta?G)V+ZQR>t@C5dqzG_<=qwQ|mY@v;ZH?WyY!%o_1yn>$_gIBGY zhpqIudoKxvLpf{BJD=N;J^0O2vIjOEILJCH|EK-y`Fnf<`ZySi2P8+?Yv$!<-7^`a zW`=KtU-;vPvwuFiqaJwQ|8CB+%;Mg=isW0uH$x-1M#wLatx;Zk)S5 z7yAmA=u)5Rzap6k_k%-Y@cTd-gXpdpMmz$ZWE>AUhK%J|KRkPj@I>^CDnSo%=sD4UgnKhMn6d0X~$%~k7pmAMSgeMx;B_+n?;=NMzG#25B#x=XdxQI&zqNjEsJPS(T zAqE-9|PyUQ=KRmxK!V~fNrV@N6<``&PPZi;b_9ykj|{@1?GNOy&5 zk5M*R`?bpJRbbP!2icB|mQR?(Cm~1p?)q6lsCzoKhWs7>jlOc)rWps04=<)pSLZzx z%XQ$x$ahn`#D2*3Tc5ONiWHZqoz4f;V7qlkPDTBR#?F5bTCW?z`UQU8k@WmCCQ{712#U%pDTY3e@!?$9Ztn?y|h~cPQ@zH5v@n};k%4vJl0Pi>(AWS zJcHJ{KF&T+!@ktWfv6rMOo7QZB;sE6AM%e#NPM|HN*Bb%#3|5{V7&4c@@U-661}Z*CJoY_(tXu%2h&RhOr4x1w5ZlTg7+2 zeY`F8%EYAo@hyW7KY}jH2Xhy*;X!3Y*9oSNWQ;DI+lc!aBNy13voG#5^|~gW-waO4 zNB7+O{G<4HG%@@~WrMQju48{st;>~d-hRN|hhg?w#@o9vq<_jQ%SQ=%=dSM>qj&1y z_qPY@v(E?NY4oGt{9PFp_!dF$gzymK%9`^?qjHDwpUpk6I-@vDaSP0vbJa-Qt1 zW_-T|-t1Y8&)@Zva`!w%=VTK3dp)3GpYGBSPoH7jWq;l^f;*yD{(u^iQIBPL|Iw(G zzb8MFgFy}#+@HMl%mo4DH15S$r4M*jiN1g|rR9$vI+Po>kt)=xC_eiQiZz$%Z{ zO#lC5zMfXd*KdO}&esO2RU>0h}xUl$hO-}Yj2l_S}xPxL_cY?GZ+@AWS$Q6NPvhXCdm6dV$lcNS3~{RBZ`oMom!*s2 zZ~Dg8`;kXV`6*(nuA2Pai$7(KWHtbl$Jd^E>ml@DsFAoUS&?#fj(mSDW$mH-F=t;IL|H z(w{N8$lR>E;2Gom6Z4_(_(RiG8$$kc`-YQ(sfu;Sai_gU{LCoyhiIr=Faj`%mUNz0&>e;=l4e%KfPyzji&B7{}i28C3^}7py*B zU~JcP+WykFJ12GcHvV3XTz(2&_I?r7zKkjGboC@9_OSc)klB=O;ut zk526gnRV3CFa{i=Re2k&(<5jT@EOOsl;0$)$NAhreVe%x5tNA{ovNC+Nds;YX^Wf7j{z>B@-4Pm4hp`E}DVb-<`7Ilg z*$Lls_26q{PAV^0j&4-&UvR^+L$^V<&J<`~_Tf)A058}vH#8j58IMMO*ZBjTE9}E3 zJr^Cz;GfiU?t?aKAIDeFoG^JR=B7PwKu#Xr+URUzncLU1KCi94mptV=n{}q|!ca9x z(yi^tE6L}h@LzoPx|1f>F!Ex5M{v{lj~A(Y%KNt-?tu1zoKAYUdw`SgC;6yd{GLgl z-`fYzE{*ggpZ~5@o?ZC*rkQ>}3a5p}JS^!P*edGS-ze11Bv?i&s{vv;miD)zLjWPDg?4Ovi+Wm?qa4WZ^aemIV z?`5CnZvGxpqP-axcX;^spIk+I(RF|^)c@(|RMm4-lGhg>J%3G`-s$1x8VAok%||wT zVQYDnJ@4i9U%r7~M~rX$U0a7Fo!^1aEF1q``kD%l{t^BEmGqxI znSJTLDPbA71%K~PmL2->6Lt-k&Sr>V^t={4%yDy<;Rj{QVl?YrEotS3#VhXRINi~H z0=BjgZb;REN-ysj;cy3M)|>C<*PD$6wH!Z<>hwI1Dm@PDV&HK2ed>#lMUSOb@m|3? z-80emJuQ3@IPv!xWN;7TJ+k5JTg#I69H#a_sQuim7*71%&pHk4KC{Ql8l%03xwO$; z95%kw+#Qu0O}|;zE9xq@%YN;^mb?cZi+>L-d+AsG%NBi$_F2}F6gAYc z;hJBPw|*n0B>owh+u>k>qer)YjlWI&2`s#-QhjDO>)tcYhBZ*T@e)3httEam+J6u} z&ACUQ@jORg;%%0m0y^1?5KnG`M%A4>;Kr0J9McPSe!U~y?QpDdWBQ1rPc?v&on$20 zj^nvqckCHbuM;2np^YO0#wxmfEUq?-Ij<)FtNjuAEZk26EoQyozCC=Jy{Q}CwX;m; z|HdWO9?yIvmN0j2q;5EI=k35Aq)*9BcYi3RKMot|#`;2fy3^t8C1E{%r=TC*H11wy2h zqcKh!ceFt7sN8PuLGk-RM&{7<0DKia;577z7SS{Te7Z-$*Jt#yH)nlU{9fMCSO;&u z%$lt|jZs(fE}#ka%(Bk)$=-|p#mGXRvP0OkZTq=XK)!Jquv_>|dZGDK|E6F`#|fF8 zeH(81+FdW+{N%ud2;8wn$JIAlX#wPIrHiJ`jbL36-mD5Ia_r8DXp}X)u>)A^g1~0FN zmzsA8?#;-EC(OTUY=hBN-uLreV8ko!HEFJ$$UIA$yFJRQn5Qq4V|Qz+ZQF{>J43}+ zp1)qs9;f7E@Ujn+o@Lv7#o<>Q_2Jt{Ue7}RB1fOck*IMxm?;ZiaB@w!{=J@>KCsXK z>~MRWm8IbNE)73kf@bxvSR!ETo;LX`dj2iwn&fm)cHZ~98~k>BGmSrS19)}U!jTQR zt(C+-EBU+;SILgsM`Mbigj^7f54nF9+yH`joz`gg$Y9%LPs*&%+nZ zjg_={nl^T=uxqB5b>}?C&-z3-(X~@7u}`!jha(&AGyeFWSof~c`D?dkHhh6SJl3KK z@UnZCt?%pQyn*cFo!8Aiyjb%b{%an|&wrq&%;b#Cnh1}^;+MP+{*LP$9L`8z5-PSs z*GJ{~$-6zEnYFJ<^Z(bZnZIEylF4(db+?JX* hj>&aFGyD0*7NnS?mdCooY-H{Z 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

+<{~9M4X5x;Z!^s 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⋘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�`^{081dxwNQlT={q@cMJ;7I?Q> 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 #J>@Tcj^2oNqoutut9#0q9+=Um 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 diff --git a/third_party/prebuild/aarch64/libmmpa.a b/third_party/prebuild/aarch64/libmmpa.a index d7c29e2b85f165c17eca9700d17cb7ec4e4235a5..7d042c4c1e13d2d63065d39ea6fe44d8b5ea2371 100755 GIT binary patch delta 13805 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 delta 14890 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 EAJC3FN&o-= diff --git a/third_party/prebuild/x86_64/libalog.so b/third_party/prebuild/x86_64/libalog.so index 051f85d9b9b5482169ebe578cce911ae560a3541..4c8a45a4fce43e3262fc1fc2aa162588cbbac055 100755 GIT binary patch literal 173984 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 literal 164208 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�a!R=nO|`dgHFMl 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

;!u4`Tw-{HQ;epW!i5iC8SIl2P{|t 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 KL87U*q5lu&?{icD diff --git a/third_party/prebuild/x86_64/liberror_manager.so b/third_party/prebuild/x86_64/liberror_manager.so index cd9ad8bcbde41fabcc1ff2895b3428afcd04ecc7..7574476555d5c637eac88f0224dda2dbea1f63aa 100755 GIT binary patch literal 1133320 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 {PxoPD*q@UWYRj>SZyi?$_eWUO1 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�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

-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

=UB$yHcjgxTivo#2C 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 literal 852544 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≦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ⅇmUZxf@@B({dMX!YR2EFThE;124o0xg9UU zak&j&iDPmLz6wX>CcGF&m z*8Jl*&d8PcPdF`?<2Ia<%kXtLDVO5waY8P^H{iHjgm1(#xe(ukqjCXWiX-xH#QA0% zmWOaV4#|V~795oO@vS%@_u*yOFZbfxuuty6x8vMHntzng+<{YaC%ywG z55a@*sW;2jzbJcN~!W@G9(=d-3DgC->kdaPDuKf1JV@xf?%; z({dMn3a8{wyc#Fv4!i~@~QM861;a@LC*|oA5duksI-|I4n2d9vqVE@pCvR z*Wu@JK(56vV82|0U&KDS8oz{dU7CNK#u>R1zl_szIqtv2RL{W4}J^h z{;K)M8Jv;3@!L2pcj11Vk~{G`I4O7FcX2{)$M4~|+=k!BF}Vf*8%O0PoW&8j5f9+7 z+<*shNUp~laZs+qAK-voi$BDExdwlPeR4Ja80V6jf1JY^xe|YZ({ec;!YR27e~OcG zDgF#6|>(3mlUR@s~I%7vN1eA`j1U{tAcXAv}yj@*w^X4$A%bYaEdK@Hf~m z_u_A{Pwv5+aqa=lKlY7x&dA+(98Sw!xB#c*PP`RP${l!XoRHh`cpR78@HRLmx8QAY zRBpl(a71pz+u^X>fD3U*uE*cOLAefZj{|Zo-U0jN8vI@CldJJWoV#E1kNr3!SK=LU zS}w;$I3<_iop4ev#XIAKT!M>nTrR@9;Fw&9zlWo80iJ{-^6=@-yW+4sgiCNp9>lxh zpxlpl#{szy?}7btFWwXTj+v0v`RM`EAcgO9?wdo}+!gfntCJ{qUxF8ouRk~{G+ zI4O7FV{t-m$J20JZo|jnnB0PYhNE&5uEG(y5g(7kas#f$A-Nv^90%n(d;$*0wRk%A z%Qg5H*e6%xU*cS+<{yV~My|xa!fCl2*Wi>~hEK#vxfGv-6LJZjf#Y%!J{ia4LVOC2 z$_02Pj>yBc&ZpwAJcMg;NFKze;h@})Psahd56{AWxflN$`{W+{8=SjG^N%AqBX{H9 z;u^f$#J|HyxdWep6LLE~6UXH?d=`$$E%3%d?k*_E%+)Nm7DNl9FZGw zGY-oQxCMvgdb|V&5*75n8Hd=2)=)%aSRyIb>*<2WN%;y>ZET#nmtN-o3K z;iO!Oug3|w1mA$;auL1}$K*nM6OPIScqxv^!!w<4#$kB~x8smJh;P9`xgXz(19Bf; zhW&Ccz76~29(+5_-KF`*37nC;@t<*8?!p~7C3oUGa8mBTcjAQHj_<;8xeecqV{!}r z3y#W7csY*9jrblMmK$&<4$1ZSUL2I`@O?NS*Wwk}FW2Dvu}`kX58&LLntz0oRCZKLpUxM;fHZdF2s-Es9bl@Hj+_$i!{JMn6qlsoVmoRHh` z(>N}-;b(A6ZozADRBpoSa71pz&*HG$fO~LAuE)>epj?Na#{sz(zkvO64So^(AU&m3o0I$apdH7`K zH*i=U!hJX-58{8~pxlq&!~wYvZ@_-J7yk?UYPFak&k@k7IHR{x^f=k}@mE$fLH54UVrZrgP0KEF=? zt7@J4s0(IPwT}O*yRABWQ&sbOb9QwffzN(X*EUJG^qS*!Wf`%$~c zU&0+*D;l(z1HN^SuX^&^t*V-HRZnJ*sv7r9)yv<`ndBC@cYcA}v%vpvd9kSnxV!o0 z{-|of)NS3GyESv`vwhW)smx<`KexrRRqp?u89&b5Zyc)=W5qsQ?G|~gclTKXXSsXu zKtA@v=c=!Ck9A|2JD$%0^-X;EsadP}c2)EIP0e#ZTQcLbswLAltwBQ4OzCK&y z)^<^9;ti>VsX064SEl*3s^+!XQ`~np?l>m8$VJb3Yi|}Y@&8@K5C3}+vs@H^c6FRh zF!AB>18(CiOijF=`f4|yZ?K{F{bF>TDqJ{+@MCuXa9^+F>(%bf;HuW*(`RV%XSm31 z=WkDPH*UR;dzNpGKgy-Eyq*)?A6A&+2E4ASd2Z^AswG?RH<_tvo|Zj0<+jnfi4VJV zm{Z8-xcUax@U7NqnW`nzQ?4W7e*3Me`9&7|;ZrPlhWpMmwAIvY0Qjn>X|3(B_S9Po1{z8Q(bF zuWHGR>={*u?5wfQIb!3Xu4?2VtKCDYn%A=u>xQ%vBj34a^gH*v?_`hvhx_)DS)1}R zcJxUnR$cKyg4JtYHCw}aD59GiX1bgI+O~_hkK4Qpa^u_<{so_8;|(R7czyF`7ag44 zHnEwZr`&H{G4yFHyS2F4{Su-Z`k=cpL*LEamru|24IH_(yW0{izN$6s{%Xb|Z#AB& zYJNR?=X%DpD9VcE@3SB^fzcLj;ycsQZW`Tx-aWjT^xek#OkBu^M{il$+U$03ZQgu* z^P229_v07dbf)ceHfmpU%X7>A*T1;S>g-{+yIc2{JlwX@q`vQdzl@Ppdn0?`PK_)) zc4T|M%!Aehs#?8;?fq{zQn&t_2TpQ7?XzW7*Jc;zxFe&Pw%kqka*e)q(L8t8{66`x zd#5D-9rh8oZrWAf+On$ClJ46{R(Z)r9yKjC;{Pz)&C?dU&Ex)ax%bdDtG#U#a=&=w z#cQ)E?Kjg_x`(c0Q7N}&-F!|rQ@rX`?_m?%!?FRlecd#_;ePp!jZx!mj1Kp^sBW5@ z+%_@Oe5kwc0H509_F-4BXy)kP2Hw>g#}(DB)Jx{WmS1U+IZ2c;l+wPZZ-2nRCILrV} ze2E8XHnp%5-y50D-!m$$!Y7W+am_%Nt9vHbY6|G2hHTOV(yryYIWh-;(JZA-C5Na^k{2yY(KpNh{BR zQjcqAq27V=_7C}z@2Dc?eP`p&UZzd+hkWM7v3lcv<{KxvZ)|i|C0ic-QxmA@Pakc$ z$CkC+!&@BNuhf-iSFyjeo|!xC=+nK^Jm4vn@?Q{3L-y0`BnF%Lq);9kB=Oc8-i++8rM<3?d+Q`dzRy5P)p4F`!fplOx>k03P8u6YQT6mq? z9PX|e_s|UMv1Gh|x_5S;`3m207d+$7JAp(8`~~Y=s3oq=e(6TL@m8}wZvUK?Vttmq zuZ42hly~sf$BkdxV0nIhUUP?f&IEj{xLc@;*JgV)`R;kBQ~%m*fBvkQ=R50J@{>!Z zU0>DQ=XO>12>!k2Mv!*T-1O$T7iClK=NG)E=}P-FJ$$u`wXxm$X(_9-pD!J`9(d0E z>N8K!i?u4nb9johR!nuj@NW(_@AtSxc-I4N&emq%&x~9T>@u?Y@3=RQ28!KLG=F7a z_WL;}Y@Fupn0oL%?!hB_s%By)rw#8JuxyYo*@t!4%iUe`-&x?kliia`8(k`JZFlqx z?^=OIcdal*hwz7j?#Aw^>km$u6UNnULUc{==}kIWyz71woZ&C>hCkPRFoGNYdG7NM z%<#8$TdT@DmGeRQu54}gA8h>A8@vmER!XauEb>-Chmn1rchCPt$GUvMD*oTM<-D)^ zx+U!BE>Ae`Z|8pO!kf0Fowg>gg!CN$#)5Z?w zbe@K0FsHjKBAqIZ=1&~>2KYr6Z_U?cqpm<#h5xm-H@eFP*7h2A&iFspc3ZQyzjt?K z)33f^?AqSzK4O5i8OmR~!sTC3|y)_!Egx8)Rc zxZ;Uz?w>6a7xH-wBRj*cx4Z8yxgp|qDlpZq@#KsUNzl3b)jsHgxw6pM5((VJLL zUdrC%_O7G(Kv4FmI2-?Bx9=Ri;OlX7CV0=HjoZdY?vS63wb@Vm{@?p}7y6}t_wF$F zyYZ?8+IPnd{NNj^T$69(HX}>)uGaRwFMsdqxH&q1wcPD~Rm~42baTT}ck};W7+mNM)!Oy?uGOx0VV^fV z{xXjn-sv}JcvHs??<05LswIoOg0vkS98c%lD9B#(5{QQMB_M)U)6*rSm z7YjE&>b`7M%$$A6<+0o3zhv=dlfU(bw@$j?X)RuNz1HbvcZ@Kbyprn%@8CcU%lomr z($HyVfX}&cYsRKpD@z}v#kawcM0JQ@RuBXmb7Yst&7rbVBHf~ zn70>167Hd1%&fibW^L@{%gBa#{dsRZFS(=K|2>{*k7!XNJHXxU0gUHcw~g!$b&dO+ zA&#&7c_p`#U)-h8Ypyvyh}cl)nzex(z&9{KHt|NY1}-8TpL z>q4VPUjCL6Yj?rT+pW$c;s4bgGp{vm~C*pyYIkq z4lVgJ+GL&_OSZfQGH|=2dw+sA2qrG%dOmwMM=7_5ESV8=4@%@OM^k!!>RQT0?po@t z>~rp9KjwwGGWQS1F)!iW!#(n^ z)ajyby*rGJy#DcqUca2ii-z7?NbXN`Pj;6IRadOxDRkQCt8!DC=Re;(cisPb`Yf3L z{J4pWely$WyTZMk>;8<_#6>j@?p>|kO82go_xfJ(mF{bIh<$>aCF7&qxK)qd&umP4 zi?5G$E8=G6E$588=gE4D%DsNXs_4C?r@V7<>(onG?wK40^6xo4>z)%Min_>DMb!YsM#hmN)ZR7R*%ePp@x3`o^2Sb4=eJUf;uv zsI_94nmLwU!uIb-|I%=f*Z{mmQSUS1!|%HF`mR{r?%)w83ky`qb+i;wgA zmUw-W@_qcg>B#uD9^3c5eBUh77x4OiM&Ev>ui5lX_4;0;p|xUnuW$Jw-u6r_AMLwd z=cFzB%hUNcT0YeN=8bP}uW!9uR`#J5JyiS4uBPt=y>3^0me;p}nfPO?z+*8@3;BBgG^t6*S9-;pD)%! zHGij?z8$>2yBSey#V6dj^IyI%e)nkK8Dsml&iAd-{^pHuE3a>bTS#`1=^J=vbTP{w z;OpYUyuK!{Z$iG0pEn&D-)CvQ-m-rt-5V@y&*`RbYp?G}`if28C8qBnukRTeS}S() z`j!U0?U}r5v~S_qzSHu38??W9;~Vewz2ugaz3VDHRNHeq)3-{OD8(mxeRp!>&VTtn ze%^Fsd^?Zr8=vnx*Ys`U^+o8bFnu@kYHt3tHr?xcpN7_o3a@YFkG%1vz1Q0He7N%^ z9<*h9zHpnjJ-^ZXd*j>I>-)qlEBo}7qvJck^lex{UVM?)_Y61g{Fm>Gn7%{D_FaL6ijVX9 zZsBIh_(}Obe%^HCj$4oI+aupM%k+)&`c9#5KhxK2`lfn)uhGz2aiG_?{6KGe^7E!6 zeb+zF*IS+s8}jdEeyIJ;8()Ffmvzg^KD0m&)%bQbeJ|(|rT8qbZxuK0{FmGj>>7Lq;F z^gYXqC;9zlzSp;l*BABrvSr@*e5UV}o-yOQ_m%=Z{|+*JTX}s4()allqvJc(^zGpF z-OY$vE5>wAWV){1?+zNH6v+cSCF z=!z{I+xJkuZ-e$XZ+zQ$eQ&vCW$%jVp?W@SXZlv@5~cWLukS%_-1#rx7czZ2kL^1@ z-*>L*^M&+$h|*VK`fh%FbhW2@eecuIS~1P*TRGVqUwYZ-9q(Mn*ITyd9{Ij+H2>cC z#(90?=zIE)qvJck^liACy!axo?=^1R`7hrWF@1-Q?c3nq2jcwDYWfPizBadz>fzFXY8DD>@N`nK}=_Mz{+%SXp|yy^Sq zE{*R-M$}rdi5qwR%lE}h-$`Tpj>-3}(EjFa&#k?_2i-!lb4}kHe;-}#RpX_)Azz18sAx7-wWKh^IyI%Z2I;c+c!PmH{bMa=k+zyH_i0j-!0PpEr(%3TOy6fujTzsq`M&9< z@4H^#ujwl`eV3TNgS@_HXlSiC#OqsH>TS>DO{3#mIJWQTeBTD`Z{GO)Uf;)VS=qZT z(L?oo*v|B=(j`jq$zI!!0X2!}LAsy{4z}o$K{&jyHYZ+@|r}$cS1iCU||b^L;VXchcCthk0+`&EE>` zZ{GGS_WIViWo74@zBjzr^fbO!uWx^^?`Ce6jNi1EH$K1Vd-sVk<2yayH`Vm*;`Pm- zZ@lR{$Mo&t^*zjpS}V%DzQy^z#P!-JTCq7}`@ZF!emA}sw7+@d`<~bLzFSuIhKokG z=U3iqY+B5UW!j#{d3}#@#{^Zz7ntRX19>+G}CvF_nMxz=Pa-93mV*y9eaK2_VC7+X&W8i zgR91j@0NVu4yJE6udj^0SLck5?{L%i;VtCFS9*P$xpC*ed|%Y`9Xqz~=zQNY?Qh=p z+}-PY%q=8)rs;dudreQ{oA34Q;`PP7zU=Pa_6*uER`eXF#;dE?vD>)YU#m0e`|2E5nw zw3ub>+Mb7beO=tR^IyI%VER6LY|Qwk<@=_azP-G@^XMx!eV3TNgS@_HXlSiC#_L0z?3R_it3eOVu+6tKeXDedQhc)4_X;=e{Fm?e)d!t1x{xd#~wfdrtTI-lw6p;!Lk^Wr;Vw^tGeoyR&=D_MDOL z`$qHcjjz<}+nc_pFBl!)0j6)mQu5-9yuL5Eap%8$U&QnsI<{|zd|#{S+sEtcatq1M zFny1Dujy%g=X!nHczsuSed~Ai#+SQhbbMW#^i{H|`%@?N+aEf3NQz zZru5Ak~coT>C?}9j~=i6`M#;9Z-1}vO!~%~zH?099$w$WjHva0XnPkpt)}mPe7a1g zs2ORJ4`t}0kV4a^C<>FOKJ_tZl1qe2MLtE7T%ybj^B509O>&7`B9|CcDyk{fGa)9@ z1!?rDoH4~nGA`-&UTf`r_TJ}tp5pWU|Gi$B=j^lge($yRT5GSp_CDuio+WsN3U5}# zbZq=W`t8pT^XXs*3sz6L;8dHPvLd8 z@ansGV-(&H3$MN4-A{OJExfRW*HiE|5JDvLD#4p`w8*pULBrp)cO3p&D!kpSZ^B;( z!D~Ty^KUl%9b@6GM;iL6PSq3-4sXdl`**Sr*>QlG9^( z4iUV4gb>NRTky)83xAbGhQE0W9R6|@USkXI6u~=-@ID`7`0H-r?Vd*E>Gugzfy3NORL+dI$U?_7m9z{2Y!cy|+Cx`lVUh1XH=Rue)b z^HRZ^(M;r78aDjpyLj6k5P5E4eG~pV3tlSW&AySV%KT^HE#VL)eURX7r$3ng6kab2 zubGSYu)-T-;hipcv(Si_Y2iICIX#x=0KwZy2$9TO!CQEg@K;f2_8($ zg}*Zd?{vajHQMmk!NS|}2$iQ#5WEJ07gBgbExax+-j1-yGh*SLDR?W;mX~AUEs~rb z^EXED8VKHF^aty|rovy%{f57lZ#n$UP@^yq1EufH;a|_7l89g*WRy77BN4yoC!O=0Am( zZQ-?X@wVWDv`R>GuiV@q#y4;f=NME^zVMD!iGjZz9hgg7+ob@`hV@ zYb2+~{7n+P=7LvBe=z?w5&n`ay!Ed;{B5~UnV6Q5#G?(Ml(jUx!3NORL z+dJ3cufM_@VBsZY^ZwXFgqLpN-EQG^6ui}h5Xrn=@Mbg?d6wR5_{(?kek~ArZee{B z{^|(c@q{;f7+00~&%#^6Axion!P`rJF#jpMUKU<67jL%08)MQRk4sLE z*x8(sUPoE%o z%>^%{@P=A=U0l4j3NK>e^%A^K(UzBE;VqJ!9`iRw@EQo-OY{fx-{Hbv&1A#h%2yr! zw&ctBwY2b(hO)j~Pk1}7GyL_n@b-t9zv;wLB(s~~jZ}D(Exds)-b{rzm-S8Qi{R}= zTVAe(w^?#}%wI(C+6mqo`h)qek?@yh;cb7#;qMZK*VDqQD|iKjmu%sUvhZ38-U8w% zl6i&T6)L=0_png7W8+=C-}6MCYgylfzj}h#obXDnHS+vba%|kp+(MRTAHl1pKbZd% zUS|uhzKi#=!W&}Y)fc>%(1_R8!V6n?Jq2$AAw)9o61+JLMV@7M8~&!fOuzm4?=pqA z`vJ|zilxbd*NyP#jY`3a^)i*UZH`TH%ec@ajxve_e*Qyi5!4amneiJO>EgPC|%emJn=F^1@`{ui_5F z-wU(pw{P!DCd>Hk=kXW*>I&Y)gtzJ{!(RsrZ%ZEYH$m{)30_Fy4YlyPxOn3fUc|zy zCwSY?mX~AUEqcOqdyL>U5WIKj59Yu6!e7nphH&Kz^xNmJxx#B{;nf$sTM2K+m0Xp_ zudju-|6VFjpH3V_GDCtlQsGUu@CLegW%r0Y=d!+uJd*{lKH=qBc$+1s$Kw|fymo@O znf_q@t0(-WS$Nx@claBo@OoN!4FszU;f{@W z@fs_Od z_YNBI+FE#F3$Lf(Z6Jh5=7WMar>@Ae>^8&SwCCuzuPR^d&u@EQr;X0+vHS$Ho?PLJg|MDX?z0$z_ru$ceq z2!E9m41e>Ub@MibuWgAIS(Exg_LFn{+6-noJ|SmBMe@GfxiW-7dy ztZyREBLwevwB-%A@YYC9kNKMZ#5xAGV=s)#(~yJlzb>1 zZ}`i1@p2X37S=c6FHP{yCA`^#xT?&57TyvLQPKwqUNgaKukd?ayudCpN6y8t^kKPw)`Ii!f7qRe;61+WV%geFw7D-Nz`5Pm64FoSr ze=z^;7yfE);Z8E)%9##cmcnak;WZPyJi^;CkgLl4XW{L?lgiVl6GxHE!GbqZ;Z3&i z2D*6r?+|&;WqlKQrVCy(!ppVrHcL*AyB!g{c7j($e=z_3A^fFTc-x`F{?{L9uq3}9ec=cVpbcHv>!fPRTQMBc?weZ3gUQfZ>KnRh{rwFzv zdCu=5&$6+GziCg>Z-4$9IVA2;M$Ih-5A$Sj>OF34fLUG5pPY!r`y2!fR~d z9V>Wu5Z>n(8~(amc)KSufAJa*Ie)_=?~_=UxmLU3vd174u2&IucL+6Qt+NaBi_&1hQG@#yvBm}B5@SS94B}a z6<+bpT!}k2%*7j^@RqQ?34g5wuOs2n`_Od0ph|Lj+|10|s64%^;MEnp6or>z;q9G4 zguZ?zE4%>~-tmIB6m5Cw7T)a^UPr-OO$d?9sRUb;Jfl|RSvtn>m+#`uzfHz(3+tQk zmmzo;5#H>J41WzRyd@l>qz@9jHiFk);q|icnz?wR6y6vM?*zfCL|a~_h4;AR^jMw) z1aBuHL^9_SEatyogujZL41X^?=EyTu;qB+~7yeEZym5rL>feUH4i?^)Tq;kWAb5QQ zFQo8>T6kStym=Euo)HVLwcynyyc`Q}k>vE4zcGT>K=3xwAIyLIguj{_4Sy@AJNyk% zcr7iwHi9=5jd(i-82BjQf76MhNajev8>#RnTX+Lqyp{@YF6*1fv#sE@A-r4* zZ?oj|n7@eNwG+Hw=?~_=pM}3P3vYXg!{3%%k!Mc}ubtq{MullG zcky~Eydf4|d%@d?w!F3$Uf9CxDR>(QA(HtT!D9Z~EAlKGW%!#mjeh(7W%qcI=Wf(dc{g|7G|)#==|6AxioP!Rsk_-4tH7h1bT#o2l?7S$HQ4-mhrO%d+rZ4x4Td z5xjkbfLC%8EatzTgulv>hH&0ghrb+!*Vw{4MerUVywCd?{<>RuyT?&^`h9|Tjo=Md zcw;TR3tYTpg*TJ+P2_p1;2leN!!5iulG9^-nIw441+RwwVE)@9{NXc`=!`rVwf<3u zza_WI_;s}KItt!vXvF)uui@`<3$L-@y+|BIGN%aMM1@y;gTWi-;@zz9max7Ff2Rpv zPr@s(@Tw%I$NbG4OHHPC6}+Z`m!j}8EWEvsIQ+F#cmpiFPJ;I_+VavZyxT3jj)J$E z5F(k+6D;PxA4Q&}BMg7}F5c(2h&;Ejz6pPIiqr6B)t=W7-s})pmGz&6w}eBK^g)8x zMey1yyj~VwGZ!zc@Wxnpbp@{mZF!j%-s6(fV|fk`yq$y)$y`OSnEz^ozl!08zZZ%f zd1flS{XG7{Up>K_LU^k#H2ih2@V4Ac<>?aykJ-fePlY$s!t3JV?H?!dj97SeW^sPE zDdFW(u{`?--YJ6DLg94=Ue)&F@U|^}gE<@1d#J2m_QfsS zNG-?<^GYN1lU^Oiq>ltidl}LKmvlssl+Vjat5>+BX9r2YqbNj3JGrE3LDFT0w7yHa z19>@zt!ajI^Mejsi-V-24C(7G>BB+Na||iH|IrfGupsGChIFt?+C50>jrJwL=PAq( zGzpR}F{E|fR{x94og;xq4e7=rr>_fxq&FDS*Id#_khF&(o#K*S7bHE>kPdQ5{~09R zIm(y7DK6;|LDF{(DW6w0!ukfeJx2n?hV=6X90@E4k`6bduehW|LDI7f={+v#&>(55 zAsy(F((~p{U$;~2Ay&}AC2bTWU1UiA3_EOXMK;c9^&vz0nM*n^NP4{?o#T>*gQVRI z=_Hr*>L6)jLwbozdS;Mx+YP=1PI5_8f~4;l(mx6v32Z^W&XK@_hIE}v`c{ziT0{Dx zOL~8hw5uV#(=(fz8Ol zIT9!|q-$N$*Mp=(4C!+&XY?~-;5l72-oiAdlCm$Yt>^i4y$ zufUPOMr7$63EXE$KXgf73zA-GNN2gEQ-Y+O4Jp5W$mqbJAZfB8?dP_7N|5x6>wO6v z?~*13N#8J}d-EL$e2zSxBY}KFy2d4aB}jU?A${5E@_7# z>89&^3AA)c|3v!EVQa1--IM1?;Ikm$2a!DrzNl!JT<6P29f~0i} zX&;yLq#)^rYkdhE>yrL~gqtIQR}E>+y^aLd1xY6x(p4_$i$T&HL;8eEdS{UIWJCHN zmoz&_dSIx})&(wU+aT$BLwbx$`WsSmjs#vdq~A|*B=AX)^ln4?zDxQ-kn~bRI>RNs zJxJQ#kdARl{~aXVe~mAJ^IX!_LDEkR>CrA}Es}PQ1YRPIpOf3zD`oq&K>x{ez^xU+qhvmrHs=khH>(rn{v3kY;n(nr%qGyT_5hhe6Ui z4CykLbXJh`B11aOCCv?zwlSomT+)6)(qD)85;(^tJw8bKu^~OmCEbfeoFjqf4XJmx zBY`zR(usz2iA(x)kaU0{ebgnrHAs4*A-%yR4FySmxyqM750{kk=MGyR8PX$N(mhDk zIi$}T(w&nW2}FaW6AbCQF6mQ2(tjD!VwZGWkTk=P4tGiW1WA9s(wD$lF6psB(hm%2 zs!K}e6C4RVV@S8(*mF6oUy z(tns%uW?Cx1xbGx>`S1FOPU@eU1>-gx}@JBW#~xYaYOp`?T!SN1xarV(}JYu z8`46TbX1VEg(2nh6h>dq36k!<%$L9!ZmUNHNmm%s!(37iNo+>~j~UXhCOQ&W5+uFJ zkiO}XJ{lzLZAkBPNpA>}HaDbKx}-gVq}79b3GjJUBdjBXq-BOQ*==>_n1BRI4CxoQ zITCm`NIKe(zTuJ<2T9L0r1>r>J#X#|K{G>oxl4LhkhChtm%wQ*X=;#ksUfZBl5W2# z(1EFjbkhV!0*ivABMs?Xm-L|^X-`9XuS8PXh=v}=%b$ECgmPIgHT z50Wl6qzA@3Y*mg9NZ?^Zy51$7A0!=SNMCkI9|)3mH>7vFq}K#Vn;6ndUD7T=(*IuK zOQ5|=+Av7E(2(xG)sev0qXH6$7}8H&(zk=8*BR26T++fI=|2tWT`uX6An6f?^kSFv zj3DVZ7yA-u=aL>4Bwb)gf4{|%z*i#!5-2jH6)x$ULDHdyl;1yOT=9KD(o92ohui9v zLDEKs^dgtEbC7gvwl9G;E@^U*be~gQRB~ z(upqV=eVE};c;lYeL*eq!FZevTSI6yj zQIcFQq#Ej0-mVM?!wctbx4$S=dwLl#y`r4$y~7ouNaNRA)lFKQ2J}!-=Hs96wm!po zZB7@Jzz6SZ{ZFpq+f_F~Yn1R60=@uO83zJvR`z9#0fa#;0wdGLDC-;_BgJ5lev$Ts zb3B$+Q4W5Ko)w`eoShOBTM=Ls0W|1@3i=XUNtxD2v=^=^%-TD7(%z);CrFd1Kx&Br z(yEsfYWM+Q@Yydec3On|@i|RZegcuvg>GMKhiE+d8uiXP{=k9M1rQ#}=`0zvvL=W;w-Rt3dJT&zrLWdP0=`OQ?m zt);Q!K~sw%z$E{(rste!`2?{S236yYL56)nOZWqPM+z}ZI&W8Jw204O7RguRNW^Tq zn}EKU93hnOvu$8>6KOA>IN?S<5?78fB8$l-+m#P#!gfplW!bLZW75(45F(M#e9O)T zdU-f^Wo!q^#Y`ZutO}SV;Iqo9iSwn23IK1yJ)D4{4&<=1gu?4cj__WA9<@r?qxu&H zdL;ez$D0g=zfpMO37SwWC1`=apf{v^kUP_#eL;|(d4*n={S{_&${=ho&Taj0KD9-b zM&d}svg<%k>1V7zZ`c2h{r0(kAN!5IHg*QMOoH2#@?pH_}TDiK3Db1RHkm)N73 zR|buUdij@V&ASvI?QIWS522NEfSA~#-gO;l1d`ug?e|*EcOIfG%v=wP5Ogrh1A=e%b7D*DQ9Bx_Sq&THb9 zx^+j@2;6cJecLv3bF;b-ebigmg^LmP4JgMM+0VF`CykTN<~x-*aK8z6E0jr3PD61~ z)H*dnz@Z@0 zNig&w>Rn_NaFgd)1>9~&6exk6F$|xjT}$3QZ{=W1YAtB2AT^nZXhsq#JqLP>SL;Bb+-8I#?JA511UQ5i}R$7Ee{pXe=XHZxCKL>To3I z4P0YvGe2o6`tb%Pn6>7|ZhQwClOsAMVNAa! zTnvpFfLrNdQ=v>Ml%iXcS*N7JC^$qQU|jG$jlrr-{JvOzms5F`{4S&4-Q_nri1$g$ zZ)WS8UR;+oCtb=*iRN}*=u*sHhzPX^5-ZA@K{qP@DO$`_|Gi8!bOu}&X{i4E_%m=^ zRVD1b{FA-!fL1H&CTi(LtAP7kVijF@SSnZ^!F`S*D zoHVIfNIRXNeiflZ6#MYVv5u9JUU4xTe^@wx3^H8Ae{~G!pHjQ51%8=!F29xB%x$`g%bArN)WPL(<^E#@6 z!%sv8nd4JMEQiscLas$Q^DN%SwdGQ>>N%GAoJ=lInNKU~70DBAbN*c6tnR6*qI`6J z{0^@u8ZZxIwNS)50zqjpDl+q%2l^tjEMfeR>Oq#To(Cc=5Qcl+Dq!9&Ax!a*k6lea zNrxF=B1qMpNx0*+I2YIAwBzcq=&$GNZ;P`)UzEINsiVJ^&i)0-ccCsB$sgWCBp;!! z#7O>^)?6Bte5p7Y)`u4;TvL*tA-`D){mIr8-!+hOQ1bmxvLt^EDk^17EcvrQyL(7&VABKf1v zq2i#|BKhYLuUnGO2dTOf#vQK>>BZlWe4BrQz9@OjyZ;Bt_o6Nt$#*(jB>%Xm zXu#XlJAsH{u&(6a6A!~WUz*J%Z2m9EZi?0h;Q$?tspHnCm{OeG#V(aJQ0c{&ZmC{;@fB!(ytk>|CbKau0=9^@|N z?4n*q#{&nJ)tE{~30t8GG4 z_=m6rJsI^6u$r|iZ_=&SA%$)8D>=#zA1xm z)>SR3(ZpFM)vKd1SH-15TWl{Je*Q>vH!khmI^C6R8k578F^DEn7ByH3_2ZOyFd4yH zHZ@2tbE3kse6&y2hG3UF!t7d=Q5c&eCM8@C_o`VcO76O#brLqg^2;QlKM1DY8bw6- zughrn3tJfZW#i95`BAF;?S{l{@*nesY%;FfgyJax5wu)l( zdP5_=#>#{4GQ#6t4;isZpF(9yG{ji|Sj z{GDvAfD>->&K4lx9FD4S1!}1I<{1hEsck3ek?ft+1?6V3;9Cu=P}G})tRqQ=x_Bxr zUg@{8`yMoRY7Gy}AF~=KzPA!lf1-LV1|+_B6PEvp>dk^vPIRwLJLg^o`98HK^*qv5 z>|bE9S(LSx6yg(aFJcD2EzoMi#HLAj(ynl>$HcqB8z7UB7@u&~A9<7hsN?SJ7}ZG` zfhXZxywy5s#E6hb`-yB_xm}mh{*3H!o_OHT1L60Hu29ic{u}MKppviOl$sx-WOY&< zD!N_~y^A86q*kW*OT8((XlptYUNZPkVr+gk{)8(E3;N@4jNTRqQPf+3kqi|T5HSt( z+n2L$9*ZKTz}wR5h&pzMhE-h)gr&5Xyo{2s{C=r03@XCaBL!o*6<#@C(Etrb3Wln7 z-^BtWb!iFpB@~HpsY8Az=_1^8-ghlRMNN4(FX}CTTZf?>8;X>04b>;n_=cE2t6#Ia z9^!RP!AOG0TS9-5#&^PfE{J3sF4fVPL6qcjj z6-ZlEXK}#iGu<2{Dqd8g!Tvna)gwC1P1O6hiOPRsLlfBt%yl9no6wY%G|2v#=j~E4 z8Tr1bmjiW&nR?nxv&=Qe9G{;La68jGox_2)WE$%(#*{-AXqw;!#@Ef$0 z@4qxOWmk%r7iJMMuO$9cQp*Y+sllKA;Q}O*@Fy}7f1pLJQ#%xl#n03Z116_-$SF?k zFl1J0hvB8E9mbTUcF3(r?J&tcvrvFA=K#e+1>9&PJ9QzSiNHY%7{t5uoA-4?zx))s zu`DgrVPz~I-&xV`$=C9WR|7r;mlL<=(T{|t~v3)B!$;kfQ+dlJ?g?z znWSjGsxQLAzUyyPt$^2fek%(QwxTlA6wU00wlNDI*S0<<=N;@{4W3>`M@834@ zy$nj@geeR`&=x|dPk-UJ*=?Q)3)KMki>iwHN&JiuBDW$KCvhNxQ@QNOiXh4U7R z)<2^_YbpOUKpNUWJ9PTv)&}&ux<3A|Lhl&q#mvbf%x^GI5FJH>;2`QvfqCLL3vD=Q zN0?LxD^mKSd3+6%Aq0X-$Y66ZYg6)Xe+Knn8(e^+2jkAAHW`ZZQ&c;k2Y(_=KDhK~ zpdm>fiCLsg=y(bx&A77=5#O1RiV_IKUugvg!EUBII!etfrwowOOeepYSgVEbalkH> zP}r!V-jNWEa^e*I(H&U}(SWo-5oXR@2yO_0R}$hgXA>f?JoDkkiov>{d5CGDJz9Y9 zaw`%H=UdzuC7r*ew(B7d0uF68;Q9+?^-JK1HN~}9HZui6O}N8m;to&H!9BOqlW1hj zR$K^QID}+nc4_}2pEsOItuUWoofY6y`?L5f=vXONW3iy6?AFELN4=Xc4<+)(Wr&jE z-peZsQQZofG-y2Y$~x0^aXod7-}#B_Vql`)b}=6A!;Dr5a6tDS36L<#g^Y;hhgRNo2o1m>;>nQ1h__yUDTM9n&=B| zx54cg+4%kjPD>1H3nr=rtFbd+yUN}Y`6@n`=$zr3DU7Q&AzQs(JMs15KcP#fNXi~ik-iUwf6j1QjS zfN43MEsLb@_^D2kvZ&EmNy3d&HFPuT{dNSdNgd#5Oq7%CJqOEx>C%p!$>;d;7cJr$ z#hgvi_C@-NTWEYHCdUNhzoLE|4WgQ;whwcruU#0gxMyiV*9tyHtFK7ly~9zWTFJ(A zk5=4MG0aQA!%{flXNl7=NsjMr`b zx|6xCe|Y6bgkEws7IfOd-qi?wwEei2p)YCf803lMEIM{N8pnl>&PaWELamP=S#J5g zfh5tJ6S)+!x<$itM1h-J?aG14nZIQH^+4{N22bbzCoCA z-GN}Kg_Yw;3U$zDN(0$IUkbiQc^8(JK%=suu@;J7_b=)yoi9}__s;1(kaVOyyg@nU zQ0M65CY2dhxwMn_hzpHmZB$m60%rrMmyyu!f|k>u^Ib3rp>Oq0qKSh`qTb=;22>RF z3|8`e!>jnRsD*B#Z!aocsV`4PH~WXHphEq_I|(9;MS~atx{3qeAjH8~or6BRx(hE? zsCTeOGIp7t`8K2D0B7T(BuOTXO zxasP^C1_BMjyf41(+=qp)ZMi8XG;9G8u)F+S~9r2AE~Pl3y^JiB3~l-eIFBwZEI@Y zBwwYbS4;-zyUt0Q``QP_Sf{U-_276C=;fSWNM(ID^mp~L3VzBS}@ew;Std4d~IMy)GP zwuh%fy5zv|ZCb|hE+^|i8wx2^1Dn`jHaUxl)coVo$*OexZ&?O<>%IR6nKgySY&dNQ zRP}Zw&!DjBoQ={Xd(vApJ|7aythbM5+^Ba7_m;Y~V(ICer-A*GiKujV5v9Xb$L^8e z40tAWvM71iQ`oQw!%rsP%fFbn3lS7syoD$S&zU>b&M&m+5?k&8S3}N2p|xaEDPUn9 zVHGg$yIgmxcNF^AA6Xo*P>Ypx3V+*f$t4S6+Bv`#9DHtgqt3Ro1PUta*I1# z5_4G|qS+pYrQY8Sa-kuQG%JAUVT{RR`qxb=s$VyR98M&8C@zp^IzTH={Bu0SRhZ+c zC1@1%KRcyrH#HDTm%o#JvY}fQpYGHKf%ax9y3_^q92P}QH456IIaoORNAXG}RFOMlywW2S zs;CbBOsq3gQLjpVGvG{C`s6_~v{%~o82w_e^d@Z!vd65TzMVm{t~jB0{;8c1-=XoS zt|v|i{lt826);R!P9tpf9zvIt6S@^`cukP?fD`J)PDsyz8Hv3R*-51m?ukE>aLH4+ zamixLm@>VxVvAX@;>yq7gLE`VKp z5L*5l{Qd?hYZMCaQKLRx;-+%7x6jQ*^`n+(T0NqmJ9q;uh(=DKwlE!BD?(#7-u#uQ zc+Jb5dxR$Q?pYP7kFi;miCHn}bfpSP0JrI&Bv+ZmW@3JvtRFUM*k?I5C36F>yuiWV zB*oFZQvt?z{+=WrqNSpEIm@{N4zl+wX!Up5i+#- zBHs;N;A|&`3i)N|he*4UE^on9YP@Ni9biJbBaK=6U=SC^Wj<{i1!tKE??Cw;|7&Wc zNVdu%yrra^MG1uqkpiUD@uvjd8V$00e~>(Pqy)Ykf9A`5-nCi;^}(=2z3(`yFPm1f zq2a_RgYS zUo@*Xce#V8{WJ0~XiON1dehOiCSg`U(v$$iUmu2^c+WM(^^}#gx2Se?{q+LP{HQTh zwt=)ChIdluw{UMgvLjYr!MQhwY%(lsf062hA88z<)qa>a{F>CFuV18=HDb0E@w7{? z*gXnKMVlmQin2o^|HhiMkT2DADv>Aei<10?f~-l{J1i0*^qpgr1^JDg0aY|tbW}Y9f<DH??A9pjY#;X9LlZ{+MJG4qP(K!JHL5foz--FX}*_j{9w%(85^= zontVS2v3tSA)%2mb%O$dwIK3E>&}O1$M}xyO0sgFpyoo zpb2%BHp$fpiHA5S@7ZJ_BI6+MZE2q>F7GMYiYdqKCn6q1{Hw=Yc`aXqGf;yK)}B1n ziy=rC9>=_dMNwhaFF<66azB?4pS0eM;0DNU@e3;p@!=8l+a%?Zy$j%jeBKX*_|I)* zeo3&t8V%Woib(7f&|>3;U~35WaQ_Ajm~O;CuYpm<(G6bb<OKkh8w9c$Ox{sAghiSlvm2O*%x?o`!lB0ycGGi~5b{LF-aeuvnZA zKv&hg5qEwbMk%PU^0In20n*{A=p}7vXy_C;9BnDKCrO?|-2*{CJ$L7Mlj-^c?UL0l z=?4PF(;;Rl;;SF5@8_@f8LpQo_+x(R{)P zMfi|Xm{&3{QEp6EhAeiVCI+^*wZ} zL_n=R^i6_R+q$jpLooU-2Af8k)d+R>pyPSJ*QpweR|Tjs^R>1DCta0Ra*xG~D>m9_ zGWN{F(f`E_)7!ytp7HdstoGn~co~l;&eKpLAX37YYLFtC{VGKducTl7OD(iZv7805ZutfH7Niub?zVP{%pTH@beV$yXrLjx#okPbAZ4j=%qqqL`~e^XY{B%>E# zYGp-l$qK$XEOkNFcBII!?NKi^e>RL4Y4ZlfRXf;>B_?b|I=~^D3KMxK7t#WfOKFem z7k+(_nu(WSEniH9p317><)v4Y zglD!MMY2vJE=|MzrFa-s^zkUYkP2oZ+yytcBRj=IQDY$>O943tui%)~Kb$qg7MP6w z4C?4KJS!u~zFBlxz>a}3HmHdAZ*8P8r^M#M{^4(wB7E~PD*}x!kKGC2l|xz_sN!Q; z9LwHGbDen?*CslJiP!H?s*$qMc-0HjV*d;)vg(s@N0qSr*V5cWxf;CpLk&qknj=Vq zoE7a^)n`&i$9w@aw}}VPgqIAL3+47^a>{rUkv`W71V);9lK;($`xUmiQc_y_N5-p*Uqrm@$^Oy%UU#?>HK(70T$i^QGXZQY+qSWc zcv?G)XCO$F-rGi=k0Bqx`u1;Y?IoXET04iV$10 z8X%^i4ez0@xFhfw)Y?zTOA7b6``5MhCCOlu)SwY*s)_%T*1muh++Wh#WB1xxyM^}x zNQKC|X!ZPswsQ2S8m+BC1m#uJIvq1Z9%;5jqJ{8kUTfNI4QOp=Xf2NR1y0|Q#w0<% zJa|F;^AF;kE>eLmyBpqX5clbr;2&o2O12-iB@dT1Ks!UW@xd; z>WC+{!HzaW9);H%u40tJqnJ1Y6#5*b9alnY2bBgSMvrD57^XRN!{5*Eyo6@iO3 zV<%ic=mRCe^U7F_Db< z9Bq3I4f^_outDwUs@!cWvumO5$YQ{(O|;D?I!}KS3y@3;gUJ3LD!}vX8JtX{VmO|- z=jl6hT^b8kn`e0f3~b}}hXd9rdV6Py-)fDT*ssXh%ZCzc2?R@ae!zaCcNEROWLQwh z3(anWb>@|ta9;R}<;&zrD{+2tK0+O|gj1IO0mhG7TL&1I;ern^dL5DSm9d6TN~=mm zV!`XaL61L|{Z4UHq-S&mwmn)cb8c1AEv$C%OitB$^;_-sRjmwM&r{bUQhzAJdq0z^ zo(~XAb+5rm61F$x58R$ zImxuu%jdim&474c1E&C`iK}S-FG}7rt~I7Cs6lcy|Ki>Av6v={i)naG4hHKg3Xs+D z)vM8xJ~_rcYRuupR&O{wwmK-*59cqu9TeXptj|Lt$mS2c7=F zT2al}w4Q(qrnNhF=|>7WXdB5{xF>syC}y+XHezW?%57J;=aSPiEVE9*g`7){B)__* zP7>$gdmDsv!qt=PkIS9AHXM z5WjX%=RE2MVbzD*?a z%GFTNNYA-Zxc4{6^Q#u~DAUR-GFH|uyi+9oET>%uEDfBD z*&X}+-uhi=L&8#tg#L2=@)b!X#6opN-8sXrz=QNJ&V zU-N8!0Kg55AH!r88(+d6pm~5@zO6pofQf|KYZilgr;tN5ww!?^-D0-pBL>tlG52&l zD;WR0oni*6>WqJ~SBIupD^@1I1)ET(nDr>9u~#80;)E|q7;rr@Y1W*R;rkxS4(Cm( zNgA)tE2&^xOyD6%-%LSN$pd8U;~y&C$626@72dFg+}YUEC}(5Ruw~0V#i0!t7ymS# zp`MX&H!Wd0m_$k>^6_&fJC^`0OtGYldmr|X{6;0DeTf>ia9%==S9{g}q^mbq(y)-6 z(GFy-%)TE|@Lm>AXYYGkI04DSvW+5sv(O_)(_RY%-9j@G{hYj%`r=2e$MPjbt!M>4 z54pWhJU(A%4P|iILt4g;kjIYlm1-0cqE6fDpce3D0JYa*&>RFc{$gt}ni9Jw@QGk~ z26UhpEEmS=dm#ySA?MXd0-%a|FK?u-QD0C|AHRG-@WG2UsN$vE>ebb4zhGj-9`qV-jzKEacs@X30lobL7FgXE|5ue5 zq~r2G51>u5>oT~LQiZ*NquH3I&b69yqYAYha5b%1T!atHpicWlBHlyB%BRBbc&E`p zeEV(HuxWeV^nWYwO~wanwa<6n$bORq2L)!Hj-e8zj7!)rk~46Y0;$B9U_1h+n#5Q`jp;&u2^a|%aDAys$t|w`$z)`}XP^mfKY?iG~JTv6X z!kB2R^LWA}MnTMsCdp<72AZvpw|a1PAA3(`_vRziTAj5FN|QB!%c2~wy6ft!GEy4~H_KIrQa?iDyfxv} zn_<<1($cxWBjjZo$=<0uv~|I_I@|svRvPFrzr7p|dsj;DZ0)beMe(Uix8+aa?9_a% zB3!JrTUb$^^1Olgi=!;Z{VXDhxE^Vrc%;}l2Le2cA`xoa`W#r)e-?#40Y>kSN;1<* z8n}ig=ECJUxa*K&)Kr=S_uZ8`PemU~((@Ocw@s0m8ja$VE}GD}Am}3OhfD)Ax$}`G z3~?H6kZz+Eg}k~>Tzix(L54kCJ*;R`+TKn+GG&UM)z8)$a`J zH@!1V%IVxUdV0rZk~-?Bx5j(`wN}?5x_>fFk90qh{(dPfX0x+ZvxEJnqP>Rd-zvY; zYovEEf-~t|VfI+;WUH7%!Tj`|Y8DXR9>8yLzsHd;vYuFQn;`Z+}9EArF@)Kso|mAEG-M#w6cN(yuH?&ChR`lq9WugUQYAYkgoSu>A8VR~jk6 zsX^|_a>_tQO87FuuUtgB;IVfk$J&f?LF&=52tB=v5tdgO;y5qP%R{75?_3@c_0B^+ z&O4Ud=ICe}R0X1ikRrXPG*Uu0{WFyBV+2)4;pE!`tFx*5B5RP{aJIP_=7tNT1m^)c zF2h+~L{gCwZo~*{F2XI!TKK10AEZPrhi6eQi9$j1c-%O?C4vBR*U6=p)=^O6syrNI z)}2<)s+wZ1FjQ6z5c56=0jN7hZYcNMPqgqV! zRjsYIm1s=19y8TVfKZ#7;85TBSS+|79 z3A-8-$z1%ls8cnC2NAI@ZMo_1@J(KX6wxU-HtP}^*QL{W119QS`ZCHLL`zFHkc~Pw z$1)>qEQ`n!;7l}^;Qe5fHczA_Td#)pcAx%eVZ;R3DW~kwetW z!)4XmhZ`{|p&z@3;E^pTQ6f*{eu4KA1dIo?)Cn&G;aX7eN$`#0i7%73sk*O(e_~Dz z)>wx;t<-31YEbjf!s>&>FZsl^GAVKMT9KZK)BHrg#%eQ-Vg7GV5Z~*Cg6+IUA?OX_ zX8Ns6j%~$5<~ha%UXSP|*vcL}03)oP72C>r93=!CY0Evat-Rs4vKP}HG)KGWnx9D* z0u$O99Mj_cf)wVuN^d4K7$RHZ%`n`AdU_&(cax9ErIyxt$iY;-g*e8N;On#i z2}-c$b@2>!WZqSic_1X9H8p9}sq=!2jx~&a;`@%cAwel-O;`Gs1gDZ)a9oHb!3o^3 z9}>Jnijc^KJb|FaaUr)?fm*qc-84m+iRNm){j`cA`^cD3M!eeJsZ zC(tI+t{w=q9PK)mvK)Fm$qN|mO5$6-cKrxhTekQdyh2q|L=C!M7~rQ7BhD{M793ewgRqNiIPoB?J?hXAQUAZJ7SM%_$od~T>OX;_+`x2J_Z1nb@jMwFBIH`Dx}A+9Z$R@zqLHd1Lo;F6$)s?JMyl~UfsxupM?sXi3?-v9Bejli`6IPL zF7-&=3L~xhuj?rPgHfvbz?88+q$PD6fA|@s?Zzv5@E&4^Cpm)sSVb6rcH=>)`AD+vkzCY~65out6H@+kTJXNN&_@;< zgEhd{QdpLFfX{nBSl1fhw&bdvhO^D+r*Ol*Dfayyw221zR76ycDf0UQ)BxW@25$zq zhW4pdCIXWCMlSULKMDs>om_S8_p}rg*=_}L;G9Bg{&TRksu^T(4(?R6rcW%C(ZJLN zxGM112saxdU(c?v%5+~Epf6P|V=y`yQdyBa4Lb>9G%`d!#y+T(rqdYD!9J@N(Ievy zA0HZ0!MM)CkU_%t8Vr%o+oM*QUIg8ZvZ|aIj2jH8U~IsYr~Ahm3HhC8hr2&+tE zG$o7L)6WTR z?ZomX1?|bxiI}L@he8_K>sQxe z%7=ZqjNS%`x3espJZV|d#4-5)@%P+-=U=vhC~0-pw@4;uEu$Abs6(w^d?in_sLOZX zf)Cq_&6k&+tCJ*eSYAjqy{6C)U1vIoBrgs&ctN=mtL5sZsY|g*jO}A78%k8FTPtTn zlX|kxrh^d7eKC;LIMDmXin%;+$mcln?fNkgmNe~YjMQ=s=RAeuFU7GL^hy%re>j5W zo&GskB7FU+>H`#DI92b~)9XX=l=JVn34kAJy&yNKBw;mP+Lp{0L#wwPc}5 zA6USx`3OeVGV1hW6cmcuw5RJR&CSRW@fJN940r1rifw5#UcSs;*L3)@cli$3pzV6> z%}a&SVlLJkUNVcs#Z9&23J!;#X=1|1;A;-wmEUMH>b)Vq(IKqwmqu0PV|{a!%sN?pY%Tb_ z>vOdHW>foc1qOZ6Q%R}$&u}y(2AGM)in5+UAFhnshXRU5SsAzw%Tbq@JSVmfuRg3O zar+q>YNZKNi|B#|(mV9Ad?hS=@m> z=lLC|l@8Q|iezsY``sCO*H`cH^GrlrkbXN^($3wzopuggud&p7{qNTM{2A`|pubyh zrqo*xDH;jy^KyQcq^&n zFejdX`2@taWh{c9&V|UsNDC)l+lzkjy#-tTJRnbuJQ!2&gNsJzuv%@ zdgrk#On%?Tdy{`LULU{SaWVD&!7)Yh+kU;ird|`j-u9=1{Jk}k`+2@!?_yJL1I^Tt z##_I|`ZAfq^GN2GPe5Lgo@p2s@7p z@BfsFa9fV;(W|;rl)>IaoU79vow=rdo`lSi}2>85%KMQHYN`Q)M<>coh6p zhb{O#FkPFsqSdbM)t)q*9?{xWnB75H^WQo%&=N_y|M|>7>GzgBJdcY6X9fnt^Tkh1 z1kMcH^9Bgxof+6kH)`rQ8rHb7tTjO52c6v$x$oMbgL}Bb|T>oEdn0E{*b`&J6sQ zW3IqRtt^p|>iQmWbcpQXwNHS^5vVm%^(8t_G*UZgLFLr7Myh;k@TN6VuhIsR$sX>a z06tN2>6*s^BlSAWF{D;NCsGt=l1o$hmOoPYa;Zlub0J15=FGq~?120;0~r{$1ZM_v zF)hR&yug`(ui#MQo*AeIzTFlMdS+ndGV~?RnSoso{G~GkZDGejw1b`*h;tq&l6l`$ zQKxq(Y7Cwk$m5&5g1GE;H7pVL%)s$slqb@X=g3B#o0j?&@KV=5Gq4(=bV4oZUJ}rf z!nLY9u;(`9HH^BA;ak3WUoDq9^>h&~rM8F&gyv7q1&erBK%ylSvU!ZQOi zpNu6w_?dxM;R=GyAN0(?V%i1{IKPzgwb@c zm4s&o-uoOa1h>Qfd|324mGk%s+$5q_grhib4)sc?r&}=bvO|i0W?(72fm_#dlh2X| zcMQOCllk1RKcTJSK}m3CpxdJX1Gt~}(lE`U`@fT!88>+o-}2q$5V_QDvdP;pfWVo7 zJJwSJfr;ilY?@H(Yk8VTAVGa*pmu7IQOnYw^nFL%UERB03D&hFcn!IQL=rrY8}=ob zM~aYWqS=SUhLeTQ(wk@CaS?o}CBc*VmM=j*Ph`%heDo$H`1j5Xgpq%Ve`eqSk2;N` zPE#U(k{|cXz_8gcig;%R{)HQV^~}IEbAy(pLlpbWz~)s6O2&=t^Gc56{2A#ZzU6Dz z61mj&c{991@XWyI=gr8+oEaFvHxG4Y;IRr~CSc-YiewPJgGMJD1ReFKQ)bW+q%{Z& z$%YdT!s9On>so_w7n!Zour&zRaKpZd&%*SQa1f4)1P0+cs4@2nCcZ%e9KD@$A>Z-` zp_^RlL8yY2#5*&voN__oK-ACiptCa5CKWg{@cgqhjE9Q)cYjQs4vf^tVHv4j6qFw- z>c0`n=nB*tsU|N|3kla}KOhQl>sllADVac`k(y72X3S+DMdyjkWmHjMq!uEk;$C5- zP9>u>)7ebE<&V@ua;Zn^Tngv|X9mv3DE-wl0}q4NjWqP&*=GjUU=;x>!%K%>^Q`*7L3_S24T5!g}8sLr; zmL(qGCeH`!S_AwenU~XWw(*DS$%xGWr<0y08sI`K3!K@O&dYGGAe(=Y!J7eok8k+{ zJXbFD0ACFU5I8gNDvzz+??yYTO!wte*iM`?1HVH% z9E{O%Fg6$>A7h18rZH|NjMy^+j~P-4`cAVjWRURv2t(xacC}Te7eW0{7U#^snTAv_ zo`byyW!1zG`F#9_m8_=Ie7p#E5a-OmCx%oo&WVHZiXrkbrdwqi<2=HMJu`5lAr*`- z5P|6a=?S2ZA@VWKu*x*X*D$9zX9f;4q=GRa4#u{n23O1eW2;PK+(8(zX9k`(q=L~j z4#wSv$me6URi-hT10#55;5ty}dIumWP|xz~Ej9Jt_UnaX>fJ`dD@v|yr}1|3FUGsmuXk}wy^CgZ zJ+yop#q|0yY-Oa~%hO&K{&>eBFm$&v z8cp@LGJZf{rM5EmKI)g!`a+d{ZA#xarRAn{t|@)Xls<-1e=Ea(>k#h*^lI<#E67d; z?HOR&*^5n2{Zygz%qs59fY*(?73gewyp?NHW#~-{tlj8=Qv7pXF*xw;#CYYmCBAnT zqVYrbWhVy3P#vl-

EA@%|dtIi@9R^T*-6IY!w~9SYBT*22?I-eVs}MuzsAyFq&J z4Y?J(@(sMyhtB)tO{z#5KN!!%Zwjd+J-5DvF{kHx$XVe%C`e3h^*)}ZLNj_rH=RVl z=?z7HDWZ5>S5&{POM1VkN}k1d;gkn${PT9!95y#x243`4LD7Ya&$lj%E;TL6K)Ss_84ZzVhojr>Vfo3|kxIVdPn) z4P7wlL7WSrQ}`!`GkVby0Uwp0#?OepK>0^?ryZ=G-cNHj$mi(7-j7gslBl%>q=~Hj zGmP@Do5^{l;LGv;sq5FF`r#G+tDNO!Brp=r=}%>5VKaD>N!4q#M_rUNL#nd!o;ev| z$uutKE-j>foW}jYu+v+1cslCOok-1ZCZ`QR1^cvke(+vlLa{x*r|#XYbc1KvIn?qn zzQmC%vSR&`pL6e_%Bqhkx-Yc6L5(xWAVfTmJx6VkZ?MGk77|oQyNy68)1OB~1!XM# z@uwQ8(2INcbt_sjx5Fj+sE_iLhj;!&@UkH897}KZ-4@Nw%)2AKpK-rx5SJV2)xa;t zbd&Z|DaNUrK!9gIOi1e0$Kb~w-V^CY!r`6Ac~vF4wXACBh!WjK*tQbgRoo|gMDKtF z17|2iz+>KsD74%!<>uo_+55dtg5-k4t1Y;)=tn{h6M?l}+$Ia@Ktmf$) zo-OjGlyFqF$?xDjA6@iYaN0eMd*(>fAw2aQqK4#*r`|c5+77(`2AVA%NIYjRIIwa! zFenq$Av_@FotSx(%93)=M;Aeb=V=iJ;gi4%>9fxKMG+R}?q{@DEhVC-p=#zEwMkFJ z8gwCEgGwz%LiFxg{HE7W<(8uE88=a%X~OH(9tSZfUz+#*RIObQL{1D9Iww^saUJq16p$I^QrV8Zw@lw%kFGT*!HWN z5D_SCyb2zOKAIfK+DHOi@-74z8MCo}(eN@HzFmgLA(Olm#9riD3ceiQq<{Fk{^5NT zE7Zk!>S_%j>0&gASLU2qUnJ70x;?(W%m;Y4dbIxUAFkHq8+q>CM1aQu(0hj_Iho*k z57FN?rkNp>hyyvp%!)C3ob*oVNfCLH4)2rGBS*zwSAqE*p&9=0F5FkN*AOlHOl~Qg zFEM?~*DTOK_S~CiQw^+WP(VSA=woXl?w(b7OH*C)4TUEtnc#oT<`a}u*T;R-a=&J? z3IYSiAr)1`jZk`1Oh68qqJ&BkRwq?L>}?7yudRnBC@|46K^p4^#RU8Y!F1GvszA?# zk?NP^r83F)DN#*z(gT3`1z%w>(jz_WFj~w_`gQbZ;qgT2O{W?Fe`F$Gd6-A z2d1DwRs{V6d3Y)bM$kLOH$!b)C-cw@RQSsgbTMT%F-XQQKSV))z%QSLHdSO86UWgq zj83hw9jq%LLeVuNZ>3;5)`muj7V;1v|BRr?Z{6sp>-@gO0*;16x31gZXx?#?1Hh6M z$ND3jxW<#bXn;N(^7Uu2R^;~b$QwnRqFk&(CY+VaB(^sH!}d@@e4NE+zq4&>tFsPZ zilMjOsdvap7+W>HlNRy`NoXKy#ZWUi)3RggCb~_j6cbT+KZKa}|0W zqq*y0_Q{YQ`Us4BuadS<~6U^t)cL-TXtF z*UbDZ@k=%;FNA+9h2xxK&#p2zA=FC$2$8J+TB#Fx(xYfi;=paRIYH6A`|YGBNl>xh zPMS87iy>E<3MfjEHPBPnQ90JFG;LWQ2a5R$&81I+Fz^+cH)ycn;?=j4DsIJPyl*Gn ze+|(A)c$tTEvPID+J*MFlZvCtxEb-_MA06V`Nv&>1lYiygNhJ|XSSKk zVMFTceuZWn(qgJpPy+wkNu!~W-f&(BzVGd)wUVTH>%v!iGm)f&**M=$fgFwggqG{JWZ>ZW@8c2nw3yti+6V8sl+efv^c9`V{E>fKNAE1M_YSx9-GI9{H7Y>X6J-|k2;MAn`_l5=P!98Z$VNPQ3? z$WwC_DpSyXG)k2rY@rkeTOjU6y_<<|sz5Ih*Q@r+$syUYT{z#DZDfX#?UYe0+s`0k z?{oB?>QJL=I1C^w=gSYs5h&RNSt9Y@Y}WjjTA#d z*#xrn1JDD|=HMK!;snY!#q;H4#x*oN2;}t{cM~nEMAu2s9`xv-Ut-KdjG?iO{h(<= zP|>2ZY*QWk@;;|yJR##DOFK(0SEg6|Qd9F5%QfWBFbx~=WKExN#BBc9C-8pohLzm^l1sFPKzTSA$P%7k!1THe_O?`o`$!C>{ za&lf~F87@jhawfsF^Rt3Nb^(7*BiGY=LOxOhv&+aqv$b*ig4*fw(51wZ=ex&*=!x` zSe`-?-i4&H;rG3*oHX4;-QAA)*t-W_7gCJ#^+rDyh_UNxMBzFlbEHn=cQ7m8MlL#@ zmH$dC#aQ{Rmb9; zlhYWU0DakBO)gW(_BvAbgUhxP$Q{|9rs_bpZ^KHxe^X#)Yq9bGl=D+Q-C0S>7UW_i z!IISEeHEHXxPCw!p*AjMF?RsO+5*&O7ZlYabG?8RN?v)*(FgqM3Hsh9s0h1a2~23p z*yx>4K7?i;^~!BMm+Ahh>FO>RgWtb26Dc~Y=#y@;`(;tlL>To#7+JrK475R60Pgkc zJUrAbxxSl*&Md5TpAyZlCU=0|#+@~#*&E2&IGL{;RnkFazUpHX{md87mn$cuqlH+H z;cv-AK4=x8gIvLwEpG|k#N*aWa26AM6w>-yq)k6l%!hD7-3y2`_5Mb@Q^Iez!}M4v zet@UPb0~44+`@CD`n*GhHX+3`*dgQeMkHr4Xo}SY_$8UQyjnrTT3(5&m{I8l9KvyR(N#zg?}MbFrm&b+Q2YVhH{qT1-QoJKX*+UUn!bCX zzDtRHt~(#;?W#8|&gz3RayP0Qr%-@Et61=bF`$(n`mk&;5m|i}sg#e<(GI8wr)bo5 z<(xw7))ua$o^lM4N2%j9D*rb)$ZiLOgaPXC1j2Vf^?y@LAkJkn%UVb+8Q3!NH` zq)#6TM<&+Zn~WixHA_Ss^~PPq*Q5aWM^fd8=8Hluo+G`&Cl#dlC@cd}n}V-W{GFj& z`BJ%ATJO_fu{cUG)^#zkq~KbF81{!RLmSbo8SJlkprhWCT%SBDIuP|<0~@l&hwNx{ z0md86Kanaku2GCSrW*s%j6|4@%!hDu)Xog^rQ|t&Q!-vHxCmeA7_<*$&U$Rj8TBpJWkYtN9J|OTvTipUIa&mzELL+Vs z(ilKvjJ~rc*?Xza4ipG6xD@Yx2(wmbD&fEHRnpuoE3X~cL@Y*iTDGYTmt=1&#cX-I zCRF>DApv1gg?XtEkf%K z!cI(t=xq$b(kU7tuzE`Vs!nUz743X@G&-xOi{vgS`=w8-WMG-&tfKT>sH1;W{D^gt zbPtmjXPRo1XtzDaeL^vzuAQh=6%$A$lowJU-1a?bzLF;rqkL}(f1C`42gm2nIcMIoEW#yXNKOlc{_ z6pb+q>xgxfb>vE{V_ca;zhT25nk5?k;h7!BXdSbT^?$!V-}`x<-^^rpU;n>;^E}_< z^Zgv}&*%I39uKC&8Vxeh2_rd9s%)iB7hDVx%qx0y_RL3fO1QX)Dw(L)AAu@d)|9{Q zsbr<1C5`t$pOJgE6Yjsjh^69jC@O?B$aD~1O?}d_TC3aJBN(Y83awy$Adomd0jI6i z8cHpiu4|mB8pnOigmpzX+Q>v>1lVY!pxfB!^H7&8tu8yC^+5+)jqg+@DxAQ;FR@c$0K}!N zO5{~?gf=7D^>Z_(R^U>w^(gyJg?UE`KVT?@eOlP5u#h;BvJ^9dNxuL;0%XW$Eq7x8 zN-Y7I-IU7}gSqu2-uRV|uA1j1>;*LT2$2*|%z9RU*TD>B>}b*+JlY5P2`Do;##D>m zj7xOJc1e*CIF1un^E5%Bn}@V!(NiRw0DIGhG*RJp>lVGWObvXCz8BG6!lD--Y<3pi zYdra#V$nlRiCgsN(};XD#~01$-(>UKC)Q! zTF+2hwCI~JcHPG<`oTZpow8^*UsN8w$E|p1v_l z)P&K6Z5&Y4RI;5g4Xss6e2(vJGxb|q)ZD4@gCO?Gz5n}OIr`o&bno`3m{v7akvLXG zVNXOkzAqwkp#yeTO`S`>Ab!MTSS$2#W#k0qSqq}&lV{wpqu1xwMkUOQ3BRF3a_vxV z8L3mrrWNo`(9sChAudErGQq-6VyaQW$IwM(;>&4@KO70ZsYD)c3m%8Fh=fkC6LgLK z!f6BVGeL(nS^AcU9vQ~k2GpyevLTRZ#ZdLgYx2C5lJcyoExi| z(GTzAP)rIzuTpJNM!66vLNiL;C)lJR5GoVZGR?vqBEPpMA37e6gW%83;2gJN(6*zI znWz{x68}Ui7?Ox-=P>MK)Yy!+a8D=pgYAj(rk|K5UJI!6e6Eu%ygC}1%2NW+WX#Vn zeO23@f*1zCxQ!I4=>E>pAP3)4tJ)0RH5{sT=StlN;80iyaY1QwK?#*k{q9_{#{TY7 zQfq&2I<v8_#J<<(}_=_J3YPgfX@Ew|*h8yu8_Wum%&QafcsuiMH4$C5U4Cj)e+25TEXJPcku0-&|=1=&x zVW!FD;|M2JpGFycTGQfE@s-Y{Dw4QuD{I;x=N5m8}KP?QTu$1+>iO z9py$Hyn}vPpXz-_**+s$L+UceI^+@%ryJau$f_|jjy9p3!w`8EW{#$w5w31>9YQ%H znSe&{Wf6UaF1K>NE9asq#4h3IV3i0L6<5rkO=U-Na%9B<8V-M&JLZ;vZO97B@(KM4 z&KJSU<7QwfR57}MHvub$lMA(6QB>1Tw!ota|7-G{k)#v3b91WN8Kt`5{I&EYV7#PD z4n|7B@4dZ@O7QL=AmoBy?MKD9h1^jo`B=K2Omy9FG%=)TLEbIqM*KLM&3dr_gN$~8 z#2I!_0n2R)cl7mmT0yjmE&k2@h40O9oRUS^Gf!MAv});8at>5)qL=feSmJ4Voss2Mf@w) z&ZFUoE^M?YQIg2~<=Mq$vP_b&T9q5tcL*-P+@6jb9%X#7N{m7aW($Qu!HcC}4_(Hn z$Mu;1mqxhI`X3_gvK1rCK93%rl+BSK9jh9xs1!wWDURlgNJr3Pt|pC=Q0j3AxL2$J zV{6Gd2Nkx&6v|ynaC0U6=wiyMV$g-f5M#x#b4S3BUdD->?WutL{Rs=4uHpn%d{k8& zqADK2ibX+1s4VhVqOXPsY3pbvaBcHaY6cb&lw&`gtrF0n$X#mgx^eu8rP1 z-N(IRhkKg>B6&}G$qqgw9Zp10h7|`Od`}zDWlaEpD3bbail#`LX0C3b93ij+sJ+C6 zGW~^mz?9WdKS}N~n8L6}Pf>3&(f6V#`s&ti6LzIKPPp zdbMIdKymc;S@^s3<#8vPa{|XPLKvNu;~b`CZ;E$01_GvcVaTPt%aqf6E_>ePejp9J z3)VKVw1=Vk-i7yLx52xtyDVhzJz}b@dzTry92l}Uw7*T>rG_bhgm+ngHJ&=}(xpgw zmm?`b0e|ORRo0FYeJGD4X^zjJcI>8GS1C<4suKn+j5krAoq>7Gbg4Z>&lZsc-^_HE zNv#g7^&fZxzppzL5Rq%r3iorm;qh#!W#|AyR>>~@<2BMk4oP@yK$@!%WU{S1qKgw( zP-QWcPb*D$P~}qq9zWvzOKqJ`^GUq-#1?9M z)J$w6HQzC_n~fTXu@G(6_$*W_!!=Zrz5-`@;s!BGT1nol9iv-?A?etjA5akYByMdp z%;7Lc-tzBD#64$dXf@nP^^0uUq=P=35T( zo_@6T)Ic|D0yp~OeV|a@Iyr|QX1RtihnbfD0bIHHefBnKiit+oAvj8Fbfh$zqC;o_ z1Gz&YM?xt$l8LU>fuzjLq0lrN-ZmNHv7F57SjzH;`KmDcN-IFiB?nn4I@=hn zS}&XVbLq^V^YgA+3qkumK;>ULUu{(Z9%f0Yp zb3WO|JVDH?`q~&j`rwrshnhcAaM1Rt)xLSC`7>sU<2tP8HbwpXK=sQuGo7Z8Cc zq`2qP5GZoZA~uVyG5&H(3DtAR+E@2N(IG|Et%3q3B*IKRJnhVRKDeTw&WEW00ny-=02*sbdMO9rwDB8HaYjCwZk zeTj=Rq{UC|1H>84N7^{!Ll|*1{SW9aem@56Qe&7TZv{R>xe+PKt>SH%eNwBgr9+w-=Z_;LXea4W#@Aw*`>Uvrj7FGhoWtf@+HIA z4RaN~l<#3o^6Mk$_Y-@%$Hoy{)l;%Dtq`9$jT?Gxq-z#4152cD` z&=1T-))CLa>JI@JyuLx-$?^tl1gGZlCu(P+H}^JsPS8Lms^okONFYmiYQN5?vZj$` z4Q?yiC?I;{02b~&2!-uof6?G6yTJ^fLkbs-M90$l)n>$TYQ?_4oXF?(4Zh_itb>~} zB+CSSkY@iR)3@X*-@+3thb)$3Q9KrbVCG}FovLa3PvSr%I8iYQ3=;eE7@?b||HYn= zo`5ER_!2O6KHGg5sW1H9`ks(~oxy^1D3#hXjzQR&*b}nm6bQub@_Ga6#@-UUyaoZz z!(ComF#na@6EYOKjMQA(F0WI@phjX($aeD7?FqS5NQmw7x*0S7EUj+hx7yM!uPZQo z(|vqb!_B|PyZD|ET2*Pa*)=tL6yDt;AGh}d;juytCO)g z82mW;>_@c{6B8}_iaAV`yX>$(fJTSV#y;{zuNArhJ2KHyDWBMnur-1YfSwA4yH`DLNJJJdRZQO{E1_#a4m4CQ-F2 zyb)wN8gL4=9%3S%Jj5rSbZd!wO1e|`!A~6*y^4`x`$yENk*E+UI9I zQFIOyC4ke8GFb&dSPw$13q|4f)fVNVW^Cn0vjOIGf6(pz8^Vw8m>3HK4H@HY!y|LV z6zo<#-sM^ScC+;GOB;=C<8@Dc)UVgEc7US3099b(Of)# zh_VspP4v)PRNfcSrlBk8yD=!Ob!vrm*#*vu^uBn?hb-TB7ZOJ_P>2AUb~NuEB!Gdz z1}qTYu8uz40}uJ6<$;CnHwKF(-gg2ht?H;`mXXhz(pLSa@aVL zE;j`m>j2-*_+qL}CDPg3*?mnpmpO0{#Z3=7a=Un6bW{cg=&)}!Kt$~=uA#=v6UWDa z*7DC+#VJ66r?P@~w`BhILT`k@GIsN_vXfxJi(tVEV8QeKfirI*OLVv&TWMbvd^P@` z>qoeMjbM~|Bjcg)Gc@(!M#iK0P&wdxWJvUU^Qls_*tO9tM1a8G_!^kKvM-PIQQBN< z65gNJj;f;LnY0@jcbtax!}yJiJ%tWhJLr(9?2qF}MD`mQCm*f`k+_j@3|~krAiOzP z{#*w3K`Q2MhetSzH#Ej?WSouRYxc|?#I|DWnJARG8yV|QMj>;vU`sbLel87z4s3mC z$Z{j&7CvRT$0i4b=Yv#?MZDMl!Am7>Wc-M(FHYt&2;N${k#Pik6NhOSXvN!~FS3fa zmp_R3jg0RCUNq~D5So06_7Q^Ijf{(!SulKS=|;v!!Eht3)EgOz_qIU%M#jf3LMR`P zfUA@~$QGd4;<%MqXsv$M`$irLY4bUU`vfKZpy0H@q%7Q9TZlFlE-Abzgw@x;>Z@V( zRopinxBT!%#>b9ClZkTj9 z#U2079(OE003>GduE)q!A{KYNu#=3nwYXy|OlJcB>C+bxsRwG?3WM@%_wxe*FZNPy zc?UpP7;n*|NPDXUik)9xh3QVxFC*?QfRg#t#JTkWR3u9*(zIQ6Zheb=7l~Np>$BU$ ztsdL7#;y0T`Xj9eQ<&P`KB)be{^m|vMR{VkwaNfsEGu5@!6e@;$|03>B5C{g z5D|wt1Krd1^nvhPH&v_tQpU(A5fN@#z8UHzGSjqS@a`l@Ts8_q6-;C@0Ewp-$G?6E zD>{6VsNh4ufYC?Iey&itxnU100Sz46jTe@vKnZkW{;Qw#O}pzs&;z4)Erv4nE--y; zZxUz+dbj+Ua)Idy-BC^nnuwmpL!oO&(&gIgCVw&{g9agD#SXPMqc4G8ZE5RXmUC_0 zEPuw@T84E2BY{*`lb%?aY_XpsDF(x8j8BjIbDbvcG}I7-l9{Lhn%~k5x@DYZ>Z&iW ztc*jdE|x#R5Vao=j1jH4g;OmkS9pW&oOa;KOg3ZjlxHCE#R+I<`7=d%dTt?Pco~ZVQBfNX1YyQz zm^0a!BJK;b?%AK`MEJu z5&649LN6NfEqZHu+d|S;TN;w6`-3qEsGwd=F)2RU>j6czAW0)oXPb#fVae{SCQ+qD zb)8fiZzW5rG~T8?$tQ+)HjVc_e0OxO_>bk$FaZU$gZ(8F*+_5-U1_Ms?zg*ot3f*> zOxCeN`u)jj_FqdEF`6!-gvKN5K-KK*T}-^ag`X7=jS9k1BNIIhpQw~sC>w{KgH@l6 zcLU>P)u$f=k#N=LHjE>B1t|=)5KW-NQL8?us#W*!9_AKuCFP@gK+sKEQ9B;Wj*^Q$ z4`WY4OsU8(dZtYD2jWASayjDAaAR5VH?iEL9`vxvthcr73T}JGy+|@avcvdG zq+nXj(odK2MC;(x;9H%Y?InC4$RIEzv+MNF0cXZ5c*RsCoUPq3+;WDktC#_tp<_qk z;D$tthK_f=_fPW9#zj7dKu-@eSx<)FNp)9gkW!N6vSKMS#+Y|Gh-a&S8!(guimIpf zhw$Z!`SA#D4tideK`X}M6!~5{y86%bc?ng zM6xo`T{|ELalh#W53WV51hm=Q^qNQ=p{-%JZp;0b5Hu9MT1u+^H)jrC&X@2oZc&{* zc{ENii!MlUr4PE5kjYdBXuKJ9BT?!s5qKvfI+|WXSNfME+d?1qqTo!*F3DJqP-GoA zl6RFONev4Go`Q+W=f88BX}p3qm1_W8o<~v$WpzvTH*>$J)-(JAiRMVclE2UkeZlHq zYXi>;MMp^nX`*3neS0+CEQ0DTU|ta!hT!guI{7NWB0CR4iHf49G%IgB39MA70nDSl z`{+jye9_kUt=7uXF5-D08j+%+=xN=+ML;fm+2Co=RmlGC0;t~`OHqsA4Tjqf@IG;o)5dILOil)=F)jn(W`2;mr&?sSd zbi^e8_ArYlu{ZOestKLY`tmarZ`jvhmiq3?K#G}zT*v1$S$8J%Ek1gYk8}dJhXh|Z zz@h6@cDCD3EE4sBh6GzD)lRuOZoymZ((BJs zP!-27w_E9G3 z+)M;0-k&}L1_MMHTURz}6)HyMLUTP1@8&J79`X`4Xjg1nGzJ^SpW=;n6@zxfw}Sw4 zYq|sGUT0jFDQXtDCEE`us=J66TcJ^WPoh}PKByItW=x`Wo6GD`IoW()vXxY*=zb7e zHfMMnyYP&AyT(Q3MXQt>KIr$((x-#)DpadtKNl0{@LNv!_7Z}hAi-ae6%~V~Y#{_6 zMuK}vAgZcWBHe`Zy~DmkvAnC!!!h09gm3q=y}h8F@Q2z9%04T)cSU2C)P@UDw+h_J zX_$mxhOGWHI zPn&TDMrhzkWn^p2=s(TY##L1ge?zMBgkhijQ=E@Yp z&Z2r4t!ub{W74uxXt~Rbp)a4{2zcI|=E>F=>azMSWiOQ%t!!7@FK5jkI$-3D=L>xm z-A4s&9*Z{hi-Ez5{iQQCaNF7LWJS;!&$yF?hX<8^*(fKcbmq%B(>q^2^W|TE&Cj`v zmipXLP<&k8OU1u9A0w+6HV)OI-T+;co;7Q$^060T@jUYzD$d>Xts(!J;zh;kqI;@IHDHtxmM!HXRCVp;Iwb9L<~)ulOj@rHY`S73@y zx))~zFK%})?g(C#x)-a07n9wK4go-paWD1{UJQ0GE(l)i;9e{UUToxEycxXsQeziJ zzR^~`7+1L$!-5yjxfdnDi@V*6hk_Sn?!_m;iz)8KHe36h|K7bA9lRLsUR)Kt*x9{U z8ocQ0UVIt6_?JQAitanXmK~VA?_Qi3yjbR5Tphev^a~X>Xux>4 z6YTf*d{dEo!agKv?nK@tnwdKZ|KK@HNe8?nti)h2%P z2GKa3*QB&|m~CymYV9i3S|#sJ)vZ;cwfTwGhNral9}G#2x~pn!glcU8T3ZAcKyX@s z))pmNYZ{px=~K2f&MQV%4B8H@9rPmG8Cmwt$g-bCa>wqEo+KVjv{G`3(9<|;WW~-u z_eb>?RP~QB%fOC$e8SDEes;3@L8^M8l&a|dv2RF?yHz%v^!=~DRyG_j{~ay=JwpC_ zsQh=h{C6<^i%@pD-V=P#AH3Zq#f%MO*#bpTCK`!Jc&2D2(35;q5o7<7LrRQMcrjMqafTmVYZ3HgJvUNP=o@ z9Z&PkYkX6&>ECgR|Jmzl*%gB_ouG9U!*0hv(M6c;q2(EaNKXI8trN{(h(;PYZwPxm zk&iFnW8mQ803aLoiwyF;bjA+z#8`^;_F?(Pl$#C!HNlzr{j@PRHKF!vrb)c7o0N%UUE zSG)-*9O#AY`aTc^ksxrf6g-P8PHEJ?w7K)eNu~{BTgKT}2fk~hL061o8ruNH1M#0( zo2l0FuG$`iH+JD5dN#nXD+Ti9y0!yae=b334IWc*d@8q;9{QDR1*N0r?OxKgag-*z zsBw=(8*|tOpOVR|F(KDwN2I90IFd0!3RiUBBpBqGTEqeG`>?!W%638d{d9TudW!2c zDUEgQ(Z;)#jqNOv-G2OqQ^Q(_CMSC3yI+3I@E0Q1mAQFy^;O+G_X}&q{Z4ye1_x}# z=A~!VghX;)iwE$rWX5dK+oUL$-Rz?bmZWfquLGXd;zKSn0lcUPc17%lU7epRb~PRG zP_!KuRHA)BPI(R%Hs{uXBxy<(F-K2SzY8aFnJ8~AkGxh9D;oBs4$oY^h`F2vLof`Ba`JUGpFZaG`h-87-@dZ$_8=0zy4z?w=&`Ok_^u{M~{? zKA?!qQ$+S4kIw@@W}Q)%qj&7Y6ZaQW=S-cam7P#YLVoPEC3Y(OZ?Ruqz&~3 z>mdIO_1Ow$oh_p@9)d`H$LtPv3{sbyCDl_Jb)qhA^Ai|?Mdcvncx>_IU(BcE)x|Z~ z7EtzDaoLk9c9D3atajeq(-6ue9FMx+L@uLJKhej%-=Gi4265-wL!wgV9+Z50hUe=e zsW1A3aW%B5W+ZoHmSe?LU&tbMT-*Z}^$R5`@)=R~@8Yr_kUENvLcZEIumlYNUGE@~ z#T62WakxK98L9(R32LD>oR@S#O?&H0J_}yXN&i0t_Y|oW-N$2sX{o(ls4bdps+Hrq z73DuJhUY}*^T6qOZ0YHL(>7@BmHwgfg75LTLdAokpYO5oc&1u4CHV75*%qLAB16K8 z;1V!g9iI%JnEU_Rk|E#Oi zKY|Gc1xzA2xnQvh5S41>;LczmkN2(+{nq$as&-pLNw^%5H>Xkod<_}<%a_ztW6lk^AFf!r&r*0VDO|)ipb*rJy4Ry{Q=h^^ z6ot0W1&He)Qe05LUSWS5lNnsJ0zU*R7lRc-FcijJWj3A2qM0=kbygJJ+s>2%M5d7O zJrK__>UkA2S~C7Y#8$R-BRAK9>n)CH2sF_)c7Cj}Yjk56&MB}>eEJEueSzbe&F8w; zZ|89Ia&777xMSei!j?#F^pZv!2^=tJ_7-8uI@och> z|5S*=a!Ql)5f@xAbTQ3LG>ai|ItQPC0@*=dq9zx1RJZ76FzBCul|k=-nd9ah)fhFZ zem}~ncH*dppeapuF~$B2Hl{ht`QQN5I#$*C0f~25PFL3I5UaHX1Jju0od5MNSeUxs zZ~SLO=up@D+orB3|H~7tzVmcGxHAR7E0P*U>P}MBouH^I<81hJs;*Y!20HFQjXwun zLKItadb|X4EThMBPzlzq^tfU)iUpS59fn}oZ~7U7D!2g5CN;`{_7k|s+Eaajen(77 zv6!o=>Mc|WlrBQt8XbZ~JV4+iNl>J%w-cu6hb8#T=d^{_M&hA-MFjuCsVWyz6Up%K z2nf$3K`aIbA>Vw#uS|5<&Sc3l=ZFQqDt8I|UVlJsu=J_?o{*d?4Pe!-qA0QfUBR|& z6+T|J)nuZ4s&DyN`XT)(&)n!FAXsvf4A%LEwkz3cX#1%<=>ZA|{))L*lzCgOe>>6hJMk;b==w!!1rK9>i#OQTrx7CctGRYV$I z3s}B|_}2v@a7t?B)c0A!QFGo)DqW*oJ_yQ0^$m!B&~OwdX=@=VSXD+ep{9?Z_FB0=nkyih-rkH46&hsqxVLa=3WtV7)w6C->@Q{eE>c4II|K=mSPBXqf%H z*r6TqH=q5KntrtFSdOiR^lA-KHtcCX;+^X$9|mfA`T|O-d%A!gFX^lY+c^Ej0t`KxBk2vI-&(fuDKwDdi43^C7x5RiI??-8SG(?lmlB%_KFLGIm6amkgP8VyQiypmWd`YgQO34_ax!vxsTjz zxbPSGC0yu_5Lk%;8^crpcLyha$O%w2+vm+02Wby&fAOY6+vUyK3BMbz;De3xuF?@j z6*Nk$q&tunHtS1R59uL9U&^i3k+WUHA$8V6I-PvfLz1&`7}8tBV0nh`UFT2~6K?A>_m9@d(*~aFdBJBH!1B3++5AsxTHbgDDn7N3=tY5 z9`6m6%c{n-iCZ9GTr>>Kj}_WgufQYS+aVZ10|FoQfSy%8%)zaB#{gTUtMlQVipvh^ z)bKIeLdB8g6H$&SG)&hVNgFetp}y;Z?&O}~62^*UhvZ9!TA9okWbPDaSCgj4l{6tq z?5Cg@nGnH-MNtG9O%5%By{MbA{+grI=^0j(&R<$OfCB*UpG2^$o*{q51c+9rP1SGd za2e8vki#W68ad?4FOkE$h!KgJz%$Rv^5#5&fj2ye|9HmsOkZbgBH&4E7(`Tq2z{f{ zy^yO{<;r-KLApwXt8!sj<=A+YgS`hbo^Oz8WVa(+8+)RS=+!OoJo~x4qGqK9IOC?3 zgsv7s_=dPxrY6uz{&`BBn)!AM7^d_7o-bs`#!yW(rUEpzUTRl(3RBAZRMQSW1VLmn zrz@&3J5HRGEXQ1xdZ>EMV11^Tcd^K$O!NbSGW<=&!T;mADz*UJfp6Hy6f00jjMumy zRH|U`@?kEBRW$HqJcUWd_STdf17(MuaK6msfsFjm>!980i(jw-c~tp1AB}ob^cUMy zM<9Ymim0Odey}I;jBBHFzMxTnM4ejLgLKdZ#tvJ4OJVz8)-|ah37I7>Zo;^l85hgH zCbm|j+}kVUI7)_jkx6aML!7;nKbtytFZfuUhj;)xm*CBx{Sxl+NePu@W?4Y?zCxRg z&8Bwzq^)^~T|aZPlZN$P9%8rz0-Vt=(L8_tqhDH1L|h8XOC};1KgR{VL5YYtpL!(5 z6A@cu+K1L{B4Sqw9{fba&fo>aHlL2xP2j#(;XySyxZIy!qg47d`dlEfna4H66A`0< zASxzRn@d|uL@a?y+s4l4q}0nabkL1~w7NCPM8vv2sxQ1A(PXFW!}~#9bRy!Ce~P*c zz$`bqvRMzGnvW{?x!RXX<6$D=D*f6^M643GEm-~!h$5bd7;9?4QqcbQn2BWJ;O-#B z4mzHQ*v!#&5mZkHnv?dxsB|LYo(37!Uz#zhB^0w_SuuO>WyM4YE;m9o|) zv07KdHN{QmGiZ4%5pfYPwe5+BccE`~lxc~G8!=fiiHO=r#*{ay3jP?syHw;sUW?P^~vjfWUms$Y8;SPP)lVa2-;h2@k6)iI`q!oc+mSkk@7t~9vv z(-H0??;pp&E{-nF4>SgLSzHP_Ax1eu!lxY~)pVaAO?8^U>G5x$A)YWnET4UfzHUcqf zJpO$x#}EU1BN=J*_y^cR3m7;LF3%8V`gs{u+Kz!YqqN4r?J$dsp4u3lI}B8(hBkBs z>H=iLoahGZ0_JGcd-M}wPBnNGJx3+Xx8(2QQMS_Z^K)qu#5SB3N6_ zih7JkjM5|`zvFqL4pp(d+omO`r=Y{Ou{i2=){O!6K6*QedjEtGYEV2Hal63>q+<-~ z&8`=98G>U@(KXam5A_~)wJ(>(L)5F#uRYXzAJD2%Z!JV&Ii*qWL{med-p`Cs(ot`3 znpif}+tShXC&ZU}RD1Tus5I(5h$9P_{w&0yo9HQuS&d2}zkT7Oo#{09LM@GYC8|~# zYt4?;s$>EvW;$Q2N}%4KkYsE->U{uxv!hHyz44?@quzTT$(S}Gb)Rsis!{I@Neuas z-)Zma5r?SP4T4{_kO3X7}(ciOn`xvgboRz3GAKN?&%49s_QO+|dENA=nc7?sAr`*0Qtqq+mr+30b#YRg4@!N7fxcyXq4BWr04 zoT6&YWvv;pTGzmk;}{sdnZUrQ$g#H_16M=e>?qSP@cZpSoyNeo{~=>)PwGCBjGo#} zaw^IDOL#0q@$JX5$1 z1AklOcQJx3C%Rk79F2NU)(LY~fJf0XDxrsZZxtj(*YAzCqTT?H6#?oUAsJJDzS{@6 z(H2qfs{j0wGT&YJgW%F{N4?6ooU{_C*BgO`k9q_CFRm_ogBMBE`-w)TwdGA@X{;@0 zMLotNMrjhLcap59wLS8C9y)9ri=$qiZVafmu0{YLK)ogyp^p5H)19^*)6tET=T;onmSz)N2o5%z}FR z(ZsT$-nNdeS%@z+>fN{sCS8~bscM6 z8LM?OH_yZ(zxA&rP;V9vC$}B-K8C*8QKq3@^|qi+qu!cTGN!JiE@E<8M}Fr3_(Rm2 z{C7R#5cLMA6;inPOti6NBeHHjnhz&u2s8bxV&0|AsCS=4^@4i4W3f3}(F~d#>isVw zzl*R!-~>69tkM|x*gL|im%y>;1*)Wnfv;m{OI(nBUu`P}?&UEiz`*+i<$Vl14%65c zF|ZUX1Ie7<9qa!~47_HglU)J>cR--wW8hv$TZhWi54=cX;14u8je&nhmd09kRt#i3 zVpJ%Bf#W1s&~^;0f=1iM;uyGzZVYN&zdVV7U%(_a29A-eonYW$I5BE4@QSxYT@Jt` zIJ%a4>tWzxSG!ai4>9mM{o2F8H2_+TfgeK@mQxx7Czu)v1OLMaB|Y*RK!eMMfm=Dc zE(MHg44i^PxCR3s#)cpu`(H7gjjAYS4+94y@#0Kpf7a3%I8D_mXRRw@wQk_9kr)Pk z^-2N*FU4N$wqxLj&^J5EGz`2QhcOKX*1aiX>O|_+F*&UIDOL#SVbzB_we@3{<=8)CXaMtzc@;UJW|M zLbxR2BLqf}AC}X(i=R74X{9*j}MFj+mY< z`z<{+0JBU_ZubCIzw<$0GfsHe-GFwPCv*U2cfnv1iQNUMUyjoTbP{HPfUqOcw79Y_ z5K87f#k^y!V%7mjL*pejjzIr$oJBnyM3m4=`kh^ghS_Svjs2|L3-Br$E^c_yqKSQd zr+eK2a~5rPJs45x&4dH7`v`XTC8m>6A@!1^Xxb;b+JmHVZd`D$57MuRCVF(6VRRZz z4tYLoYztFbA;}W}n})}+F~)E4YuKV5&2b3dHMwUo=#h;&6@%uk6mmKHjjpG{3g-$7 z?EYt#9Y`is3_3xTEo0f!Rap_iS(wrUBB%n;+J>AA9>Z2ZBZIkqk=WLXTbZ%;z6TO& zjoD|R?(Aw}I5S@&Nq?ivQwTq?p+#)W+>F?oX0;cAmW(vKzmU^`GWv9*L`^T4arvtC zzPD>-F)2~X*Km1EwNCA9g|QzRf-o4YTje;!yoXue6~R-jKO>gWsx?W}#F0{EN-Nbm0fBDA-(sqDqb>vX{~ObP zP3{}pIMv!sk-H&6Q;!oX>`z9@RtD4~X(2A&B~jW2yRsT;59*Pd>C z&Tt*UDK@j6L@V&r^mbEP>Bca)$%Jl9cO8Bx`7(*Qx_P>>nIborpJi#%EeL zKEXL{sC_q<{Yr^ebmL$l(zj3EuckO0=*AGLw-&;tFmhWYrW-qcfp;6O8?T8(oNgTP z9lH>Zq@7PE6^+Dn<8D%`$(jaq&ZZl?aWkC~->+3k-Ppvvo&sypy74K)CaoI_xxcVt z*m%ruqeqMqYTbC9r$kiacT3|TZY57PtNB_tni#!$x-r|7R=TkxhMmxjlU#?( z5Y}sQ_a(X7C9Qu&$Zg>C?LWS_^pTt{EUR^6g(~|!%f7A3if*jjn<7r z0SvxwoMuWZ-N=PF61q|7I=mP20!{8ExHH7)#(T?!+}Ga*xu3wtE6zcpS~rejS*;rn zsa!u&Xz zYLrmx#!asFWNAFqjcNL|ryIQq^U9|b%k0&~8^xxy(v5~?DY~(f>#!_ib>ly{LBr_A zv&)3s$1sJBRv;v?64ko#Hp^<=xK@>2%CfhqvZ5Q8(Z2*TIO#{PB`1VWX?R))&oD@l zpf4G3yv{|54cConA`zz>htV_xy1xC&bn5HIQ65>nELln2c#rc61q=^8p45$}-RqtJ zacziW$Uv&Bm4?W3geP&dZw*Pd>iN%K^?(G^x9%+!tTVM;6A zcpV6nz>Q9>!*h|4(B$5Y+dqtM-1(xAd(#^r_dy1}MqFAqrm?KnjSE%TyIJ-!RaSK4 zC7M7WgDGEnEjitI6{$a?8+VxDq~OM5Ofoy&h~FXdI8?{XVdC$m>8!8JuO&yYrII$L z+nJ~av-oT^XV4E~6s&1acIN2q^?!gV%NsP(`&Vg1X6k0n#Y+14`*Djo=}*q%Eu}I) zQ@1kvcWTU7V(Ph*a7bdP3tw?VaxK09j6ezh4;sG4KzM3{xexqVPh*mA6d(RwC_r){N}P@4*+*O+;qGZ)qhd&8FT&f%J0j;E zJ5iXt^x;=%r#VNF`rQJ>56$h5)g(2+VT|BrsD|y0ltZpKZ7F#lrc^Rf36;nDKFm%k zj%YHUg}L#4+k&YrBIn5vbD{&X>QAm1_T#$;IFF1RQ~2G36CPz#CSR2=)OeaO8A4LD zayHe&HmDDC{zWqIJs=^7Clhf$F_A~^nt_aZoT$$t>sdbE*(1f0KuWw14@$7ZI*g#! zXvq=C!1A)`^3!qq!)NNloBM)BYR=pbN_Nq=TptTVXxzr#N_`RB>c}$i0{TPM7uvk* zB77S_nU~j^QDe}l61t);l+YCtWsv{w3qBp$T>}cnP0401`dEI-w?*9-d^%W{0KUpp z?JWeC=KCp0X`!S1Z)``g(X4nn+naN~7kQ=0A1yA0s|MdiBOhmMtMsB1ht;b|j3Jeh zT^`H+Zt`a-?`*b5e-`|7PO@-W(q0*TW-3#dj|>H_rYP*8|1Hq}_K|-<&^MU0JL`0M zj92%qlIHApg^Z3XRij>KmBUZWCYCXrG;-(+WouCmbx}5MZw9|_?LMIJwDsg};!8@J z_q#9z#b!eDT_i(4QXu&;`+;9|qZ(|DhdZJ0%?%$Qc_z7ZW^GQ%IAl=(3JQczQvHpWaBhOtT!v~f_R)gU0wFb4&I{4Dt zPHl11mk|FkLdSRyFNj+*QY?^OoM!`lndmmyfLl8NGa^3ac`p0(zxaOr(A8+i`+ofz zG2b?Pzy6PaGZi>h8oY%IPJF-qd1N8n_v?rMQ}veke*MmnW%&L2KXZa32M?hEvPLCL zoB>HAo4X?>fH>tVhaqcq{BVIJIbdaQ*^M(*olJDVIx@`^h^Nin#y^{F97{0aOCRC)kU{#JJ;+dlS1~9nfbkJw#sP+G z?YK`B?>P;2B+wd6Kr5F@+rc2j#4$+`=86Zp8a8EsDq9GE{Rl3)cn0%D)K5eg%V1Ag z$V~sTV?GQ(S7=>+>ej$vAl8%Jp2P#m7zi77z@H*Y`S#h~NMVGM40=J(UkDXJD2BNu zpv(`A%}rJOuHKMX6g!^2j~5-dFz)HE`AAKG%Q+3ixAyWIU#KLP{Yw<@@)e}Nub)|_ z=FG2ImO76Joj8s*gMYsOV8lv@h?AL_yYKf(ig6@H9EkaCXl9z2->>!BQ8Xo$>fR^g zN(EnOG92995-94$clo95IG384-Ti+xUAm-F4cbdgXS6rEzgea$-fc5^bM8Z9>Ryx~ z)L*$sO|JF0jl$CvKWgNw_`N6*Ml9l0_oCeM9Oj{5{X#4CmzMInW-h1R@tiJ-_w5+c z>U&YXW7MWU`}V-=_+6fR>e0PW1p!TN^HKaIbNm;G|C*Q`xmS+`I1>|7eRMhagujvJ zGIypP*?6dT@5#03#@tH;#m+=Cy$3SdJ=i%2odZJk-6>~%g-J-qH}O1{QVTQ`Rv>A( z;=bOUq(~ReY|goCC%lAA?X+fN&?%pqq#<-FEuKs7;Cei3l%w;FUe@S$FgV}Y4nwr8o$bM2lKISNrDTn=*xY$f7{yKI7}UpEYbmAA z5l(p1$T~)66ue4&>a6FfAE^HAr&;4@X6?r0a0`4uR&SG*x*g)85dK@T)QX09Y2{+| zEN<~rq@1Z|1%`Vv8sbPs@ezv3Eicnw!Baq^hy9>S?j-fxIW-HXC*6}U$b))Mt@RO% z=?racpU;;Lkki0itMrRb$7=gIkc{OO%>JcAxPo@$l`PL|hm%pKUZ207a?r+6pDe>O)4=y{Ad4er!vdNG+L~r3d{4^7I z!uh3GlJ_|8#~Zwn3JJFzq_kT(cox70aFW_h_hg|-UpJcb7o+W9x<^(JZv2#v^&E3O zU_RTJzxCdkT|J@#ao26WuZQ-k5$FM47mfhDs{4*n1HuPRRgA;GG7-lo?*v#P{)@7OuhLWTKU!scuTxl*wPM`_%Y!JZ#*}7_|P#-k%ppBcK5Gelu&y z&o9_*fatl=bOOIxI8yp(^oN2p2~qrZra__UzYOO^=(xZ26KNmy=uC4&x?U4#PV%Z+ zom_?=B;j*|ST5iSN+DKIMhlt6>i%dxlSTR7xTmWzQ@4C;Ij{~5N=6PPzWiG;IX>$^oz zB?0R!^ORMvQ4fET{PXO&2l1+mj<{JX%V&2xO*P0KTy<)+P@l!y1z96huLCm6puT@s z{~h}hY^f@fuicB}e95es1)8tdL`H#uHenl}%kIOsE)F4BcHv_N@T|?Mx7F+4Zdn&UH$d2{%!Ae62t&%vkd@S}OuLkA!v*jmx<#33~u8;0U{>C9^REM7G~N++MiJG34=TOw>2G;yKu>@j?VBz5T1MSygVmgyA{)5U_o};zdN*t8Kt7f9pxlrRKLM!OdmesfC7wWw= zIJ+L$B-_gIK?#aR?vKR3ndmxJD{XFHatPE%p3GEFI^wQi{p4)*WFygxkFZt$S?tlG zW?ZsBM)?y49qmHd(!_CXA^uSayZ0SWYIdI#`H7C$G+K)~DyoyohW`A65)5sk7?grae1xNHYyfHskMSxKUGg>? zWV%=WdH|-MIb3-*WrK=iOCOR8|hbcRYWnI-N@+YGSjMCjq_$OKjQr@sV zb7wBPJ%oja6xCnY&9wFnvH^TDZ8P&^EuJ(|jfEFL{I2Te?_6cy!N+X!MOdDfTF-9F zd@nT-n^UyXUj9WT#EdG7M52(<)cN2Mq{uI%j0(P6tq!Qba7WDpDJUkvU+Hyh9Uypqu^_H<)bPg;cAZ8Nw_a<-$>Y~4LCq#(-KAl zOr#7o>^L6qVZAq$hMLBE7%@VcRq7`~bQ)~R2B~zvn^I^K`nAq?^$Vcuwy5;8$rPT)(<0GjimVt-Rmv%zu3#=l@_K`$#H&3ys>#+a!npO@C_Un%&YS5Yv_3$1SP24&Q{(xs7%APY9;Hpk#> ziCAz=-SiDr6MxfF`G_X8MGLWjF%Z&H!cr--(a@4ASp5=M$D-4U%he}$pnD1#Vba~d zLWpPQk2hj|inp~84yt9MfilqnKq{<5Gt&L0jJs732V}s6NcQ~k zdup;hY=r6@XJ?9PfC-BJdr(;=jzK35VCkcUqofhmhM)VmSS|Z?G7adulcZy64eH9* z67X-1rnLN4lEF7}m2*BZOMZ4M?hEvKt$5jw_KQ(^V@B9pB|%sZETTd1XALzN zzp+H@v4>w*;xI<%SK^183gpeX7W`?LLneW{g`8I6W7s+J6$H4YlqN)K7b85Ak2wfm z%fu^F8!0CcBY6Ke4q6cfB^YHMpM!Z*bQRMGWy_--M33v(_fA;2j9$dj2;$Ar{@O`@ zC>~0Lxf+vS7rEgBN9ton?VvtXa6p(_Z8+dXp`$6T;K#}`jGG@5L~MKsx40vX?@0 zDefav!l8r0Ff-9t=5MoIi{*68x&DC!(qd3k>yuoIoJ~Z=F@O&KmSlzgtu})3x$b?U zGAUH&*>l}Yl158#wx2n>1qmgsJ5J6Vh$H+o5-y)W ztr*lv5q>ZUUx{>xYFrcEWoWw#3qkx2jXc>XO)wpY4I325FSk*OhjeNzOnJHBa(S8G zsIoZvs{YCFh>iTj1^L>8jVxlmF~}Qaqk2zL%?J?eK1R)YufadjR&lDy?j0KUPa*0d zdUI0DZ*s(kvsfahL-IrVs^HZ_`r5EeB(A%f97o6>|IWfz64lwSOJL^tL7!5dTQsN_iovRK2gom3^r_*Dgwqix z{?l;?_t_ckgpr*W@SkCa;GgJq*sm_?^j0ylS|S5BBjzALzde#Cje}8vFY~3MSfjlB z2I$?moxJ28X(6Bx0+*KqNqdkc55Iu16Xq6XrD-jh@s7;X)<(O-vh>1IK01gVdIAjv z3roNqm&zXu_fS(d^<^Ig5RxF@Qam5PSubRv`JLvH9$A9I09{Id56B+P#~dSa`UBXn z|0%)W(CN{&>772U*AZyg&KslCr6OhT`-ROwIJhqQCbAztwZ7RYcD{t~QbLsKA)7>Z zM&`MI=OtjaF5nUQQ(VAJ#svgEky_HhEu$Fxwp0<`MBsnJ!k~vqA{P*!ZHaYY1z1D* zs4M@gbt@n07>&vVsSTegr4Wi>j-!IB-O-QoD<~m7Kf{@2plZ3%RBDquI}u|=?nism zj5vp{XE*l~&CBSk0D59lHzBQK5G#z!g*yr#Ci*ckX2A=P*O(tuM6?M#%tVKR(JFpi zz&~BSZ4v+6w~PcZu0?JHVdVRKczGQkO7JVpXvbKyjB(Zy7SwST*WXa87IAqU9@jCE zj!(q$59~`&F&WBcqV~W(tST@@l-k0(QCO0}BY#KXgJQW%G5X)bh4r$L-w{B=Cc2=B z=*eZIVtF)*=ULRs#4%9*=*uPeyY%IWenh7ya5WO08xcP;Lp$C#{sGSp^dr!F9Yskka4OeM;)mKJX$F zT}<$lRVw@m-IP`iel(kjq{pAx=zNeWBBB97GCMMKR{trWvy&pnr}I3iYw7%&4mD0E z&+qxB+;$FDO0=M0A*Aekic7+aY#cmJ>RQSM%}JrG5K#TwC_97ke=5&birb=EWTR|1 zscR|wOKA#aoL~Gl%FYoHr15P1!>#eGztpvqwM(Py3uK;u8)e<3xirc;Da31mXYXA> zCRxhPls~y=+OvmGnBM}{nG;KG*Rwv*gLG+rCGkK@()>aKbW7Rm5|YO#>v8dKrR*y+ zwI>OIZN6-$G1>I&aj9!58<0lXop8K9&*Jm$J!j*+n(;ezAX)>1mNK1VM35vcot zb8Kx63f*`9vnZRq9YG%_n@S}7Lj&Rfj=4jMz#kOVH!k*iaS;`uZ{>{v1@0Z;R=PxJ z=DuEx16#_;loPGcwm{{6RBY{Q9=ci@)agCf9{QRBS8lTm94qQ0`YV$KBK$@?bQc=( zPW2r{MU-h`?9AAcFcZf&)k`vFJFp}xEd#OtBTUv}m^$dRIZBCzVtS5wqjo@V2{_~X zUQ0ow3ahq<68Q2q+pWg67D?4%bB@jdc7aad_X6_ctB2UMe^&n*&^@x^Ttq%9?pg_} z#8JN`+*QuWe{>`j7p9C&TLW)5-lV9 z<0j)>7NJhX>5<;nrJ`pOCsXJ;yRZ-OAzdbraVEMD{dn)=@|QB(L;ki5#ULxmSYX^C zoDtPQacZGBH6XSI3eKb$V>~<;-M<+-M6gITL_NwxXNZWbt;&8T6>iUl4 z|K-Njj<%yBa56~<rzA?yV-=u4m7O!HV4;?M|0bj4kca-Ux_kEm2vIrtx7Qa{8N> z5W}axse>^>YFXzISx50A;L+QyTnj(pMsX^*)$%9`F3m>K&6U~Sth~U!(PqxTGED-4 zPvDAvXEa_=My*TuOL^;-n|57p#Yrx9u6t|Xxf(Z=80XdR7geI+@z2gP_$Oc%egJCd z&UF_~Q5*@*bqCTr&#h>-utE}^_`Z#{k&9M$85vXj5DtHHDi)S+3aT!rahUUUF-KXn1IJdrQh6ro_P~Pe8vXwtjhL# zs%e#2T_yA$(^1)zQF0JvMe)6FB9_1#A1Bd52la_+U9vzRL}Z@(k`k>wN!1E}=Asji zKP#^F`7;iGwQM<`!F8o`VGm6F(%D1PFX%^%Fll_jUkM+HjV7=lP4%Sylv6B57874C%W&oSS|#9&e)W z7T|C0FmrpITanm1sOCv*-Oawlu4EL}B4R&b@g*KZzK^=;63cnnyrD)@T9E{oF<)}l zgB+Wrg*H0}KdGG+atEVm`DB^t$?H7rSj@({I4NJFrF2r}V)W^6Hi6TOM-AE{r<`ly zBHq(0FhgC-#8@03MCZo^*xxT{DPD#kXUHT%>Z_+=-nRDpkR|nFqBFob9TS}mg`#MT zsKfY2#hgu4w8xP|2x6BY9^Jq@C%&`BhLQL8C5MwRIlv>Nzp&;gKq4XdDrDppgDLC5 zFn-P2gf9=l*hEBuZ^j6F2`qs!xP^CyLDOA<^>OQQIQHuTq;(=zJE-6n4UTSdRMH zl|Qj$t6bV5qI||Kuk*43!a3R6u*dR(C-`>p|gbz2is}A9P}4I40Ac4)&+P`3oRs zX9ODP4Fd(rQeq<3f6bP^IWuiSe1T3x3)UcrK_|`rUZh3oF{#RMYI{ljit?ijgzdNj z?Vs~kGvbtJHcLi*N|ojTs137W(=hYE!0=eIVeRC1kWn8fb*)`I33((k)%ggo2q7ke z82AQR|ASbBOJ`t4WcjX@Lh>`B7j8u2|1#08+)?1tmz^f#&$Qj$0f#Q6V|V%;yxZt3 z$JnwTi_4nel7J9o0FXjdoNl3oeUvZHw)-fTK-a2JcmWz%ge9~}ETzpyBMe37>ur*Q zWD2Oa2G^n>{5vX0N=UW_Z|N7%qy(FbWqro%5(RCt(Xv+WECtPJdx!U`P*Rc&$@MVFy3|Hw%TS>S8;c{=#N5Q4_evj&0Va9ei8!#mXlxtKX=xOR=qQ zwYCs8Rg<)-8aDVSW|!0=f5Wu$aIZj>>>I_e@Z0L^7~RAU5foYF157Il zscU_bz9JJ1kilAo-%0*tVj9*Dyv7OZH=|jc3c7PBXljbp3b4D?4dZvgzU?TD(6xL- zD=za37@-7_J^cb^Jgq44gUnAFB>`7cmDoh>1u^VLABc~x4v-+V%p6rFCCBB^$ZSK%wh~y+ zC>qKkKpLzzyhoWhe9f2N0lwZNb*;L+f?$G!77H{hmJ@+{0lr#yO0v^58M>N@o*@Ix zuDKQJ!noWA@C+;M*qYfx&3?RCLVTxWj7VrRx4-GP?4y_ljUo_5)-wj5VP>ZQ8zr&+ z%GHd%+0Phkd=V*BmVYG63f4>2q4Fn;E<9t2}wnY;eYant~#3v#`Vi2!P!7%-b0jq-58guo=pv{(vLzYWiiM_2kiV{e*0) zD_+*zK|4~T+4)wpOJ_Falyn!#$W%f+YR6|VtZ+`!igu{;*V6ZD$w*q|tC2r5fEbu2 z@lL_UN6}qp2#2zz2S)z^uQ8NPV5G)>6N#m2lZ*%o=4EI7Xwbw3>hup(FbHZzF*DIn zO!gg;_n^R_n~<$?T@?tEtnO!`%jC~ic8rq0at;o09Zr3gA-*$7zYJ z4pjb;gO#??f;@ViZcBhC3`x7APaPXkKL?{zm|ND}PWzsQW@NWhQMH|Oog%<2ripD( z)D!9QeK>Wj%?v`fV!=O>D(E@R#@MR6XiS$RqVc8+8D_AO3PPJy0}{*Pnf_PxaTw?K ztQ<4p;S6}f6&l)bGlm8xN!CG_H%&C0NNsqx)0xgkxC}qW6wJQycP4rjDGrf@PJ#Bl z+sq(kyhqTG#jYVQeD6S5hpwhZ=&sIX`yZ!or)d1mfibYi{caP?106^#g$FPmMrHJ7 zK%;%15O3g#uz@cnO|4v%YM>E7)lvf&g$-PDYMg?}katTB>=QO{qC|E+1-D)hHUNE0 z723y!_FxM4cL1=q9woQY5O@{jwgduSCy3Y@1)0g@x1P&$JJvwLg-d_(&JyS z7(7PYj%dc6^wJ>HzD8_;zRl#WR$ z>c$Ux^g0oR)!^~=nEaH39>`=R4|@ElJS3S0XQSx!4|;gq$$rkG0_l#1Ql>vJ#Bnq! zIp@(E1i@J{g{JsxS`Z{EKzQzsd7Nr&CphLYa=aZ?EzkrMO1iZOL`Mq%;E+Q!7zVDB zIl};4QQbWDA0G2a)!6GqIY3#Uv1N#MHdJGeIn~qHW~GXtSBZQ+ry)s=y+A-Np|O`J zt)Yv=Xr0D>LWcrOAV>X^GYOS#I0gk{DqAEdXI1ul24dy?g}`!OWgqcWwv(a16Dp^u z>|@eMOl8k84d}726z`HnWxpm>Evszm*`%w0iMk$GlvG)tJx1eNIh%CPDQL1SXOlhv z966=^(!gz?v|GDz`AS=R9h9>X33DoKsignKVa>zpN7P%A|7}p(@gmB&(jEs@hSEwj z+Gd=+{SThju7}z~->la58ZCdvakgC4Frl?C&ymszt$kSJ-#X5AEJ6L4(vD_0>u~lI zntPhkE)tgoOYw1b3sg=~+Md!#Oli+F4QQoZeL6eNqO{M_|Fo>MsW^K>D@vP!l1ZHn zaJK1WP|^mRt-{)gQ`sM_{?Hj3KwWp79hI-LA5vupqdrx(Rw5@+*>?fC(G)}$ZNk~D z(Teahz}YcaO4?AI{pU%Z#ug$l@ilhJDET|CvHzfDB_o4wSIFap#!eRWZe3%!A1AJ{ zcZ#-Kn0=JCo~E(iPnEtyjXedGQ#5w6G!oO;CrtxdV|SL0vuJFmV@ZaDMH>_u)H7OF z^-^JW!!>sJNocVR8oLqJm7K;Fr-JN0baRS2Ut@O%(b1Jm6+mOR7tbpi+j{|?FXf^@ zTOxzp)W{%j%7$y~;PIZuUV9$tau~bx2>Cm%vAZfTt+T^Zv#N=+q;x`K$9a)~CzC{A zP|Nx;jQwIF+q4?{OSZt^P~{y$jeQiAQ#7_p8i{Fa2h)Jo*o&m&EE;<}ea~;u*geZ_ zz5kKMUULFkY=g!g2Z(bTd$VL(=%am%oqe>W&ezyKLD!;Hf;!8ib7Wp38hgPVc;1!q zR9iIm&jfJ#tN>$Yj@fXHz4G^-#;%bmhtt@u#q1_A`Y~u^UMvF^wH#8qgZM40W?c1^3YR{05Dk z!MTd6_dn9u_m4-5ZP3`ev9HK!>^dT|sE@C)Z;Z6m`5K$K3YytV_9ZQko|Wi8H1h(c^bRhS!~v6?D!)2JC3o-)kGzZu|Ffc zN9}~hu9H?<*Vx+`Rm3!Q9%trGV{fIYr)g~cxzcy2u}7kE3dSBMjl?weF4KV4*gWYt z3&yUe@A(ZH``TPv?|-DReF$A`(AXyUIj6DvFf)+Q*q&}wzQ%S3(a{v~lgpz{h%R)# zVAJ_{F7t=BXzYPzUJzhx1H$4B)!1Igcp5uh<~dGd7adIc5*WL=0@Jw09&xdhPH5~6 z66d$BvEymSF^zq19NV-}!RO*u`zvjs&Oz{UmC2sUJA@j0D=MdG?A_8xOk=+k43H#8 z6;nqOq~k0aTS(vY8#J~D=PCbFjGYFz+7^u+4xn@zJNx(KYCI~Ke7L2~*VsP-NTQ`O zby*%AFB2%i*b|xglKF$tShWI$EV@|*M1mICKV;SQLPvCvD5x#R=iZu5{2YY0Im=Ja za&4_*Y!6AoAuWE;n1hhXm1NxDN^(P;ap%SwdymA?n5Ec-6Gc*TdF5&h6c=ckogjv8 zq@~*Q9j;hHofFzj^u1V+UNF;3s*h9uu%x<)KInZR@WaoG8;&W?u-QI%gyjgVR>gMg zZhR&MDO+;a5L38H;O*EQe5!pt0mjKrvMtGdiI6bHAuY6bF3k4k8HDj3w~W+Vr1;(Q zElICUN>cou_HJcsqZ5%JX^G-Sur{6IZ=h!BZ|(=g7>bjN2k`v3KY_Dc@8sF4BS|IJ z%48>IhvL56iHT%jCfffT(~a4AJkDQHNINGld*W5ze-Gs!7OTbgptC>8HDY&=BbQNSWz~DO`Y( zEosi?aC7PU@iZVH{mqx6ZT?8aAmg|sE2#8JvaTTW;qcK^PW<^uZ-mW7kCa6KR|^pE zYcebf#m^>jN26WoCTG*>3HBh28-dQb4Kds@egPeCY%AjLgajFHi&Dv@5i6i?i@mh5ut=D-Ma&sG&ZD+Sek&} z6S-D1Wgz>i@K`;%1LhT+>3JA{s$;vo86pSJ8(Kp8M?an$(h@xrFeJ=!VPvH;VHXxR z!yaX5o)4I#qc0$8XTU;B68JYVBbJ-WOKL+uFspaSJHv2wPuh7!g@;T;8=@j-uD4p^~*Sjvj{a|Qw7|e2*zv=GSOWf=XpHP!d^yJyWQ0(XeQ`UPXXS$Xqsdp1Y9fG#}l43P~ZsN-|Nqd1>N(4!t|hQ3lB! zmN2F8me==~7)jY>dDNMf*K+EI=vUS9-k(kfd6|*TVD)}3@6NsD?|3fnOsZFMg>ST2 zQ8Jg;iT)bKr$PzrrigF)+4w*dh^0h&OYX;}LwX*-h+w}9GX+YO~P$G#eDUmOU04lXnmAdH%SSGiQ~Jx}Xs4NZPKaWu>VnT3HEXbJ>qiWL)v=#~y9~wGtnzl)~x5 z;ZUn(ezrUsC#hNi#tC!qyqO#cvmXHxsO_B>n*Q*o+AIYCk$goJ6`#f4RDr0R{wrj};1>Nm+tvYt@RPuXAu6`4XHTphT*{j~aE$ zT2Y<5j(q%apx*4a$B^_m1Po&52f{Sa7_iOE!dt`IW(v4~eD+YhkdYCsT+hUpV3v`F z-Ki(BRn$BIqEv`q)Cvuas<8O{536zKj@F-hVus((tVW0{lQ7J z12rn&AB@G^BwBJlYb=k7r}JO&2cv)(QFJo?PWJ~o=G#{m#&ExTG6j_-I^GFwT7#qh zC!?Ss$Fm9qg6<|*H*-q%p8JvUcAOoh=N}G$ceWkpi{a@(w7WbTejDo)pGKVmM1Rsz zIdSwy86)AJ$fDt~3gjg46cG(Ol&lq(0{4j5YA$r;Xc-+QRfT;J`f;RqHM)-u6jP=; zDwMrUY}exZ`SNG%ke=2{c{xye9duV^3>JueL52t?n0L7+XVtO+-qI6w98 z2~cafz4QRPMSlU~74Dz&;` z(qw8Gne_=|rVpYl1fhrKJ=MqDlOWlJpD#drz+Pq-4lVnNS6Kf8sOV3*hRn88uHl!U zuaqel`-8$x1>oshY$4j~5x&^7M|zQ{g59N^yGv7X5#-+oD+0xaR;WAR4%e-irKbJ* z7_z)`dZ{#hsb?8}YySpp`U_WmFK%mV2Qmb9Ckut455-z*9MIO*_9iq-<^ychBb^Xy z?U%l>)>@SKbx;;>jxF?U!WOl_^{p7=fZo2qivjvNoiqxrz!!M7%(=4OSw+ba{Dn@% zTNd072?>*}Rfy@u{brh>5%~`wEFG%{Aq+9GcG50k#Q6S|3^WssM<5xn?^!jVEAgW;|k+13;l}J}oy~LRKlV;6UO9 zIewiHI{^Gk=fU3TD+{{b7MQa;4&`HX%@SdX53?EU4?#w}b2S#>;r652NaZWQ=yWPC zl}viTEN^rlB4ui*B!yKs>@nT?DeihEN0(k9T63eITPhW_8COp^HCV_j34W@<;gWjSbYaV z%{a8={dsn%3Fhu5V(?(F8@Ow8{rH`UZjr#7PP&$VjuS{`eh1TMT0W-5a^v}|-XNK0 zG_^P1f$AfO1_|Q+1Wq{1I+(XRo*2CCB~F}g;YdgKQKjTxB$nmU$v}ycvik<2H)A#u z_EhbPbP0j3>0&BD>s~$1SFP-_@wwIz#;r zAGQIl{pZ8P`(?4&9igwohx1VRPcd$Jupaj96AJ`j{Xl0V)sN}Ol^t%t#yIP{HtToFQ zb0wsl2!zBMbWOX)`yt^<80>u8idt*IAa#m59yRO)NqQ)0R)h7u({TL#+W_--?c^Hy zO}9q#V%Kv| zKiLesmc!!j6NWPxRrz_1qj&^ZLBa=_5=CG&W)aO#pW$ z#2pKl%9`dCeVg~x*l#%o#l)w3CQ7LpifK_;{np`aDRt=(S4wNF#8t}M=$L|CD|*`; zA^sWRS6tiv+cr5rinp0&h4=r#mh&ez5Z16i@=Z1zaQk6)-h(pEL?1$V00vC+z0F6| zFU)P1B4*0r`(ZnRd)g7UVRSKS-rO!hrxV5;OtWG2d^Iw|RxouSEDsoVrB z%eS>C3Z<1*=f}mj(-QgrX1$%0$-*9lJbq75^!+So2zgLGs#;7=PgY;rl8?C<1lyMH z;o)CdE0S7=04eczEnIqSPTrhyGEA)@`$Y6pL~sU-xiP#uR`~H7f44wTokaGAAl4N_ z+}jewW*Fb%Uq{g6Fd7onFd6q1;$^+cksm+xHARw zD#&^;zUPppbz^!Zq)D@ZmTaAGwNB*aqj)gqis{GsaFV_^K|MV?OA1*6W{f!8W_T{# zi@(kAT$`B?xVaPQEWOQeIn`TlGyHuX2g*C2mynB!QUA~0`M_0O-~0b79*vBQ${HE7 zqmhylp_!49p`xOplA5EU_+|RR`TytpJ?ES!3ofZ5 zJtcjFxq;r%^NbN?&m4}l%z|1#FH;LD;wUm8&)>4ozs#m>-6`U&lKZ&eh^^Q2t3BuG zs~mG%^=i*>c{}L*QKB61`H}%Ea(fJzeXe9k@B43ZV6L~Phs^ImH_x}m*7FIlc^Br-Z*Nc$qrFhEAT=%KCEip-~>IqZi!wxjxN*32FD)Ult?J9R!D?7xX=x zDkBZ+Fsza~stG=<(!yld%0%5n%)u{ERo4iz_k4&)AnXmsZ(0B8gMq%m$VMTOS9`|M zJyrj~`z2XI$e5+?CFXS)KM8ZDtYpjpXG_m8eV;3b0Q!3LY4XuP-)Ia54&HPN zZZFgy7aY;^V;TWHq{bRb^meI#lWOp{ZOF1aI9kZYNAG(^8!(6PclFsUWGs5f7;%0q zo$^5~Sf?q$-eMd|$ynUUh|b6_qoh6|{6e2yL))%8QW=Be6z-W0SfS{(O7VGb2)3eN z%jP$fg0rpCW$j+}EoM+D`>*RWf!^Di*?P;QDqTr3XWg^OArsVlHC1=8bMQhb z0NG%^+M_>jd%ya*nx`1a)z8&zr?^5sS95{BlX3Xfq-L4g27In2Lt?yNA5<4IW6&Bx zKUZ^*pT8J7ta7DcSjnl$cbT`M8+=n(OD%rX<~v zWBgow3Ne$D_S7Tm$-`=IF}}2#6}5|1=3!d5c~kbYGVg~;=V_{WP&)Fwcd)hT=}=MO zb2Y-wl|GBCll~PZo!Q~i*?juxj2w{8*BGb@%$*7`=$`!~Mjo zgDt`eDWN{e&h>Y}aZVmLLQXG@FK%rkx_0C1_6L6YL0<&%d*S-%rGD_?uQ4PN`k9Az*)W=)dDtld^zVhb zZyq0xxXLzuHfYVXQeZ}VHXCo_IEh61ic$V?`c_1qOp{A^)u-!aJZr;Sb8HA>oe}u2 z=1gYBeN=xtpksV-Hc=@ZBRI|s`US+$mSc_~DZval-|^b!id?5OH1p{wxj)7JldN@0 ziC)aqtkm)qN#fs3)*P zN+jg>HU>1yk7SU;lJPtpa>`~|OG{GBUBg?&+&g${o7*BcItHX1QkKCSTt2k5^eQ@# zG!1*Ht*oU7uPcoq^LgvWXGm|YCDSbTLgoZ}{xBO#*vaPf4kZtK$|_W8!EwQsB=sis zXDmARUZiJ8?@Rh+`x8@tW!)I^d88NhBOASHe@NS*fCsK46G;UFRT`2v1{EK1z1;2 zA#9vaMTqm5{@9wi9taob*TToSEJB>yl{m+Si*rr*I8QR>I^}(u66Y(E!{mKx_&A@5 z5a;VM?3-ol3m50j&krt7^EYUoXCAb|j?|p(-XWuena1c~8g_3n2lf|~1(2D7o4Lz8 z-I-^eMN3z(=ACr9LHpp105{?IU?&aaH)AEZtZm*kyWu&@#S~8F9$Ngav7pgsqDCUe zLcJRuP2sh<)~Oqzzb5pnJ%<^$2dzeaNY<>e#cHX>jpnIHFc(bIoxd+v-9&^ai>J7v7Vh=m189gFsjix_e#_5c{e*IOTgJwqOj%Ij? zep#03*1yY&wadz@^>Wks^5rpV*$?T~t|Ky{5vgl~t@QC@(9{EAxAN1%AT#*LkhrmDT>d%91=^LB%SM zR_QPG_{?}UZ9fMJ-8joMIbYDU*z94rDBN(I3pWBc5_bk}9PSdF8#f+TjPu}z#S#WL z9OuG~z>UP6fs4kSi5rDG3#Ym9kBh=-DZIu-;fCW}xDmLKI4vCw7lj*+bKyqdM&i!E zMdQxIjl!LUi@}|Z8;y&_or^mUcRp?m?gHF}xKH8Ya2Mgm;x5L;<35cWhr0yl#*N2K zz+H+!d-z&#$Aa^!A-?Y!(D}&j=LH+19uHB6?ZLeChj_1 z8t!`BES#22zHw2w8+e~C*YdfBi^2`Zxo{(JBXMWoqH$;9M&ZuF#o&h3;U6~~=faJ^ zjl`XSi^iRa8-+Uy7lRv(I~#WnE*5t#?mXQ2xG}g3a2Mh}g^R;ogd2;y7#ENGG;SR3 z5}X@19ybAZDJ}tb8EztO5-t&UIc_p;3N8tE1uhwPC2m+lY(o@oIBr-I`M?dwxo{(J z$;nq1RaTT-srQS#H3by~t2{pQT~TGRCt3QHW~gNqC6#&QWmSG{p3gTIQMlMsRYe$W zwr`a#nVmrTr2H$YT(hRK;>v1&S$S31M9d_Ui;8srw_R2>^RnXG>Dq2yxk;eXx1@5W z`?BK1%c?GSXG@3nxy2}VNm;qaT~ff`V)}nbI6c^6BQx&Of+}}KrQcmvQRb(w7gS90 zyL}#SrO&UJ9~yp8x_X3+6U83Pa+etq`aG*B43CfWLxUIiR_T7K%ggml@h8;7p!g+( z9kHiI;w{Ev_nHE)c3IUa!xOf=vZz3YJ_+TKV#`}&RE=eBNo92fC1w1ZH}zWn&2-;f zac4#4U1kV(Wl>SJkNhONv&%gNRUUUysi){pH=`ZVuS!03KJM}{cG@*F(C#^uScThP z>DC8kr5;aJKFd4>#e-_yT~JZ1+orb!Z-Kv5vMQxDFx^4ry@DKB#Zy^gmRGQShm@F< zrxEA>SiA*3U%|Se#_RLA3vf~wRRwE2hRt@9G>r^xXM?)S@|)+*owt1XDa%I>IFtep zO*dH2zL0u5b-gT-j;+_E-5c~dS;}7ig{Cv8UM2i|85g9B(*3-C-)V)D_FxYxcG`MR zOft**H2UFEucsn3B6ENWwR=EwuBt97qOYDt{+3s+@%T&2DptAg@>TLT*fvAspS@!4 zvH>HU5kR`I{_iyXC%M;pidYG`@ARzGyBn2JZImt}s^_!S1?C9HuqtD0HDgAl*H}H> zcDwtoGWukJyUOnqlNscy*LW)Y#%05fh~X;m?kg(_7mz~m73VRG_}5)26?bJ>MNxTm zvFFN)^2$=?lnVW7a;evAq_ZYZ)^hIg*Sqx`UL;Gna`Y=w>XauRL;nrS60Ei=hw7rXG|@cdiB)e zX`a+;N~X<7ol$V@)mIl>Tj-fKz4)rBGfJjjHDg*~$+W5NtCD9VPt_zJnvpF{H&Zjx z)Cwyr8R09m;Nv@tK~bpsX@5ONAC-iB%p7USA*^f!vjAJ-(9i%DeP& zU8;JLHpwXWQ`b|m$Il#2{dueXR}wGz)T>RJQ5_TWWWeN{^SIlCnAxY&)k-k8Chj>)7hmUIQ%%+iJ?@m6dGq-* zXO8@t?=CBGuPR&XsnGnsYL8}xDA#v0<(lk`s;bc4W`$Ojt@p4Il5+NWO7bY{qC0~{ zEm!aKc)SBH+mRTJ-i#xyxIa=R)`%AKIM zc&pUSnB8m2D05n6QF*1#&sJCZ`IVz!?O6UMR{g-cjC$j_RTrnc;>nj=SQ$>u5MS!>D!gzPMo{UIiDGN ze6mG2&3w+2alkpgd8ZrCeBxQ?9MAmIjAtt2Tt?PB$B3p5ah#jVIF~VZs&jlp9OtGo z&SlJ<<{aM;$GNGDa~X55a*l6^_+*@Oo*$;pJ>7gVzAcClPsZuS!??CALOiECu1#fJyE#HU zgU2;?Ojoe>Tf^Gy<`wg=NM*?zvOYGp1j?38UkRH_!%0_|yG(ohj_g1A)cz+;ksZVp z#tuSFj7?)@1*aFG?IvP+RuFep*(zh(A-fgMq+~Op??v(ot4m7Q@f8>N3lcAPPYJy$ zyDPT6#&JNJY}se&hXTf7Kwd$0jb`uMWSyLN`4zLus`B)`8PT!G2&)?#Kw^%p8hgNX zd13Z}MhtnLa*rJ7P$Z|nkCsg#CrVXU%Jwj?Y>l^E-%PK`Gqh zC;MW{`xUc74{xrRMG2ELJ)B++rwFF|u|k=rQL8-q=8sLZrte|p0IayuW1RYzl=BF%Fz{UFNP!W;X)BzGY}IkVJv<3`Icl;DQkN|Kf{ zsd|zo`>oU1aRv8Vx=mHdMvIc>H%)IHayL`GIz8-FW*IX#+|FV1%>kfQi;~~sGHJtd zuqUg-0&c4Msx<3N(>(v2uivMU{g-~8B^%Z?o;8)eb>p>c_IsRadVG_(vtrzV9k1E` ziwNN6)Y?5ed*Pt#zUm5p8HeGzwy=UoDhkStlYy#%ag>)8vg7v@g^kGXF(a9094Az9 zw&|%T@`!oHeTATD`T$_tS5iiZf{Jy6%HT-XXS8gy^G3htmNP%7<(FE(t2oS6ZxgmiptzSRc@i6NRjD;Y<_|1f! zW4Bvi&=l?r8TD+Jvz2i=3P*ISk`xo=#1wNpp$Ek5V#^9+ysP5ewXB3weA6~}Suy#v>eIaa8@x$d=-~*+&JbS1=5v)8DDe{|o3pv;OUieRG$M|ovW(`S zEufXjAX@D=8$U;Ux=l;u-g1dPN+xT|sw<4EM9yVtI~rr{4#RbGI5#G$s_H^R zXZ0h-rC7xk6g(B&=%qu*jY?@I9(PbaRpO8ev!XDHCRh|@+{X`2 zY-TIag6SHbF_Jm6lp{(r7HI*NL>XC4#>$i3qzq5X*Hsjm1r%zUAqOL~OeB4|(GqMr zdMjh-E-71O-@KQ{DzxR~*1bl`!RXCvtnn{c!e*0{HPb462+b?LDlaI*?y#dDwCzVgf>^L z53-7%0w%&$1T`9{8LOrh6c@X_LO8u!h{mB+{os+CBsdSTHX??5=iWqIABQ4SI63VJi(L~bE z`%TNZ>9MB3UnB#x**+!5W;VH3w}f2LX-dj!26YX?zYKUxmW9=2<#MA-pDLv#>QPvO zP4Ggn=aH}Z#yV3U%NfyVC&p6AO&n%B)}IzBWjVmU%kuBjmm^lAl&Oqix5`t%^DlT( z;-#4wt(-gWgFM;(s)D_N39+oIlo3!e!%$!c^BIww7Sj%V3?fz~)2OPdg61LGbD}-e znQhow>=}*OXlRS|#kE`CYh=z@EahC`k*T1-x6XZ6DU+<(1N5NPhohn%Of-cOTAS$vQqbyFQnltXDv!IHvieB zp=4NZ6iaEMYgp4#A0grOmSQ&T5J8VvRqeQ$4vLm~85U(t#86nUMlI?E9(FLyDJu%9 z?z9ZE!&-JM^>I&*#i4GT8rl4rTrSq9qv%PV;lYn9nDf^jEnMiXLn zr}Sw}la632C3@FPvffGu*B9lQxp=ZVs_soQ<{azUJ$+dyDKjY<3U{JqIbcMpF)O%> zh>a_>zhc(siXb+yweheRGq1{imIVPFPTxJ6A$@*xh%zkDOEjFnfpLk)5PyaGBG^cg zmTwpwOxiKtav9KV69@YCaqN@*siFZ~2YjPo~&#))~bhmFAS5;bRpW%Al8!bj%od`eG*AJZ32mz6R|XP@m$j#K#H20B<3Q>K=j?he$lG!uBVm1%~KhTeMnXx}kb3 zRstd6_1Vr{TFFx(p`B>yN@h`NmWOpQB)qg}-Ch|T{G5PQvC4LvYZO`2 z_{zL;5Mq^Sc>gRHI96iRitNAI%NeeRXJ%wxlPA`!O&0^Bk&V!S$>?rYIjO^thevpV zZQm?!T{i@ur>N2wY^kbl7Uf+9oKS{DVwFQ_QBk?Ol%d02=wmD`k|(6h%qX zDq&KxJgD}D`r~=wY6^HjO)vxuv>{l&c6c)^PiOe0knNh_T*lbY7{@R&SqwO!VHwDo z;KJ-|W7Z@&d1~64uh25geX;7tJe`qMH|Kk_EkApRN*_z;a$~B~r&Y6`a{y!=@>tok zqBqyI#(2P!D#2x;kppXqYU#$>Z&vCwF=I->ib5vBgO z$$VcIfnPNG|FB>iGL5oKW@0Tm4@Qf1`0O$o6`c6c7VBhqh?_;f}ew9G-d$_z;E~WI_iT9@ z+jzNL-*p+U=NL~&8gGnkj~p=b@d)+O%@wkp^c1Vt<}*Y4jSI8o;Z3>SVZ2?meCd+l z>4J}&ImXH(aW=!n#EI_Y)dwfTgu?%uX8K)f;YJ-cAa}r^`Mj+&qw<$RjnyY=CnYsJvw^OU$FM@ zR9sojk_?m8YUH|JzQLlq&K+8>c(5y`ptziy4(5T9?{=$+{?oKi^X8@tue$Hh-9pDCr-TlwyC%OYfxcDQ89C-!=PdfE^uun zd%v)~%^sEicc(tix42Qrt;Cjh?r7n#) zv(pzsX4Jujk7{n{kYvsL5!RqXweu4%S%;dCnk!{7^M9}sj5Ybhf6bbwJ8N2_E9ch# zEc?g*`SrOn@E#fndhwF;nU##VdR9XxuY-pvrn3sJ*@^`oo=3uXQBP_+5OWE z!p(#VzNUuz2?gbeMiZA}o@};gc?3F-FM>JU=xhsyRsh!-r-Vjw)QNr`sjjNk>IjyL z^WYkX};;!62Wl!+60HkL+dm5F{aY^mrU z8p-2+LrA0{UJLbaCm1|x+xh&5$)9mDFmb54`G>JzH$xLNp*_d;Uv%Vo_M`>Bc%YT^s4O-UxcXMXs&tZNV z(jd(PX2Fj_4t44JKb3x^{-D9o=jp-g2U*bSAD0|7I|r4-p@h7`GD`=3dj?h$6~{nVKz<@w~$V?SkWt*vt<*IyA(*TE7 zdHU?0a;&QQ8}D!aZuWn|{mb9YKE0{`&+kwEZuUz@`UFeDznguZaDVZ4v+r-TfB3uE z|G&6Da2VC}%f^@Y|KFXq!hFMT$TC)bgMfecS{IGCf4KL1drkzt@xqC~&v1XneVX?f zxH8-p+$&ut0`qaV;wo_W0u?euJT2!BzEz4H2W+l}fn$v)17|&YGLV3~9=8%# ziL1wb4fi7MKX6BJBX*n&jKf`n%f^-AHsBt^?ZN#F_Z}{Qi+k*3U@C4At_W9)`wH$k z+^e{5+()?cb{g)&uh_4xYyXUN|AXZ-^NEvzf4P%^B--KshTBBC-9vQAkK18tdHtH= z&ZIu?d-!CapT0d5_w7#*W+?IhE&M*}VDpa$T>tfe_XBPD;{g4Ptwz~>8eWC7)*vdE z`=?!%x7^EpVLpTH;hX%q`@$E4$Tx5-T#{;Sf@c`J)oCgEcZSHW$;=M~k|Or4gORVnuvEBRWOb@Qgpn`b7v+&}eNNpDTTot`|t zX@w6S=J^X&sV0TIK3y9^0x53>ho5HT!8ATk|8^{Xc*-(R2`euLg`YZA`O&F)Vf1Ny zS3vL=ss_b6IKC8lsKQtV5Aq!@{Tb#Lg9N`%FH9&q6NA&6s;s-i*ne&CG)Rw^`kJA( zkHUf~&%)EHX~PD>Pt9A*Hw4t=omS9c7Z1NK=?YETHA2(6xAX@xdHui#{eccX@%c3D zg)hU{D>d!cFa?hILw_I}CO|J-1smXQ*qWwkV|x1oo$!u7_6MS`*R-P_;vd$3)E{Vv zJBFPIxMyiv${8mDi8pB4hEXR1Iqwr+)rmm!QB9i(z1Wch8{qd~3;ZeUfN#NGINX0C z5Q}|DkgsCWmceZJ5cI@xUFh7w(6#d}HttDBqC2Xf5%;_0S8S zgbnaL*a8#pB0Ss+d*Pp9EZ-2EUPE|T0<+;(=!M5%1B_iqc(@UEz$alZJOE?)M&N#! z0&CV29v+8Y=)RlqFdMeOJ+K450ej)7TEg=Uz!PB#oCCAr9ncHc!v@#_Tj0B}1O5^A z!r`AIJm2_x0Zf4tVK$rv8=xPy!p*P~J`4Nc_hB60?E4d#3Qxiu7<4R3`S-^g17-S7#R4ktf&B2WsmVLf~cw!q@epZV=xo`9G1da zTd7|-Z5wvbFSo#E_!=ywe@1(!OC1jGaS!gDJ2bX2Txng|5db2bd09U^(o7O|Ta}2V>{b51$}BoDZ{M zKJ>y3umLv17Wg{sfIYAmj%=d+WKcga70!n_un^Y3dtf7c0Jg%HVK;mOYRn4dUnAeJ z2WG;oC&@ST!Ft#To8j}Y9Ug=|@EDBdXD6a}kuJ=JIdCVeft|1s_Q6&->KoJ(Oo4rH z5sX_v`Y;vV4|8B6tbsp)jj$88!sw^48(!E|f220`mXRsUY+)a7G z9@qi@1bg907`sr@#3x6;Xw!utz1eU^* ze51DVGk_aOMVw?+KVs+z5}!2QRsztd>6anTd)OgX{Eg2*zaLC+z;JL zD2EqG7nZ?NSOe=}BW#8-KO!8Q^Ah3Un3oB+ly(f$;U<_5n_(S%1vbGWunnHEpZvlL zpq8y^mqIt32Ge2rk4YCk0PEp)*bJY9?J)Wk@(ahp=$rV?Etm*9+Q}~*^%L?7H~p0Q zg>S)Dn0$bGf~#R4O#2z>E@M3b)8SJvA0C5sPtPSv4WpMczQIJ;2{Yj{ zKPO%IA#8wSIw)s20d~NBun+dbxD}N58>9>0g86Xte~>Pm1DjwuY=c{2H+%&~->hjL z9Hf3>@h{0Q+ycF@6*j;_um$$R4tU|4^aq#%V^=b7!W8I-*>DT=!hNs-9{d&M1>K#L z7hDAUV9bAF_h(oq!BqGZ%!e<+I@k@H;014CH!OwSa0}FOH0`oqQ(o}1FdIGwz3_Li z5yo|qE?oaM;ov5y-9rAM8}`9;IO-kJh2^jwuH{U%8Fs*ScnJ2u<1qSG>b;wEVL8l% zTVW||hV}4G*bGPghVbx0*aIiP=-ZeVUwYeF4za%*OP8J!6{gRloZ&{ORnQ)w8%|k3Il=X?6y|4APOt*Dz&)@7z5;t;CycG6A1owYxDsZ= zV(5h@7m+TEy^(a`WY`I>&mvtf>p|#-TVXof4fEm1#pD;xht04ScEATYhXKUgz-yB7kXhQ+yeXHP8jE7pO8&G!Si7bTn%gBCfEcgETdh*&%kbY z57eqyXTe0c7iPnT<%EN~VI%B^ZE(~I!olfK^V43T8`i)~SiX{Sg7a@79L#~OumpC( zH*Y0eHS>Nh>B0SXkRI%WUKpQ8{lHw<0$+li@F47i=jD^nwWJGEVIj|qV?u5;7A8d!+um>K6(d(JNVIqtx zBRoulr7#oL!&2A`AB64jDcA#BVf5X^2NU7m)#MvS-ATUT7}y9W!dAE%cETFi2hUqW zzH6B`VLHr)`S5O72e-o}_$F+JF%`6HI2Oi!4m)8AEP>hZIp~G&!Up&;Y=JSA^b0s0 z_Q5$Y?jB9M38uo6Fdr`Vk}k}HP4Kg@4Q__r@Cm5hOZ$ax_z}#637@6B;4;_%pMfoK zKkR@K1X@M`LG3Uf*r64_QDro>=)?A zFa?gfhwyMR^ukTB5$=U;upM^8n0v8%6YT`LVFk>DFG4RoqmFPe6}G~J&l3)Q25Mi_ zv~R&g_$JJRF&oG)oB`|Ma@Y*LupNF4_P{^G=z7lE?jt;$4m05^&CrQsRx(|^I<8hh4rupHp9LLNf$P6CS7=7JN9m--RvYB{5mX! z&%=87I&6kVU^`5BoN|JRP1ySo<2X!#ewYoPhF;hK8{kpc0)Ox|(uId%FZ4V~d)`7g zm2lv6auaG`Wh06|6 z9`FfR2lvA!cnr3|nE#@^!zEDLPQ5`l+yT>JE6j(-VI3TEnDFp2*ao-3Uici0eT4BB zroiamQjahbdSM}KfVHp%?tmTe4cH4mfU%8?C+`s+7Q$?}0eWErY=9lG1s;JN(DggQ z!wE3|{gbCh%+BYl_x7sG5=3cYYWY=AGqR@e)>;Yq0NWZwCIlsC+Q>CgxBVFRp# zdtnot`~m60MX(p&nAq1H>f za2%|IvtSck2HRjh?1s<5=&v%a!$f!pX2O103giArx^O0JfmN^rJ_>u`Z(wW_?f4jW zLpRKZHLwP5f{k$apC~Ul9d^Q%un*S3xUZ2uOobo792kF`@bEg=2*2@X?1tKh*bQ%k z+LMegFa;im*>L_}2nScdM(BgBun~5`S709;-AB4#XI_A*@G6)CuZK0T2{yq4uniuC z-7xke(%r>41>NvQm=5b&4VS=dm{0unEqAZLkJ*!++NT0qvWV6LiD4VSzw8 zTnY2xqp%Ks6E?~9s6e0%&KVvE^gthsZf2Zv1p21NIoJYwU?&`PF5%!L822puP?!qW!yMQIYv8o=C~sH=+u#P+4fmZ- zexJjRG2|EK!c4dumco8m54T@Hx^NflfU_iL*I+h$GM;t?UxH2W z5Nv}ZKTSU2Sg1WuIxrC)f|>9`SPEU^$R}I|TVOftfSX`1Y=W^b$oU)T!q;FnjJt&L zh0|ao%z~}31a`t2*atVkxIN5!Fctm)=D^8r?1mYz2{ynsxEFTA!%+J-;vbLQFbihF z5?BiBU_EqAz;3t^H`V) z--bD`57xl*FC)J&8MeYFVGn!>Mz^x=f{F0#iP#Hg!BThtHo*5_3p@@x;EYM63o~Hs z_vlwJ1vbHK_y+XCafyV7yI~uA1$M(@PY z9=Hldf1iCnOoTs$neZc63ZthG9>&3DI19GJT-XD*!{~ji|6n4Vo`l_S3G~7q*a$~o zL3u$p?1U>}AN0Yvf9H7!m4R*q7XH#A;Q{K=G-=9l3n2IEjkoiGzV z3rpdLupYXy2@h|B9k3eq!Y{$tSJ-dD6u1{=!?SOqoZ%$c2xr4qmuFdI&UUbqQ1z_(#5{0r=a=iW@Z za0-n33F9D4g>S-q7`>AEg?X?Uu7mCH%diJN2cuu(d;})K6EG8A{2AhrvgY$1C9BhTL2N+ji3hag1aPn>B7p{d3 za3gGi&9DQ$4trq_jQtt)mrMJAkHCER16T)t4x3=~?W7A=z;5__9{GKp@fD`PQTe0` zFN9t=9yY+0um!#fJK!PM3wvSg&*`rPgoo)c8#clk_%qlDA1|by;OHXi31-4R_>zZq z-NAeV)8Xh6?1n309sD9}f=|LW*aEv@7u0^CX;W7b9)1pH!d)=zc z3GRn&@EzC<`=RzGGbu?Gqk=jWA{{^$pWuCtL#i z;FHk(Ys%{`$_;LX`S4{}2m4?XEUTg1;gWTfJA4dAcVQn)g!^G89JwC5p&Qo2n_x4{ zgYEFouovEbH+H|x^D{6Neh715d@XjvIj|9y!dAE*cEU$sAN&T4dxv%eQ{n3{2fhz$ z;770#p8q+*!||{aUI+W&N*MPp^#Rl2PhdX$FIWd-?jheW9=5?`*bN`Kmwb0~J_r-x z0hkGY4@;q|j(o%OVKZ!l9q?_~3;zORe?vKap8A64!fdz*df^?g0q%vZuoHH|k6|B7 z*nr)KSck$?_&CggQTLH=cnCJZ4`Ca;bR%}dbg2Co^D}hAMwkwthxu?ntb^JY2oHY+ zJK+3H*bSe9v4`oOU&L;B56p&}p%?Ce4X_!u!039y!?CazCc)U>(obLt%!JwS7U+e3 z*Z?=c7T5+m;9Ia4o^?Or-{brlrb6uj@(pi>HLw^q!X2;`ehYTOPS^)OhH<~6KR-ym zVL8l)n_wO6g3T~tGwl?5VK4kVjO}5a08`-OFdM!Oy|D5j(uEJhR``3^4VP@8ynoO7 z2D;&+Fdcpq=EHx3b?`md1T()xy72q355_cL?-9xirow!f1Gm5$xCb`EL$DP_KTLk% z4A=*AVch!^6HJ9Iunv9zo8XwOv=6uf_Q1n1`Y8GTGVL19f|;-wmO>w_hw^WX0d3g& zW!kWs*kKpPoDtnHjIdmf$2Ao2Ec6|`7#%x*bljqI&blkQPP<|3b(613m>@yLPX_L# zd3**@F3cVsyD4h!*&}m^h_|8_h`kE36vhR?UdC!l|fex0hXwe<}23$Q;))mPbiG5UD) zSXIB#);FS`i++}>&$snm=+FPKKX8ev-)igo(Z7Q}R@HB|^~31jLXT7R<+kpM;$8;& zWL5XrdII{h5z@~<-;F+34S$avz8L-I=ozYhudQ!HkEeVKRXyr<-Gj7`UFdh97l-J1 zL47~^lju(NA4cDe?o_|7;gm0WUP$~#0ZaM`=*Q5nRQ1)i{Tb*{)ZZjkFSPYy^ik+@ zRb45cjp)hfb5#9vcKBWB+2{|cdQ`ogfAk-q-=OO2?eK@u-$uVt)uW6CCi!!@7;_dl zmrnxvXmqFcoq;|UJwGJ=+k*BLqu+`?PStO*?c0c+gYH-LsLEjYUFf?bgx`<;47y|g zN8f|)RDZ4!%$ewShoomM26`>JQ~4C5*Q2MX@!zTBAH5O1Skc?E~UTvGcV8e-AD`5l9n%asX}BwWK%A@F(f*BfX|2;qxWsvy*uK z9bJ#7#5o?#gP=O57Zc+#BX$s!)tP0sNoF%OML*W)?QIi79AGh4tv3&%FN>fbN6$ugs_%o?xe|RdX}RRafl~fa8|-$I#)9p|2=T*#J(Ho_*dEF3C z21?PL>`X&1j-cnF=SR?M(Q_l{JJE9@==;!DM9{m?C4Wxqihgvlk8WX?k+ScKKZkqh z=;7u=Dd#lwJoHL6yp*xIcaqEEFM;{zDf}Im@%+~B*lA@lp8w7s&o>j_(dYXEtJL_S zjEzJR*UE`!`V0Mmg%Zz|N<5Ngdva`)*~cV!25u+*m+a{eY+?Q9idXzE+C2O|*YG97 zlHE~-$=dL8d2wH|7PTnLoFEuRkF3iR&^Y9+{7{C=%XkG%EZ` ze#bB`J+tyeAeYy!F`@pWlyy@r3$AzYcOCwM{mk4~ui#QH@w9%wKX4xDyWVZF{bW5f ze6#Dm5yQt~I3J9TdK~*bhW$}DlYywHWcNLiF?cK2&9Om}k#gBXyuO$F17DGHxkRzg zj5q2p#P{T*4`gj#(d|xS1Dgw2b{LLet zCVf3Jz~7hc_M625{0E`H>dnvm^%pZ8SIPi;%(Nt)F5-Fg zmJ@*mYCKVMg6Z_5w?)w7$8fI>eX<%}ITuPpKZedQYUfwkZ{(tPqfb|L%0rgsVqY!# zafk3y?zzlQhtL~&?Yi|jI}It*Ek>D2Jo|}f*{#lY97az^ce2BE0rLoY8gT{dOhklsw;p$7) zEi!*f`WMQ)HRTyQ4-3upLv(2Sh`EUA@OD0%8K1WY1)xbhVH zlh7|m57+KQ&q9wwpQ_q#p6lrOj}TsO|I9}cK85hEFE`s|V4jsqwBk?ZPq)|+g}+M0 z-vWJI8x>`icNgi6%s&zMwmL2he@3r#v8Nw>dx7&lGM;;Gi+LTiLobV{*?OUI zS^TYFzIq#fMbdBIeaiML>(Z4*pCu}7AAjOXoyX%Y^f3;)q_dB7V$rYVwd-LeodM%* z0v%!k{@nNr+O7243{wwRE|N|$x}=k>hL<&rIrhtC$OM)yd9mYq?? zf&pF#J?M8h=u!^bnAdJam-2S~`z||_ti+#-{wDfoLUdyTEP5^a=rZSg?nEEupi4gY zp^rdcqsA}os>te1Mm`VYZxQ~S>~Og$2Xu)um=ELjlU_~<=$p`;$|(cgkM2{$N3GF~ zkbD-Szk=>mP8-oDtmZq0L&ASs4=*+qGjHuhe~{O%KR#*OD0%(7kyr62^XJ$*PXwM8 zf4>~y@2j@IJ^0&+zYOvBvf@wK_le!{;~B5;SHSCFxhT&qq@jO=?o=+h=soBZza8GZ zZ!h+yG5?6}ABi0|D0av=w`!!FfBa4NnfF8PRs0Q~Y7BBu7=68{PWH#)-={hMYjz%tc{^DOUF=LF z1O24KFk<^r?rZ0we~j)lj@F{T7eU{N{sy{7jb9l@_o2sCJCCDX=%dhOehan-b8eG- z%KVvtUK>UGyRpgkW8~9otxpp0TyvLmJT5AFE4m)f6z6!#iRZm_;nz!2o}1Cfu0Ii2 z!Rw&CQA_oPA^L9gCFp6YPWzViHIjCKKdaGC+5Yi2=I#jX|1!=C(4FdaI{K^#;a8xq zMi1A%Bp-hC9Q1JWo8&|0&lTu*@Y*%}t9DsPUtVGNlYPYV0REiT+g<28(VhBXKl%>z zaCV9v@oens(N9&L8Tgx4>s+42=ez~4Un zrK|pw^SRv ip^!zkD9K5oZlwD)~hzaBG*x%nRFeZh2eA9~1n4E9*(S}V{uMbQ1| zJJ2sz?Nsh>Z9|vum?S&4jRi)%OTGBroUfblyP}nRm}f!~O#F2b&tCi`l3%slhK~zQ z8~S+bO2ps2&i9)V&|~VH?ae^HFoIr;?v9{uM4yb#G-unXJioRJJt2a=AAMW|{V;kQ zx>G-JQ4wN)xbl|%nt&c3A^r?Ae6ni4EXpOUIOZF%|5MWLav!tvNShgcwow<7&Sv5n z^Lgifv>QDg9oTUw?dAZ&BJ>}rdelDM5Q+aN`cZVZs+;>5vGV|SioTxLu2<=8*4kbA zn%5q8rn4ZPwSnJ(P~$PSy?T3Efj$kL;l++aIZyPXr=nl2>Pr0E&=;dGQ}rlggCP0X zgI4$4)5p^|~7kwYP)A+p~{Y7+OhgZhmUCe{+=x0g4x^cVhNBY$;yI;jz z$r|&E;p35VNJ4)R-D%wx!#uMWJqy3CV_&h;iLwu1BpyHUyoJBfybk79xo@@&y&aw5 z$=1#LZc?v)(s=_tMe?&nNk{TC(a4YZ+ljxo>dk#_o#Jo6KG(&8>xcMr%9qTa$IzQE zAiXpt9@(cpc7fhtC0|*@<9j0f_$GQe`bP9~cpc35BBQ;Fy;;mpe)L-;U*nW|GS+8{ zC1-m6@%PkMX>Tt4ovHYf{9owOBh>SczbC%VZxIot1=#r0OneWh-Mv;$)l=3&qWv;bPJ3u_m zPdSf=N6~kn=c@ULG9GM_e8f!SybAq7RaeHdB=iI5%T(Q*m&MK)=9QD^dOI1f*r~J= z@i!fR_w1veNPgxj^ztz{AuV-5#rB9-x)!#MSmnh`a97dkC6U8^xYBS??V4(g!uc>pN$ZIJR6*S=;x8w zV1HHC0cq&Zp?^=+>4QzC62OYb$nRTLL}HI?2K{lr^ExR3y%9ZJ{Ydx>^sVUO+KK4J=o=k$mS9>2^W9qX zcCn>$t8HuW9#vGUWv}FG5AluuvGIIkFkjLh4q3j8^6A3g8~B?`7}cLF@x-ov^bgVL z2DWalza*XbYc%c5R|cF%Njm17CBejgnLlUXuS#D3`@?oz=6z=Mc|b|mPrU2#@3fxT zhF*j2)V}thm!O9$Z?XFzdJg)j`ei@IMDR}T_C7rn+omwKv2Uyc4fHGXMd1IEu?`1>pVoa$*m`s8-!dN_=p5J7j% z&k+DrV z2iZnE5B$_Q9zXFkqF*8F#O(v(xzt|IcM;DMe8;}iIYdADF7&Z#zLj&Q`0I@D6I5M! zt|<+@iSQvhd66x!UjOJ%qC55TS~I+pz7zfN2=?tme+2zp)jnlk)rDSa(Buv<_XrPjcx)1KUOLK1s2}!*3ZRtLd2gGbyKy=uPP1?38qh zna8%E>-GKX&2~D{Zj|~yKs?*{4Fsojj-o$_?v%~}(rG}~)A^!vI@7P`xepioYo1UbOg=dWhj5qzive{UHhcO?0R6ILiz_P9n5yQSOJ8qrXLXirLncbHB~# zz35K;VK@2*=;7*5>_31m_J^DArCxS3-)X<#b6g`RhhIHl+hB}iXOA%Z?U)Q#6)Vtl(KARcSPryR`ADwVF`ap*4t*Z4UH2(=M5W_H0vYwOlXxD--#K!@ zDo=CmA^F{hz8O7Sc}O~4=9lLtH^S zjdaY>$jDDQ{$hR=em)g@H=~b3FW_}B9?H$!qRLgho$g6zeS^P{@>SN?2hnTMoyz4n z`fBt?nLpHYhJVSJJGiQ+6F-~hEIY%`yJBw|`l$ar_4>LPf9?1SXOEQsM)bYt^Ce-c zp3O(1MBjzph3+&?>_>k+f_@mi4L#iauGjw@`X#zkc_yHrL=R`bltTvkQS?)lXF2}v z__cFBHlt^whZ}z+o!#h*(9a*Hl#|hS&#-Dv@^cV>S9gWCSM=lP3FuDcJ%#~f5qdZ~ zB>Z&r4D?%hZP%Bva1cAkq_Lkur~7HHZ*H>v(3Y#sjwk-o@V6a*GsNG0ia+C{UR*WW z;V#nKg}-p+FZS$5--^z#VyC5?PaQ^o2Hj~~b!BjFgg#LXUtkz2b|#=dhyHa{H~RM@ z>Nt{xzsYYq-{&nyPefm?#uH`SIFfv9M$biG5uz{ElMsD3dIP#sJ`SL7L3b*rqv*Bh zPWL@x7?58=cUn&+p}&B>GQ>XPfGmM)G0Z$@B6x==oMBKhzW&pY^gOl`-* zx9d$<^lj+3zUw?s?m@3acdD;#*df0~q}y>-css=2efV2#`8&tiU&4I)E&kpjOt8Jn zxZGjYzR^yz@E6-1{ya|7OQJ)>pl9>i_4WJgxCT6zw~ctF<2rPxtu=SS?7`BVJ;iF$JVb%SlMG3Mx>+!KEp3m8*=L-|DU#u~p3 zKd;MKCRg?Oq#S=w9gZ;mp*Nz3%eSOcp3Z&~y;AIXK(U9q816AfK=HQ?f3N@6w0phc zZ-CwXq_^XDCjuXr& zcO&{Pbk6`i%Djgpm-YUSzeD(Qng{a6G&hJ%9GBhK+Bp+})R z#h-=lMz2xRk1_^gNxvMu27PUaZVdLKZ$^I|{Ss9-pBL2gZ|Y9t=K=Jn_npVjqv$ix z)71E>2W!6QTm$TEg!`{}_F; zswq2+^!CCJ|A00uD&*JoU5kDc-Ko9r zGU(4~D&Qp?|*4s0DZKooA=G7-yT4(K|j?#bUt(WB5ONW|9qL^;QFu^@AyJB=d==%dlYjh7OC2Ko&2scQVn zIe9Vq0`zd@A>lWo&p{8@ZloNFnYX5+C-T}gWxbt;BCB;8?ehTfh(D)tIEp?2{T$U! z^E^dwKcsUm`m>VGtLyA^sF$d(+vD-*AM@-{uYdGo=uY|Fg?OS^H{N46p`2HmE?2`1*-{W<#{TS(m+{ZqEzs$clpK~2WFGLSlKa$P? zIz%qI-k#sDw$mEW4yNC1#N*TsR-o^2NJsDg=-VRLxefhU^l;@b;rF2LM!#Au5Az&d z^093R=NRaEJ|_`U~!X&*a3w{j4DDSD**Njdi8?{55s zo8Lu`zm@YQbf{E&A6Z=sVGy(8HCN*tZY;JLn<#R6Z}(h5lP~ zr+(Lu{vQtUOMP@PPaZ~pnAfiND?{t#i}rk(LBn72SLc0J0tT)`|GvcYeI*|2`JiV* z>vtRR9m0P|yHn=xJ?NwRo%bgP(Jw+DOM1a}q&!cz2Ybe#>-&!diaq9-Bf<3i<1Yz+ zGkEX1RPi@p|B;c)bL#kW>aWG<5|2}UHlpXCJMB+)q2G$`v>)4#UV<)m2J=f^WC)Xd z97eB2Upe@kbCG(^8FM@LNlrMomn8H?bfRf9Y=6KZ=Dhw`=x&38yN_{9};`x z@8J2kli}Nu=xOM^=uY{`ML&vuCw_zF5oK(orCw^$Q%OHotrzNT_(-c(3_Ew>&#m#B zhavHNOYbz2@BQd4=$FcZHaK5=Y4{e`LnAhiyzh+R=Z*??FiH0~{&$T!8F+ex;$PDJ zsyqR}HU8=O&*Qf^V^2EPXBzrd=;ufPD_wIxDdBU`C!jl(PwoF_?_I#-n)Wd6J(F3} zTY41)QB^U$s48Lx;qAEs9TpOb(iWpTv5u@7Zg>)2AJ;W%2BIZz`MT}eA zW889j>WJYu(SGmR>)pxDGJATy=lL$r_dRExr~S?TzwiF9wbx#I?X~xwnLr}WO*$p@1tS(Tb@12Q@{No z^$zI0_jK;BdFSE$nnf>yo(J9O{94BKv;7{K+@9j;*pA`cf5+LjN85jO$hQ-GPUF5j zf66?+dca<`Jl5}Aeb=+!b|BxIKIeQb$hQug!(&gHitUp;iQ{M_y5E5U=y zD~{OO^ZBLi`;_I-*Fnb-+TE7!a||nK|RkCxgk7%oRB$>EN2Y#M(CO58phA)rniT zZO>N=U%X`dz9#q{3vA!l4&SoL+xO*Rm)|obyHB=9F?^BI%;!zHodq-SJOuh7c<*T` z?{0g3wi;n`o?QZ84SXfix7Oz4vk&Q$<<+CSweSs<0qcBVyU*DSeGT+X{XnkY4!st7 zrt3Xf-&_nGG3XWc{OUd%zrC&MQ3T(Q@Rizqw(FBJ=sO+nJib;!FMvMQzP@dqTmyYH z^i1Qc+>Qq5h0rJ3*SGz>losfLEbDhbp8!2mKbHCPaG;(9-Km|6pihHdY%d?jll2_E z40;9hVRqg29KDkIV7sm!>zdyuDZ}~cEUb?!F2hrY1#4eha~j_JmaEJ9HX&av{7&uF z20aSh>Hd@lQ=M0!JN27F=xd=LDGRjfg6);3DOr9A^i5gHFNeM%i(Uo23Ht8#{PIKe zSeE(gpuYNwuL^oT@;mLnI_N{P=uOabp*yu-8}w}T_uzn+y3_T0A@okvKa(!UjS}da zp+9GDKlBg%dn^_3&CjwO)zGhjKEj@7rrOVA5Uap>>?Y_R;Js%lE^4g4*mZsD?(w|3 z75PR^b?*0_(957_+Ai7e3UCP>fIih;AKP=jV(4M$a@_8!i|u*!bm&W>K)K` z!un3zlZSzKP!_!idSB>H$6Fb6SwA1j>MEaOw(Q46IR6ZQJ_qkTzfJGUO2iSGn^My9(6R^J1_~W?@&p)6$wMQZJGqUI<(957_Y7e=+ zg*gAn`kULk!}hng2Kl1!53_HNZF?K2J8f?Z^eU|Hw7nhB>!3SrZ{FpYCuY%$pf84= zX?x}VDubS_{*~18?Axb4=4|fo8t4m=KhyTf!lT<9m**H`njiE6Y|{iYSZY}?TZ zU2ca{I}}`jd9Z^n>(PnxYBh9u-t`=FMt9%TKJQ$PJoDijZm+NH^Cwl%Z-Or8$zA=M zb7ZssLthF#)A1zrCg>}nPqwe`Rv%`NdK>gNq3>_kZO^wn=$M~CcWUoK=x;#pF+Wi4 z%~_jj?^5`FcgQ2_Q2{*#{W^O+_(K#@uZBM9ByUx$A%KkD2=b@$0FLa^5?1t8~#xixE z$NaM+vYs`_^V!K;x8ZhAx5uqImDC%c=a*&H<#@CP`qN%AY96cGy1O+XB6Jmi0TRJ6$j2 zU1b6jcwcliWdgfw(WT|H%^fYv*eq92+4f+wt z)wMt5!+0#pdXz(V2e)qf*sjYuY_!f+s=cb=Yk<$`d{hs84Roh^G()e2o@tzy^{B`B zPOg6w-h1SSq^!Op>teg#op&|*&#Bt^2%bw(UD;km(1%067vor0j+{HqhgMQAgC0H2 z`8cYCz5x1Qc)Ql;nMAH%1N|E4e!GtHX5e*_&PyiM=^-eeo}+!@aI zD?QiaJ_&TE^H3r5vCy6Rc?tAF=tJ%0+wM!3Lmv+P7`x67trj3w1$_$iK0U@Wk2#*n z{ZI$J=-jQ_p0Tel#{=~d02wvUGtKb53g2?wcVG9oA@eohym{!%t=nqlJoG=ucek0^ zuZv{CvR(x@;CykO^L(cm`eNv~z1E#W*6ZBv@?@TJ_&&{&rwaP(|3#j9_geve(3?XjR| zdsM==5Wb@{pZtj}*2YT%o@9iQwcjqv>l-)?x{)xNy< zAoW)0Dd@Ou+^yT5%XUH^b7AK7Wjo39=Sb+&@ZQsFiYsLV!Lw6c~>!8oelD~=TJDp$JpkILXGxaZ7zNZTJ4WJj>>&J0H zUQf5p!}$&RhtivKZ1*-;*V7UFtxSG*MCL0)zFjYJzJ9CRj$T83FMEA#*LMxjha!KT zUFZF?Ld0rtz8eDl3B325H@UmM^4NP=9ec8#oyfBoKBxUwa0})y4&})8i=juLXKGhj zkLl1Wp`U>FUHjb}qj>T|SmvpMZ%LMV)IqPwqBlXmGmG8^eF1c*J+R`gxyPWOSv zKtCIL1#)Tov&ZxCGWZ^X&uKd=q1QssH1Cx4tbzUpbf3K(&MBnc0R0{4W9>Tc!^wWv z0=*Ub_V!mNeC`V8dKN6eF@ii!+ffWX?V!tg$n)nG=oo(RoTH?>&E#=tyFXBcJf*0| z_Uc;?-xXQv+YG%Ti{1`BbVOs4rI~CK))`F zUJ89Kbf^=12)qN7{_9k;3Rz4D3O+hUz(wC7@t$oCZdd%)kd-L~ILXr=Dd z?w!!cJD-e-+_LotnYEQ`pUMi>ORkuBTvyKS@u8lvCs$Dx5M`Q zt`2$ubd=D&owm=rG(kTi%ld85$3P!%U*Gn*SWh+PFwmXOw}sFrLw9PY66j|@FSY0A zb@Uj-3UU64K)(a;J%=6Dy$#*Z?YT9opVlB>8~jfDtpWPy(D$*IXM5h=0{utmPW_^T zy3_XNp`x3y{s?=1ehxwI_YQ1N8v07PJy%WW-X3*sH?KD3@iZNIF1-|=Bg6Zy{;7U$ zTiySGUIG0;yKevef9Ug}_p|G^`$vsj-$`$Uek#@Copwce;Ny5Beu1?Vs-d3%-Dw_Q4}Ai3r~AUq(1XyO#@}}6CuPxd7vb-&KtIU79sFLYtlt>uGof#? z>+ZMA#*%s|^dXmP&q-~cqpE;D1v+licel0e_i?JBKLkBff0gZA54|3GseOIf&RtKv z)%ei@-zNB;wEK8}S=O@y`Z-rPZ%5wU`25El=kc%zdR`X24EoN{2iVK!crLf261o@q z_WDaLd~+T0$n9u^9)f+AQ~3vol|gi7b< z#wF0h&?jkm^)b-nSbv~BzwLf}DfAe0r~79W(B*by8b@UQYUoku z#rFKzPV4?$J@lub&$R2dzmw7oy#u<_c-jvA59o7xtglWuvOnb3U_W2Eb=#+QUAFVP zJ;%c$_}t;lOSMeZuakz`wZjstDW-{;yiQ( z^m#JRU4O~b^&FuZc@oz;=cz!RFQJ?Dx%4l2y6V${Jo{hooTmYKra(9IOm)sv5XJMU z`ObMdk*5K=nP)%eJmttEZg$Qi&!0n~n|TI0=cz}YOK)+`BhQ};pqqLAd9dUD>Oh{4 zZ*|Vof;|6%ZsytOoTvDHock9#&(Eeq9|zs(d^`{O80Z7+{ogk4uZ6xV^gO%H`&@Fo zXoNlh`YCqZJ-S#=Vg2hT7Y}akisf(c>j`feV z>o|VpBS4vdI`k0qOxq`quX)hRpr5L(uV1&;!FMx!PUB`1^y{+dZP2gEqI({|@d-WC zJX+SX5c=8Bw^z?n`0mJ3P6hN^v*^{(Z_J|CL!Sq|$Na~3omGwV+iK_^qRyTp59;p! z*7dV?pSBbErrqv*9aVq{%5>;X*HOjPGhIi?cAE};2G-wRyH&w=7kscuH(eB6!QY;L+rZkb5DiP8?)#o(APje$G*N>-H4FwP!4@F z^zF4nHGI2QJGVnU^qsTl&CmyD(c7W-gPy7X$a*&8d^jHZ*?8|6aA0@;k#m5u?s222 z7T0C)?Qh>+`Qa2S%RFV!=R@D#_RfRvN%)-hdoA=wv*?Y`AI_q;LSF{mX+G2my$<>) z`*x_W<(c!7f(J3bfbMktSq%O0Eagv!zADT5^PtP}apl?F*1RuTfKV;;R~_=pcAkgx zSR?c&@ZNI~_J%b-k^9T`oTCkSj=E#(w$<=;d1x4eP!saJ3H?%;=SW)~YuwPDXBREQ zyy#Bn^HLe~PUPFoUY_l_TqX41p=Ua;nf>Q}+^dI<;S9f*F|NDLa=Z8}+1!5kf~dz8 z(zjak+5XOA8_HV&U#9brY-i7MJU@Y+>AF+uh0qs6KLqc)+Ryemk`m}oLCJ41p!=Z@MtNQBWt%rtLLUL$sXc3;Pk^4OJ>`C{#CfX%`dM;5y>V=J z8ERgBqMVmYUoCtO-L0;Vd-&Wv|IUI3H}clQ=Q#dDe+qi0`GMR&CD4~;(aWLV1|4VQ z?z-CUt5k9Q%k8>b4XEb+hyG8jpK1R}y$Sk{(4G2s8}yH$PqgQ^-9Pp`gzG|w^<_I2 zLjNB6Y4-Ki^&I!Ax}GbAFaI9r?W};lFZ50JJhuBs)zCkK?$i$T(8u1Jx!=fo%Jb)B z=;plr8}xi@Jk+k&I*@0{ea`m@@*YOtf$lUO6hV(cpWI_R)B|w2KgyuL1ATwH&hw+x zE1`b@-D!W;K>q}~)BbFL{s#1Y?D_5YzoEB4&vacN+o=P3pQv_x$+1FodbkJpe>v0}D6nZ7zdwSXGYmI|!Ls`76Pr)k88{yA%f2|ODG4wj<$IBJ0 zZI|t+x`K?V&p*Sr;lJ=z!?)$X@HN1<)8g#q%I&Sid9N5gbKKtxz1gaxwY|1+Uv5us z4D+__H5z z(BFaXRKEu3A7;tl0{sK%PW9`6F6-~KeR-HD%JMVK&&>S~UAAwg@kQ!o(0_;Sw0)J( zw`M8726`uSr}{TQPiI-b1$qbcQv3enb+W8q2lQbNIM*-lQT$y&=mYKR+wSugLEi~_ zruxa_s0{ib=opT=`>z}qmRO^q8eitYSDmFEwb1W@?zEp8p)Yc%huqFq=nJ!~-wAyI z^ilSD+OK~eQ{_AD$71MS!%vix>!ef>FEDSV!#&hx?w=wqNCspXN6n`JvxLobDn zJ1^bihVAnJ_0VTP&(vRJJ)5DQ0KLq$uHZgX_0i=lxLx zeKd5ZmD0HXu zK`HdwEP4g>hqCC^&{sou8jtFsFM*!vIF;?t4E=uSPW!VR`Yq6%`a|yD@O`H&>yLqc zNtW_Up5Gc+fj-0Rsi~J7slID zQA_K(2HTQzj;m`NYek-0mpkw8PUtsg(F>l&90j^lI}}5|I?MXgp;toBw4HK0Jig+YbBv+dAa=K1)5CpnsdC9&OOSfbMi$cp5O@hu+WL-nP$~6+(Xwy3_Sm z3H0}%=h@e{eICCYdII|Po(ELJmxgb+J&*148}-nC&!RU&{{#AH`}(%eyR}32tZ+U* z=RSk;GxYuK>)YA_x6?LnEQ4MQz1Xg! z9ptT?F^Co6d~_Q05Aojf{x049-nuWLJ*TWgzHRVdYR~7sus1 zv*?~@aeqFGUI^Xyu=DX#0zEH_UJl)zMX!Rs1?A7^v3+WyF6&g?_4BODUcW-)ehs0Dfe`XTmqwLP!wfIb7dQ+wq#8pesxo!YAi`jJ`mGU)q4cWSR9oPUmh zK2x@r{52Z;yodK!#E)?eS z(EY%GSmZWl2&h+y%`W3^m-x(Ota2+y?^1EHF-yJQ{~+)*@pg`JiD=9*7P!RYImU9A zSdwEr=MuN&7@J(;cenATTl|t^Y|hz36>$JoI$qScjdF3b+qho*%Vpf>5?{HDM_I(K zM~P0CajN*qg}k4*jHg^8>Nf6ntM&iyQ_aQ*idn{WYV!u{58fc2b{X}qJk@TtV>xSm{PAz$YO>WWe&}O7 zB3F4SM|{)QSnG+q9`9>B<`p;hHJ<1t@IKv3+~3!DvbTKyLvQh3U*qOJ;+4L}J$=O5 zzQ)!*Hz5!9+HR+d&pg->%^u@7R|{gddBkrX<6j=tO1XI`qfi`XOao>8me#mj3tR^u ziYbOG@a;h3F}HXz*Z9P}^Zf&I*5rsk`{(?YBi_x;Y4ynWtAzMIH|Gx_-!Jm|e(0am z|>FgsO>7Vm_UxD`@^g9&Ad^SLQ zI?#v>6dMK_>jw%%{v2r5$aS5O8ytpuo$os12)RwSy2ahSjW1*$Sd}Bz^fnqjcpDMo zt=`5f0&h2oqrUHJeB>41_cm_tCARg>S<>rRL>}#ZB%XKm5uf)pYWj)|eT{fu`F?&s ztDO2%P|h~jLB}3}-z{?O_JG&;+$B=Nh`2v;VWB-o{3eWBJyKZf5evM=N1pjoSmQ+o ztT<@C+l?n~ZrPU?$$f{I{a>!^(MO9?<6NZ;I1HSz-`y@FCOZP$eM-d@#;shCfxM$2 z%oOjrjI}P&?lQh}sof^E5l2H?=@Jj+Nb&9*W2IYso@1akzQz|G0Z*fM%yYTM>Rw`1uJLv+ad)m!-CO+G4?9i#(9ig_xA>r+@m(JQ&&IyD zqLt02UAns~PYyA2OaAS0)wsn2sJN^$dWq`Gd%Jc!1W#|*xo&d(nB)4|jWa>ibM&Vk z;|JMiXhYxnFMSvT{o-(JwORg-Clwj8yu~@j3vO|1j`2@7oVZ=1Uj4 zkMie^01p*M89}+cbQjlP88|_l?wZs0I^%ZPf~rQ_1#j9>(lYP6k zxpMb{+?8vas~-kmjDXv0yJ4s6<-qu`OC()r0P(WRsI%?P*WLHIj=>oL+21KNzIKb} z3yoztB35X;kR$FZG^#w}#zNyip0V(JC&W{G8`WO1Y;WTYuUNRZ@vT?!g${`29bKV_{M7_+~Pg2@tIq^;x&GAi?v>3VUAetmF@me zFJq}k+}+Dq;}P?F84HB?pqH^+h^Ah~Q$jr5%lK8?u8x4-XNYr+u&T!Rzq!OmImX+v z2mIg?n{$j?WNk1eRC(lH##as8Vu{E2RldDDN38W2Pvpp7e8wio&LA7*|4W@=DC+zF zRA&(Xb!QmA#w9+$$zJY-luP`SW85U$dzo9@=rNv`Z*p22s>3xhi0VBUPj_oSPu?|9V|?xwPvjW)J16v}TQ>eW zw^Ysec2?W1I3IVGvF9+(xS{<2dGV_qkj+2|wd9UX%MzZBUQx zfp6d`Vvg%JS6}>IBTn0v%dDWaeLcB!M_2y|;#AkgeXlZZ>0U#gI|hcub*{xO@u16i zyj$s!YsWJL8X_dy;Z>JBH(ISR_&vGCZSHq-HuN#RkUM}i9eiVs*pg%1mm|K&G2WEF zumjyv8kb#5f|d&Ud9F??&)PL^fn{T zthozO(p!CuFIm$6+2z6S%VM{a#44=!Br(M}8-BB&|5y8_>qtX=?eAsEo#u+?-Ns!m z@u*v#N*BA0Z(LWKTh>(&x3VAP$6UrnSyve{%ir6jAGaB%AJRT(wrF?bdg4;jaBNsxW+KAe7L;>_i^lFxqBepsoiG`r@3W!8_525xF~a7*tb#+ zAXbk>*}cyZA>$gksj@GgEzWn%cZpkE2C8GZR5NtVt)9gk?E4(oS8@*atY^=UJVr{N zgXwLRag4)U&Gh}^3S>!#di}rWGv}QD?e=bOJ21Di?PJ;W))Z8=z4QLI_t3#|-ybS2 zH%<}LjR^Z_uAIS45hr4dFn3nhj<@&Sc30s29M>mq+{9bz*|X7OY_RV(b=dvaZJqUa z>^)gbHO|wjBF|Mj%6eWDbv^0EOr`Hex12Uvz0B-?&f}`R?Y7rf&Evy1r|xPFH2Nbu z6r;#_qTzm*QR5O11MM#H1yF?vG=MAig^OKAhg|#ecBW-djA2rK&z62DJ7O zUjrR|#JfOqUvbA$l-E~uVyUs8ScfIdydMGTbHz76Q?7UqsO>NA#P3Zu^cR0(sd|8T z4oh_d#A={(fM^4128#EA_JQIqoL#C0iLF>_9VDK|QpX_iD9}7ud<(P<7A-*I5U~h@ zP|Fap4NLVqh!?Qbw1apIsLc~8pdn9u095ZN?p}`ab`8hTX&y zKy`um0jMhw9|4^OqUIr#x4XC*Xy0AD3{(vjYk=0F;zyuksQ4IY-b38?Fv{CQQ~`~{ z#Co7*n0OMX$5jE)w5Rw4s2wh%btrGRxCN-*OS}Tq?IqR%oqLIPpr%lK3bYrB`&Xg7 zy+s6Q-CMj0bnGqu1~mJ`KY%u$XayQah{Z9KH$vPB)Q=Re0Zk*tQ$Xz~u^DI>B|ZbH zM~ep@L3yLa0-$rWXaaCy@-)!CkN780HAZ|6w2l!=R-?Qz;x?dpU-3H7wy$Ua8pnz) zK+9P11yH}ASo$c++fOV6YR8EL&@fIs161!Xeg^9H7heLM`-@tf@@ftcw*&15h`$3> z2Z}h*dZ73h&~c#n3TQ484?d3aibOTgc#wDlXgNqc3)K6?FF=!Dd=1ndESA-yyo1FZ zK=pX>CQvtCtOGj7iw>aX5b+Jreu!B91j;*9+zGTEDmDNehl=Nb=EKCVK-*!W4QMPD zE7qXAVsRHxf4F!HXgXXx57ZtZ(m=xz;#;8lNU`!sly{_91auxLnt_@L;sv06g7^)n zI!dH~)}zEjYf;`&;%=aMqIerjFK-4{j@{SSr0`13$jX>38@eakQaT`UFK zr;87Psw7lbHv|)`WfQpMwB;0{0mF9 z=ZZC0YB*Os2vpA$9|LtW#T!89Oi}eB$~#Z|f~EHJ#FJR6Di_Ou)^hO)&`~bl1e(tm zx4eY%&KDh6Y7B|BSZWE0uWeVMrJRg`y`_#I1~mx%@})m$zf2HGzdUjS8ChERj`HS;|6r+ou6PzpRac7`(0aA_8tAxMybCm6Bko9`ylX@!mKv`W>#)>v zt#|~epC`Tnn&yf3fZFTCoqtDp*NH!|RDHd84oh{{i`78q^`Z@^xk0=SwBI1^dIRNQ zV!IWKt>E)m?f@SJn{RZ9Z^1UO1#H9wdC{9F72Jm9`kP(i1uQp#kAbySxR(qzfFFR> zxS+dx1Ih;HgPmX_ScBQw<6t}Z9ax3i!AYH58eni<0;CEU>jHuHs0nE--9jS zhhY6em$%+=(j*Z*Gs zYk~i@!2ep{e=YF87WiKa{C}VY#y#pWYuU0d?z7;vWwlyfePS5Y6@%iiaDE)UU`hil9GYs-ge%g1WVCv(~SEE&q3&*faR7KU-z zvFf<&&*jn+)bY6sm%n^-r1=h?mNQ?2Nb|F8c)x|Z{M?&-$&hZ6FrtJ>r9)?8luf?Csx z&w5fVTlJjGhUi1TRh~tLjsI*@UlXwQ+g2{mTBGu9S2pJ_~WSmTpNis#INpC63Cw-)!43I%GM25)-86{(6oJ^2OGDW6I@9`|3 z^pSotKnBSW873oSl#G#aGC?NE6qzQyC$N0dNBYSC86-nwn2eB7GDgP91eqjLWSaC& zW%;C!^pgQHNQTHT86l%&jEs{BGD)V$H0hnj@<|`*Cj(@V43S|nLPp6L87C8Dl1!0l z(t9GyCw-)!43I%GM25)-86{(6oJ^2OGDW6I?@275^pSotKnBSW873oSl#G#aGC?NE z6qzQyC$oIgNBYSC86-nwn2eB7GDgP91eqjLWSaDrv3$};`pEzpBtvAFjF3?>M#jkm znIuzWn)IH+@<|`*Cj(@V43S|nLPp6L87C8Dl1!0l(i>#?q>uEI0WwI2$S@fpqhySX zlL<0OrpPquJ(cB?KGIJH$RHUa!(@bvk})z)Cdee2BGaVzG?q{LNIw}MgJg&dlMymX z#>hCCAd_T@Oq1TzSw86_{bYa)k|8ooM#v}`BjaR(Op+-wO?uB@`J|8ZlL0bFhR84( zA){oBjFSm6Nv6m&={=L>lRnZ<2FM^8BEw{ajFK@jPA14CnIhAqcRI@_eWafZkU=s; zhRFySC1YfqOpr-3MW#vbSuCIQk$y5j2FVZ^CL?5&jFE9NK_M#jkmnIuzWn)IH-@<|`*Cj(@V43S|nLPp6L87C8Dl1!0l(mR9YlRnZ< z2FM^8BEw{ajFK@jPA14CnIhAq_gt1w`ba++AcJIx43iNuO2)`InIMy7icFKM#jkmnIuzWn)H^l ze9}ky$p9H7Lu8nYkWn&5#>oVkBvWLX^q$Z1NgwGa17wg4kzq1IM#&f%Clh3nOp$5Q z8)EsSkMxrPGDwEVFc~4EWQ>fH2{K8h$TaD_faQ}u(oY7+AQ>XVWQ2^8F)~gj$RwE} z)1-G6%O`!LpA3*eGDL>S2pJ_~WSmTpNis#IN$+fyPx?qd86bmXhzyevGD^nCIGG@m zWQt6a-V0ei=_CDQfDDo$GE7FuC>bN;WP(hRDKbrZFJk$mkMxrPGDwEVFc~4EWQ>fH z2{K8h$TaD#VELqv^pgQHNQTHT86l%&jEs{BGD)V$H0iyV<&!?rPX@>!86v}Egp86g zGEOGQB$*=9r1uh*Px?qd86bmXhzyevGD^nCIGG@mWQt6a-b-0N=_CDQfDDo$GE7Fu zC>bN;WP(hRDKbrZFJt+nkMxrPGDwEVFc~4EWQ>fH2{K8h$TaD_oaK`~(oY7+AQ>XV zWQ2^8F)~gj$RwE})1>zbmQVUfKN%o{WQYut5i&}~$T*oGlVplalioQjpY)M_GC&5& z5E&*TWR#4NaWX+B$rPC;y_GDV^pSotKnBSW873oSl#G#aGC?NE6qzQySF(K4NBYSC z86-nwn2eB7GDgP91eqjLWSaDbSw86_{bYa)k|8ooM#v}`BjaR(Op+-wO?t0l`J|8Z zlL0bFhR84(A){oBjFSm6Nv6m&>7C2+NgwGa17wg4kzq1IM#&f%Clh3nOp$5Qdo{}^ zeWafZkU=s;hRFySC1YfqOpr-3MW#vbH7uX>k$y5j2FVZ^CL?5&jFE9NK_M#jkmnIuzWn)J?N`J|8ZlL0bFhR84(A){oBjFSm6Nv6m& z>AjBSlRnZ<2FM^8BEw{ajFK@jPA14CnIhAq_j;C3`ba++AcJIx43iNuO2)`InIMy7 zicFK<8(2Q+BmHE643Z%-Oh(8k86)Flf=rSrGEI8tvwYG=`pEzpBtvAFjF3?>M#jkm znIuzWn)Ket@<|`*Cj(@V43S|nLPp6L87C8Dl1!0l(t8ujCw-)!43I%GM25)-86{(6 zoJ^2OGDW6I@69Zq^pSotKnBSW873oSl#G#aGC?NE6qzQyRV<(Mk$y5j2FVZ^CL?5& zjFE9NK_M#jkmnIuzWn)F6kKItR!x z$S4^j<79$Nk|{DxdT(XuEI0WwI2$S@fpqhySXlL<0OrpPquUBL25AL%CpWRMJz zVKPES$ru?Y6J(N1k!jL<8_Oqsq@N6sK{7;!$p{%GV`Q96kV!H{rb+KYmQVUfKN%o{ zWQYut5i&}~$T*oGlVplaliu4|KItR!x$S4^j<79$Nk|{DxdaGGJ=_CDQ zfDDo$GE7FuC>bN;WP(hRDKbrZ?_l|)kMxrPGDwEVFc~4EWQ>fH2{K8h$TaD_ljV~> z(oY7+AQ>XVWQ2^8F)~gj$RwE})1>zS2pJ_~WSmTpNis#IN$-6upY)M_GC&5&5E&*TWR#4NaWX+B z$rPC;y-}7=`ba++AcJIx43iNuO2)`InIMy7icFK<`&mBeBmHE643Z%-Oh(8k86)Fl zf=rSrGEI6HvwYG=`pEzpBtvAFjF3?>M#jkmnIuzWn)E)v@<|`*Cj(@V43S|nLPp6L z87C8Dl1!0l(z}G^lRnZ<2FM^8BEw{ajFK@jPA14CnIhAqcPYy!eWafZkU=s;hRFyS zC1YfqOpr-3MW#t_Ez2i;q@N6sK{7;!$p{%GV`Q96kV!H{rb+LEET8m|elkD?$q*SP zBV?3}k#RCXCdm|;CcVp8KItR!x$S4^j<79$Nk|{DxdY7|&(ntEq02w4h zWSESQQ8Grx$po1sQ)HU-u3-73kMxrPGDwEVFc~4EWQ>fH2{K8h$TaC)$?{1b=_dnZ zkPMMwGD1el7#SxMWRgsgY0~=;%O`!LpA3*eGDL>S2pJ_~WSmTpNis#IN$%>~^pSotKnBSW873oSl#G#aGC?NE6qzQyt5`ni zBmHE643Z%-Oh(8k86)Flf=rSrGEI78ET8m|elkD?$q*SPBV?3}k#RCXCdm|;CcTfa ze9}ky$p9H7Lu8nYkWn&5#>oVkBvWLX^sZ+4r2cvO|1JMt)dHikCOT%)q(g^|Jm!Q` zMh!c7?15wXEs?CN7&-V>jrDyKyEDgdcYV*KXFR9t`zSr*9>ez|iVHx^k4!$KbBV#<*u)fFBGf#hG2EX6a zGd{pr`@HoHnQkS=7-)R?U8eXTW8NdyH)!ns!G`sHq3)=G{W8QMzC+jdhkE++jNkda zqMq>`jZEKj$uV{^tnUT&^viDn{k5Ov;9Et*GRCcMJ#}Z1-}mttKX2=fsCV*fL+%Xi zFTZCc<14iNvM1wPwD`e@yKMEbzF!nD<9}_Ri+Vn4^C`O3u?#$F=%io9RDV^Wzs)&HCqR z{;l)}G=BjqEVp-%=0C`c=Nrdp{?q8s)BG3HKUwq3+psc!zUG&g2l6;QR`b6|e}U%z zkp3x}|3CB()BFYa;-JiboaR5qjQ2MRHNX5RN$D@u{P)s7QuD{@KVI{HL;o1fFYpCT zng0aMzrPvpZ;aFY$Iw4j^It%Jk>upQQQs zG2{J>37Y>T`cKyUH`8CD`B&3lrujdlf3oKPo&Hla|6UkiWq&Kx{8P+$z7f>?*U~>t z^Dn3WRL%c3{bibeGySJ&{$20|Rau|YH2+a%Jl{B7^UtAwy5?U>{~4P9ZTe?u{-5bT zQ}geEF9yr{lxzNj&3L{sUGtw#|18Zvm;SRf|4RBRH2;hApRM`vw;Rm*T&DS5_`x&A%HaF0wu6YyKn5c)oF- z=D&#kD$T!;{&LO#H2n)S|Ht&7ulf7ni|4XF)tY~#8P7LDn*T)l7is=V`Y+J@E9tM% z{7v-F()>TuzgY9Az6(FQtEl=5M6`BF+CD{dJn(i$DG- z>r0hh)x6*&9=06xe7$Em=gXX`$jOQDd zY5tY;uhaY+>Azg__rf2WlKC4o|9CT=Z(O1I=g_}i^RJ|Tj^_WE{wB@e2Y;qWwtuDO zpJc}S8*ga-E9k#c^FL01v*zDKe^~R&Kh`I=ca!Gd4}Zo=*5@kCKiiD=H(E6Ro%GMu z{4dh~k>>xJ{;M_rVEpictWT@vKhTWl8`o(5bLjt4^WRMWwVMBL^tWmL_vxRf`Q;xA zmG${v^Y4W}h9ukPI?aEg8SihjYyLU(U$6O>)4xUYzefKJn*V3|J2d~Gom741YyLyb zcz@$}&3^{{H){S{=?Nb^rJ z{D07Yo8}*ZTL!W|1)6`78P7KsYW~^u57Yd&(to?=f0F(}%`gAFsoY=Hn%{*Ba9N*` zn!nJD=Noru{uAjRqxmnR|4z;S0R7`M|10$0rTKrMzew}%f*+KT^C2Kf#RW8~1Ad8|W|5{B`u#X#V%o8|h!E`Cq4hp61UTuJS*m z`Oh-rnEz}31@u3x`Cp{JO7nk0f1T!c?WNjtf#x4>#`BF;n*VtEt2KWG{V~mdAN`9o z{}c2-qWL${U!(cIrGK^N7lo?+i#7j#W<1|`RP&!lf34uFVO#{ z=KqcU0?j{mf7PBFH2<#xeib{FU^-t@)p% ze~jk;ivD*r|LzB>_8h1AOU-z`u~GBiLVuCwe~$i5n*TTY$7}x4MQVHB)%+Kj@%~1! z=6{g>_cZ@!^iR z$C+`=|26*&^na@PU!=cW^Z$eXR?R=+5VgItH2>*lJm2_C^WR5*h35Y|{hw?8oI_Rq z%QXL?W<1~cLi1lsf2HPsg#Irz|7Y~i)%<-AQ|f4=7b zi2iRh|Bl6Kd#f~mz>Mb`ZJPf^`WI;aTKd1${IAeot@%HrKc)F|4p;SAr1|$VYR_qmTmDzgIL?nZsXT)IcE-msKA7QD*sQ90Zf6e%OZkPOgiG0lq(0{A)4`4iP z#cx;f5;o|4$FST*DlR{VAz!;qX1qqlr!ddGj1ObGg_YgNKbHQ7l>Y|C*DyYT@#`6% zI7Rt~EmnTPc1SWl;Qc*bMOzlHG?jL&#b z#h+*V_!H<~uHx$$|AX;i%T)Xo#vhrg{Ojp&WV{Rqro1mVe}(eD#kl)K6`!$E#b0Oq zNyg_ts^ayGpL~+?Pk2nlmoVPW_=?9>d@;25##e2U(fh##*`AFp;=0JoN?>#E9^+WJe)Fp zUhysXUHClb+zg-F%;f(Ve#7|d=R(`fJUbhMc;2y&$GkIS{++Ro8t3KO^0g=9`I`T5 zGyd1la|Y-irsX-wjQ{m>p0nuht>wQ5@!|OV;i3oCfY*=XOu?BdeqDiT=S`}b#zlQ#%3sX*gNz#iRiE1!f1B|WPgd~_ zjJwWJ`EN|CJcls8fblcOsB&?+YQ9FzQ2w>GD$g(#He!rdoTTDbJHLW>%oyDD_XDhc z)k6Q%@-KnoWwqN@#)p5e>SN{Ucdmg?8~^pSH{!BCOc>D9zl8C*AE@}QT=jj%`+Td) z#js<(cA2U2Y(7}U{fr;T_&x(vJ6L)8V8F>#pAm@5`pi5_FXC zH z%NQTms`B5=Jl`_@=HbeJDC@Zo26oxbQ7;BACJ6P`49d{<+sMAYZ%WhReAQc@-RM+ z+j~6YZ!n%%ui9ZJ#`m~HGV%sq!=}RPh0fPh{M6kSf=TzsL9irz^jY{(muET(0VKIOC^=RsOS= ztGLw;n;GBmp^862f8Z+RUwwco7tLtCY7n>fDMKb6rGLxIDo;O(L*}YHcZ^hdtp4@_ zqEw;eXQcvdE}U@Ri4JbtN1hYuVwu6@hbmpjsw-#DF2YxmES5?T&v=N zR@H7;G+&Q1KIUuX-;41*=VjjB%Mh2x%PAMBJm<08R~-DG((mJW)@q;L*Qq?Cwe#0d z#;++-^|8jKw-|rtF%=)idQQDwOgMOMf0tSh5{6;%Ql;{I*{I^yJaZ!BkIE0m<7Ktm$BbWdkcy9Gp2}NPp2$cQx5m9z z#(z6Xlab}1;uK+ta-~w#`|jXx{Ddl<^0wfuU=*Rp#>_xRnOlUU$en$*3dei zK5?rm*S}c#t^WKo&>;7OVJZ=D(it0ow7ESFO&c<9VNLJpDHzF8fb&o63X7 zCFbiz#!I+=4`TeXJCuLL2(`aPF`jd$iof%Ts^D{s-^RFSn~I;tc%1RdT~xU{FkX0< z%9B1=#gAnCb;j!-S8;1x-F=brFZrj6TgTCI#@Ae+$}PxIiC$v7s7S@F@#I6s7hRGV2#Ri_GzmAm$N<(Gd}lJ6}QHX(f6tS{yq2mNcyKDF8BLM_o;do@Vek##=m4c zSljzA#uss1vg#R%syvf9j#=j^&;16j>325t>+XJt%W|izP~{%X`mAOAkHb_u#@936&Kt(NGrooKwQE&<&SZS@GF9%eJTDJmyqxjz4a$EQTYU7%%Um>SG-j z6CYQ3b{eJplUeRIREi6{>YOm zf8`kEx8hURs<{6%6}R#a`J0MY-J`avlzA!`&pBNAt^K&3@k-uLu>1p_QhDmWQvQj| zGoSH~c>Qt*<8_SB<$TF%pF^Hjd6v#oc?Qsb3FBT~H|@_jKB#COr~Z4D-*+d3cZ_KeE&^$DsSrqh2Ii?@pCAuGRYtF#bCZ3>wJ=@=Ew=Wpqz~kLo_qJzM{%5aO+9` z9k5emdJg4$B@VtB~H{vzMk3U=;*XJ|7%kye} zIA6QZHW6_-4*%ZXvp+O4zHVog$Lfb4GX5~<+tzjsdVzU(Ki0bc`~>4a@;?7i*5{~3 z<-d&Mzx*8s`D$T2kW%$2S7GB{j1On~?8A7k7c=k2T@jbtbv@g8SNe}+{0!c|vbL+5 z@!Vfjxku5z-%Bdb4Qz))7{8eD2`iP~I#1=ito&j2!%_54W87G${8pYP886^{B&(jG z^(xO+o_CICo*xjm`W{0j2EL;Fn;ug6tvt6gKImu_xBAcHjQe?CE7*wL#0SoQHXsd%F{-zZ`{^tr0%3C!~*<0t!7-0DBG zUsrinu$_JMU&Hu&xypYKR}U7Hy{ z;BD1z*7F^)QRNv{tMZ)8Jm)d~6vxjm8UGCNOzqHjlgcyyb(O!2{t)9s4pi|J z{HxiYt#){x@pc|BKKjeBLuG%^$GzE%FX4629QyxYd}1$Eu65iU{=Ujn!2MCUU z64egpGtUQzXWHIh=-;7_c+G49HI8Fb-sR{aeY4g1>7=n#uSI#@F!tXpLjPFy5v;w;i5Td9K-6<^RK_5-n$Z9-qHk<9R3J&o5T( zW0kw-hbm7s=Sx<(A2a^tGb+Dz+?9W%{OgWW?O+`*cQQVa$AvYX?D4VkzsdQhmFGjo zD>=?s@$)`W{vtz_JAm!;F5_c)pUvtI!B5rrV?3woW1UZLL0tB?7r#__to`*TyX1t&A=|Gj=8kb&XynyFHtDf#JRJrx+KURCrW4x5}A1lwh zj0bsN+KLbQQf=?|Z;do7mCveOkGOS=Fl6F6#AW*z@;;bV?mrm!{zJ9r(OhZHSIU0{ z_m@@wB;xY?GHjjN-V5n3`C9ptN!4zpZY6ADd>!wfUqt`ZZ_fe`oKE}`gR{2}y4-nyX4dX8}zEJ!8#t)3&$@|Rb(tkrr z<Ab*`19;P zqnYP(#;5F~{6iVP`3IG!c)V(dJsDrZcss9itvqiszM{X%b1MCJ|ETh8dQs&W&-n9< zSMhTiqZlvxN%^n%Q0=ch7{7&a_hyyHI#2zZ@v|FM{3iPMXjggGboBJ!&G-U7-?7Gr zdd3gsJj5FJeqnss#i~A5{~!4em0v&a&tZJx?#e%m^;yICYFanWbta#te zD*xIN6}QIom5i?rsQkFhH(x{lsr->a%5U|DcNo_{pRn&1<<~!taT4RhUsCx$Vg5SH z|Cwq}tKGh4e9HkUzBm2JOp-~PHXE5~XxRkhLqK+srK|!XA|N1OMMTz$fCz{n2#6IbBAaE?its<@p69&F zeeX;rZCd*0`+WwUIq$jmz4zR6&vx$%IoJM-|Cd|OoK86Fnb-a(?T!YYtAN*_9;p*} ze5ISue8QQ}V~EQ&g8m}lb{)c3J{0u$!#@%F2Y)7fl>Thsm!2!Q(%-H0 zUlCmO@YbISpAVp~bRNG2{ClVe(DhjKZ=v5mE__rEUkrTNh0;&u{}%8YG4CVszN7ym ze0nDf{nvoE13wt~ql1Cp0DLL@pmN}cuX4}(jfC^O+y2)*z*qiC`dvmfX$2mU$g=yV>xAe`-oZLyz@0sWqz37_%E`)mO`4g3-0S#ATq$Nz-> zXy{v=$0p$OekHxk z9`^C`f!_uEwd=z3_$2Tr<_o?j=y#-QTAr816*A5T06!Uc7JmIsz@GvBOj%fuHEke# zo= zfYkh%1Ny75PWQr(%YaWuyy&_O3-~h|d9grX0ALE4cxY_ZCmw}&9B>mhR{Cnsi zhO0k!63%>1zfR~?9wuxmxLsGX0Jxo}cpUhYLuFoc{67Nz@IJy{`%p7n_%E0$^oOIL zR{`GvdO-Eq{|MJ-L2CZ&wVCjF9C;|6-{XN_XT@!P2z+PwFKVA0w7Kwk3UW9ajod&u zkN@SC{r?-#e;suNMWC;x0&E`7m!Vg;$2@*YxU2s=ZYlKtMx6Gm;Bx}u#_zE7#too< z5PD#D(Ek>AJH}x;@S?4R{|SiKsoXvWye=;5@m$b<2>dQ9E-_%i^0 zvW9JhzPeTBy$$?t2mUu&vN{UL^c?#<-mV{Otn-|2p_w4E(b>g6n+U3A_$| zoZ?^ks_=gu`;qcF3ivSWj~(EDJn)vor2jg1%Ya`FeW>f@UBZ|LiOE2YX00yIKS_`i2odl z9}n3@@F{!B_^W=n75L?tca^KBfNzO~3bG&}!H>GmB z9Qd);ylhJa5 z=K`-ADfEkhZ?vb-+x4G!0RLpR@X_`73h*C{6H?i9lL+=~7KcW2lIg!6ly4!>CEbFaZguecrFrO_C6#OQ{z10rC8TiJhNk6roVe?|4ziXNB zA+yT-(+zyY6+*u`@Q;D_Bi=p*@4GN2e4hEc@X`KX4t!hq#rnR(ON4&RLgBv$_+)|K zbg1xAzw8&lpFy35`gd;wzoSp+HP3!(sqnwm@>^d3-Uxp!jdsVE3H^N3t*PC$1bD+s z(odD!ZOVn-t~War_=6VxmB7!l?968fcgg49L4Q5!uGKyqMv9T;ya9fPj!zNrV@Ak0 zG~vB!fu8|CLis!hd=}~lbU%6*_dKMnXz&r5$)PCf?y{B+^3`Y=NU=iHxzvA^p&-SiN_kHI=sy?Q+GIf(!0 zI4lKz&F#{z+AXmO!sl`LJEPIhTL^c_&l8}(b*}Jv1NP^^hYFt;un+DGJ~M%rS#g`o zf!p%%Yv7YnpP>C&349{X0qOYEA13YI0l)G^v^%oO-T#9K=kc`jm5%~{;+pV!TnT*n zQ}VtlKbK9!`@$a6ePP#0g74HTd=x(!_;Zje-Dlq=V=r2axUdOo`_=>*?{XU?71o)H#MLsF4 zZT@+OaF?76pDg^hz&xrQ+XQ?W^0pe+x(4{RR-EKf;4dSet9tSy;1j_|<39&Xk#-OJ zv-Drz>oMTNk$*{{|E~hy4f;XtqW*;NS#H&_Y&KQ!dC>prXSD$Te7wxN>bEn1+x1S* z1Ah>DIE((g3w%%PgWCUz)1+Oy{%RTU9@y==4<1!3^y97i|5Jh6b&{J-7y487midjN zKi?(XHNUqIZt6WCw;8T_@Yk?jGU!ifgS-E|gtH!~fS;@FZg#lfXF-2H2R^fbpM!X#+G*bcZl8m`0{DRm zk%xZpxsPz)N(M-O-U0m`$hWGTuL6GZVZw*D1M|;5jqdk4oN)7A@UK;G3~Lg67x=R} zr`^DNaehJfi&cdGfbS)??xh*iEPQH^ztjEb65#hDKUIoX`#12!t+F1~t~+jq@YxXa zu5$Y+;o3K_Fn@NLDg8MX{ZTuuns9#K1+a^By(|a5v{S}S$8(z_g#J?Or#kOf0Y3}& zr0UP%vxNS?u#0qE{{;B=&y@Gl{=ZK6cEh6I9a{lb+IK?fBlDIl|{P#1&PZPXlh( zDLn~%3F0#vM~xpXd~Pn6eyV)F1iTY<%Su1`7@=>!S?G0LKLfn?KZ0w0W@l39GdMr1 z?{zis=i$fcI4=i&Kjc}*`D@1tpBdKqjx6x|QBOVwLi!`%c0Jyof!~C@fbu^fCH!Y% zU(i5kzf=027NMUHe`+$?eF^yMkWZEKx>liI@?9C9H0V2l&%!#@ILza~pW0RE zbzM(t6Fzq%-=y)Mp8|gievR4#JEw*IbDa0rb@Tx6{X2!fuDdsYUjhD#f4g1wmtm+U z9I4|>IIs7eb`U;2(1#=Eiapj*6KHoi@Ez)8-&gwa3xtn-|G+}v71sW;cc;+T?H6u0 z3EZxyS_J$ZPdz4CS7m*E_)#_f0O6M9?U-VXeyZwQ|eX!olbq2Fx_ z!BwB^3;bf#)u`WbB5?aW+7-ZGhJAGu`0tPv{&pSporLSVfYkhX8uX1Zk{yH5Lm=?Oyr ziWM(f3H+1og^!N;ktYiMjpqu!8{#S}fG_;lkrvta+MgIlfVEI$uKSTKJyP=Hp3h*!gKf#|vJ&f*~#{-`TzxY_tUj+OE?3)^& zd>{B!#JAPA`r4VozZUCS{mps6Z9ncj;6J`r`l;)&?mNO~`5uC+-g^|decm~FmeAYr zx9fo0^-He26|h4_qTMfm-~V)& zzWD;-zv;n(H-r8);1|QsRsDR`g+g!Z)$tbz{y6CO1fL%RKj2B>zW{i}#X_I`MCMoZ z^JBoDgWl72xA~sX+xGyB1AYPg8l_(f{F?WqU5#7Ly2L%seT4Hk+xH;72>hF<*H!-C z`M%I!k9rKn?*;w>>Nb;j-|3eM{q8tdqW;J!z^9@B_U%K!pFtjWSDDUX%~uHh zNZcbd8lC+s@MfGd`XlgXmk9mO5Qo=yd>goZPuliZ3jJ3x&N}|@0>Alk>4@@~aFx){ z!umZH?QVXx;2Rw(^an#<9Rl3G_ux0ckDMX&>d*cU_!69d*#Z2gTqFE#d*(*q_Bq@~ zf!~k3nD+m}Bco1Gnpu-UogR z_B)MZ9C)2u4r>VKb<}c@w7V%0^LpHMIF zdl1IC0r)4M3$FaTfZO@g<-p(GMC?iJ|0zF|cJIddR<$>_x=HZqA4-3!(C!_;H^F@r z#{vHkxP1S(f_xr#%Lmu;Hyw{<(xaF`Z2i{LO%jYoU4b{(D1^gPT&g9~s z2>qUj|Bptyw<(VJo{mHMR-qsJfxMU6br%7D<2D%w-5>u2d>qa}DE)S~37;0^BNVR# zZl7OU1pHCxLzT}hZWlhQ&`*`arGzUDUdjCVE9hIUmi`yv$FKZU_*AMN0el?rZ@_=o z{p$kY*B>o>c7k5L9r)=t$v9{qYVHvJpIG^_dBE-aZ_fjM;oibW_mQ!83ZFTMOX$4( z6Zlzg3%&YH``#t=7bDK8di&SF?;S4mH{gA1eAtqxJ;MJ5#9`E*?IT?00$ntJ z{txtTz^+jFc@g-AuS$PZPhNhn@PF$D!KZ=Qh@T6dg}tP5)eF24`;^A{&jxPC8&?2- z>UQD32ly{qD*R8u{mI&&CxO3W#W5EALg;rwoCXb6 z2Y*@npZcZnvCjiO3jF$eWnHMAEV^Il?fl4hfKS8v()j9)!0o*4GT?2vU+7|t&)dM? z#y+Kb^=rS9b|3$SjHmjE7XTmrP8i?h0io~3xkw%7QNSO3U*1c{?Hb_wo*jPQt$r6Fi+xP5U1pF+-NmQ=(`i=0}0`(y}zmtLA2Rl>s|5CzT^7C;H zeEY|R|5W6gbbhA-zceP}FcI^Z1#a(m-veF(`%U?j{#N+E4*yQ~_alIBg8E*~_x%R= zT_Z$()E@gA@JFmVifx||{&rq|ci^`kAbd3LcQf!+h&$;xzYhHFSA@O}?|bHx!oMH+ z3)LIf0JrO@mI8lch44{1EP6`vWfv|LyLT7xpGr9IgZ6oZ1Hfl*A$-)X zi~mmeti<@M47>#VW!Oa{(e7DK3;j*jd6^G@Px!g?U*~bp-wVBcFZ8p(?fb;WJtOpX z+~YUEmu5w-Qs~dY&kFr6uyb^ryMb?J>EWw@k3ybW^~Q|ngikg0JJowDfPap7zRK0U ze-Qd5kIMU|(Vv@vkANMh>+2QZ_B{ii0dII!-b?+yanB3?TIhe(+cm&5R^D*KKMMWN zU_a};_YKh-Cqzs_PLK5;F};WJsQjw0PpUV{%b$41-|$|!ByUV z3H(^ZLv(x&dQsZl7j>~?H2t>=(oEryk7nad|8XolR0hvIq)T+FS%B5 zmCqK!UE^~a=>Lv;Ep$Cjds+DOpD%pIfd2!)?RQ&mO#7_#bwaw5xo&fWHTOcr@naw}flo0GU5; zg8oXxXEbg<|8K(oSlr*D_Qnd}!#|RCH6C)w8$xg2KfKeMg5MASLdP>sxVe7=`Dk5t z?VulbR(O1V3jEzoq+MM{o37yZ8a}KyA^9wQx2*{0eQK&z57Pm>2yuJ$E58rizGr6i z--XY9W29YOkKYAupHu!9@DC7|(|(q|C47!W9983f3E<-qkGd2ua1Zc{aX;!L;5+_9 z`0S26at-hv!d>%w0qE^>AO8e?{omxh)L%Q~ZQ);m^I}?Wa5V7tAYV{~ z{>=HO_|XlPAAK6(JTGG*S2~{Cy(9RFzlP_x5BN;PZFIl547h!-(c8e^dM!L(SG_Cz z?eh-*240Lf{Al$5C+`XUR{Ex^0sk0`$Bzl2W>&WWpBoeJEpD|iX`3y2eHULdhj_}q)S3zh$V;GZEM zr}52cW-y1Lm{UunSQSulo5fgtMI3 z->E6vQ1FFsi9Dzs{(Zt(FU`3{^wM1LzZdko!+ulyXF1{A|1nnozq-+e&N}l03FrPS zs+953ed=l8_Bq5|HWvC?_-oqF@xVtNA$*F^&o1B-VZW(7JP!P(zsdW)1Nskv+vo50 z{))8wD9$73xw)HwkHa|{wGW>FZlC+B*hKi)-x)a^_$hd=)6t*1fKS6cz-7Q61#ZWG zcH30=Pe47A%Hfs3Yu}aeQMny4T_cTdRbM>^`~$r2EX>#Ez_&!4MEg0H3b$DP@3QXi zT?KqY_@M`Z&xmb=er1Kcm+q(Sz~4AT`g0NJe*)b0U!DQJC-OL>KtFO@UhmO=4$Fa` zNVr+Qh})0Gqb~w)-%9%PGVp%`A7SMeuKcR-*&KGD_F@0+1h@U-6M)<2L^j!8=*w=D zc9qYyz~@8$b-fSYLFli8y`ge`7;yW3{xtBSqh$PbyKZEzub$SJGyFO&c zU4(x5pJkkN+};PiHT)FqXC)O3=pGT2u5QBlz5elE;iK!~L*Qpv=UB&6At=*NSt#S2 zmB)r%2Yed*Ztc(ZUlaOO7YqGEX#8s6Pa{sNa`GVI`tQMh?n(z(xZUkwSB%7uj{vvx zCd+}__Z0PfUHEK_eN+3n1h`#qa3Am=VqNRJya?RBzv4f@?e9rlvb(fvpC^47_z!z! ze7f*n`|Tn0^RAHrR=;U6@GmwJdqd~z3*fgPp09eZcck#Kzeo8e;LklI{8fLJenaT( zd{!IqeXVm1+wUp#cHaLo;2WaeL+j8E-AnAEQxP{%Ke~@_p5I$gH>h#c>wv#tovYn* zZ=pZ`>(YOfnTvqmh`Q*}7|#i#g#JFPUmc&n0skW$J{^ZcM+^NfdkKHlGfx2@wvFKX zfd4zdx2_Ug>&oWsBYY|lN7DY>4tzW0&Gmg>0sfTbe;qnT_*CH>jrM;5aNGag{hLC+ zE7qyXZ4>ZftZTJ5?gBpN_tJl@d)#zi;j{Nqf@@ymTfi%}5d2E$&%Y3^bAh2Te?A8N zy~yk7cpkl<@Xx~U(DnER@ZBF4{+dTSV}GIF1@@%+Bi9hlcJDCD?!6E6_Iqt}fbbcP za~wK8w*%h<`8!=-?*l&u@j9iSRwR6uBR{Kl-TlDF{4qS9dmbqCXMkSc_xr&AK33?J z{~^UfKOO#s+S|7Qx9^{M3Ala!WpqsV+>CtgXiU!cfNu`FItzTC5}~*AQ@;ale?R(& zQlbAL>g}h2&tl-`!oJdWH!c%;`~JZFfq!tfjKllj^Aq5Ink~5Mjb*^wnni!^2l`il zzkqmxj`Qy2(ysko#c9Cp?|pOuzr@Phz6$)aHtElWXm>(|@c$fj*E)}91HTRRu4-40 z87uUUqfSrz`7-eCokh><-aTQQ(65>)@2mWO1pEvu9 zB3%C+uVnu0I39eU57n+X6S!U1bPI61{(J@Smwqkdrg5#U4if$wAkLuUvkdqT`h;HJ z_rJj3`9@eCjz3uV*!KBDz*iN^xT*ZSM!4&JhaVz*uCnz1Nx<#zbL}}n=yyWAPWyQS z@G}pVeyaZ5?NFh=7;-)ugWU++u9vtP_+qP0>}}E@A;XuyLdxs;8Wnc zT_pGj;ESt--oB6GuY|kC=YOEL?^`~8;)e9Syj_M}j&s>6Lnjf=`@8)eicKd8elG4O z*S!2P;LnvwKXqO7R|~y;uV!&v@V>`|{#rDA8F0I9ZCZ`c?+ZEnDd_uw+xHya2;4qz zyY*z@GXeI)W#H2Td<6UvmFH`LKX08we+u|XIJc|uqKYZPzY6(8-H(n2ey?S3Ka>L> zl@LDmx!sF^k3xQ5$GLr~&~I8TdPD0%H<*U^#l4F~c;AzO+vk^G0^W&rq4V11OCYlGH!jqw{8Ia-=&|UfbR#q9rLJq<0jztckTB* zT=?|C9#(zwDDYL+$++qF0#c1aZ{L@45%8ywr#lAySql6-oafbf$utQcJ8$(n;P!W{ zRsi2^w7jpr*Fnv~rvmX_9k=6v+xqrR;C7wBt}}$sf3bd54!;L{-i|W<+V1awPePnf z>4(h}KKGv}<5mGXwj22Wups{4eARs6qwW42_$R2RQhcXb!e=q+ zX_f!e!1wxHc-+2vB>IVcME!+pfZOL^eh=Kv`;VM0eC|S>s_OOyz*}~c_liRvE&*(7DP_lkc6{7~5EI=?fH5kC8(UPagG z+rTIOL;9nB+!jfp|25=I=j9&Yjjs#6?hE@JEA-D|zLft=;PyGn%Yh$;x-1>fty03r zzGtbFaP0$z-u#&k`gZs!+U_5L+wr$uT7U?=G^=tkFe9Ucv>v)c96+ZU8 z3d?}+b*s?pdmY*)^v?j-ab5~MfjUy<|2*)$5&zfq7*C`BTM2(%@5d1C8lQg9-;Z^@ z4F+$6cH#3%k;v^R;3I&Kfm@9ndS#h~@fltJ~rg@5A0nZ{ouJ3j3 zJmF*eSzB~SeC9#a4XS@Vj&R;LBXwoKAHcq*>u~|_taZQBMZh<-{GIms!rwmE_91Zl z-1LG4LVxB4qOa7x-LzBi`>goeHCg(vamAN_KZW?e@?X#=d^WsV630I$AU`l)(#=Tn5<{yy(G;P;`PMBD9E`d`X8s9$p(@Cz3Ru5r{)fu90< zK=u6b-;%iHS=K$nmlMwKYoEtF@4fu`{|TRmVGro|pA7u@dqo~po-YS}Ao4^? z|1|LF_zvuGXm|LTZn@oqaGsYxSoJN(0Jp!tyybUgSO@L?4)Zf&4{54auYpLve( ze-CvOR32vj=?8v3^n;G`LxgiY|3T~it~WtH>p^K(bzSxPexk~A+quH$krEk)deComp5Uh<|EO|!CGbT!=cxF*z`u+9n!eY(^M#N79rwFyzd|%YV9EARV4E*-5 z2p?_tpzjI)#uo)w`ELMjpQk<*c!i~Bj<`hl*!$qK;FGQTfjfcUc&5Csp8KABnb7~%(vueee-PuQ{rLxQ`#!F= z%Z1OM{wMPu$M|0eyaImN$-u{5A@tWwkpBD<_;bMjY1wrKfeS0bu*;h$@p=j9}9mwPTK_hsm)|Ob-mvX+&(YXdW-O}{fK`6 ze+T}B>g`K^0($6Am51$bWjy*%xxvY*s*(Pm4U#l)`+M160Dl7YEgB!V<2Grx5BI#O zy-{(y;P&@hZvbw`|DOQ3u+ex8VawgG?pCo-No4(|Xzs9Wf@Kf~`3 zK6V|^&w<-@eSZV~9?nfHLA#B23LpD^&P#yX--rDb@JIKQeyV*^e3$SUjr$F>pGygM z$=g$)-wtsGT^9{M6F&C$e;);Y(qE-r9nXrph2E|w{1Na?P}ih!iIu>g`CP_xG{)i3 zd%))c!TW(<4E*aK2(In^3iyv&aUeC)cZ&3+-cT}OQm;ja0*5%hK)TJ3$pXRjxv|C^)T zZGI{Ew#ZYcU2!1rub{q8<>VgVyB{cg^!sb4-!FU)gTJ8m%r3tY{9)uHG;T1Ta996- z2Kv#^!?V%PKLg+CdTI9;z<>0B@VD#M%6={Qqo^m;eIWz<_qgv!*YD;J3jH}a2OR_d zDZuUf@qP;2z6WpPhurTqf^fD^7C~>QeBKBAZukY7e>wSKp`Wv2SVZUes{V#yu+9iC{4zGVq_fb;PyH0(q+PD>poe(s&DuBjo@}X^EKe};TO+AKlgoH=)Z})r^Yv~0p5T- zwbqSn_*r%!8x8t9G2R`OLdEYqf^Uf#S^~M(v&hu`6FX>I-4X+BHoxrE+NumFw zO~zpc#`C+tMgPPXlg$_v)bE3H?aKTXenr0QkdKN29R$7$&7#(xm{mtp760KSB9*ZAKBdbLGk?Rht! zD+%ZEc^r0*wzcse1-Ikv-N0|&OXNr66(0caL;areIratN^EK2rCh%UD0^bC7pxOz0 zz9{tl8wr2qa~AM}@x6v`fX}tSi*Sxl-}jI|37=0e&boiS2K*tbKIF=mgx>!C&hx;B z?;!nA{=;7u`u7eO`PB6|9k`v}ycPH-(EnOrec+#k&j|R-N8-I&fUlS)ay}aPxxkm~ zFa6QFtixUrK4&4{p?>92z@N14Dc$l_p}!t_N%w`>!0qphd2sg7v=v6@bOFKeZPnCId-}5 zAMsVeNo>qNe*r!cc?Z>>$NtSd4yO>#>)MWcKMdT?xKK+P~?SsL7 z0l2NNI^PufZOTP%F9rRUD+E9DN?9+Ouc-sR5$vTgpkD}l80>$2-%b85e3l^}r2U)& ze8qvnU*q|m!0mkc3gGs4+rI$5A?i7m|CG0+-R+JFulFqQYWS^ck9`c>J~!I%58>1P zXPIB6e+zgU?6L6}hskdXz5U(Ep8&VN!~T21UF+fl&`-d9GT#ON6aFduw}C&U&n^eP zG0rcmp4t8#p;I_T@)s;ejpOptZfp9*5eJsvjd;1;eCt2e&?L*7OXTXOq z5V_U-Maf4(f4+53>>q*mV_(<_<1qSTp@05vd0*Y{t_FS>>Izg(J^F9=^D5vCPf5EMgZ`9Hh0ix2w>mE?fFA-qus`TG{kPCBeN*_TA2E|~)yW_= zf3k#gJX zeyV(Cf!lSt_W(b4Gtsx&?)$(?VVCOooc&+7oqRdrykG2(Jh<|?2e^G+?2o|h@4Woq zXTs;!GLbj+`>q9U-)H_y;BO#*eI&;DoBtC&D^MSz_Dmaa+wS@?@beFlaZ`O&`ML0U zeSzSkF<-L@SDh1__r;*!2BEO*)US0&gEB{Zv2V>%%rO^JwQ2OMu&c->(TDiM|E@ zyaamt-i(bm5dOzQu5`cd27Wl|h}1uN4)|x-@3jBtZzz0fVb7=@*kU8WXCq#r^LQ$7 zyYA~v;Flx*sqy4#RM6|1-{T2qIp6YCkx!MYdvehK4)kwA-)eulz9M|~K3c~ABbm-& zTW=!x%9Diua~Ra4fGX8S_|?OO{v-H_s%MHe6Wl&;^&Q~1oFx1;Ui9_Nh2Fl`?rPxn{y1j~q5t2$!bjin z5#aVdxc`rTz4s9CgK-W{z~}8Q$-ao_~mnj{}y=YD_<4*O>obEj>ETruRvYIXwYxHozNeJc=7?j)4*-J z>kY-RkE>lVc6;Gte?Rwh;4}Xq{a*t9D}mpEb3Ga-IeQ1;WBW&&?iANY57l6EhIKG$*n0(dR*Zbf*npY1I4m*BgZss~2z zBKYIKlyR5<`eCho*-Um}dwWsqu(otxdTvK1o9;_yyOOP)J>BWduw=5WCpovXrzO>y zY|HlaWs<3di-xuKboF+ov+1^?ipsKLH&L>^qq`%S>g!7_PNuuFeT#>+_oceh$+m@E zU5n|Fz<(u)G8-aI&Th)q#wvR|(yi&^J2L5HYfpD3+qbYaJ1jYSc5Q52GC4OpuP>cy zOQu@09sTKKZ-2a`IErTb=m9r9{ZLm)PjoL#wk}#^Xwr*X=cT&mrjw~|V%*jiZ}jR8`)KUv(rXe}(J{BXr!Ou4L8IK!!*gQ|0kdvPx2G0%W|PEWL9(}} zv!iu!oXN&@clONdN_BU~N|KXn>nB##CX;o^SY>-(Pgin&rl&g})!1y0gQlV_olSLg zR+9Xsk{u*@wG|7hI(z4(!mM0mlT%$?LRK<2T|2gE#-vH{rY7?o1F^AllfaVczP_Hm z?jG;AikhlKZM@q1?^wm$q(BkUSo!q$^s3t0`bnVh9x5rHo3wt5K3&>S)mSw>nW&pt zRh#e|EGeCv4E+*)vY1{c(q!@6qz^})scdYvpNLh?O?qhLfmm6ht~uUVM-v%uY^-ne z->qye^*Q)c^x5J`P4P+gbKF4>jyzM@9FJR1a0fj!@<6OSURRy0uSqt=51$dQn-uqZ zNTYB47J0g)WO6*&P&;}0XVYB)lZ8EPASP-4w?wJSZqdJ(~O3O`o`wK5-EwzO$PAj zQ>FDYnt7&ZNz^wU=?x1@dgzzvljEpolWG$*JBf(=mW(qUw|vOH_n(8=~JoSCnsT)Zv|R6IgrPZ3jt|SLnT&*W|{khA9z_)_dE8QNHEDJ~onI%#2DVt>c_jQI4UvZk$mU z>7(`5K1r09%8VI7CTxz^HPtspSo+fArp(QmUaYFNFo2r!L%&3xEGeen&3dDk@_OSjD5b5yMG)Z= z8|$^B+&m^Fw24Q4jdI|bG;`xrAu`JL?-4E~JQ9XV=Zs{cE>Snx>kYK1izW{@Sxb%$ zLv*s?X3<2s@fZatwTIRgB%_s!F3Oenp#XKFDH(ZX*@v7&QGP5DOq!^#bM0v&5fOqY zAAMWqGrg*=YI3~MAz=R7y6B=@xpy+qE-`_;MhK#Oc+`YUry<9vIf?S|lLs84BC{Yr zTSQTQtj&X@+Dl7VM4RU%jPhmO6C`(ui|8IVRg@!ZbD?#c*s!S_BvD@e?AA1rm1&s( zq1g=(MEUSuEe-NKpkEVb)YQa%^B8+|4zegu|2@U%ubWX@+t3`~C%cyL3z0;4mHPdw zZ)i?TXWcugetN@jk}p?Y z2mO|8dZVY%s}t@x|Ldn!@a6es7X`pCLueSx%3Ad@D90UEE-q3s`MR7zHe14(+g=nJO{Ql|Ns^RSO3--^ZigNV( z$BVS8G5`35X`Y#yD$aTTDW` zR*)ph%h$d-o5@5qiE}tC2G1IOQx)J7M)~?0BT+{?bkmfohUjzz^-+W@!ZYU2NTMmU z$8p5ZTRZYweJ zFI0)dvG()>ywLEkQ4apQvebyK_IZdG3Lf6?5iTXZ^flKv)F&w*5mop>Ikc&w9Q~1s z8(m2g*Gyr9`Z}+3p^>tPqWpaQ5(o(Tyn^~AKoI5Qk5?7BjFaoIZA8>eaO7N+QO^FJ z&oQcoS_)HB7};JjL8*??MYxvw{k2vN$2X1mSuKvK(w8hr@g!u+|G0vMaKuAjdJ(*SC4yjeZ0vL zIVlV7v^j_){7d|G&%!{_?C5?Q)Q}cYl%Kzc*VVIa%cdv=vnLVTnt**C^qU-n5x!-C ze)>$Ar%q=b`2f=sP1CEICr$BYwLH}Kfgg;tTk6kl4P^saAjwv%Nz952Q)qVGv=Q#H z;Ak}`dAsv-MaXLS8;bck!XvO3@S1d+62ZN|riya(dnI`qicdRIo1s^75_+#V z@ks5tEiqy-5BNZ|9ku{mk2N$VXr?LLX165vTmg?n+tSgmt*@ea<#r`w5y`O!Mn4yA zguAhC$&)1|Ix|7FQhu1oAAgY=CsC9i$MpiFA}Ex*_t{C@(M1#G#ycZZ(oW&Fv1C7V zkVJWD&%^@cj`1i3q!*cK!^{Mne3~dX_Q;sBc?y>%Bpd4MDOf=ZBbd%XgenJFgr|{S zCMI21Yf9865pPmSv`4}d;N{}|74}rLMYbt&J?nloc=`oB6lt%NH9+Lii3y63xLZRetbj+N zZSn3Jc@U#nYg~4F)?}Y8?A5T=Sai!AQGdjj94kONOm?k|#@!5aWu- zk^Mll9kwD}kCE1%Tu;7;-H_Om13wXM$*BuO2{av%px92NtsJ_*@l2#O6IF`zk~U*R zJfy6s@b#GE!Dzdo9ZKho+ci}uxtg{1ssWyhv}*jj$lC_$Ts#{FmR3I6D0kD zu^YJ`i?r#spK5AnQ1oq56-7NGYAnZUh&~c&tIRozGwSkKYq@rJ*F(|voYpT_tW!;Y z4)ZXVoI0P1w&;9AeO9(FTWE5~sq3LZwkJAcknIH@inLeC`CM;F@!_53#wtq1xNFT( z-8K+?!L3lTg2EgTfs~wqqm>YSq?NE1<9C_SK=np(jVe|(PL3oDZRyDSRHQ`{jSBTs zCpm{>X;~-Sn)8WhOU``&_R60HHbUf)Hr#q%CD%PW18BkELy`8vdzk4YI@m-7 zd@hw??P0keiL@1C8;h&zOz4#pIi4|EBKB11$LRCyp;RRr8qD+Ia6c+@!oNm17&)XW z->T_}Nj@i>aZA#{!oYbo$YFl!XbUEh@QD&tj!n17_L zoVia}T7^CrZPnBz<>+pnlw&#a(*-{nZQ0})b3C6br&o?_V_}a)+ho0xYphItOmNfp zJ9DreyP!7RP3QEP^X$4NOg9cknW>_tVm_(zq51`M1P9l?ktH! zjBZAtYMW-xH-)Eh%^R#}rOP9-=|ocrr8UZu{DSmy@u@Va4OFqzTi;wv?>cY?aOprr zFHcw>72hRet2+iX3ga@VMM=Yo27)f)=uUMK%i?6oI3Cd?|Jp{^D74bW4J|3YcR^Zh zs-UjN<1N(lLG*b5rfc{rF?o$NtEYGui(}(7ew9kP86(}B?VyVw2GQ5GJif8Y(D<&= zu)2AzAEUY2vgs|C7%i6!FPNN)k(bfn*U_5yEHkySDwdqqI@lGw<}DXGCbS5s$as(n zX3e{2X*lY|*e{_MG(DsP2K)9>E4>wjxM^)sFyCbDR7fPC)TdM zEKbvvLp?3?Y0E8a>suGSs^m_YE1U+^r=gjyl1yu=JK5Pm`(Uaw-Y~7TtBxc$R-Elw zknT=q7x$(Ivx5vxpJJv@bQ2Zb=9F_tijtM3!{~p?_;ZPw3@v1VC6dq!Gh@Escxo49--U6?vJ3uZ{#jg_)H*Ghrw{H|OPxeRng zEd`+0j=?>yJH05IY+0O5Q_L>e$JfWw#vZHSds7kLBqt`5O>_*#T^Tata#EQQj6o>t zA#1uaLle|OcM5msHLUGv8M5}ra{J`L=52lLnf2-8;u34gwNIAOHM*4l$Wp-E6Bha} z3iR^z!)67rqg{ChNhT(c5$+w z))W$;^hEP?IX+Jfqnq_LHC%#fPFW{CHmFOWe|N?l2lCZ;$&A3-7%diNz}F! z^XjflPNW;F&85^y6QH0x3BjcXRv_LSOHvx4sWeGh24Yu76eY=-CaIF7L`gc);7>$h zalT?l?!;uKI0G=LB;L=>Py&m4BH0^hi1Hg`h6GT)MmZKsPUrQ(_gGV`KzgW2pZq;b z`q`YEUE)A+IhKEzcPn*=;gBF6IGzerll7Se1^L)G_MycNz*u{ zTGKSjtqT%US)vdf2-wTldG~r}`%)cQN?&sBl4ifLC7JC@ zr<2{ZYdW%-#cgRknx<=V%99Ng=W1Qc^4nij-G6 z)urny9Y5%VQzkBQL?5+OFa_#faw{Ij+Zw@x(%dR8HE0`PkU3g zw=>a7uNtF!-02#7dHYuGD9Kw>3so`Ef}~|hx}YLS(ZqZsHZ+Sf9-Q#r&H zkM}oH>t3eObUik1VYjyrkcwixlL*{UAEOK4>27uoUaN*lG)&7c$kF6$iDT)+X|5C0 z9~Kjn8z7T`{_;>IoA_RBGfw_p`9sr_n6oEk)DxN->WLXA4$8?Ssbcc7(NK3(EKotE z1kD|7{qfRlM;oSeTu9iB7L1WDrX6!pN7uqGdPAA~RHBQ;QX0wh*0SQr9Cp}by18!B ztXav@qB1aCo0{9-7FaJ=s~!)Gcm-YN-${4#lU#JAyIK~u`^$GednFa5%4ttC??H)o z+P1>NWcII)b`l`Tza~?O1{z5k5gKWFUgp~DRE@Mg@Xlq)nuXo1#w6kWs#?a0))!S) zu=TCFfR=89S2dAKBB`yYIJ$)(XL7Ne*UnVhNz0R7N^(+?Q%hE6ZANEPb&`xBnofE( z`kiz_P}|I+_{G$wI?D93HlWR(?T_vr{+xj^!5{(2lA@BLavlxlFxHbPZvkoukA%i5 zaH%xaE{X2;9_q5#g5?-j73EwbC501(?y=OZ=}A(ytn|r{h4^gEP6j z&b$qZ-m;h^=eULRMGZ2Mnlb^msj#itWe<3B(kq}hd^dZX-6nGdWu(nxI%|TXPjB* zYy(WA&5GCRAX|6HL0*9!nkGW_Y6;ycAF&)o340qE7hd=UXnC{^ui<14eFWDNRiOm@P6pjbZ{;#8GJ{tqE}6@_ zqT^&PP`w`wT3&Nuif=BkGoNdY!-cLvJHVc}94oU7D^oUew&cuy+>;?U$Jl1XhgPT> zAyf~TP0#J=TbyWUB|Vajm3zOy10rK5Hr4}`oE4@Qn4nmc7wDiUN6a{EP1%wPifD4p zVXC#23Ss>=v#Ggp`aYCAGx$J8sYB_~f~9@4VOmpFl8m>eiE4$03^(H@lD#l!Ex!gr zF{vccNbzII8Nk=A09|~(t^|hrbY--rrGOJsVaXVT&Lqg;Ak|nB!^U5x}DWjFpTImk~c^ZuMO@qCCS>rhto>P z0#_fDj71K$wDv5d3g9*g-wp66`-|0`J#*RFNOX6n`I~p_u;frsG$Hn+mPB?CLTG(Y z*ZBPqN!U0NFw~PVN6#T-+eRGG^489D%8N#>=^L03C&za=;>A8{BnU?D$vv^>aBXC) z*+eDNqeb34$E)SpMeRv*?;a#Q$pz`fR50gwTY7|B&u!j0o(V1Z_&6^@NQy@zjv<#( zPfz$`8eV)u76*ug0b~O~@jkl-6ck8uSiET}hXAHwL&-Jro(zQho9h_En%HK>XZPZQ z5|8EWrBF|Es_$t!W{j-AphF*yT;-aUT(9Xgt$DGsF&z$EX&h~k1L@d_CdCqsZEYN5 zrp;DD=k%VgtP28!^eb5-^sQ0}gODj}!lzIw{dDaMjc$x0P-F*@UY$!Nr9@$l9Ay(N zoYj$p&)D{!zT;{8BZb5bH?lcZ(U&&iGs>RPCsOISQi6B$GE;#{tBELRL+E1jO0;!w zdAVY?gPj4VpwaM$L$-X!)g(x`h9wYAPxPDUdpw8TF=Po>R&ZQhK9GvR@v20=Ce>7siK6Q224rW znxG!Z06pp%&=g%={X`-8VA-CidlZx^%O@XnAjxG5lL;bmXOZVncsCXg?2v_NN0-_d z$OkiFKnn0Qa>$mt5iX^&;v54{TM`*02}&ul zq7H@-jLsze%KH)I_B5O0e5qudDAl7&D=zKLv>=f2iy7kb2+Xezv z8_=qjd@5zvq}ah56bbgr$YW>@sQ!k|bRTQ#AA1%jIFD}O;7c8&v_YBOA%s zhQqg>sM3}~&R*1iAdBCj3-U{Iw1dw1jMEgcKO-uIV&k+O(;Rc%f(%KlE43hvh-6?) z@<$`7LVyaAsn5ZRNXipP^n|6RgN1(jYOZ%SZTq`Ck6ZlSHaFdeg2))&bSr4DEdH@gRQ&9i|Mt7C3* z>UOoFnk79H3+-u_GIi|h@eb-&hDVI_l8zBdG|K`e@<0w%*nkSAy*$^_mnoNK)5d-M z<}eO8GSt}_iVU$j4ac~=XflP2B+1>}s{%^bQLxER&p1(KDVs(Nf)=|K681a-Ar4ONS5W${k!ffI?qiG0`IOz2-GeOPGka zR!fUoHdShkCYlx}XOTBh*U}?@y~X!|?I9Wx<17|FHE-0zxMVe-z#t1`(BU||#7%mmn(9PybT_ zi*&h_|IaNLzW?vPs%tm#~A#tGu@WTrex&S16><% zJ5i9Q&2ff^m(5;p^hyLe?HP

KC>mZWF_sowM$DIw+1+Lx;X5D4(tY;UGMedhQ_` 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 H^z;88J0#7R diff --git a/third_party/prebuild/x86_64/libmmpa.a b/third_party/prebuild/x86_64/libmmpa.a index bec195ad066b02a4966ccf47860634e9c7200bcc..13ca68db5f5ff60d6d735e48b9dd82cfc60e4f72 100755 GIT binary patch delta 14566 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%0A@Esh^w|ze|oz1i_ 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 Ook?=X*FxTz&i@bbUq`+G From 543fd0a0e82d752e4bc1a4d334c56ce66e04db00 Mon Sep 17 00:00:00 2001 From: shenwei41 Date: Fri, 5 Feb 2021 18:24:26 +0800 Subject: [PATCH 12/59] update metadef --- metadef | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metadef b/metadef index 8ab60be2..c86433f1 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit 8ab60be2870b80b1ec952bb21c7f05ae2a624984 +Subproject commit c86433f19f6df542adaa5d444ea9bc52d96e6371 From aa4045b31d1df51b208561f927c381a9f298d90e Mon Sep 17 00:00:00 2001 From: changzherui Date: Mon, 8 Feb 2021 12:37:14 +0800 Subject: [PATCH 13/59] modify pkg lib --- cmake/external_libs/json.cmake | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake/external_libs/json.cmake b/cmake/external_libs/json.cmake index 6e476d0d..04659ebc 100755 --- a/cmake/external_libs/json.cmake +++ b/cmake/external_libs/json.cmake @@ -5,10 +5,10 @@ endif() include(ExternalProject) set(JSON_SRC_DIR ${CMAKE_BINARY_DIR}/opensrc/json/include) -if (ENABLE_GITEE) - set(REQ_URL "https://gitee.com/mirrors/JSON-for-Modern-CPP/repository/archive/v3.6.1.zip") - set(MD5 "5bda78ce308e6cfcf614dcf1d5ff27a7") - set(JSON_INCLUDE_DIR "${JSON_SRC_DIR}/include") +if (GE_PB_PKG) + set(REQ_URL "${GE_PB_PKG}/libs/ge_nlohmann_json/include.zip") + set(MD5 "0dc903888211db3a0f170304cd9f3a89") + set(JSON_INCLUDE_DIR ${JSON_SRC_DIR}) else() set(REQ_URL "https://github.com/nlohmann/json/releases/download/v3.6.1/include.zip") set(MD5 "0dc903888211db3a0f170304cd9f3a89") From cc456d5803a736c41903cc9ae16b52a94f03521e Mon Sep 17 00:00:00 2001 From: shenwei41 Date: Mon, 22 Feb 2021 20:51:01 +0800 Subject: [PATCH 14/59] update header files 0222 --- inc/external/acl/acl.h | 8 +- inc/external/acl/acl_base.h | 85 ++-- inc/external/acl/acl_mdl.h | 356 +++++++++-------- inc/external/acl/acl_op.h | 119 ++++-- inc/external/acl/acl_op_compiler.h | 47 ++- inc/external/acl/acl_prof.h | 75 +++- inc/external/acl/acl_rt.h | 143 ++++--- inc/external/acl/acl_tdt.h | 31 +- inc/external/acl/error_codes/rt_error_codes.h | 136 +++---- inc/external/acl/ops/acl_cblas.h | 179 +++++++-- inc/external/acl/ops/acl_dvpp.h | 369 +++++++++++------- inc/external/acl/ops/acl_fv.h | 14 +- .../inc/ops/elewise_calculation_ops.h | 97 +++-- third_party/fwkacllib/inc/ops/linalg_ops.h | 27 +- .../inc/ops/matrix_calculation_ops.h | 23 ++ .../fwkacllib/inc/ops/nn_calculation_ops.h | 21 +- third_party/fwkacllib/inc/ops/selection_ops.h | 2 + third_party/fwkacllib/inc/ops/spectral_ops.h | 10 +- .../fwkacllib/inc/ops/transformation_ops.h | 29 ++ third_party/fwkacllib/inc/runtime/kernel.h | 8 +- third_party/fwkacllib/inc/runtime/mem.h | 11 + .../inc/toolchain/tuning_tool/tune_api.h | 36 +- 22 files changed, 1134 insertions(+), 692 deletions(-) diff --git a/inc/external/acl/acl.h b/inc/external/acl/acl.h index ef5b4772..eae87835 100644 --- a/inc/external/acl/acl.h +++ b/inc/external/acl/acl.h @@ -26,9 +26,9 @@ extern "C" { #endif // Current version is 1.0.0 -#define ACL_MAJOR_VERSION 1 -#define ACL_MINOR_VERSION 0 -#define ACL_PATCH_VERSION 0 +#define ACL_MAJOR_VERSION 1 +#define ACL_MINOR_VERSION 0 +#define ACL_PATCH_VERSION 0 /** * @ingroup AscendCL @@ -70,4 +70,4 @@ ACL_FUNC_VISIBILITY aclError aclrtGetVersion(int32_t *majorVersion, int32_t *min } #endif -#endif // INC_EXTERNAL_ACL_ACL_H_ +#endif // INC_EXTERNAL_ACL_ACL_H_ diff --git a/inc/external/acl/acl_base.h b/inc/external/acl/acl_base.h index 839bd597..165b0812 100644 --- a/inc/external/acl/acl_base.h +++ b/inc/external/acl/acl_base.h @@ -112,6 +112,7 @@ static const int ACL_ERROR_PROF_REPEAT_SUBSCRIBE = 148046; static const int ACL_ERROR_PROF_API_CONFLICT = 148047; static const int ACL_ERROR_INVALID_MAX_OPQUEUE_NUM_CONFIG = 148048; static const int ACL_ERROR_INVALID_OPP_PATH = 148049; +static const int ACL_ERROR_OP_UNSUPPORTED_DYNAMIC = 148050; static const int ACL_ERROR_BAD_ALLOC = 200000; static const int ACL_ERROR_API_NOT_SUPPORT = 200001; @@ -135,42 +136,42 @@ static const int ACL_ERROR_PROFILING_FAILURE = 500005; #define ACL_UNKNOWN_RANK 0xFFFFFFFFFFFFFFFE typedef enum { - ACL_DT_UNDEFINED = -1, - ACL_FLOAT = 0, - ACL_FLOAT16 = 1, - ACL_INT8 = 2, - ACL_INT32 = 3, - ACL_UINT8 = 4, - ACL_INT16 = 6, - ACL_UINT16 = 7, - ACL_UINT32 = 8, - ACL_INT64 = 9, - ACL_UINT64 = 10, - ACL_DOUBLE = 11, - ACL_BOOL = 12, - ACL_STRING = 13, + ACL_DT_UNDEFINED = -1, + ACL_FLOAT = 0, + ACL_FLOAT16 = 1, + ACL_INT8 = 2, + ACL_INT32 = 3, + ACL_UINT8 = 4, + ACL_INT16 = 6, + ACL_UINT16 = 7, + ACL_UINT32 = 8, + ACL_INT64 = 9, + ACL_UINT64 = 10, + ACL_DOUBLE = 11, + ACL_BOOL = 12, + ACL_STRING = 13, } aclDataType; typedef enum { - ACL_FORMAT_UNDEFINED = -1, - ACL_FORMAT_NCHW = 0, - ACL_FORMAT_NHWC = 1, - ACL_FORMAT_ND = 2, - ACL_FORMAT_NC1HWC0 = 3, - ACL_FORMAT_FRACTAL_Z = 4, - ACL_FORMAT_NC1HWC0_C04 = 12, - ACL_FORMAT_NDHWC = 27, - ACL_FORMAT_FRACTAL_NZ = 29, - ACL_FORMAT_NCDHW = 30, - ACL_FORMAT_NDC1HWC0 = 32, - ACL_FRACTAL_Z_3D = 33 + ACL_FORMAT_UNDEFINED = -1, + ACL_FORMAT_NCHW = 0, + ACL_FORMAT_NHWC = 1, + ACL_FORMAT_ND = 2, + ACL_FORMAT_NC1HWC0 = 3, + ACL_FORMAT_FRACTAL_Z = 4, + ACL_FORMAT_NC1HWC0_C04 = 12, + ACL_FORMAT_NDHWC = 27, + ACL_FORMAT_FRACTAL_NZ = 29, + ACL_FORMAT_NCDHW = 30, + ACL_FORMAT_NDC1HWC0 = 32, + ACL_FRACTAL_Z_3D = 33 } aclFormat; typedef enum { - ACL_DEBUG = 0, - ACL_INFO = 1, - ACL_WARNING = 2, - ACL_ERROR = 3, + ACL_DEBUG = 0, + ACL_INFO = 1, + ACL_WARNING = 2, + ACL_ERROR = 3, } aclLogLevel; /** @@ -305,7 +306,9 @@ ACL_FUNC_VISIBILITY size_t aclDataTypeSize(aclDataType dataType); * @retval aclTensorDesc pointer. * @retval nullptr if param is invalid or run out of memory */ -ACL_FUNC_VISIBILITY aclTensorDesc *aclCreateTensorDesc(aclDataType dataType, int numDims, const int64_t *dims, +ACL_FUNC_VISIBILITY aclTensorDesc *aclCreateTensorDesc(aclDataType dataType, + int numDims, + const int64_t *dims, aclFormat format); /** @@ -327,7 +330,8 @@ ACL_FUNC_VISIBILITY void aclDestroyTensorDesc(const aclTensorDesc *desc); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclSetTensorShapeRange(aclTensorDesc *desc, size_t dimsCount, +ACL_FUNC_VISIBILITY aclError aclSetTensorShapeRange(aclTensorDesc* desc, + size_t dimsCount, int64_t dimsRange[][ACL_TENSOR_SHAPE_RANGE_NUM]); /** @@ -424,7 +428,9 @@ ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimV2(const aclTensorDesc *desc, si * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimRange(const aclTensorDesc *desc, size_t index, size_t dimRangeNum, +ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimRange(const aclTensorDesc *desc, + size_t index, + size_t dimRangeNum, int64_t *dimRange); /** @@ -461,7 +467,7 @@ ACL_FUNC_VISIBILITY const char *aclGetTensorDescName(aclTensorDesc *desc); * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclTransTensorDescFormat(const aclTensorDesc *srcDesc, aclFormat dstFormat, - aclTensorDesc **dstDesc); + aclTensorDesc **dstDesc); /** * @ingroup AscendCL @@ -549,7 +555,7 @@ ACL_FUNC_VISIBILITY aclError aclSetTensorOriginShape(aclTensorDesc *desc, int nu * * @retval null for failed. * @retval OtherValues success. - */ +*/ ACL_FUNC_VISIBILITY aclTensorDesc *aclGetTensorDescByIndex(aclTensorDesc *desc, size_t index); /** @@ -560,7 +566,7 @@ ACL_FUNC_VISIBILITY aclTensorDesc *aclGetTensorDescByIndex(aclTensorDesc *desc, * * @retval null for failed * @retval OtherValues success - */ +*/ ACL_FUNC_VISIBILITY void *aclGetTensorDescAddress(const aclTensorDesc *desc); /** @@ -600,12 +606,13 @@ ACL_FUNC_VISIBILITY aclError aclSetTensorConst(aclTensorDesc *desc, void *dataBu * @param ... [IN] the value of current log */ ACL_FUNC_VISIBILITY void aclAppLog(aclLogLevel logLevel, const char *func, const char *file, uint32_t line, - const char *fmt, ...); + const char *fmt, ...); -#define ACL_APP_LOG(level, fmt, ...) aclAppLog(level, __FUNCTION__, __FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define ACL_APP_LOG(level, fmt, ...) \ + aclAppLog(level, __FUNCTION__, __FILE__, __LINE__, fmt, ##__VA_ARGS__) #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_BASE_H_ +#endif // INC_EXTERNAL_ACL_ACL_BASE_H_ diff --git a/inc/external/acl/acl_mdl.h b/inc/external/acl/acl_mdl.h index 5886d857..4f3e257f 100644 --- a/inc/external/acl/acl_mdl.h +++ b/inc/external/acl/acl_mdl.h @@ -27,19 +27,19 @@ extern "C" { #endif -#define ACL_MAX_DIM_CNT 128 -#define ACL_MAX_TENSOR_NAME_LEN 128 -#define ACL_MAX_BATCH_NUM 128 -#define ACL_MAX_HW_NUM 128 -#define ACL_MAX_SHAPE_COUNT 128 -#define ACL_INVALID_NODE_INDEX 0xFFFFFFFF - -#define ACL_MDL_LOAD_FROM_FILE 1 -#define ACL_MDL_LOAD_FROM_FILE_WITH_MEM 2 -#define ACL_MDL_LOAD_FROM_MEM 3 -#define ACL_MDL_LOAD_FROM_MEM_WITH_MEM 4 -#define ACL_MDL_LOAD_FROM_FILE_WITH_Q 5 -#define ACL_MDL_LOAD_FROM_MEM_WITH_Q 6 +#define ACL_MAX_DIM_CNT 128 +#define ACL_MAX_TENSOR_NAME_LEN 128 +#define ACL_MAX_BATCH_NUM 128 +#define ACL_MAX_HW_NUM 128 +#define ACL_MAX_SHAPE_COUNT 128 +#define ACL_INVALID_NODE_INDEX 0xFFFFFFFF + +#define ACL_MDL_LOAD_FROM_FILE 1 +#define ACL_MDL_LOAD_FROM_FILE_WITH_MEM 2 +#define ACL_MDL_LOAD_FROM_MEM 3 +#define ACL_MDL_LOAD_FROM_MEM_WITH_MEM 4 +#define ACL_MDL_LOAD_FROM_FILE_WITH_Q 5 +#define ACL_MDL_LOAD_FROM_MEM_WITH_Q 6 #define ACL_DYNAMIC_TENSOR_NAME "ascend_mbatch_shape_data" #define ACL_DYNAMIC_AIPP_NAME "ascend_dynamic_aipp_data" @@ -51,123 +51,123 @@ typedef struct aclAippExtendInfo aclAippExtendInfo; typedef struct aclmdlConfigHandle aclmdlConfigHandle; typedef enum { - ACL_YUV420SP_U8 = 1, - ACL_XRGB8888_U8, - ACL_RGB888_U8, - ACL_YUV400_U8, - ACL_NC1HWC0DI_FP16, - ACL_NC1HWC0DI_S8, - ACL_ARGB8888_U8, - ACL_YUYV_U8, - ACL_YUV422SP_U8, - ACL_AYUV444_U8, - ACL_RAW10, - ACL_RAW12, - ACL_RAW16, - ACL_RAW24, - ACL_AIPP_RESERVED = 0xffff, + ACL_YUV420SP_U8 = 1, + ACL_XRGB8888_U8, + ACL_RGB888_U8, + ACL_YUV400_U8, + ACL_NC1HWC0DI_FP16, + ACL_NC1HWC0DI_S8, + ACL_ARGB8888_U8, + ACL_YUYV_U8, + ACL_YUV422SP_U8, + ACL_AYUV444_U8, + ACL_RAW10, + ACL_RAW12, + ACL_RAW16, + ACL_RAW24, + ACL_AIPP_RESERVED = 0xffff, } aclAippInputFormat; typedef enum { - ACL_MDL_PRIORITY_INT32 = 0, - ACL_MDL_LOAD_TYPE_SIZET, - ACL_MDL_PATH_PTR, /**< pointer to model load path with deep copy */ - ACL_MDL_MEM_ADDR_PTR, /**< pointer to model memory with shallow copy */ - ACL_MDL_MEM_SIZET, - ACL_MDL_WEIGHT_ADDR_PTR, /**< pointer to weight memory of model with shallow copy */ - ACL_MDL_WEIGHT_SIZET, - ACL_MDL_WORKSPACE_ADDR_PTR, /**< pointer to worksapce memory of model with shallow copy */ - ACL_MDL_WORKSPACE_SIZET, - ACL_MDL_INPUTQ_NUM_SIZET, - ACL_MDL_INPUTQ_ADDR_PTR, /**< pointer to inputQ with shallow copy */ - ACL_MDL_OUTPUTQ_NUM_SIZET, - ACL_MDL_OUTPUTQ_ADDR_PTR /**< pointer to outputQ with shallow copy */ + ACL_MDL_PRIORITY_INT32 = 0, + ACL_MDL_LOAD_TYPE_SIZET, + ACL_MDL_PATH_PTR, /**< pointer to model load path with deep copy */ + ACL_MDL_MEM_ADDR_PTR, /**< pointer to model memory with shallow copy */ + ACL_MDL_MEM_SIZET, + ACL_MDL_WEIGHT_ADDR_PTR, /**< pointer to weight memory of model with shallow copy */ + ACL_MDL_WEIGHT_SIZET, + ACL_MDL_WORKSPACE_ADDR_PTR, /**< pointer to worksapce memory of model with shallow copy */ + ACL_MDL_WORKSPACE_SIZET, + ACL_MDL_INPUTQ_NUM_SIZET, + ACL_MDL_INPUTQ_ADDR_PTR, /**< pointer to inputQ with shallow copy */ + ACL_MDL_OUTPUTQ_NUM_SIZET, + ACL_MDL_OUTPUTQ_ADDR_PTR /**< pointer to outputQ with shallow copy */ } aclmdlConfigAttr; typedef enum { - ACL_DATA_WITHOUT_AIPP = 0, - ACL_DATA_WITH_STATIC_AIPP, - ACL_DATA_WITH_DYNAMIC_AIPP, - ACL_DYNAMIC_AIPP_NODE + ACL_DATA_WITHOUT_AIPP = 0, + ACL_DATA_WITH_STATIC_AIPP, + ACL_DATA_WITH_DYNAMIC_AIPP, + ACL_DYNAMIC_AIPP_NODE } aclmdlInputAippType; typedef struct aclmdlIODims { - char name[ACL_MAX_TENSOR_NAME_LEN]; /**< tensor name */ - size_t dimCount; /**< dim array count */ - int64_t dims[ACL_MAX_DIM_CNT]; /**< dim data array */ + char name[ACL_MAX_TENSOR_NAME_LEN]; /**< tensor name */ + size_t dimCount; /**< dim array count */ + int64_t dims[ACL_MAX_DIM_CNT]; /**< dim data array */ } aclmdlIODims; typedef struct aclAippDims { - aclmdlIODims srcDims; /**< input dims before model transform */ - size_t srcSize; /**< input size before model transform */ - aclmdlIODims aippOutdims; /**< aipp output dims */ - size_t aippOutSize; /**< aipp output size */ + aclmdlIODims srcDims; /**< input dims before model transform */ + size_t srcSize; /**< input size before model transform */ + aclmdlIODims aippOutdims; /**< aipp output dims */ + size_t aippOutSize; /**< aipp output size */ } aclAippDims; typedef struct aclmdlBatch { - size_t batchCount; /**< batch array count */ - uint64_t batch[ACL_MAX_BATCH_NUM]; /**< batch data array */ + size_t batchCount; /**< batch array count */ + uint64_t batch[ACL_MAX_BATCH_NUM]; /**< batch data array */ } aclmdlBatch; typedef struct aclmdlHW { - size_t hwCount; /**< height&width array count */ - uint64_t hw[ACL_MAX_HW_NUM][2]; /**< height&width data array */ + size_t hwCount; /**< height&width array count */ + uint64_t hw[ACL_MAX_HW_NUM][2]; /**< height&width data array */ } aclmdlHW; typedef struct aclAippInfo { - aclAippInputFormat inputFormat; - int32_t srcImageSizeW; - int32_t srcImageSizeH; - int8_t cropSwitch; - int32_t loadStartPosW; - int32_t loadStartPosH; - int32_t cropSizeW; - int32_t cropSizeH; - int8_t resizeSwitch; - int32_t resizeOutputW; - int32_t resizeOutputH; - int8_t paddingSwitch; - int32_t leftPaddingSize; - int32_t rightPaddingSize; - int32_t topPaddingSize; - int32_t bottomPaddingSize; - int8_t cscSwitch; - int8_t rbuvSwapSwitch; - int8_t axSwapSwitch; - int8_t singleLineMode; - int32_t matrixR0C0; - int32_t matrixR0C1; - int32_t matrixR0C2; - int32_t matrixR1C0; - int32_t matrixR1C1; - int32_t matrixR1C2; - int32_t matrixR2C0; - int32_t matrixR2C1; - int32_t matrixR2C2; - int32_t outputBias0; - int32_t outputBias1; - int32_t outputBias2; - int32_t inputBias0; - int32_t inputBias1; - int32_t inputBias2; - int32_t meanChn0; - int32_t meanChn1; - int32_t meanChn2; - int32_t meanChn3; - float minChn0; - float minChn1; - float minChn2; - float minChn3; - float varReciChn0; - float varReciChn1; - float varReciChn2; - float varReciChn3; - aclFormat srcFormat; - aclDataType srcDatatype; - size_t srcDimNum; - size_t shapeCount; - aclAippDims outDims[ACL_MAX_SHAPE_COUNT]; - aclAippExtendInfo *aippExtend; /**< reserved parameters, current version needs to be null */ + aclAippInputFormat inputFormat; + int32_t srcImageSizeW; + int32_t srcImageSizeH; + int8_t cropSwitch; + int32_t loadStartPosW; + int32_t loadStartPosH; + int32_t cropSizeW; + int32_t cropSizeH; + int8_t resizeSwitch; + int32_t resizeOutputW; + int32_t resizeOutputH; + int8_t paddingSwitch; + int32_t leftPaddingSize; + int32_t rightPaddingSize; + int32_t topPaddingSize; + int32_t bottomPaddingSize; + int8_t cscSwitch; + int8_t rbuvSwapSwitch; + int8_t axSwapSwitch; + int8_t singleLineMode; + int32_t matrixR0C0; + int32_t matrixR0C1; + int32_t matrixR0C2; + int32_t matrixR1C0; + int32_t matrixR1C1; + int32_t matrixR1C2; + int32_t matrixR2C0; + int32_t matrixR2C1; + int32_t matrixR2C2; + int32_t outputBias0; + int32_t outputBias1; + int32_t outputBias2; + int32_t inputBias0; + int32_t inputBias1; + int32_t inputBias2; + int32_t meanChn0; + int32_t meanChn1; + int32_t meanChn2; + int32_t meanChn3; + float minChn0; + float minChn1; + float minChn2; + float minChn3; + float varReciChn0; + float varReciChn1; + float varReciChn2; + float varReciChn3; + aclFormat srcFormat; + aclDataType srcDatatype; + size_t srcDimNum; + size_t shapeCount; + aclAippDims outDims[ACL_MAX_SHAPE_COUNT]; + aclAippExtendInfo *aippExtend; /**< reserved parameters, current version needs to be null */ } aclAippInfo; /** @@ -339,7 +339,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFile(const char *modelPath, uint32_t * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMem(const void *model, size_t modelSize, uint32_t *modelId); +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMem(const void *model, size_t modelSize, + uint32_t *modelId); /** * @ingroup AscendCL @@ -361,8 +362,9 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMem(const void *model, size_t modelSi * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithMem(const char *modelPath, uint32_t *modelId, void *workPtr, - size_t workSize, void *weightPtr, size_t weightSize); +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithMem(const char *modelPath, + uint32_t *modelId, void *workPtr, size_t workSize, + void *weightPtr, size_t weightSize); /** * @ingroup AscendCL @@ -385,9 +387,9 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithMem(const char *modelPath, ui * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithMem(const void *model, size_t modelSize, uint32_t *modelId, - void *workPtr, size_t workSize, void *weightPtr, - size_t weightSize); +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithMem(const void *model, size_t modelSize, + uint32_t *modelId, void *workPtr, size_t workSize, + void *weightPtr, size_t weightSize); /** * @ingroup AscendCL @@ -422,8 +424,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithQ(const char *modelPath, uint * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithQ(const void *model, size_t modelSize, uint32_t *modelId, - const uint32_t *inputQ, size_t inputQNum, const uint32_t *outputQ, - size_t outputQNum); + const uint32_t *inputQ, size_t inputQNum, + const uint32_t *outputQ, size_t outputQNum); /** * @ingroup AscendCL @@ -453,8 +455,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlExecute(uint32_t modelId, const aclmdlDataset * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem */ -ACL_FUNC_VISIBILITY aclError aclmdlExecuteAsync(uint32_t modelId, const aclmdlDataset *input, aclmdlDataset *output, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclmdlExecuteAsync(uint32_t modelId, const aclmdlDataset *input, + aclmdlDataset *output, aclrtStream stream); /** * @ingroup AscendCL @@ -829,11 +831,11 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPInputFormat(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, int8_t csc_switch, int16_t cscMatrixR0C0, - int16_t cscMatrixR0C1, int16_t cscMatrixR0C2, int16_t cscMatrixR1C0, - int16_t cscMatrixR1C1, int16_t cscMatrixR1C2, int16_t cscMatrixR2C0, - int16_t cscMatrixR2C1, int16_t cscMatrixR2C2, +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, int8_t csc_switch, + int16_t cscMatrixR0C0, int16_t cscMatrixR0C1, int16_t cscMatrixR0C2, + int16_t cscMatrixR1C0, int16_t cscMatrixR1C1, int16_t cscMatrixR1C2, + int16_t cscMatrixR2C0, int16_t cscMatrixR2C1, int16_t cscMatrixR2C2, uint8_t cscOutputBiasR0, uint8_t cscOutputBiasR1, uint8_t cscOutputBiasR2, uint8_t cscInputBiasR0, uint8_t cscInputBiasR1, uint8_t cscInputBiasR2); @@ -849,7 +851,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, in * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ +*/ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPRbuvSwapSwitch(aclmdlAIPP *aippParmsSet, int8_t rbuvSwapSwitch); /** @@ -863,7 +865,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPRbuvSwapSwitch(aclmdlAIPP *aippParmsSe * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ +*/ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPAxSwapSwitch(aclmdlAIPP *aippParmsSet, int8_t axSwapSwitch); /** @@ -878,7 +880,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPAxSwapSwitch(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ +*/ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPSrcImageSize(aclmdlAIPP *aippParmsSet, int32_t srcImageSizeW, int32_t srcImageSizeH); @@ -898,10 +900,14 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPSrcImageSize(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPScfParams(aclmdlAIPP *aippParmsSet, int8_t scfSwitch, int32_t scfInputSizeW, - int32_t scfInputSizeH, int32_t scfOutputSizeW, - int32_t scfOutputSizeH, uint64_t batchIndex); +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPScfParams(aclmdlAIPP *aippParmsSet, + int8_t scfSwitch, + int32_t scfInputSizeW, + int32_t scfInputSizeH, + int32_t scfOutputSizeW, + int32_t scfOutputSizeH, + uint64_t batchIndex); /** * @ingroup AscendCL @@ -919,9 +925,13 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPScfParams(aclmdlAIPP *aippParmsSet, in * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCropParams(aclmdlAIPP *aippParmsSet, int8_t cropSwitch, int32_t cropStartPosW, - int32_t cropStartPosH, int32_t cropSizeW, int32_t cropSizeH, +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCropParams(aclmdlAIPP *aippParmsSet, + int8_t cropSwitch, + int32_t cropStartPosW, + int32_t cropStartPosH, + int32_t cropSizeW, + int32_t cropSizeH, uint64_t batchIndex); /** @@ -940,7 +950,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCropParams(aclmdlAIPP *aippParmsSet, i * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ +*/ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPaddingParams(aclmdlAIPP *aippParmsSet, int8_t paddingSwitch, int32_t paddingSizeTop, int32_t paddingSizeBottom, int32_t paddingSizeLeft, int32_t paddingSizeRight, @@ -961,10 +971,13 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPaddingParams(aclmdlAIPP *aippParmsSet * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMean(aclmdlAIPP *aippParmsSet, int16_t dtcPixelMeanChn0, - int16_t dtcPixelMeanChn1, int16_t dtcPixelMeanChn2, - int16_t dtcPixelMeanChn3, uint64_t batchIndex); +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMean(aclmdlAIPP *aippParmsSet, + int16_t dtcPixelMeanChn0, + int16_t dtcPixelMeanChn1, + int16_t dtcPixelMeanChn2, + int16_t dtcPixelMeanChn3, + uint64_t batchIndex); /** * @ingroup AscendCL @@ -981,10 +994,13 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMean(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMin(aclmdlAIPP *aippParmsSet, float dtcPixelMinChn0, - float dtcPixelMinChn1, float dtcPixelMinChn2, - float dtcPixelMinChn3, uint64_t batchIndex); +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMin(aclmdlAIPP *aippParmsSet, + float dtcPixelMinChn0, + float dtcPixelMinChn1, + float dtcPixelMinChn2, + float dtcPixelMinChn3, + uint64_t batchIndex); /** * @ingroup AscendCL @@ -1001,10 +1017,13 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMin(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPixelVarReci(aclmdlAIPP *aippParmsSet, float dtcPixelVarReciChn0, - float dtcPixelVarReciChn1, float dtcPixelVarReciChn2, - float dtcPixelVarReciChn3, uint64_t batchIndex); +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPixelVarReci(aclmdlAIPP *aippParmsSet, + float dtcPixelVarReciChn0, + float dtcPixelVarReciChn1, + float dtcPixelVarReciChn2, + float dtcPixelVarReciChn3, + uint64_t batchIndex); /** * @ingroup AscendCL @@ -1020,8 +1039,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPixelVarReci(aclmdlAIPP *aippParmsSet, * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP - */ -ACL_FUNC_VISIBILITY aclError aclmdlSetInputAIPP(uint32_t modelId, aclmdlDataset *dataset, size_t index, +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetInputAIPP(uint32_t modelId, + aclmdlDataset *dataset, + size_t index, const aclmdlAIPP *aippParmsSet); /** @@ -1038,8 +1059,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetInputAIPP(uint32_t modelId, aclmdlDataset * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP - */ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPByInputIndex(uint32_t modelId, aclmdlDataset *dataset, size_t index, +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPByInputIndex(uint32_t modelId, + aclmdlDataset *dataset, + size_t index, const aclmdlAIPP *aippParmsSet); /** @@ -1057,8 +1080,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPByInputIndex(uint32_t modelId, aclmdlD * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP - */ -ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, size_t index, aclmdlInputAippType *type, +*/ +ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, + size_t index, + aclmdlInputAippType *type, size_t *dynamicAttachedDataIndex); /** @@ -1075,7 +1100,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, size_t index, a * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName - */ +*/ ACL_FUNC_VISIBILITY aclError aclmdlGetFirstAippInfo(uint32_t modelId, size_t index, aclAippInfo *aippinfo); /** @@ -1094,11 +1119,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlGetFirstAippInfo(uint32_t modelId, size_t ind * * @retval ACL_SUCCESS The function is successfully executed * @retval OtherValues Failure - */ -ACL_FUNC_VISIBILITY aclError aclmdlCreateAndGetOpDesc(uint32_t deviceId, uint32_t streamId, uint32_t taskId, - char *opName, size_t opNameLen, aclTensorDesc **inputDesc, - size_t *numInputs, aclTensorDesc **outputDesc, - size_t *numOutputs); +*/ +ACL_FUNC_VISIBILITY aclError aclmdlCreateAndGetOpDesc(uint32_t deviceId, uint32_t streamId, + uint32_t taskId, char *opName, size_t opNameLen, aclTensorDesc **inputDesc, size_t *numInputs, + aclTensorDesc **outputDesc, size_t *numOutputs); /** * @ingroup AscendCL @@ -1106,7 +1130,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlCreateAndGetOpDesc(uint32_t deviceId, uint32_ * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure - */ +*/ ACL_FUNC_VISIBILITY aclError aclmdlInitDump(); /** @@ -1117,7 +1141,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlInitDump(); * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure - */ +*/ ACL_FUNC_VISIBILITY aclError aclmdlSetDump(const char *dumpCfgPath); /** @@ -1126,7 +1150,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetDump(const char *dumpCfgPath); * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure - */ +*/ ACL_FUNC_VISIBILITY aclError aclmdlFinalizeDump(); /** @@ -1138,7 +1162,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlFinalizeDump(); * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure - */ +*/ ACL_FUNC_VISIBILITY aclError aclmdlLoadWithConfig(const aclmdlConfigHandle *handle, uint32_t *modelId); /** @@ -1148,7 +1172,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadWithConfig(const aclmdlConfigHandle *hand * @retval the aclmdlConfigHandle pointer * * @see aclmdlDestroyConfigHandle - */ +*/ ACL_FUNC_VISIBILITY aclmdlConfigHandle *aclmdlCreateConfigHandle(); /** @@ -1177,10 +1201,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlDestroyConfigHandle(aclmdlConfigHandle *handl * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclmdlSetConfigOpt(aclmdlConfigHandle *handle, aclmdlConfigAttr attr, - const void *attrValue, size_t valueSize); + const void *attrValue, size_t valueSize); #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_MODEL_H_ +#endif // INC_EXTERNAL_ACL_ACL_MODEL_H_ diff --git a/inc/external/acl/acl_op.h b/inc/external/acl/acl_op.h index d2e59bfb..b1be0d6e 100644 --- a/inc/external/acl/acl_op.h +++ b/inc/external/acl/acl_op.h @@ -33,9 +33,9 @@ typedef void (*aclDataDeallocator)(void *data, size_t length); static const int ACL_COMPILE_FLAG_BIN_SELECTOR = 1; typedef enum aclEngineType { - ACL_ENGINE_SYS, - ACL_ENGINE_AICORE, - ACL_ENGINE_VECTOR, + ACL_ENGINE_SYS, + ACL_ENGINE_AICORE, + ACL_ENGINE_VECTOR, } aclopEngineType; /** @@ -148,7 +148,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrString(aclopAttr *attr, const char *att * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListBool(aclopAttr *attr, const char *attrName, int numValues, - const uint8_t *values); + const uint8_t *values); /** * @ingroup AscendCL @@ -163,7 +163,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListBool(aclopAttr *attr, const char *a * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListInt(aclopAttr *attr, const char *attrName, int numValues, - const int64_t *values); + const int64_t *values); /** * @ingroup AscendCL @@ -178,7 +178,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListInt(aclopAttr *attr, const char *at * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListFloat(aclopAttr *attr, const char *attrName, int numValues, - const float *values); + const float *values); /** * @ingroup AscendCL @@ -193,7 +193,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListFloat(aclopAttr *attr, const char * * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListString(aclopAttr *attr, const char *attrName, int numValues, - const char **values); + const char **values); /** * @ingroup AscendCL @@ -208,8 +208,11 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListString(aclopAttr *attr, const char * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, const char *attrName, int numLists, - const int *numValues, const int64_t *const values[]); +ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, + const char *attrName, + int numLists, + const int *numValues, + const int64_t *const values[]); /** * @ingroup AscendCL @@ -239,10 +242,15 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, const char * @retval OtherValues Failure */ ACL_DEPRECATED_MESSAGE("aclopExecute is deprecated, use aclopExecuteV2 instead") -ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], - const aclDataBuffer *const inputs[], int numOutputs, - const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], - const aclopAttr *attr, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, + int numInputs, + const aclTensorDesc *const inputDesc[], + const aclDataBuffer *const inputs[], + int numOutputs, + const aclTensorDesc *const outputDesc[], + aclDataBuffer *const outputs[], + const aclopAttr *attr, + aclrtStream stream); /** * @ingroup AscendCL @@ -272,9 +280,15 @@ ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, int numInputs, con * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, int numInputs, aclTensorDesc *inputDesc[], - aclDataBuffer *inputs[], int numOutputs, aclTensorDesc *outputDesc[], - aclDataBuffer *outputs[], aclopAttr *attr, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, + int numInputs, + aclTensorDesc *inputDesc[], + aclDataBuffer *inputs[], + int numOutputs, + aclTensorDesc *outputDesc[], + aclDataBuffer *outputs[], + aclopAttr *attr, + aclrtStream stream); /** * @ingroup AscendCL @@ -292,9 +306,12 @@ ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, int numInputs, a * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCreateHandle(const char *opType, int numInputs, - const aclTensorDesc *const inputDesc[], int numOutputs, - const aclTensorDesc *const outputDesc[], const aclopAttr *opAttr, +ACL_FUNC_VISIBILITY aclError aclopCreateHandle(const char *opType, + int numInputs, + const aclTensorDesc *const inputDesc[], + int numOutputs, + const aclTensorDesc *const outputDesc[], + const aclopAttr *opAttr, aclopHandle **handle); /** @@ -326,9 +343,12 @@ ACL_FUNC_VISIBILITY void aclopDestroyHandle(aclopHandle *handle); * * @see aclopCreateHandle | aclCreateDataBuffer */ -ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, int numInputs, - const aclDataBuffer *const inputs[], int numOutputs, - aclDataBuffer *const outputs[], aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, + int numInputs, + const aclDataBuffer *const inputs[], + int numOutputs, + aclDataBuffer *const outputs[], + aclrtStream stream); /** * @ingroup AscendCL @@ -344,8 +364,11 @@ ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, int numInp * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, const aclDataBuffer *srcBuffer, - const aclTensorDesc *dstDesc, aclDataBuffer *dstBuffer, uint8_t truncate, +ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, + const aclDataBuffer *srcBuffer, + const aclTensorDesc *dstDesc, + aclDataBuffer *dstBuffer, + uint8_t truncate, aclrtStream stream); /** @@ -360,9 +383,12 @@ ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, const aclDa * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, aclTensorDesc *dstDesc, uint8_t truncate, +ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, + aclTensorDesc *dstDesc, + uint8_t truncate, aclopHandle **handle); + /** * @ingroup AscendCL * @brief create kernel @@ -381,10 +407,15 @@ ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, ac * * @see aclopCompile */ -ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, const char *kernelId, const char *kernelName, - void *binData, int binSize, aclopEngineType enginetype, +ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, + const char *kernelId, + const char *kernelName, + void *binData, + int binSize, + aclopEngineType enginetype, aclDataDeallocator deallocator); + /** * @ingroup AscendCL * @brief create kernel @@ -399,8 +430,11 @@ ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, const char *k * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -typedef aclError (*aclopCompileFunc)(int numInputs, const aclTensorDesc *const inputDesc[], int numOutputs, - const aclTensorDesc *const outputDesc[], const aclopAttr *opAttr, +typedef aclError (*aclopCompileFunc)(int numInputs, + const aclTensorDesc *const inputDesc[], + int numOutputs, + const aclTensorDesc *const outputDesc[], + const aclopAttr *opAttr, aclopKernelDesc *aclopKernelDesc); /** @@ -441,8 +475,11 @@ ACL_FUNC_VISIBILITY aclError aclopUnregisterCompileFunc(const char *opType); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopSetKernelArgs(aclopKernelDesc *kernelDesc, const char *kernelId, uint32_t blockDim, - const void *args, uint32_t argSize); +ACL_FUNC_VISIBILITY aclError aclopSetKernelArgs(aclopKernelDesc *kernelDesc, + const char *kernelId, + uint32_t blockDim, + const void *args, + uint32_t argSize); /** * @ingroup AscendCL @@ -473,9 +510,12 @@ ACL_FUNC_VISIBILITY aclError aclopSetKernelWorkspaceSizes(aclopKernelDesc *kerne * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, int numInputs, - const aclTensorDesc *const inputDesc[], int numOutputs, - const aclTensorDesc *const outputDesc[], const aclopAttr *attr); +ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, + int numInputs, + const aclTensorDesc *const inputDesc[], + int numOutputs, + const aclTensorDesc *const outputDesc[], + const aclopAttr *attr); /** * @ingroup AscendCL @@ -493,12 +533,17 @@ ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, int numInputs * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopInferShape(const char *opType, int numInputs, aclTensorDesc *inputDesc[], - aclDataBuffer *inputs[], int numOutputs, aclTensorDesc *outputDesc[], +ACL_FUNC_VISIBILITY aclError aclopInferShape(const char *opType, + int numInputs, + aclTensorDesc *inputDesc[], + aclDataBuffer *inputs[], + int numOutputs, + aclTensorDesc *outputDesc[], aclopAttr *attr); + #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_OP_H_ +#endif // INC_EXTERNAL_ACL_ACL_OP_H_ diff --git a/inc/external/acl/acl_op_compiler.h b/inc/external/acl/acl_op_compiler.h index adae90c7..6bbb855c 100644 --- a/inc/external/acl/acl_op_compiler.h +++ b/inc/external/acl/acl_op_compiler.h @@ -24,18 +24,21 @@ extern "C" { #endif -typedef enum aclCompileType { ACL_COMPILE_SYS, ACL_COMPILE_UNREGISTERED } aclopCompileType; +typedef enum aclCompileType { + ACL_COMPILE_SYS, + ACL_COMPILE_UNREGISTERED +} aclopCompileType; typedef enum { - ACL_PRECISION_MODE, - ACL_AICORE_NUM, - ACL_AUTO_TUNE_MODE, - ACL_OP_SELECT_IMPL_MODE, - ACL_OPTYPELIST_FOR_IMPLMODE, - ACL_OP_DEBUG_LEVEL, - ACL_DEBUG_DIR, - ACL_OP_COMPILER_CACHE_MODE, - ACL_OP_COMPILER_CACHE_DIR + ACL_PRECISION_MODE, + ACL_AICORE_NUM, + ACL_AUTO_TUNE_MODE, + ACL_OP_SELECT_IMPL_MODE, + ACL_OPTYPELIST_FOR_IMPLMODE, + ACL_OP_DEBUG_LEVEL, + ACL_DEBUG_DIR, + ACL_OP_COMPILER_CACHE_MODE, + ACL_OP_COMPILER_CACHE_DIR } aclCompileOpt; /** @@ -56,10 +59,15 @@ typedef enum { * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], - int numOutputs, const aclTensorDesc *const outputDesc[], - const aclopAttr *attr, aclopEngineType engineType, - aclopCompileType compileFlag, const char *opPath); +ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, + int numInputs, + const aclTensorDesc *const inputDesc[], + int numOutputs, + const aclTensorDesc *const outputDesc[], + const aclopAttr *attr, + aclopEngineType engineType, + aclopCompileType compileFlag, + const char *opPath); /** * @ingroup AscendCL @@ -82,10 +90,11 @@ ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, int numInputs, con * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCompileAndExecute( - const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], const aclDataBuffer *const inputs[], - int numOutputs, const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], const aclopAttr *attr, - aclopEngineType engineType, aclopCompileType compileFlag, const char *opPath, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopCompileAndExecute(const char *opType, + int numInputs, const aclTensorDesc *const inputDesc[], const aclDataBuffer *const inputs[], + int numOutputs, const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], + const aclopAttr *attr, aclopEngineType engineType, aclopCompileType compileFlag, + const char *opPath, aclrtStream stream); /** * @ingroup AscendCL @@ -103,4 +112,4 @@ ACL_FUNC_VISIBILITY aclError aclSetCompileopt(aclCompileOpt opt, const char *val } #endif -#endif // INC_EXTERNAL_ACL_ACL_OP_COMPILER_H_ +#endif // INC_EXTERNAL_ACL_ACL_OP_COMPILER_H_ diff --git a/inc/external/acl/acl_prof.h b/inc/external/acl/acl_prof.h index 990c70cf..93bc3a9b 100644 --- a/inc/external/acl/acl_prof.h +++ b/inc/external/acl/acl_prof.h @@ -23,21 +23,24 @@ extern "C" { #endif -#define ACL_PROF_ACL_API 0x0001 -#define ACL_PROF_TASK_TIME 0x0002 -#define ACL_PROF_AICORE_METRICS 0x0004 -#define ACL_PROF_AICPU 0x0008 +#define ACL_PROF_ACL_API 0x0001 +#define ACL_PROF_TASK_TIME 0x0002 +#define ACL_PROF_AICORE_METRICS 0x0004 +#define ACL_PROF_AICPU 0x0008 -#define ACL_PROF_MAX_OP_NAME_LEN 257 -#define ACL_PROF_MAX_OP_TYPE_LEN 65 +/** + * @deprecated please use aclprofGetOpTypeLen and aclprofGetOpTNameLen instead + */ +#define ACL_PROF_MAX_OP_NAME_LEN 257 +#define ACL_PROF_MAX_OP_TYPE_LEN 65 typedef enum { - ACL_AICORE_ARITHMETIC_UTILIZATION = 0, - ACL_AICORE_PIPE_UTILIZATION = 1, - ACL_AICORE_MEMORY_BANDWIDTH = 2, - ACL_AICORE_L0B_AND_WIDTH = 3, - ACL_AICORE_RESOURCE_CONFLICT_RATIO = 4, - ACL_AICORE_NONE = 0xFF + ACL_AICORE_ARITHMETIC_UTILIZATION = 0, + ACL_AICORE_PIPE_UTILIZATION = 1, + ACL_AICORE_MEMORY_BANDWIDTH = 2, + ACL_AICORE_L0B_AND_WIDTH = 3, + ACL_AICORE_RESOURCE_CONFLICT_RATIO = 4, + ACL_AICORE_NONE = 0xFF } aclprofAicoreMetrics; typedef struct aclprofConfig aclprofConfig; @@ -98,8 +101,7 @@ ACL_FUNC_VISIBILITY aclError aclprofStart(const aclprofConfig *profilerConfig); * @see aclprofDestroyConfig */ ACL_FUNC_VISIBILITY aclprofConfig *aclprofCreateConfig(uint32_t *deviceIdList, uint32_t deviceNums, - aclprofAicoreMetrics aicoreMetrics, - aclprofAicoreEvents *aicoreEvents, uint64_t dataTypeConfig); + aclprofAicoreMetrics aicoreMetrics, aclprofAicoreEvents *aicoreEvents, uint64_t dataTypeConfig); /** * @ingroup AscendCL @@ -139,7 +141,8 @@ ACL_FUNC_VISIBILITY aclError aclprofStop(const aclprofConfig *profilerConfig); * * @see aclprofModelUnSubscribe */ -ACL_FUNC_VISIBILITY aclError aclprofModelSubscribe(uint32_t modelId, const aclprofSubscribeConfig *profSubscribeConfig); +ACL_FUNC_VISIBILITY aclError aclprofModelSubscribe(uint32_t modelId, + const aclprofSubscribeConfig *profSubscribeConfig); /** * @ingroup AscendCL @@ -167,7 +170,7 @@ ACL_FUNC_VISIBILITY aclError aclprofModelUnSubscribe(uint32_t modelId); * @see aclprofDestroySubscribeConfig */ ACL_FUNC_VISIBILITY aclprofSubscribeConfig *aclprofCreateSubscribeConfig(int8_t timeInfoSwitch, - aclprofAicoreMetrics aicoreMetrics, void *fd); + aclprofAicoreMetrics aicoreMetrics, void *fd); /** * @ingroup AscendCL @@ -206,6 +209,21 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpDescSize(size_t *opDescSize); */ ACL_FUNC_VISIBILITY aclError aclprofGetOpNum(const void *opInfo, size_t opInfoLen, uint32_t *opNumber); +/** + * @ingroup AscendCL + * @brief get length op type from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * @param index [IN] index of op array in opInfo + * @param opTypeLen [OUT] actual length of op type string + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclprofGetOpTypeLen(const void *opInfo, size_t opInfoLen, uint32_t index, + size_t *opTypeLen); + /** * @ingroup AscendCL * @brief get op type from subscription data @@ -219,8 +237,23 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpNum(const void *opInfo, size_t opInfoLe * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoLen, uint32_t index, char *opType, - size_t opTypeLen); +ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoLen, uint32_t index, + char *opType, size_t opTypeLen); + +/** + * @ingroup AscendCL + * @brief get length op name from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * @param index [IN] index of op array in opInfo + * @param opNameLen [OUT] actual length of op name string + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclprofGetOpNameLen(const void *opInfo, size_t opInfoLen, uint32_t index, + size_t *opNameLen); /** * @ingroup AscendCL @@ -235,8 +268,8 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoL * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclprofGetOpName(const void *opInfo, size_t opInfoLen, uint32_t index, char *opName, - size_t opNameLen); +ACL_FUNC_VISIBILITY aclError aclprofGetOpName(const void *opInfo, size_t opInfoLen, uint32_t index, + char *opName, size_t opNameLen); /** * @ingroup AscendCL @@ -293,4 +326,4 @@ ACL_FUNC_VISIBILITY size_t aclprofGetModelId(const void *opInfo, size_t opInfoLe } #endif -#endif // INC_EXTERNAL_ACL_PROF_H_ +#endif // INC_EXTERNAL_ACL_PROF_H_ diff --git a/inc/external/acl/acl_rt.h b/inc/external/acl/acl_rt.h index eb6b4240..8fb7f05a 100644 --- a/inc/external/acl/acl_rt.h +++ b/inc/external/acl/acl_rt.h @@ -26,62 +26,63 @@ extern "C" { #endif typedef enum aclrtRunMode { - ACL_DEVICE, - ACL_HOST, + ACL_DEVICE, + ACL_HOST, } aclrtRunMode; typedef enum aclrtTsId { - ACL_TS_ID_AICORE = 0, - ACL_TS_ID_AIVECTOR = 1, - ACL_TS_ID_RESERVED = 2, + ACL_TS_ID_AICORE = 0, + ACL_TS_ID_AIVECTOR = 1, + ACL_TS_ID_RESERVED = 2, } aclrtTsId; typedef enum aclrtEventStatus { - ACL_EVENT_STATUS_COMPLETE = 0, - ACL_EVENT_STATUS_NOT_READY = 1, - ACL_EVENT_STATUS_RESERVED = 2, + ACL_EVENT_STATUS_COMPLETE = 0, + ACL_EVENT_STATUS_NOT_READY = 1, + ACL_EVENT_STATUS_RESERVED = 2, } aclrtEventStatus; typedef enum aclrtCallbackBlockType { - ACL_CALLBACK_NO_BLOCK, - ACL_CALLBACK_BLOCK, + ACL_CALLBACK_NO_BLOCK, + ACL_CALLBACK_BLOCK, } aclrtCallbackBlockType; typedef enum aclrtMemcpyKind { - ACL_MEMCPY_HOST_TO_HOST, - ACL_MEMCPY_HOST_TO_DEVICE, - ACL_MEMCPY_DEVICE_TO_HOST, - ACL_MEMCPY_DEVICE_TO_DEVICE, + ACL_MEMCPY_HOST_TO_HOST, + ACL_MEMCPY_HOST_TO_DEVICE, + ACL_MEMCPY_DEVICE_TO_HOST, + ACL_MEMCPY_DEVICE_TO_DEVICE, } aclrtMemcpyKind; typedef enum aclrtMemMallocPolicy { - ACL_MEM_MALLOC_HUGE_FIRST, - ACL_MEM_MALLOC_HUGE_ONLY, - ACL_MEM_MALLOC_NORMAL_ONLY, - ACL_MEM_MALLOC_HUGE_FIRST_P2P, - ACL_MEM_MALLOC_HUGE_ONLY_P2P, - ACL_MEM_MALLOC_NORMAL_ONLY_P2P, + ACL_MEM_MALLOC_HUGE_FIRST, + ACL_MEM_MALLOC_HUGE_ONLY, + ACL_MEM_MALLOC_NORMAL_ONLY, + ACL_MEM_MALLOC_HUGE_FIRST_P2P, + ACL_MEM_MALLOC_HUGE_ONLY_P2P, + ACL_MEM_MALLOC_NORMAL_ONLY_P2P, } aclrtMemMallocPolicy; typedef enum aclrtMemAttr { - ACL_DDR_MEM, - ACL_HBM_MEM, - ACL_DDR_MEM_HUGE, - ACL_DDR_MEM_NORMAL, - ACL_HBM_MEM_HUGE, - ACL_HBM_MEM_NORMAL, - ACL_DDR_MEM_P2P_HUGE, - ACL_DDR_MEM_P2P_NORMAL, - ACL_HBM_MEM_P2P_HUGE, - ACL_HBM_MEM_P2P_NORMAL, + ACL_DDR_MEM, + ACL_HBM_MEM, + ACL_DDR_MEM_HUGE, + ACL_DDR_MEM_NORMAL, + ACL_HBM_MEM_HUGE, + ACL_HBM_MEM_NORMAL, + ACL_DDR_MEM_P2P_HUGE, + ACL_DDR_MEM_P2P_NORMAL, + ACL_HBM_MEM_P2P_HUGE, + ACL_HBM_MEM_P2P_NORMAL, } aclrtMemAttr; typedef enum aclrtGroupAttr { - ACL_GROUP_AICORE_INT, - ACL_GROUP_AIV_INT, - ACL_GROUP_AIC_INT, - ACL_GROUP_SDMANUM_INT, - ACL_GROUP_ASQNUM_INT + ACL_GROUP_AICORE_INT, + ACL_GROUP_AIV_INT, + ACL_GROUP_AIC_INT, + ACL_GROUP_SDMANUM_INT, + ACL_GROUP_ASQNUM_INT, + ACL_GROUP_GROUPID_INT } aclrtGroupAttr; typedef struct tagRtGroupInfo aclrtGroupInfo; @@ -472,7 +473,7 @@ ACL_FUNC_VISIBILITY aclError aclrtRecordEvent(aclrtEvent event, aclrtStream stre */ ACL_FUNC_VISIBILITY aclError aclrtResetEvent(aclrtEvent event, aclrtStream stream); -/** + /** * @ingroup AscendCL * @brief Queries an event's status * @@ -534,7 +535,9 @@ ACL_FUNC_VISIBILITY aclError aclrtEventElapsedTime(float *ms, aclrtEvent start, * * @see aclrtFree | acldvppMalloc | aclrtMallocCached */ -ACL_FUNC_VISIBILITY aclError aclrtMalloc(void **devPtr, size_t size, aclrtMemMallocPolicy policy); +ACL_FUNC_VISIBILITY aclError aclrtMalloc(void **devPtr, + size_t size, + aclrtMemMallocPolicy policy); /** * @ingroup AscendCL @@ -557,7 +560,9 @@ ACL_FUNC_VISIBILITY aclError aclrtMalloc(void **devPtr, size_t size, aclrtMemMal * * @see aclrtFree | aclrtMalloc */ -ACL_FUNC_VISIBILITY aclError aclrtMallocCached(void **devPtr, size_t size, aclrtMemMallocPolicy policy); +ACL_FUNC_VISIBILITY aclError aclrtMallocCached(void **devPtr, + size_t size, + aclrtMemMallocPolicy policy); /** * @ingroup AscendCL @@ -648,7 +653,10 @@ ACL_FUNC_VISIBILITY aclError aclrtFreeHost(void *hostPtr); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclrtMemcpy(void *dst, size_t destMax, const void *src, size_t count, +ACL_FUNC_VISIBILITY aclError aclrtMemcpy(void *dst, + size_t destMax, + const void *src, + size_t count, aclrtMemcpyKind kind); /** @@ -695,31 +703,38 @@ ACL_FUNC_VISIBILITY aclError aclrtMemset(void *devPtr, size_t maxCount, int32_t * * @see aclrtSynchronizeStream */ -ACL_FUNC_VISIBILITY aclError aclrtMemcpyAsync(void *dst, size_t destMax, const void *src, size_t count, - aclrtMemcpyKind kind, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclrtMemcpyAsync(void *dst, + size_t destMax, + const void *src, + size_t count, + aclrtMemcpyKind kind, + aclrtStream stream); /** - * @ingroup AscendCL - * @brief Asynchronous initialize memory - * and set contents of memory to specified value async - * - * @par Function +* @ingroup AscendCL +* @brief Asynchronous initialize memory +* and set contents of memory to specified value async +* +* @par Function * The memory to be initialized is on the Host or device side, * and the system determines whether * it is host or device according to the address * - * @param devPtr [IN] destination address pointer - * @param maxCount [IN] Max length of destination address memory - * @param value [IN] set value - * @param count [IN] the number of byte to set - * @param stream [IN] asynchronized task stream - * - * @retval ACL_SUCCESS The function is successfully executed. - * @retval OtherValues Failure - * - * @see aclrtSynchronizeStream - */ -ACL_FUNC_VISIBILITY aclError aclrtMemsetAsync(void *devPtr, size_t maxCount, int32_t value, size_t count, +* @param devPtr [IN] destination address pointer +* @param maxCount [IN] Max length of destination address memory +* @param value [IN] set value +* @param count [IN] the number of byte to set +* @param stream [IN] asynchronized task stream +* +* @retval ACL_SUCCESS The function is successfully executed. +* @retval OtherValues Failure +* +* @see aclrtSynchronizeStream +*/ +ACL_FUNC_VISIBILITY aclError aclrtMemsetAsync(void *devPtr, + size_t maxCount, + int32_t value, + size_t count, aclrtStream stream); /** @@ -854,7 +869,7 @@ ACL_FUNC_VISIBILITY aclError aclrtGetAllGroupInfo(aclrtGroupInfo *groupInfo); * @brief get detail information of group * * @param groupInfo [IN] pointer to group information - * @param groupId [IN] group index value + * @param groupIndex [IN] group index value * @param attr [IN] group attribute * @param attrValue [OUT] pointer to attribute value * @param valueLen [IN] length of attribute value @@ -865,8 +880,11 @@ ACL_FUNC_VISIBILITY aclError aclrtGetAllGroupInfo(aclrtGroupInfo *groupInfo); * * @see aclrtGetGroupCount | aclrtGetAllGroupInfo */ -ACL_FUNC_VISIBILITY aclError aclrtGetGroupInfoDetail(const aclrtGroupInfo *groupInfo, int32_t groupId, - aclrtGroupAttr attr, void *attrValue, size_t valueLen, +ACL_FUNC_VISIBILITY aclError aclrtGetGroupInfoDetail(const aclrtGroupInfo *groupInfo, + int32_t groupIndex, + aclrtGroupAttr attr, + void *attrValue, + size_t valueLen, size_t *paramRetSize); /** @@ -929,4 +947,5 @@ ACL_FUNC_VISIBILITY aclError aclrtGetMemInfo(aclrtMemAttr attr, size_t *free, si } #endif -#endif // INC_EXTERNAL_ACL_ACL_RT_H_ +#endif // INC_EXTERNAL_ACL_ACL_RT_H_ + diff --git a/inc/external/acl/acl_tdt.h b/inc/external/acl/acl_tdt.h index c357518d..61995121 100644 --- a/inc/external/acl/acl_tdt.h +++ b/inc/external/acl/acl_tdt.h @@ -24,10 +24,10 @@ extern "C" { #endif enum acltdtTensorType { - ACL_TENSOR_DATA_UNDEFINED = -1, - ACL_TENSOR_DATA_TENSOR, - ACL_TENSOR_DATA_END_OF_SEQUENCE, - ACL_TENSOR_DATA_ABNORMAL + ACL_TENSOR_DATA_UNDEFINED = -1, + ACL_TENSOR_DATA_TENSOR, + ACL_TENSOR_DATA_END_OF_SEQUENCE, + ACL_TENSOR_DATA_ABNORMAL }; typedef struct acltdtDataItem acltdtDataItem; @@ -64,7 +64,7 @@ ACL_FUNC_VISIBILITY aclDataType acltdtGetDataTypeFromItem(const acltdtDataItem * * * @retval null for failed * @retval OtherValues success - */ +*/ ACL_FUNC_VISIBILITY void *acltdtGetDataAddrFromItem(const acltdtDataItem *dataItem); /** @@ -75,7 +75,7 @@ ACL_FUNC_VISIBILITY void *acltdtGetDataAddrFromItem(const acltdtDataItem *dataIt * * @retval 0 for failed * @retval OtherValues success - */ +*/ ACL_FUNC_VISIBILITY size_t acltdtGetDataSizeFromItem(const acltdtDataItem *dataItem); /** @@ -86,7 +86,7 @@ ACL_FUNC_VISIBILITY size_t acltdtGetDataSizeFromItem(const acltdtDataItem *dataI * * @retval 0 for failed * @retval OtherValues success - */ +*/ ACL_FUNC_VISIBILITY size_t acltdtGetDimNumFromItem(const acltdtDataItem *dataItem); /** @@ -118,8 +118,12 @@ ACL_FUNC_VISIBILITY aclError acltdtGetDimsFromItem(const acltdtDataItem *dataIte * * @see acltdtDestroyDataItem */ -ACL_FUNC_VISIBILITY acltdtDataItem *acltdtCreateDataItem(acltdtTensorType tdtType, const int64_t *dims, size_t dimNum, - aclDataType dataType, void *data, size_t size); +ACL_FUNC_VISIBILITY acltdtDataItem *acltdtCreateDataItem(acltdtTensorType tdtType, + const int64_t *dims, + size_t dimNum, + aclDataType dataType, + void *data, + size_t size); /** * @ingroup AscendCL @@ -250,7 +254,8 @@ ACL_FUNC_VISIBILITY aclError acltdtDestroyChannel(acltdtChannelHandle *handle); * * @see acltdtReceiveTensor */ -ACL_FUNC_VISIBILITY aclError acltdtSendTensor(const acltdtChannelHandle *handle, const acltdtDataset *dataset, +ACL_FUNC_VISIBILITY aclError acltdtSendTensor(const acltdtChannelHandle *handle, + const acltdtDataset *dataset, int32_t timeout); /** @@ -266,11 +271,13 @@ ACL_FUNC_VISIBILITY aclError acltdtSendTensor(const acltdtChannelHandle *handle, * * @see acltdtSendTensor */ -ACL_FUNC_VISIBILITY aclError acltdtReceiveTensor(const acltdtChannelHandle *handle, acltdtDataset *dataset, +ACL_FUNC_VISIBILITY aclError acltdtReceiveTensor(const acltdtChannelHandle *handle, + acltdtDataset *dataset, int32_t timeout); #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_TDT_H_ +#endif //INC_EXTERNAL_ACL_ACL_TDT_H_ + diff --git a/inc/external/acl/error_codes/rt_error_codes.h b/inc/external/acl/error_codes/rt_error_codes.h index 2109fb79..47f16d9f 100644 --- a/inc/external/acl/error_codes/rt_error_codes.h +++ b/inc/external/acl/error_codes/rt_error_codes.h @@ -23,80 +23,80 @@ extern "C" { #endif -static const int32_t ACL_RT_SUCCESS = 0; // success +static const int32_t ACL_RT_SUCCESS = 0; // success -static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid -static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id -static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null -static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context -static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context -static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal -static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned -static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed -static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed -static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream -static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread -static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set -static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create -static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream -static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type -static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle -static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type +static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid +static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id +static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null +static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context +static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context +static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal +static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned +static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed +static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed +static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream +static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread +static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set +static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create +static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream +static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type +static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle +static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type -static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support -static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error -static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error -static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow -static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device -static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail -static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission -static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource -static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource -static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource -static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource +static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support +static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error +static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error +static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow +static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device +static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail +static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission +static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource +static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource +static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource +static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource -static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error -static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error -static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error +static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error +static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error #ifdef __cplusplus } #endif -#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ +#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/inc/external/acl/ops/acl_cblas.h b/inc/external/acl/ops/acl_cblas.h index 3d81eb2b..a2bd8c61 100644 --- a/inc/external/acl/ops/acl_cblas.h +++ b/inc/external/acl/ops/acl_cblas.h @@ -23,9 +23,17 @@ extern "C" { #endif -typedef enum aclTransType { ACL_TRANS_N, ACL_TRANS_T, ACL_TRANS_NZ, ACL_TRANS_NZ_T } aclTransType; +typedef enum aclTransType { + ACL_TRANS_N, + ACL_TRANS_T, + ACL_TRANS_NZ, + ACL_TRANS_NZ_T +} aclTransType; -typedef enum aclComputeType { ACL_COMPUTE_HIGH_PRECISION, ACL_COMPUTE_LOW_PRECISION } aclComputeType; +typedef enum aclComputeType { + ACL_COMPUTE_HIGH_PRECISION, + ACL_COMPUTE_LOW_PRECISION +} aclComputeType; /** * @ingroup AscendCL @@ -53,11 +61,12 @@ typedef enum aclComputeType { ACL_COMPUTE_HIGH_PRECISION, ACL_COMPUTE_LOW_PRECIS * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure - */ -ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, const void *alpha, const void *a, int lda, - aclDataType dataTypeA, const void *x, int incx, aclDataType dataTypeX, - const void *beta, void *y, int incy, aclDataType dataTypeY, - aclComputeType type, aclrtStream stream); +*/ +ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, + const void *alpha, const void *a, int lda, aclDataType dataTypeA, + const void *x, int incx, aclDataType dataTypeX, + const void *beta, void *y, int incy, aclDataType dataTypeY, + aclComputeType type, aclrtStream stream); /** * @ingroup AscendCL @@ -74,10 +83,15 @@ ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, co * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure - */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, int m, int n, aclDataType dataTypeA, - aclDataType dataTypeX, aclDataType dataTypeY, - aclComputeType type, aclopHandle **handle); +*/ +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, + int m, + int n, + aclDataType dataTypeA, + aclDataType dataTypeX, + aclDataType dataTypeY, + aclComputeType type, + aclopHandle **handle); /** * @ingroup AscendCL @@ -101,9 +115,18 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, i * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, int m, int n, const aclFloat16 *alpha, - const aclFloat16 *a, int lda, const aclFloat16 *x, int incx, - const aclFloat16 *beta, aclFloat16 *y, int incy, aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, + int m, + int n, + const aclFloat16 *alpha, + const aclFloat16 *a, + int lda, + const aclFloat16 *x, + int incx, + const aclFloat16 *beta, + aclFloat16 *y, + int incy, + aclComputeType type, aclrtStream stream); /** @@ -119,7 +142,10 @@ ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, int m, int n, con * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, int m, int n, aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, + int m, + int n, + aclComputeType type, aclopHandle **handle); /** @@ -145,9 +171,19 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, in * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, int m, int n, const int32_t *alpha, const int8_t *a, - int lda, const int8_t *x, int incx, const int32_t *beta, int32_t *y, - int incy, aclComputeType type, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, + int m, + int n, + const int32_t *alpha, + const int8_t *a, + int lda, + const int8_t *x, + int incx, + const int32_t *beta, + int32_t *y, + int incy, + aclComputeType type, + aclrtStream stream); /** * @ingroup AscendCL @@ -162,7 +198,10 @@ ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, int m, int n, co * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, int m, int n, aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, + int m, + int n, + aclComputeType type, aclopHandle **handle); /** @@ -194,11 +233,26 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, i * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, - int k, const void *alpha, const void *matrixA, int lda, - aclDataType dataTypeA, const void *matrixB, int ldb, aclDataType dataTypeB, - const void *beta, void *matrixC, int ldc, aclDataType dataTypeC, - aclComputeType type, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, + aclTransType transB, + aclTransType transC, + int m, + int n, + int k, + const void *alpha, + const void *matrixA, + int lda, + aclDataType dataTypeA, + const void *matrixB, + int ldb, + aclDataType dataTypeB, + const void *beta, + void *matrixC, + int ldc, + aclDataType dataTypeC, + aclComputeType type, + aclrtStream stream); + /** * @ingroup AscendCL @@ -220,10 +274,18 @@ ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, aclTransType tra * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, aclTransType transB, aclTransType transC, - int m, int n, int k, aclDataType dataTypeA, - aclDataType dataTypeB, aclDataType dataTypeC, - aclComputeType type, aclopHandle **handle); +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, + aclTransType transB, + aclTransType transC, + int m, + int n, + int k, + aclDataType dataTypeA, + aclDataType dataTypeB, + aclDataType dataTypeC, + aclComputeType type, + aclopHandle **handle); + /** * @ingroup AscendCL @@ -251,10 +313,22 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, a * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, - int k, const aclFloat16 *alpha, const aclFloat16 *matrixA, int lda, - const aclFloat16 *matrixB, int ldb, const aclFloat16 *beta, - aclFloat16 *matrixC, int ldc, aclComputeType type, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, + aclTransType transB, + aclTransType transC, + int m, + int n, + int k, + const aclFloat16 *alpha, + const aclFloat16 *matrixA, + int lda, + const aclFloat16 *matrixB, + int ldb, + const aclFloat16 *beta, + aclFloat16 *matrixC, + int ldc, + aclComputeType type, + aclrtStream stream); /** * @ingroup AscendCL @@ -272,8 +346,13 @@ ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, aclTransType tran * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, aclTransType transB, aclTransType transC, - int m, int n, int k, aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, + aclTransType transB, + aclTransType transC, + int m, + int n, + int k, + aclComputeType type, aclopHandle **handle); /** @@ -302,10 +381,23 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, ac * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, - int k, const int32_t *alpha, const int8_t *matrixA, int lda, - const int8_t *matrixB, int ldb, const int32_t *beta, int32_t *matrixC, - int ldc, aclComputeType type, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, + aclTransType transB, + aclTransType transC, + int m, + int n, + int k, + const int32_t *alpha, + const int8_t *matrixA, + int lda, + const int8_t *matrixB, + int ldb, + const int32_t *beta, + int32_t *matrixC, + int ldc, + aclComputeType type, + aclrtStream stream); + /** * @ingroup AscendCL @@ -323,12 +415,17 @@ ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, aclTransType tra * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemm(aclTransType transA, aclTransType transB, aclTransType transC, - int m, int n, int k, aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemm(aclTransType transA, + aclTransType transB, + aclTransType transC, + int m, + int n, + int k, + aclComputeType type, aclopHandle **handle); #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_CBLAS_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_CBLAS_H_ diff --git a/inc/external/acl/ops/acl_dvpp.h b/inc/external/acl/ops/acl_dvpp.h index 8f5d3904..42ec4a8d 100644 --- a/inc/external/acl/ops/acl_dvpp.h +++ b/inc/external/acl/ops/acl_dvpp.h @@ -53,109 +53,123 @@ typedef void (*aclvencCallback)(acldvppPicDesc *input, acldvppStreamDesc *output // Supported Pixel Format enum acldvppPixelFormat { - PIXEL_FORMAT_YUV_400 = 0, // 0 - PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1, // 1 - PIXEL_FORMAT_YVU_SEMIPLANAR_420 = 2, // 2 - PIXEL_FORMAT_YUV_SEMIPLANAR_422 = 3, // 3 - PIXEL_FORMAT_YVU_SEMIPLANAR_422 = 4, // 4 - PIXEL_FORMAT_YUV_SEMIPLANAR_444 = 5, // 5 - PIXEL_FORMAT_YVU_SEMIPLANAR_444 = 6, // 6 - PIXEL_FORMAT_YUYV_PACKED_422 = 7, // 7 - PIXEL_FORMAT_UYVY_PACKED_422 = 8, // 8 - PIXEL_FORMAT_YVYU_PACKED_422 = 9, // 9 - PIXEL_FORMAT_VYUY_PACKED_422 = 10, // 10 - PIXEL_FORMAT_YUV_PACKED_444 = 11, // 11 - PIXEL_FORMAT_RGB_888 = 12, // 12 - PIXEL_FORMAT_BGR_888 = 13, // 13 - PIXEL_FORMAT_ARGB_8888 = 14, // 14 - PIXEL_FORMAT_ABGR_8888 = 15, // 15 - PIXEL_FORMAT_RGBA_8888 = 16, // 16 - PIXEL_FORMAT_BGRA_8888 = 17, // 17 - PIXEL_FORMAT_YUV_SEMI_PLANNER_420_10BIT = 18, // 18 - PIXEL_FORMAT_YVU_SEMI_PLANNER_420_10BIT = 19, // 19 - PIXEL_FORMAT_YVU_PLANAR_420 = 20, // 20 - PIXEL_FORMAT_YVU_PLANAR_422, - PIXEL_FORMAT_YVU_PLANAR_444, - PIXEL_FORMAT_RGB_444 = 23, - PIXEL_FORMAT_BGR_444, - PIXEL_FORMAT_ARGB_4444, - PIXEL_FORMAT_ABGR_4444, - PIXEL_FORMAT_RGBA_4444, - PIXEL_FORMAT_BGRA_4444, - PIXEL_FORMAT_RGB_555, - PIXEL_FORMAT_BGR_555, - PIXEL_FORMAT_RGB_565, - PIXEL_FORMAT_BGR_565, - PIXEL_FORMAT_ARGB_1555, - PIXEL_FORMAT_ABGR_1555, - PIXEL_FORMAT_RGBA_1555, - PIXEL_FORMAT_BGRA_1555, - PIXEL_FORMAT_ARGB_8565, - PIXEL_FORMAT_ABGR_8565, - PIXEL_FORMAT_RGBA_8565, - PIXEL_FORMAT_BGRA_8565, - PIXEL_FORMAT_RGB_BAYER_8BPP = 50, - PIXEL_FORMAT_RGB_BAYER_10BPP, - PIXEL_FORMAT_RGB_BAYER_12BPP, - PIXEL_FORMAT_RGB_BAYER_14BPP, - PIXEL_FORMAT_RGB_BAYER_16BPP, - PIXEL_FORMAT_BGR_888_PLANAR = 70, - PIXEL_FORMAT_HSV_888_PACKAGE, - PIXEL_FORMAT_HSV_888_PLANAR, - PIXEL_FORMAT_LAB_888_PACKAGE, - PIXEL_FORMAT_LAB_888_PLANAR, - PIXEL_FORMAT_S8C1, - PIXEL_FORMAT_S8C2_PACKAGE, - PIXEL_FORMAT_S8C2_PLANAR, - PIXEL_FORMAT_S16C1, - PIXEL_FORMAT_U8C1, - PIXEL_FORMAT_U16C1, - PIXEL_FORMAT_S32C1, - PIXEL_FORMAT_U32C1, - PIXEL_FORMAT_U64C1, - PIXEL_FORMAT_S64C1, - PIXEL_FORMAT_YUV_SEMIPLANAR_440 = 1000, - PIXEL_FORMAT_YVU_SEMIPLANAR_440, - PIXEL_FORMAT_FLOAT32, - PIXEL_FORMAT_BUTT, - PIXEL_FORMAT_UNKNOWN = 10000 + PIXEL_FORMAT_YUV_400 = 0, // 0 + PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1, // 1 + PIXEL_FORMAT_YVU_SEMIPLANAR_420 = 2, // 2 + PIXEL_FORMAT_YUV_SEMIPLANAR_422 = 3, // 3 + PIXEL_FORMAT_YVU_SEMIPLANAR_422 = 4, // 4 + PIXEL_FORMAT_YUV_SEMIPLANAR_444 = 5, // 5 + PIXEL_FORMAT_YVU_SEMIPLANAR_444 = 6, // 6 + PIXEL_FORMAT_YUYV_PACKED_422 = 7, // 7 + PIXEL_FORMAT_UYVY_PACKED_422 = 8, // 8 + PIXEL_FORMAT_YVYU_PACKED_422 = 9, // 9 + PIXEL_FORMAT_VYUY_PACKED_422 = 10, // 10 + PIXEL_FORMAT_YUV_PACKED_444 = 11, // 11 + PIXEL_FORMAT_RGB_888 = 12, // 12 + PIXEL_FORMAT_BGR_888 = 13, // 13 + PIXEL_FORMAT_ARGB_8888 = 14, // 14 + PIXEL_FORMAT_ABGR_8888 = 15, // 15 + PIXEL_FORMAT_RGBA_8888 = 16, // 16 + PIXEL_FORMAT_BGRA_8888 = 17, // 17 + PIXEL_FORMAT_YUV_SEMI_PLANNER_420_10BIT = 18, // 18 + PIXEL_FORMAT_YVU_SEMI_PLANNER_420_10BIT = 19, // 19 + PIXEL_FORMAT_YVU_PLANAR_420 = 20, // 20 + PIXEL_FORMAT_YVU_PLANAR_422, + PIXEL_FORMAT_YVU_PLANAR_444, + PIXEL_FORMAT_RGB_444 = 23, + PIXEL_FORMAT_BGR_444, + PIXEL_FORMAT_ARGB_4444, + PIXEL_FORMAT_ABGR_4444, + PIXEL_FORMAT_RGBA_4444, + PIXEL_FORMAT_BGRA_4444, + PIXEL_FORMAT_RGB_555, + PIXEL_FORMAT_BGR_555, + PIXEL_FORMAT_RGB_565, + PIXEL_FORMAT_BGR_565, + PIXEL_FORMAT_ARGB_1555, + PIXEL_FORMAT_ABGR_1555, + PIXEL_FORMAT_RGBA_1555, + PIXEL_FORMAT_BGRA_1555, + PIXEL_FORMAT_ARGB_8565, + PIXEL_FORMAT_ABGR_8565, + PIXEL_FORMAT_RGBA_8565, + PIXEL_FORMAT_BGRA_8565, + PIXEL_FORMAT_RGB_BAYER_8BPP = 50, + PIXEL_FORMAT_RGB_BAYER_10BPP, + PIXEL_FORMAT_RGB_BAYER_12BPP, + PIXEL_FORMAT_RGB_BAYER_14BPP, + PIXEL_FORMAT_RGB_BAYER_16BPP, + PIXEL_FORMAT_BGR_888_PLANAR = 70, + PIXEL_FORMAT_HSV_888_PACKAGE, + PIXEL_FORMAT_HSV_888_PLANAR, + PIXEL_FORMAT_LAB_888_PACKAGE, + PIXEL_FORMAT_LAB_888_PLANAR, + PIXEL_FORMAT_S8C1, + PIXEL_FORMAT_S8C2_PACKAGE, + PIXEL_FORMAT_S8C2_PLANAR, + PIXEL_FORMAT_S16C1, + PIXEL_FORMAT_U8C1, + PIXEL_FORMAT_U16C1, + PIXEL_FORMAT_S32C1, + PIXEL_FORMAT_U32C1, + PIXEL_FORMAT_U64C1, + PIXEL_FORMAT_S64C1, + PIXEL_FORMAT_YUV_SEMIPLANAR_440 = 1000, + PIXEL_FORMAT_YVU_SEMIPLANAR_440, + PIXEL_FORMAT_FLOAT32, + PIXEL_FORMAT_BUTT, + PIXEL_FORMAT_UNKNOWN = 10000 }; // Stream Format -enum acldvppStreamFormat { H265_MAIN_LEVEL = 0, H264_BASELINE_LEVEL, H264_MAIN_LEVEL, H264_HIGH_LEVEL }; +enum acldvppStreamFormat { + H265_MAIN_LEVEL = 0, + H264_BASELINE_LEVEL, + H264_MAIN_LEVEL, + H264_HIGH_LEVEL +}; // Supported Channel Mode -enum acldvppChannelMode { DVPP_CHNMODE_VPC = 1, DVPP_CHNMODE_JPEGD = 2, DVPP_CHNMODE_JPEGE = 4 }; +enum acldvppChannelMode { + DVPP_CHNMODE_VPC = 1, + DVPP_CHNMODE_JPEGD = 2, + DVPP_CHNMODE_JPEGE = 4 +}; // Supported Border Type -enum acldvppBorderType { BORDER_CONSTANT = 0, BORDER_REPLICATE, BORDER_REFLECT, BORDER_REFLECT_101 }; +enum acldvppBorderType { + BORDER_CONSTANT = 0, + BORDER_REPLICATE, + BORDER_REFLECT, + BORDER_REFLECT_101 +}; // Venc parameter type enum aclvencChannelDescParamType { - ACL_VENC_THREAD_ID_UINT64 = 0, - ACL_VENC_CALLBACK_PTR, - ACL_VENC_PIXEL_FORMAT_UINT32, - ACL_VENC_ENCODE_TYPE_UINT32, - ACL_VENC_PIC_WIDTH_UINT32, - ACL_VENC_PIC_HEIGHT_UINT32, - ACL_VENC_KEY_FRAME_INTERVAL_UINT32, - ACL_VENC_BUF_ADDR_PTR, - ACL_VENC_BUF_SIZE_UINT32, - ACL_VENC_RC_MODE_UINT32, - ACL_VENC_SRC_RATE_UINT32, - ACL_VENC_MAX_BITRATE_UINT32, - ACL_VENC_MAX_IP_PROP_UINT32 + ACL_VENC_THREAD_ID_UINT64 = 0, + ACL_VENC_CALLBACK_PTR, + ACL_VENC_PIXEL_FORMAT_UINT32, + ACL_VENC_ENCODE_TYPE_UINT32, + ACL_VENC_PIC_WIDTH_UINT32, + ACL_VENC_PIC_HEIGHT_UINT32, + ACL_VENC_KEY_FRAME_INTERVAL_UINT32, + ACL_VENC_BUF_ADDR_PTR, + ACL_VENC_BUF_SIZE_UINT32, + ACL_VENC_RC_MODE_UINT32, + ACL_VENC_SRC_RATE_UINT32, + ACL_VENC_MAX_BITRATE_UINT32, + ACL_VENC_MAX_IP_PROP_UINT32 }; // Jpeg picture format enum acldvppJpegFormat { - ACL_JPEG_CSS_444 = 0, - ACL_JPEG_CSS_422, - ACL_JPEG_CSS_420, - ACL_JPEG_CSS_GRAY, - ACL_JPEG_CSS_440, - ACL_JPEG_CSS_411, - ACL_JPEG_CSS_UNKNOWN = 1000 + ACL_JPEG_CSS_444 = 0, + ACL_JPEG_CSS_422, + ACL_JPEG_CSS_420, + ACL_JPEG_CSS_GRAY, + ACL_JPEG_CSS_440, + ACL_JPEG_CSS_411, + ACL_JPEG_CSS_UNKNOWN = 1000 }; /** @@ -509,7 +523,9 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescRetCode(const acldvppPicDesc *picD * @retval null for failed. * @retval other success */ -ACL_FUNC_VISIBILITY acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, uint32_t right, uint32_t top, +ACL_FUNC_VISIBILITY acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, + uint32_t right, + uint32_t top, uint32_t bottom); /** @@ -588,7 +604,10 @@ ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfigBottom(acldvppRoiConfig *config, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfig(acldvppRoiConfig *config, uint32_t left, uint32_t right, uint32_t top, +ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfig(acldvppRoiConfig *config, + uint32_t left, + uint32_t right, + uint32_t top, uint32_t bottom); /** @@ -1077,8 +1096,7 @@ ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescMaxBitRate(aclvencChannelDesc * @retval ACL_SUCCESS for success, other for failure */ ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescParam(aclvencChannelDesc *channelDesc, - aclvencChannelDescParamType paramType, size_t length, - const void *param); + aclvencChannelDescParamType paramType, size_t length, const void *param); /** * @ingroup AscendCL @@ -1227,8 +1245,7 @@ ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescMaxBitRate(const aclvencChanne * @retval ACL_SUCCESS for success, other for failure */ ACL_FUNC_VISIBILITY aclError aclvencGetChannelDescParam(const aclvencChannelDesc *channelDesc, - aclvencChannelDescParamType paramType, size_t length, - size_t *paramRetSize, void *param); + aclvencChannelDescParamType paramType, size_t length, size_t *paramRetSize, void *param); /** * @ingroup AscendCL @@ -1528,7 +1545,10 @@ ACL_FUNC_VISIBILITY aclError aclvdecDestroyFrameConfig(aclvdecFrameConfig *vdecF * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, uint32_t size, uint32_t *width, uint32_t *height, +ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, + uint32_t size, + uint32_t *width, + uint32_t *height, int32_t *components); /** @@ -1545,8 +1565,11 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, uint32_t * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, uint32_t size, uint32_t *width, - uint32_t *height, int32_t *components, +ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, + uint32_t size, + uint32_t *width, + uint32_t *height, + int32_t *components, acldvppJpegFormat *format); /** @@ -1561,7 +1584,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, uint32_ * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictEncSize(const acldvppPicDesc *inputDesc, - const acldvppJpegeConfig *config, uint32_t *size); + const acldvppJpegeConfig *config, + uint32_t *size); /** * @ingroup AscendCL @@ -1575,8 +1599,10 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictEncSize(const acldvppPicDesc *inp * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, uint32_t dataSize, - acldvppPixelFormat outputPixelFormat, uint32_t *decSize); +ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, + uint32_t dataSize, + acldvppPixelFormat outputPixelFormat, + uint32_t *decSize); /** * @ingroup AscendCL @@ -1591,8 +1617,11 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, uint32_ * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, uint32_t dataSize, uint32_t *width, - uint32_t *height, int32_t *components); +ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, + uint32_t dataSize, + uint32_t *width, + uint32_t *height, + int32_t *components); /** * @ingroup AscendCL @@ -1606,8 +1635,10 @@ ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, uint32_t d * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppPngPredictDecSize(const void *data, uint32_t dataSize, - acldvppPixelFormat outputPixelFormat, uint32_t *decSize); +ACL_FUNC_VISIBILITY aclError acldvppPngPredictDecSize(const void *data, + uint32_t dataSize, + acldvppPixelFormat outputPixelFormat, + uint32_t *decSize); /** * @ingroup AscendCL @@ -1671,8 +1702,10 @@ ACL_FUNC_VISIBILITY aclError acldvppDestroyChannel(acldvppChannelDesc *channelDe * @see acldvppCreateChannel | acldvppCreatePicDesc * | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, acldvppResizeConfig *resizeConfig, +ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + acldvppResizeConfig *resizeConfig, aclrtStream stream); /** @@ -1708,8 +1741,10 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDe * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, +ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + acldvppRoiConfig *cropArea, aclrtStream stream); /** @@ -1734,9 +1769,12 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, - uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, - acldvppRoiConfig *cropAreas[], aclrtStream stream); + acldvppBatchPicDesc *srcBatchPicDescs, + uint32_t *roiNums, + uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + aclrtStream stream); /** * @ingroup AscendCL @@ -1759,9 +1797,12 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channe * * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateRoiConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, - acldvppRoiConfig *pasteArea, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + acldvppRoiConfig *cropArea, + acldvppRoiConfig *pasteArea, + aclrtStream stream); /** * @ingroup AscendCL @@ -1786,11 +1827,14 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *cha * * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, - uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, - acldvppRoiConfig *cropAreas[], - acldvppRoiConfig *pasteAreas[], aclrtStream stream); + ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *channelDesc, + acldvppBatchPicDesc *srcBatchPicDescs, + uint32_t *roiNums, + uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + acldvppRoiConfig *pasteAreas[], + aclrtStream stream); /** * @ingroup AscendCL @@ -1818,8 +1862,11 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, - acldvppPicDesc *outputDesc, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, + const void *data, + uint32_t size, + acldvppPicDesc *outputDesc, + aclrtStream stream); /** * @ingroup AscendCL @@ -1837,8 +1884,11 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelD * * @see acldvppCreateChannel | acldvppCreateJpegeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - const void *data, uint32_t *size, acldvppJpegeConfig *config, +ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + const void *data, + uint32_t *size, + acldvppJpegeConfig *config, aclrtStream stream); /** @@ -1856,8 +1906,11 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelD * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppPngDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, - acldvppPicDesc *outputDesc, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppPngDecodeAsync(acldvppChannelDesc *channelDesc, + const void *data, + uint32_t size, + acldvppPicDesc *outputDesc, + aclrtStream stream); /** * @ingroup AscendCL @@ -1912,8 +1965,11 @@ ACL_FUNC_VISIBILITY aclError aclvdecDestroyChannel(aclvdecChannelDesc *channelDe * * @see aclvdecCreateChannel | acldvppCreateStreamDesc | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, acldvppStreamDesc *input, - acldvppPicDesc *output, aclvdecFrameConfig *config, void *userData); +ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, + acldvppStreamDesc *input, + acldvppPicDesc *output, + aclvdecFrameConfig *config, + void *userData); /** * @ingroup AscendCL @@ -1932,8 +1988,10 @@ ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, a * * @see aclvdecCreateChannel | acldvppCreateStreamDesc | acldvppCreatePicDesc | aclvdecSendFrame */ -ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channelDesc, acldvppStreamDesc *input, - aclvdecFrameConfig *config, void *userData); +ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channelDesc, + acldvppStreamDesc *input, + aclvdecFrameConfig *config, + void *userData); /** * @ingroup AscendCL @@ -1954,8 +2012,10 @@ ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channel * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + aclrtStream stream); /** * @ingroup AscendCL @@ -1977,8 +2037,11 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *cha * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, void *reserve, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + void *reserve, + aclrtStream stream); /** * @ingroup AscendCL @@ -1990,7 +2053,8 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelD * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetChannelDescMode(acldvppChannelDesc *channelDesc, uint32_t mode); +ACL_FUNC_VISIBILITY aclError acldvppSetChannelDescMode(acldvppChannelDesc *channelDesc, + uint32_t mode); /** * @ingroup AscendCL @@ -2025,7 +2089,8 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetResizeConfigInterpolation(const acldvppRe * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutMode(aclvdecChannelDesc *channelDesc, uint32_t outMode); +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutMode(aclvdecChannelDesc *channelDesc, + uint32_t outMode); /** * @ingroup AscendCL @@ -2122,7 +2187,9 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetLutMapDims(const acldvppLutMap *lutMap); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, uint32_t dim, uint8_t **data, +ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, + uint32_t dim, + uint8_t **data, uint32_t *len); /** * @ingroup AscendCL @@ -2140,8 +2207,10 @@ ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, u * @see acldvppCreateChannel|acldvppCreatePicDesc|acldvppCreateLutMap */ ACL_FUNC_VISIBILITY aclError acldvppVpcEqualizeHistAsync(const acldvppChannelDesc *channelDesc, - const acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, - const acldvppLutMap *lutMap, aclrtStream stream); + const acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + const acldvppLutMap *lutMap, + aclrtStream stream); /** * @ingroup AscendCL @@ -2162,7 +2231,8 @@ ACL_FUNC_VISIBILITY acldvppBorderConfig *acldvppCreateBorderConfig(); * * @retval ACL_SUCCESS for success, other for failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigValue(acldvppBorderConfig *borderConfig, uint32_t index, +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigValue(acldvppBorderConfig *borderConfig, + uint32_t index, double value); /** @@ -2307,8 +2377,10 @@ ACL_FUNC_VISIBILITY aclError acldvppDestroyBorderConfig(acldvppBorderConfig *bor * @see acldvppCreateChannel|acldvppCreatePicDesc|acldvppCreateBorderConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcMakeBorderAsync(const acldvppChannelDesc *channelDesc, - const acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, - const acldvppBorderConfig *borderConfig, aclrtStream stream); + const acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + const acldvppBorderConfig *borderConfig, + aclrtStream stream); /** * @ingroup AscendCL @@ -2325,8 +2397,11 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcMakeBorderAsync(const acldvppChannelDesc * * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateHist */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *srcPicDesc, - acldvppHist *hist, void *reserve, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *srcPicDesc, + acldvppHist *hist, + void *reserve, + aclrtStream stream); /** * @ingroup AscendCL @@ -2335,7 +2410,7 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channel * @retval null for failed. * @retval OtherValues success. */ -ACL_FUNC_VISIBILITY acldvppHist *acldvppCreateHist(); +ACL_FUNC_VISIBILITY acldvppHist* acldvppCreateHist(); /** * @ingroup AscendCL @@ -2392,7 +2467,7 @@ ACL_FUNC_VISIBILITY aclError acldvppGetHistData(acldvppHist *hist, uint32_t dim, * * @see acldvppCreateHist | acldvppVpcCalcHistAsync */ -ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist *hist); +ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist* hist); /** * @ingroup AscendCL @@ -2415,4 +2490,4 @@ ACL_FUNC_VISIBILITY aclError acldvppClearHist(acldvppHist *hist); } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ diff --git a/inc/external/acl/ops/acl_fv.h b/inc/external/acl/ops/acl_fv.h index 27dc367a..40cd50cb 100644 --- a/inc/external/acl/ops/acl_fv.h +++ b/inc/external/acl/ops/acl_fv.h @@ -32,8 +32,8 @@ typedef struct aclfvSearchResult aclfvSearchResult; // search operation type enum aclfvSearchType { - SEARCH_1_N, // 1:N operation type - SEARCH_N_M // N:M operation type + SEARCH_1_N, // 1:N operation type + SEARCH_N_M // N:M operation type }; /** @@ -104,8 +104,7 @@ ACL_FUNC_VISIBILITY aclError aclfvSetNMTopNum(aclfvInitPara *initPara, uint32_t * @retval OtherValues success. */ ACL_FUNC_VISIBILITY aclfvFeatureInfo *aclfvCreateFeatureInfo(uint32_t id0, uint32_t id1, uint32_t offset, - uint32_t featureLen, uint32_t featureCount, - uint8_t *featureData, uint32_t featureDataLen); + uint32_t featureLen, uint32_t featureCount, uint8_t *featureData, uint32_t featureDataLen); /** * @ingroup AscendCL @@ -234,9 +233,8 @@ ACL_FUNC_VISIBILITY aclError aclfvDestroySearchInput(aclfvSearchInput *searchInp * @retval null for failed. OtherValues success */ ACL_FUNC_VISIBILITY aclfvSearchResult *aclfvCreateSearchResult(uint32_t queryCnt, uint32_t *resultNum, - uint32_t resultNumDataLen, uint32_t *id0, uint32_t *id1, - uint32_t *resultOffset, float *resultDistance, - uint32_t dataLen); + uint32_t resultNumDataLen, uint32_t *id0, uint32_t *id1, uint32_t *resultOffset, float *resultDistance, + uint32_t dataLen); /** * @ingroup AscendCL @@ -350,4 +348,4 @@ ACL_FUNC_VISIBILITY aclError aclfvSearch(aclfvSearchType type, aclfvSearchInput } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_RETR_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_RETR_H_ diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index 9f981d12..bc35f4ce 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -32,6 +32,9 @@ namespace ge { * float16, float32, double, int32, uint8, int16, int8, complex64, int64, * qint8, quint8, qint32, uint16, complex128, uint32, uint64. It's a dynamic input. \n +*@par Attributes: +*N: An required attribute of type int32, means nums of inputs. \n + *@par Outputs: *y: A Tensor. Has the same shape and type as the elements of "x". \n @@ -3559,26 +3562,6 @@ REG_OP(MaxN) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_FLOAT64, DT_INT32, DT_INT64})) .OP_END_FACTORY_REG(MaxN) -/** - * @brief Element-wise min of each of the input tensors (with Numpy-style broadcasting support). - * All inputs and outputs must have the same data type. This operator supports multidirectional - * (i.e., Numpy-style) broadcasting - * - * @par inputs - * one input including: - * @li x: dynamic input A Tensor. Must be one of the following types: float32, float16, double, int32, int64 - * - * @par output - * one output including: - * @li y:A Tensor of the same type as x - * - */ -REG_OP(MinN) - .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_FLOAT64, - DT_INT32, DT_INT64})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_FLOAT64, - DT_INT32, DT_INT64})) - .OP_END_FACTORY_REG(MinN) /** * @brief Calculates x * maske * value. @@ -3640,8 +3623,7 @@ REG_OP(Lerp) * rtol: Defaults to "1e-03". * *@par Outputs: -* num: A tensor of type int32. -* diff: A tensor of type float16. +* num: A tensor of type float32. * *@par Restrictions: *Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. @@ -3651,7 +3633,6 @@ REG_OP(DataCompare) .INPUT(x1, TensorType({ DT_FLOAT16, DT_FLOAT,DT_INT8, DT_UINT8, DT_INT32 })) .INPUT(x2, TensorType({ DT_FLOAT16, DT_FLOAT,DT_INT8, DT_UINT8, DT_INT32 })) .OUTPUT(num, TensorType({DT_FLOAT})) - .OUTPUT(diff, TensorType({DT_FLOAT16})) .ATTR(atol, Float, 1e-5) .ATTR(rtol, Float, 1e-3) .OP_END_FACTORY_REG(DataCompare) @@ -3730,6 +3711,76 @@ REG_OP(IsClose) .ATTR(equal_nan, Bool, false) .OP_END_FACTORY_REG(IsClose) +/** +* @brief Returns the reverse tensor of the ArgMax operator of a tensor. \n + +* @par Inputs: +* three input, including: +* var: A Tensor of type float16, float32, int32 or int8. \n +* indices: A Tensor of type int32. \n +* updates: A Tensor of type float16, float32, int32 or int8. \n + +* @par Attributes: +* @li dimension: An integer of type int, specifying the axis information of the index with the maximum value.\n + +* @par Outputs: +* y: A Tensor of type float16, float32, int32 or int8. \n +* +*@attention Constraints: +*@li indices: only support int32,and shape same to "updates" +*@li The value range of "dimension" is [-dims, dims - 1]. "dims" is the dimension length of "x". +*@li y:A Tensor, the type and shape is same to "var" \n + +*@par Third-party framework compatibility +* not support all scene like pytorch operator scatter +* exp: +* var.shape=[2,3,4,5], dim=2, the shape of indices and updates should be [2,3,5] +* not support the shape of indices and updates is [2,3,2,5] like pytorch operator scatter. \n +*/ +REG_OP(ArgMaxGrad) + .INPUT(var, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) + .INPUT(indices, TensorType({DT_INT32})) + .INPUT(updates, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) + .REQUIRED_ATTR(dimension, Int) + .OP_END_FACTORY_REG(ArgMaxGrad) + +/** +* @brief Returns the reverse tensor of the ArgMax operator of a tensor. \n + +* @par Inputs: +* three input, including: +* var: A Tensor of type float16, float32, int32 or int8. \n +* indices: A Tensor of type int32. \n +* updates: A Tensor of type float16, float32, int32 or int8. \n +* assist: A Tensor of int32,also a assist matrix and it's shape must match the shape of var \n + +* @par Attributes: +* @li dimension: An integer of type int, specifying the axis information of the index with the maximum value.\n + +* @par Outputs: +* y: A Tensor of type float16, float32, int32 or int8. \n + +*@attention Constraints: +*@li indices: only support int32,and shape same to "updates" +*@li The value range of "dimension" is [-dims, dims - 1]. "dims" is the dimension length of "x". +*@li y:A Tensor, the type and shape is same to "var" \n + +*@par Third-party framework compatibility +* not support all scene like pytorch operator scatter +* exp: +* var.shape=[2,3,4,5], dim=2, the shape of indices and updates should be [2,3,5] +* not support the shape of indices and updates is [2,3,2,5] like pytorch operator scatter. \n +*/ +REG_OP(ArgMaxGradD) + .INPUT(var, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) + .INPUT(indices, TensorType({DT_INT32})) + .INPUT(updates, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) + .INPUT(assist, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) + .REQUIRED_ATTR(dimension, Int) + .OP_END_FACTORY_REG(ArgMaxGradD) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_ELEWISE_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/linalg_ops.h b/third_party/fwkacllib/inc/ops/linalg_ops.h index 330fef2e..1a59d88e 100644 --- a/third_party/fwkacllib/inc/ops/linalg_ops.h +++ b/third_party/fwkacllib/inc/ops/linalg_ops.h @@ -160,10 +160,8 @@ form square matrices. \n */ REG_OP(MatrixInverse) - .INPUT(x, TensorType({DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ - DT_COMPLEX64, DT_COMPLEX128})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ - DT_COMPLEX64, DT_COMPLEX128})) + .INPUT(x, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .ATTR(adjoint, Bool, false) .OP_END_FACTORY_REG(MatrixInverse) @@ -223,10 +221,8 @@ dimensions form square matrices. \n */ REG_OP(MatrixSolveLs) - .INPUT(matrix, TensorType({DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ - DT_COMPLEX64, DT_COMPLEX128})) - .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ - DT_COMPLEX64, DT_COMPLEX128})) + .INPUT(matrix, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .INPUT(l2, TensorType({DT_DOUBLE})) .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) .ATTR(fast, Bool, true) @@ -259,12 +255,9 @@ dimensions form square matrices. \n */ REG_OP(MatrixTriangularSolve) - .INPUT(matrix, TensorType({DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ - DT_COMPLEX64, DT_COMPLEX128})) - .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ - DT_COMPLEX64, DT_COMPLEX128})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ - DT_COMPLEX64, DT_COMPLEX128})) + .INPUT(matrix, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .ATTR(lower, Bool, true) .ATTR(adjoint, Bool, false) .OP_END_FACTORY_REG(MatrixTriangularSolve) @@ -432,9 +425,9 @@ y: Tensor of shape `[..., M, K]` containing the solutions \n */ REG_OP(TridiagonalSolve) - .INPUT(diagonals, TensorType({DT_FLOAT, DT_DOUBLE})) - .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(diagonals, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .ATTR(partial_pivoting, Bool, true) .OP_END_FACTORY_REG(TridiagonalSolve) diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index 6bff7f82..32631f14 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -1043,6 +1043,29 @@ REG_OP(Triu) .ATTR(diagonal, Int, 0) .OUTPUT(y, TensorType::BasicType()) .OP_END_FACTORY_REG(Triu) + +/** +*@brief: Returns the upper triangular part of a matrix (2-D tensor) or batch of matrices input \n + +*@par Inputs: +* Two inputs, including: +*@li x: A Tensor. Must be one of the following types: +* float16, float32, double, int32, uint8, int16, int8, complex64, int64, +* qint8, quint8, qint32, uint16, complex128, uint32, uint64. +*@li diagonal:(int, optional) – the diagonal to consider。\n + +*@par Outputs: +*y: A Tensor. Has the same type as "x" . \n + +*@par Third-party framework compatibility +* Compatible with the Pytorch operator Tril. +*/ +REG_OP(Tril) + .INPUT(x, TensorType::BasicType()) + .ATTR(diagonal, Int, 0) + .OUTPUT(y, TensorType::BasicType()) + .OP_END_FACTORY_REG(Tril) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATRIX_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h index 53922ee6..8cbdf9ff 100644 --- a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h @@ -408,8 +408,8 @@ REG_OP(BiasAddGrad) | Filter | H | [1, 255] | | W | [1, 255] -------------------|----------|-------------- - | out_backprop | H | [1, 4096] - | | W | [1, 4096] + | out_backprop | H*strideH| [1, 4096] + | | W*strideW| [1, 4096] -------------------|----------|-------------- | y(fmap) | H | [1, 4096] | | W | [1, 4096] @@ -428,6 +428,7 @@ REG_OP(BiasAddGrad) @endverbatim * In Ascend910, fmap or out_backprop's H and W not support 1 when * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 + * If filter_h = 1 and filter_w = 1, out_backprop_w * stride_h * stride_w < 4096 *\n * *@par Outputs: @@ -545,15 +546,16 @@ REG_OP(Conv2DBackpropInputD) * @li data_format: An optional string from: "NCHW". Defaults to "NCHW". \n Specify the data format of the input and output data. * @li offset_x: An optional integer for quantized deconvolution. - * Defaults to "0". + * The negative offset added to the input image for int8 type. Ensure offset_x + * within the effective range of int8 [-128, 127]. Defaults to "0". *\n *\n * The following value range restrictions must be met: *@verbatim | Name | Field | Scope -------------------|----------|-------------- - | x (out_backprop) | H | [1, 4096] - | | W | [1, 4096] + | x (out_backprop) | H*strideH| [1, 4096] + | | W*strideW| [1, 4096] -------------------|----------|-------------- | Filter | H | [1, 255] | | W | [1, 255] @@ -577,6 +579,7 @@ REG_OP(Conv2DBackpropInputD) @endverbatim * In Ascend910, fmap or out_backprop's H and W not support 1 when * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 + * If filter_h = 1 and filter_w = 1, out_backprop_w * stride_h * stride_w < 4096 *\n * *@par Outputs: @@ -1496,7 +1499,8 @@ REG_OP(Conv3DTransposeD) * @li output_padding: The size will be added in the output shape. Defaults * to [0, 0, 0, 0]. * @li offset_x: An optional int. Input offset, used for quantized inference. - * Defaults to "0". + * The negative offset added to the input image for int8 type. Ensure offset_x + * within the effective range of int8 [-128, 127]. Defaults to "0". *\n *\n * The following value range restrictions must be met: @@ -1506,8 +1510,8 @@ REG_OP(Conv3DTransposeD) | input_size | H | [1, 4096] | | W | [1, 4096] -------------------|----------|-------------- - | x (out_backprop) | H | [1, 4096] - | | W | [1, 4096] + | x (out_backprop) | H*strideH| [1, 4096] + | | W*strideW| [1, 4096] -------------------|----------|-------------- | filter | H | [1, 255] | | W | [1, 255] @@ -1531,6 +1535,7 @@ REG_OP(Conv3DTransposeD) @endverbatim * In Ascend910, fmap or out_backprop's H and W not support 1 when * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 + * If filter_h = 1 and filter_w = 1, out_backprop_w * stride_h * stride_w < 4096 *\n * *@par Outputs: diff --git a/third_party/fwkacllib/inc/ops/selection_ops.h b/third_party/fwkacllib/inc/ops/selection_ops.h index 33980d43..0aff5a81 100644 --- a/third_party/fwkacllib/inc/ops/selection_ops.h +++ b/third_party/fwkacllib/inc/ops/selection_ops.h @@ -942,6 +942,8 @@ REG_OP(TopK) .OUTPUT(values, TensorType::RealNumberType()) .OUTPUT(indices, TensorType({DT_INT32})) .ATTR(sorted, Bool, true) + .ATTR(largest, Bool, true) + .ATTR(dim, Int, -1) .OP_END_FACTORY_REG(TopK) /** *@brief Creates a new tensor by applying sparse "updates" to individual values or slices within a tensor (initially zero for numeric, empty for string) of the given "shape" according to "indices" . \n diff --git a/third_party/fwkacllib/inc/ops/spectral_ops.h b/third_party/fwkacllib/inc/ops/spectral_ops.h index 82accc73..34ccb398 100644 --- a/third_party/fwkacllib/inc/ops/spectral_ops.h +++ b/third_party/fwkacllib/inc/ops/spectral_ops.h @@ -66,16 +66,16 @@ REG_OP(RFFT) .OP_END_FACTORY_REG(RFFT) /** -*@brief Inverse real-valued fast Fourier transform . \n +*@brief Inverse real-valued fast Fourier transform. \n *@par Inputs: *@li x: A complex64 tensor. -*@li fft_length: An int32 tensor of shape [1]. The FFT length . \n +*@li fft_length: An int32 tensor of shape [1]. The FFT length. \n *@par Outputs: *@li y: A float32 tensor of the same rank as `input`. The inner-most dimension of `input` is replaced with the `fft_length` samples of its inverse - 1D Fourier transform . \n + 1D Fourier transform. \n *@par Third-party framework compatibility * Compatible with TensorFlow IRFFT operator. @@ -91,11 +91,11 @@ REG_OP(IRFFT) *@brief 2D fast Fourier transform. \n *@par Inputs: -*@li x: A complex64 tensor.. +*@li x: A complex64 tensor. *@par Outputs: *@li y: A complex64 tensor of the same shape as `input`. The inner-most 2 - dimensions of `input` are replaced with their 2D Fourier transform.\n + dimensions of `input` are replaced with their 2D Fourier transform. \n *@par Third-party framework compatibility * Compatible with TensorFlow FFT2D operator. diff --git a/third_party/fwkacllib/inc/ops/transformation_ops.h b/third_party/fwkacllib/inc/ops/transformation_ops.h index 1b30c2e1..42c7745a 100644 --- a/third_party/fwkacllib/inc/ops/transformation_ops.h +++ b/third_party/fwkacllib/inc/ops/transformation_ops.h @@ -716,6 +716,35 @@ REG_OP(CompressFcOp) .OUTPUT(compress_index, TensorType({DT_INT8})) .REQUIRED_ATTR(compress_parameters, ListInt) .OP_END_FACTORY_REG(CompressFcOp) + +/** +*@brief Performs Col2im for each batch entry. \n + +*@par Inputs: +*@li input_x: The Col Tensor. 5-D, shape: `(n, c1, kernel_h*kernel_w, ho*wo, c0)`. +where ho/wo is do = (output_d + 2*padding_d - dilation_d*(kernel_d - 1) - 1)//stride_d + 1 \n + +*@par Outputs: +*@li output_y: The img Tensor. 5-D, shape: `(n, c1, output_h, output_w, c0)`. \n + +*@par Attributes: +*@li kernel_shape: ListInt, value: `(kernel_h, kernel_w)`, the shape of kernel in convolution. +*@li dilation: ListInt, value: `(dilation_h, dilation_w)`, the dilation in convolution. +*@li padding: ListInt, value: `(padding_h, padding_w)`, the dilation in convolution. +*@li stride: ListInt, value: `(stride_h, stride_w)`, the dilation in convolution. \n + +*@par Third-party framework compatibility +* Compatible with Pytorch col2im/im2col_backward operator. +*/ +REG_OP(Col2im) + .INPUT(x, TensorType({DT_FLOAT})) + .INPUT(output_size, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT})) + .REQUIRED_ATTR(kernel_size, ListInt) + .REQUIRED_ATTR(dilation, ListInt) + .REQUIRED_ATTR(padding, ListInt) + .REQUIRED_ATTR(stride, ListInt) + .OP_END_FACTORY_REG(Col2im) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_TRANSFORMATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/runtime/kernel.h b/third_party/fwkacllib/inc/runtime/kernel.h index 0ec1a163..cf5347cb 100644 --- a/third_party/fwkacllib/inc/runtime/kernel.h +++ b/third_party/fwkacllib/inc/runtime/kernel.h @@ -173,13 +173,7 @@ typedef void (*rtCallback_t)(void *fnData); * @ingroup rt_kernel * @brief magic number of elf binary for aicube */ -#define RT_DEV_BINARY_MAGIC_ELF_AICUBE 0x41415247 - -/** - * @ingroup rt_kernel - * @brief magic number of elf binary for aivector - */ -#define RT_DEV_BINARY_MAGIC_ELF_AIVECTOR 0x41415248 +#define RT_DEV_BINARY_MAGIC_ELF_AICUBE 0x41494343 /** * @ingroup rt_kernel_flags diff --git a/third_party/fwkacllib/inc/runtime/mem.h b/third_party/fwkacllib/inc/runtime/mem.h index 30af85d9..bace4bc6 100644 --- a/third_party/fwkacllib/inc/runtime/mem.h +++ b/third_party/fwkacllib/inc/runtime/mem.h @@ -116,6 +116,9 @@ typedef enum tagRtMemInfoType { typedef enum tagRtRecudeKind { RT_MEMCPY_SDMA_AUTOMATIC_ADD = 10, // D2D, SDMA inline reduce, include 1P, and P2P + RT_MEMCPY_SDMA_AUTOMATIC_MAX = 11, + RT_MEMCPY_SDMA_AUTOMATIC_MIN = 12, + RT_MEMCPY_SDMA_AUTOMATIC_EQUAL = 13, RT_RECUDE_KIND_END } rtRecudeKind_t; @@ -123,6 +126,14 @@ typedef enum tagRtDataType { RT_DATA_TYPE_FP32 = 0, // fp32 RT_DATA_TYPE_FP16 = 1, // fp16 RT_DATA_TYPE_INT16 = 2, // int16 + RT_DATA_TYPE_INT4 = 3, // int4 + RT_DATA_TYPE_INT8 = 4, // int8 + RT_DATA_TYPE_INT32 = 5, // int32 + RT_DATA_TYPE_BFP16 = 6, // bfp16 + RT_DATA_TYPE_BFP32 = 7, // bfp32 + RT_DATA_TYPE_UINT8 = 8, // uint8 + RT_DATA_TYPE_UINT16= 9, // uint16 + RT_DATA_TYPE_UINT32= 10,// uint32 RT_DATA_TYPE_END } rtDataType_t; diff --git a/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h b/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h index e436dafd..47c41c48 100644 --- a/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h +++ b/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h @@ -1,14 +1,14 @@ /** * @file tune_api.h * - * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.\n + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved.\n * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n - * 描述:mstune调优接口头文件 + * 描述:aoe调优接口头文件 */ -/** @defgroup mstune mstune调优接口 */ +/** @defgroup aoe aoe调优接口 */ #ifndef TUNE_API_H #define TUNE_API_H #include @@ -16,11 +16,12 @@ #include #include "graph/graph.h" #include "ge/ge_api.h" +#include "aoe_types.h" /** - * @ingroup mstune + * @ingroup aoe * - * mstune status + * aoe status */ enum MsTuneStatus { MSTUNE_SUCCESS, /** tune success */ @@ -98,7 +99,7 @@ struct RunnerConfig { #endif /** - * @ingroup mstune + * @ingroup aoe * @par 描述: 命令行调优 * * @attention 无 @@ -112,10 +113,10 @@ struct RunnerConfig { * @see 无 * @since */ -MsTuneStatus MsTuning(const std::map &option, std::string &msg); +AoeStatus AoeOfflineTuning(const std::map &option, std::string &msg); /** - * @ingroup mstune + * @ingroup aoe * @par 描述: 梯度调优 * * @attention 无 @@ -134,4 +135,23 @@ MsTuneStatus MsTuning(const std::map &option, std::str extern "C" MsTuneStatus MsTrainTuning(ge::Graph &tuningGraph, std::vector &dependGraph, ge::Session *session, const std::map> &option); +/** + * @ingroup aoe + * @par 描述: 梯度调优 + * + * @attention 无 + * @param tuningGraph [IN] 调优图 + * @param dependGraph [IN] 调优依赖图 + * @param session [IN] ge连接会话 + * @param option [IN] 参数集. 包含调优参数及ge参数 + * @retval #AOE_SUCCESS 执行成功 + * @retval #AOE_FAILED 执行失败 + * @par 依赖: + * @li tune_api.cpp:该接口所属的开发包。 + * @li tune_api.h:该接口声明所在的头文件。 + * @see 无 + * @since + */ +extern "C" AoeStatus AoeOnlineTuning(ge::Graph &tuningGraph, std::vector &dependGraph, + ge::Session *session, const std::map> &option); #endif From 3e5f9dac74111b4f0432517d77a70408c2e7632f Mon Sep 17 00:00:00 2001 From: shenwei41 Date: Thu, 25 Feb 2021 15:55:17 +0800 Subject: [PATCH 15/59] update include headers_0225 --- inc/external/acl/acl_base.h | 18 +++ inc/external/acl/acl_mdl.h | 12 ++ inc/external/acl/acl_rt.h | 14 ++ inc/external/hccl/hccl.h | 33 +++-- inc/external/hccl/hccl_types.h | 84 +++++------ inc/external/runtime/rt_error_codes.h | 136 +++++++++--------- .../inc/ops/elewise_calculation_ops.h | 26 ++++ third_party/fwkacllib/inc/ops/math_ops.h | 30 ++++ third_party/fwkacllib/inc/ops/nn_norm_ops.h | 28 ++++ .../fwkacllib/inc/ops/nonlinear_fuc_ops.h | 58 ++++++++ .../fwkacllib/inc/ops/transformation_ops.h | 43 +++++- third_party/fwkacllib/inc/runtime/event.h | 5 + third_party/fwkacllib/inc/toolchain/slog.h | 8 +- 13 files changed, 361 insertions(+), 134 deletions(-) diff --git a/inc/external/acl/acl_base.h b/inc/external/acl/acl_base.h index 165b0812..657bf67c 100644 --- a/inc/external/acl/acl_base.h +++ b/inc/external/acl/acl_base.h @@ -174,6 +174,12 @@ typedef enum { ACL_ERROR = 3, } aclLogLevel; +typedef enum { + ACL_MEMTYPE_DEVICE = 0, + ACL_MEMTYPE_HOST = 1, +} aclMemType; + + /** * @ingroup AscendCL * @brief Converts data of type aclFloat16 to data of type float @@ -594,6 +600,18 @@ ACL_FUNC_VISIBILITY aclError aclSetTensorDynamicInput(aclTensorDesc *desc, const */ ACL_FUNC_VISIBILITY aclError aclSetTensorConst(aclTensorDesc *desc, void *dataBuffer, size_t length); +/** + * @ingroup AscendCL + * @brief Set tensor memory type specified by the tensor description + * + * @param desc [OUT] pointer to the instance of aclTensorDesc + * @param memType [IN] ACL_MEMTYPE_DEVICE means device, ACL_MEMTYPE_HOST means host + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclSetTensorPlaceMent(aclTensorDesc *desc, aclMemType memType); + /** * @ingroup AscendCL * @brief an interface for users to output APP logs diff --git a/inc/external/acl/acl_mdl.h b/inc/external/acl/acl_mdl.h index 4f3e257f..3a62ce32 100644 --- a/inc/external/acl/acl_mdl.h +++ b/inc/external/acl/acl_mdl.h @@ -1203,6 +1203,18 @@ ACL_FUNC_VISIBILITY aclError aclmdlDestroyConfigHandle(aclmdlConfigHandle *handl ACL_FUNC_VISIBILITY aclError aclmdlSetConfigOpt(aclmdlConfigHandle *handle, aclmdlConfigAttr attr, const void *attrValue, size_t valueSize); +/** + * @ingroup AscendCL + * @brief get real tensor name from modelDesc + * + * @param modelDesc [IN] pointer to modelDesc + * @param name [IN] tensor name + * + * @retval the pointer of real tensor name + * @retval Failure return NULL + */ +ACL_FUNC_VISIBILITY const char *aclmdlGetTensorRealName(const aclmdlDesc *modelDesc, const char *name); + #ifdef __cplusplus } #endif diff --git a/inc/external/acl/acl_rt.h b/inc/external/acl/acl_rt.h index 8fb7f05a..703ca4ca 100644 --- a/inc/external/acl/acl_rt.h +++ b/inc/external/acl/acl_rt.h @@ -25,6 +25,8 @@ extern "C" { #endif +#define ACL_EVENT_TIME_LINE 0x00000008u + typedef enum aclrtRunMode { ACL_DEVICE, ACL_HOST, @@ -425,6 +427,18 @@ ACL_FUNC_VISIBILITY aclError aclrtGetDeviceCount(uint32_t *count); */ ACL_FUNC_VISIBILITY aclError aclrtCreateEvent(aclrtEvent *event); +/** + * @ingroup AscendCL + * @brief create event instance with flag + * + * @param event [OUT] created event + * @param flag [IN] event flag + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtCreateEventWithFlag(aclrtEvent *event, uint32_t flag); + /** * @ingroup AscendCL * @brief destroy event instance diff --git a/inc/external/hccl/hccl.h b/inc/external/hccl/hccl.h index 46d934e6..311e78f2 100644 --- a/inc/external/hccl/hccl.h +++ b/inc/external/hccl/hccl.h @@ -27,7 +27,7 @@ #ifdef __cplusplus extern "C" { -#endif // __cplusplus +#endif // __cplusplus /** * @brief Initialize HCCL. @@ -66,15 +66,14 @@ extern HcclResult HcclCommInitRootInfo(uint32_t nRanks, const HcclRootInfo *root * @param sendBuf A pointer identifying the input data address of the operator. * @param recvBuf A pointer identifying the output data address of the operator. * @param count An integer(u64) identifying the number of the output data. - * @param dataType The data type of the operator, must be one of the following types: int8, int16, int32, float16, - * float32. + * @param dataType The data type of the operator, must be one of the following types: int8, int16, int32, float16, float32. * @param op The reduction type of the operator, must be one of the following types: sum, min, max, prod. * @param comm A pointer identifying the communication resource based on. * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclAllReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType, HcclReduceOp op, - HcclComm comm, aclrtStream stream); +extern HcclResult HcclAllReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType, +HcclReduceOp op, HcclComm comm, aclrtStream stream); /** * @brief Broadcast operator. @@ -85,10 +84,10 @@ extern HcclResult HcclAllReduce(void *sendBuf, void *recvBuf, uint64_t count, Hc * @param root An integer(u32) identifying the the root rank in the operator. * @param comm A pointer identifying the communication resource based on * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclBroadcast(void *buf, uint64_t count, HcclDataType dataType, uint32_t root, HcclComm comm, - aclrtStream stream); +extern HcclResult HcclBroadcast(void *buf, uint64_t count, HcclDataType dataType, uint32_t root, HcclComm comm, +aclrtStream stream); /** * @brief ReduceScatter operator. @@ -100,10 +99,10 @@ extern HcclResult HcclBroadcast(void *buf, uint64_t count, HcclDataType dataType * @param op The reduction type of the operator, must be one of the following types: sum, min, max, prod. * @param comm A pointer identifying the communication resource based on. * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclReduceScatter(void *sendBuf, void *recvBuf, uint64_t recvCount, HcclDataType dataType, - HcclReduceOp op, HcclComm comm, aclrtStream stream); +extern HcclResult HcclReduceScatter(void *sendBuf, void *recvBuf, uint64_t recvCount, HcclDataType dataType, +HcclReduceOp op, HcclComm comm, aclrtStream stream); /** * @brief AllGather operator. @@ -114,10 +113,10 @@ extern HcclResult HcclReduceScatter(void *sendBuf, void *recvBuf, uint64_t recvC * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. * @param comm A pointer identifying the communication resource based on. * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclAllGather(void *sendBuf, void *recvBuf, uint64_t sendCount, HcclDataType dataType, HcclComm comm, - aclrtStream stream); +extern HcclResult HcclAllGather(void *sendBuf, void *recvBuf, uint64_t sendCount, HcclDataType dataType, +HcclComm comm, aclrtStream stream); /** * @brief Destroy HCCL comm @@ -130,5 +129,5 @@ extern HcclResult HcclCommDestroy(HcclComm comm); #ifdef __cplusplus } -#endif // __cplusplus -#endif // HCCL_H_ +#endif // __cplusplus +#endif // HCCL_H_ diff --git a/inc/external/hccl/hccl_types.h b/inc/external/hccl/hccl_types.h index 0e832396..50a64795 100644 --- a/inc/external/hccl/hccl_types.h +++ b/inc/external/hccl/hccl_types.h @@ -16,10 +16,10 @@ /** * @file hccl_types.h - * @brief HCCL data type definition - * + * @brief HCCL data type definition + * */ - + #ifndef HCCL_TYPES_H_ #define HCCL_TYPES_H_ @@ -27,33 +27,33 @@ #ifdef __cplusplus extern "C" { -#endif // __cplusplus +#endif // __cplusplus /** * @brief HCCL functions return value definition */ typedef enum { - HCCL_SUCCESS = 0, /**< success */ - HCCL_E_PARA = 1, /**< parameter error */ - HCCL_E_PTR = 2, /**< empty pointer */ - HCCL_E_MEMORY = 3, /**< memory error */ - HCCL_E_INTERNAL = 4, /**< internal error */ - HCCL_E_NOT_SUPPORT = 5, /**< not support feature */ - HCCL_E_NOT_FOUND = 6, /**< not found specific resource */ - HCCL_E_UNAVAIL = 7, /**< resource unavailable */ - HCCL_E_SYSCALL = 8, /**< call system interface error */ - HCCL_E_TIMEOUT = 9, /**< timeout */ - HCCL_E_OPEN_FILE_FAILURE = 10, /**< open file fail */ - HCCL_E_TCP_CONNECT = 11, /**< tcp connect fail */ - HCCL_E_ROCE_CONNECT = 12, /**< roce connect fail */ - HCCL_E_TCP_TRANSFER = 13, /**< tcp transfer fail */ - HCCL_E_ROCE_TRANSFER = 14, /**< roce transfer fail */ - HCCL_E_RUNTIME = 15, /**< call runtime api fail */ - HCCL_E_DRV = 16, /**< call driver api fail */ - HCCL_E_PROFILING = 17, /**< call profiling api fail */ - HCCL_E_CCE = 18, /**< call cce api fail */ - HCCL_E_NETWORK = 19, /**< call network api fail */ - HCCL_E_RESERVED /**< reserved */ + HCCL_SUCCESS = 0, /**< success */ + HCCL_E_PARA = 1, /**< parameter error */ + HCCL_E_PTR = 2, /**< empty pointer */ + HCCL_E_MEMORY = 3, /**< memory error */ + HCCL_E_INTERNAL = 4, /**< internal error */ + HCCL_E_NOT_SUPPORT = 5, /**< not support feature */ + HCCL_E_NOT_FOUND = 6, /**< not found specific resource */ + HCCL_E_UNAVAIL = 7, /**< resource unavailable */ + HCCL_E_SYSCALL = 8, /**< call system interface error */ + HCCL_E_TIMEOUT = 9, /**< timeout */ + HCCL_E_OPEN_FILE_FAILURE = 10, /**< open file fail */ + HCCL_E_TCP_CONNECT = 11, /**< tcp connect fail */ + HCCL_E_ROCE_CONNECT = 12, /**< roce connect fail */ + HCCL_E_TCP_TRANSFER = 13, /**< tcp transfer fail */ + HCCL_E_ROCE_TRANSFER = 14, /**< roce transfer fail */ + HCCL_E_RUNTIME = 15, /**< call runtime api fail */ + HCCL_E_DRV = 16, /**< call driver api fail */ + HCCL_E_PROFILING = 17, /**< call profiling api fail */ + HCCL_E_CCE = 18, /**< call cce api fail */ + HCCL_E_NETWORK = 19, /**< call network api fail */ + HCCL_E_RESERVED /**< reserved */ } HcclResult; /** @@ -65,37 +65,37 @@ typedef void *HcclComm; * @brief HCCL Reduction opperation */ typedef enum { - HCCL_REDUCE_SUM = 0, /**< sum */ - HCCL_REDUCE_PROD = 1, /**< prod */ - HCCL_REDUCE_MAX = 2, /**< max */ - HCCL_REDUCE_MIN = 3, /**< min */ - HCCL_REDUCE_RESERVED /**< reserved */ + HCCL_REDUCE_SUM = 0, /**< sum */ + HCCL_REDUCE_PROD = 1, /**< prod */ + HCCL_REDUCE_MAX = 2, /**< max */ + HCCL_REDUCE_MIN = 3, /**< min */ + HCCL_REDUCE_RESERVED /**< reserved */ } HcclReduceOp; /** * @brief HCCL data type */ typedef enum { - HCCL_DATA_TYPE_INT8 = 0, /**< int8 */ - HCCL_DATA_TYPE_INT16 = 1, /**< int16 */ - HCCL_DATA_TYPE_INT32 = 2, /**< int32 */ - HCCL_DATA_TYPE_FP16 = 3, /**< fp16 */ - HCCL_DATA_TYPE_FP32 = 4, /**< fp32 */ - HCCL_DATA_TYPE_INT64 = 5, /**< int64 */ - HCCL_DATA_TYPE_UINT64 = 6, /**< uint64 */ - HCCL_DATA_TYPE_RESERVED /**< reserved */ + HCCL_DATA_TYPE_INT8 = 0, /**< int8 */ + HCCL_DATA_TYPE_INT16 = 1, /**< int16 */ + HCCL_DATA_TYPE_INT32 = 2, /**< int32 */ + HCCL_DATA_TYPE_FP16 = 3, /**< fp16 */ + HCCL_DATA_TYPE_FP32 = 4, /**< fp32 */ + HCCL_DATA_TYPE_INT64 = 5, /**< int64 */ + HCCL_DATA_TYPE_UINT64 = 6, /**< uint64 */ + HCCL_DATA_TYPE_RESERVED /**< reserved */ } HcclDataType; -const uint32_t HCCL_ROOT_INFO_BYTES = 4108; // 4108: root info length +const uint32_t HCCL_ROOT_INFO_BYTES = 4108; // 4108: root info length /** * @brief HCCL root info */ typedef struct HcclRootInfoDef { - char internal[HCCL_ROOT_INFO_BYTES]; + char internal[HCCL_ROOT_INFO_BYTES]; } HcclRootInfo; #ifdef __cplusplus } -#endif // __cplusplus -#endif // HCCL_TYPES_H_ +#endif // __cplusplus +#endif // HCCL_TYPES_H_ diff --git a/inc/external/runtime/rt_error_codes.h b/inc/external/runtime/rt_error_codes.h index 2109fb79..47f16d9f 100644 --- a/inc/external/runtime/rt_error_codes.h +++ b/inc/external/runtime/rt_error_codes.h @@ -23,80 +23,80 @@ extern "C" { #endif -static const int32_t ACL_RT_SUCCESS = 0; // success +static const int32_t ACL_RT_SUCCESS = 0; // success -static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid -static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id -static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null -static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context -static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context -static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal -static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned -static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed -static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed -static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream -static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread -static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set -static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create -static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream -static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type -static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle -static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type +static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid +static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id +static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null +static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context +static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context +static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal +static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned +static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed +static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed +static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream +static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread +static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set +static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create +static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream +static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type +static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle +static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type -static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support -static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error -static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error -static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow -static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device -static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail -static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission -static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource -static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource -static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource -static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource +static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support +static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error +static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error +static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow +static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device +static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail +static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission +static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource +static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource +static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource +static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource -static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error -static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error -static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error +static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error +static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error #ifdef __cplusplus } #endif -#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ +#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index bc35f4ce..6207c917 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -3781,6 +3781,32 @@ REG_OP(ArgMaxGradD) .REQUIRED_ATTR(dimension, Int) .OP_END_FACTORY_REG(ArgMaxGradD) +/** +*@brief Returns cosine similarity between x1 and x2,computed along dim. \n + +*@par Inputs: +*Two inputs, including: +* @li input_x1: A tensor. Must be the following types: +* float32. \n + +*@par Inputs: +*@li input_x2: A tensor. Must of the following types: +* float32. \n + +*@par Outputs: +*@li output_y: A Tensor with the same type of input_x's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator CosineSimilarity. \n +*/ +REG_OP(CosineSimilarity) + .INPUT(input_x1, TensorType({DT_FLOAT})) /* "First operand." */ + .INPUT(input_x2, TensorType({DT_FLOAT})) /* "Second operand." */ + .OUTPUT(output_y, TensorType({DT_FLOAT})) /* "Result, has same element type as two inputs" */ + .ATTR(dim, Int, 1) + .ATTR(eps, Float, 1e-8) + .OP_END_FACTORY_REG(CosineSimilarity) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_ELEWISE_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/math_ops.h b/third_party/fwkacllib/inc/ops/math_ops.h index 50d058ba..bd30e50c 100644 --- a/third_party/fwkacllib/inc/ops/math_ops.h +++ b/third_party/fwkacllib/inc/ops/math_ops.h @@ -952,6 +952,36 @@ REG_OP(Angle) .ATTR(Tout, Type, DT_FLOAT) .OP_END_FACTORY_REG(Angle) +/** +*@brief Computes the gradient of SoftMarginLossGrad. \n + +*@par Inputs: +*Three inputs, including: +* @li predict: A tensor. Must be one of the following types: +* float16, float32. \n +* @li label: A tensor with same shape of predict. Must be one of the following types: +* float16, float32. \n +* @li dout: A tensor with same shpae of predcit. Must be one of the following types: +* float16, float32. \n + +*@par Attributes: +* @li reduction: Specifies the reduction to apply to the output: +* 'none' | 'mean' | 'sum'. Default: 'mean'. \n + +*@par Outputs: +* gradient: A Tensor with the same type of predict. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator SoftMarginLoss Backward. \n +*/ +REG_OP(SoftMarginLossGrad) + .INPUT(predict, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(label, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(dout, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(gradient, TensorType({DT_FLOAT16,DT_FLOAT})) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(SoftMarginLossGrad) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATH_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index 00e2020f..041aa765 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -1205,6 +1205,34 @@ REG_OP(Centralization) .ATTR(axes, ListInt, {-1}) .OP_END_FACTORY_REG(Centralization) +/** + *@brief Calculate the loss. Creates a criterion that optimizes a two-class classification + logistic loss between input_x and input_y (containing 1 or -1). \n + + *@par Inputs: + *One inputs, including: + * @li input_x: A tensor. Must be one of the following types: + * float16, float32. \n + * @li input_y: A tensor. Must be one of the following types: + * float16, float32. \n + + *@par Attributes: + *@li lambd: An optional string.Defaults to "mean". \n + + *@par Outputs: + *output_z: while reduction == "none", A Tensor with the same type and shape of input_x's. \n + * while reduction == "sum" or "mean", A Tensor with the same type of input_x , shape of which is (1,) + + *@par Third-party framework compatibility + *Compatible with the Pytorch operator SoftMarginLoss. \n + */ +REG_OP(SoftMarginLoss) + .INPUT(input_x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(input_y, TensorType({DT_FLOAT, DT_FLOAT16})) + .ATTR(reduction, String, "mean") + .OUTPUT(output_z, TensorType({DT_FLOAT, DT_FLOAT16})) + .OP_END_FACTORY_REG(SoftMarginLoss) + /** * @brief Computes gradients of sigmoid_cross_entropy_with_logits_v2. diff --git a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h index a225bb5f..a911fa51 100644 --- a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h +++ b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h @@ -792,6 +792,34 @@ REG_OP(HardShrink) .ATTR(lambd, Float, 0.5) .OP_END_FACTORY_REG(HardShrink) +/** +*@brief Calculate the hard shrink grad function. \n +* +* Computes the gradient for the HardShrink: if x > lambda or x < -lambda, x,otherwise 0 +* +*@par Inputs: +*Two inputs, including: +* @li gradients: A tensor. Must be one of the following types: +* float16, float32. \n +* @li features: A tensor. Must be one of the following types: +* float16, float32. \n +* +*@par Outputs: +*backprops: A Tensor with the same type and shape of features's. \n +* +*@par Attributes: +*@li lambda: An optional float.Defaults to 0.5. \n +* +*@par Third-party framework compatibility +*Compatible with the Pytorch operator Hardshrink_backward. \n +*/ + REG_OP(HardShrinkGrad) + .INPUT(gradients, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(features, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(backprops, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(lambda, Float, 0.5) + .OP_END_FACTORY_REG(HardShrinkGrad) + /** * @brief Calculate the hard sigmoid function. \n @@ -884,6 +912,36 @@ REG_OP(LogSigmoid) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) /* "input:x" */ .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) /* "output:y" */ .OP_END_FACTORY_REG(LogSigmoid) + +/** +*@brief Calculate the backward outputs of the function "hard_sigmoid" \n + +*@par Inputs: +*One inputs, including: +* @li grads: A tensor. Must be one of the following types: +* float16, float32. \n +* @li input_x: A tensor. Must be one of the following types: +* float16, float32. \n + +*@par Outputs: +*One outputs, including: +* @li y: A tensor with the same type and shape of x's. \n + +* @par Attributes: +* @li alpha: An optional float. Defaults to 0.16666666. \n +* @li beta: An optional float. Defaults to 0.5. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator LogSigmoidGrad. \n +*/ +REG_OP(HardSigmoidGrad) + .INPUT(grads, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(input_x, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .ATTR(alpha, Float, 0.16666666) + .ATTR(beta, Float, 0.5) + .OP_END_FACTORY_REG(HardSigmoidGrad) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NONLINEAR_FUC_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/transformation_ops.h b/third_party/fwkacllib/inc/ops/transformation_ops.h index 42c7745a..32baf56c 100644 --- a/third_party/fwkacllib/inc/ops/transformation_ops.h +++ b/third_party/fwkacllib/inc/ops/transformation_ops.h @@ -737,14 +737,51 @@ where ho/wo is do = (output_d + 2*padding_d - dilation_d*(kernel_d - 1) - 1)//st * Compatible with Pytorch col2im/im2col_backward operator. */ REG_OP(Col2im) - .INPUT(x, TensorType({DT_FLOAT})) - .INPUT(output_size, TensorType({DT_INT32})) - .OUTPUT(y, TensorType({DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(output_size, TensorType({DT_INT32, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) .REQUIRED_ATTR(kernel_size, ListInt) .REQUIRED_ATTR(dilation, ListInt) .REQUIRED_ATTR(padding, ListInt) .REQUIRED_ATTR(stride, ListInt) .OP_END_FACTORY_REG(Col2im) + +/** +*@brief Generates a 2D or 3D flow field (sampling grid), given a batch of affine +matrices theta. \n + +*@par Inputs: +*Input theta must be float16 or float, output_size must be int32 type.Inputs +include: +*@li theta: input batch of affine matrices with shape (N,2,3) for 2D or (N,3,4) +for 3D +*@li output_size: the target output image size. (N×C×H×W for 2D or N×C×D×H×W for +3D) Example: torch.Size((32, 3, 24, 24)) . \n + + +*@par Attributes: +*align_corners: if True, consider -1 and 1 to refer to the centers of the corner +pixels rather than the image corners.Refer to grid_sample() for a more complete +description. A grid generated by affine_grid() should be passed to grid_sample() +with the same setting for this option. Default: False \n + +*@par Outputs: +*@li y: A 2-D integer tensor of shape [M] representing the +selected indices from the boxes tensor, where M <= max_output_size. \n + +*@attention Constraints: +*Input theta must be float16 or float, output_size must be int32 type . \n + +*@par Third-party framework compatibility +*Compatible with Pytorch affine_grid operator. +*/ + +REG_OP(AffineGrid) + .INPUT(theta, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(output_size, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(align_corners, Bool, false) + .OP_END_FACTORY_REG(AffineGrid) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_TRANSFORMATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/runtime/event.h b/third_party/fwkacllib/inc/runtime/event.h index 41e611ea..d4219559 100644 --- a/third_party/fwkacllib/inc/runtime/event.h +++ b/third_party/fwkacllib/inc/runtime/event.h @@ -30,6 +30,11 @@ extern "C" { #define RT_EVENT_DEFAULT (0x00) #define RT_EVENT_WITH_FLAG (0x01) +#define RT_EVENT_DDSYNC_NS 0x01U +#define RT_EVENT_STREAM_MARK 0x02U +#define RT_EVENT_DDSYNC 0x04U +#define RT_EVENT_TIME_LINE 0x08U + /** * @ingroup dvrt_event * @brief create event instance diff --git a/third_party/fwkacllib/inc/toolchain/slog.h b/third_party/fwkacllib/inc/toolchain/slog.h index 7c4f7be2..c6be6b79 100644 --- a/third_party/fwkacllib/inc/toolchain/slog.h +++ b/third_party/fwkacllib/inc/toolchain/slog.h @@ -141,7 +141,7 @@ enum { IDEDD, /**< IDE daemon device */ IDEDH, /**< IDE daemon host */ HCCL, /**< HCCL */ - FMK, /**< Framework */ + FMK, /**< Adapter */ HIAIENGINE, /**< Matrix */ DVPP, /**< DVPP */ RUNTIME, /**< Runtime */ @@ -162,11 +162,11 @@ enum { MDCDEFAULT, /**< MDC undefine */ MDCSC, /**< MDC spatial cognition */ MDCPNC, - MLL, + MLL, /**< abandon */ DEVMM, /**< Dlog memory managent */ KERNEL, /**< Kernel */ LIBMEDIA, /**< Libmedia */ - CCECPU, /**< ai cpu */ + CCECPU, /**< aicpu shedule */ ASCENDDK, /**< AscendDK */ ROS, /**< ROS */ HCCP, @@ -179,7 +179,7 @@ enum { TSDUMP, /**< TSDUMP module */ AICPU, /**< AICPU module */ LP, /**< LP module */ - TDT, + TDT, /**< tsdaemon or aicpu shedule */ FE, MD, MB, From a1795d6554728255e6436b150088a3a2c47c262d Mon Sep 17 00:00:00 2001 From: shenwei41 Date: Thu, 25 Feb 2021 19:52:40 +0800 Subject: [PATCH 16/59] update metdef --- metadef | 2 +- .../prebuild/aarch64/liberror_manager.so | Bin 1080976 -> 1159216 bytes .../prebuild/x86_64/liberror_manager.so | Bin 1133320 -> 1168920 bytes 3 files changed, 1 insertion(+), 1 deletion(-) diff --git a/metadef b/metadef index a2b80cb2..2f2cd62c 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit a2b80cb22a62a6757c7dd31e684ca632e0b79268 +Subproject commit 2f2cd62c399079f8c3b0dc9aada81c447878dad7 diff --git a/third_party/prebuild/aarch64/liberror_manager.so b/third_party/prebuild/aarch64/liberror_manager.so index eed6f93f61aa42bf66414982ebd78809fd1c99f3..6358365b0c05acca93660d60e3cf70a0a3444d73 100755 GIT binary patch literal 1159216 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�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%0D~|Ddte6~g1vA84#7D%0asw*-_rj7 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%0DWw{ce&mincQQE8)) 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 literal 1080976 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
xa;f#`qcZ6y`IE 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

qngPQM*a*kRx`3 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

uV`%lyUaY9ppW{L0rd|>UFx8LIJ`6N!1 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

2T;+9wVD{D;mxIQ(LYZR5uo5vDZB4Dt| zD&@;IJH=(cLXzehW%bBfeMO!29_1Qty3v#gGp}xFtOV(3GX=c%d0Pzmu(p4t^P ze(54BfyJ*VC8`|1^nyKALOI?Byl!es*q(^8V(EM+UD*Qm%T}opMVUNujhP&Z5T8p8 z|FA)0wq_P8%kQagWEjads&zY7oXI?kL#G?_EHN7y?Sa#6)mM_iIdf)-vuIvfkNdtr zy}yc+$}IB9_c&QqDRAiu{fq(po78rkLY)K_|hJhnDs;%6SuuobTMSSspQ ziKdoac&}0tc2c7$ssr_Ef1W~O3_;@Y65_t%5J)uM&XhoXW1v9}Pk5?MH|A>9uEpzg z)K*#459-uq=5n*N7Lk)NZ{1oTu2{BCQHXdyAx0{| z+wT__WP{J^_hN52Rn~d(D>s^NKI7v`PkfShbvP8=_EAG8?TY9+7@dx31pD2Sn)X+0=O$82nA#}M1HCu%Rs@tK` ztKyk@)woyco?R4X3fk6yX@?46hT;dq694>)(Mo4<)>4dfFdNNU zPGfRnb(~eCjm2t$s;gsGCK9Pv0$NtAsxarJ=sl~Lxcf0m(Ps7?QdH0d&MtAngEHB8L>KdK zF~0sXnd+>nC5f1TDoylmiLx#|CR?nu#es&pTF!?tf2taDjS|`0hur06N|{APJQ+I+ zJpP&9`YL4+pqPA(n5FX|O;nFn;N01>Naxc#W6Ibp_Eg8mGQw3v^e$ychgn5v)uxC1zJ(?$PyW=O^r@Vq;#SMtLiIF2E~)6qoajcBvQZZ z`9?)YNf}d5b?pjmqMKAOPDP)Is;bkYd8MVlqZ~FxQr224^br!fBx?eyylRxl0M0eE zxvkThl5H4%Z-bYkar9*!CV-v*Q7QC|HqcD&8Wrl`m1tgKm0cZ6BjeLH**mMT^aE;= zu%)SBB40sPEuhhMV*NWC>MANdHQu@^^pWgRDz2C*G{0nFXuC^qio8JN;dyEHypk{B z>4nMym7}N5_%1UASRVzE0c6Sal@*BP@;c8L(?0aek6dH1c{@5sn>sprKf2;IBZN)H z%(_}x=vg}1tDYD@Ol^`n$LplMB7ImkvPzPHG)J9Ukd>A#PNLNQp-CB=s4O}vYiP6X ze7eDz$Rh=orma(cuRSTNA)KW_`*NoZ1 z=X#G!1#(zgEdk9Dpn9AhzOuGb_PJ%jtQt=b%Zf!eg8DhWfD(}7u&RRO>FT|*v5PN4 zCyMbSz5#O^8uePX48d7|%fMQFM*A;5y%LJKi0Ddea{41KzmgPFwBsUF!S>h~rz@Y{fuDURi<3W z4q#iw3*SXkiQLB)LKVwJ;UsAkvYf~hcrAaiHbxb)MGsr^tJI7vl^!l#gRj=h8Dv)A z`Y)DVt&3Nfk`XOC*U%y)ZWtv}YBgsVG7!v|YBe-RTR&xht3`!j8c)_hRmluJ=U8Xq zm02h?b8t$>aIys(%9<9K6`Yln#vOA#t!pzRLTF%VCWpSwyW$7KAYj0$<*%93=QmZ9 zra(13S-QlsBw<{-<#KG$Oob$Cf}>TZEVoV+dW^)L>2yJ=1H^`u(P$-)t6#cac`oP- zix2kpnl6jF3f9XtRti;Jd^_UOajM1Egt+?5bf#I!!6Y73=%rpWolLRGQfW3wr=_Y- zr&z&)IGQAm9jF%Hl`@-J9TuopgT&{z*y8i9bo%^pLq!}a;xDw4=wWHyrIW>>9Dg$|zeu#ASCoL| z@wB{aV$=9)8^m92@icjQ%ms0GA1-~M0k@vV@&EMDl6-pHK-2fav!?1QVwgHjaTKw;zjs4 zrN*RWC9u;QpAM%*00t-YggmQcZ%Fd|W?oKv`Gv``p1`l97c|<9B$GvggDJ_Dg3Wk6 zpY!+1(6b)c(vlIInyl<`^HuV_2V1eSZZa1ndgs!%=U_{gWJkglE3BBUmQ+#G-1K^} z?5OmuGN0ZpRiZ5m1eqqSSp@T0=47$IqD|5hW8B_GEVG&}ObyLSC8fVx4SEq_YuO|R z=JnvG!dQ9HbfynInnd+*l5|m%)=Ej=s%;X}8nQ1-WFN`eUa_aK_yaR=ETa?rto^(^ z`By6&IY}y=H*TIuyduk7S6JRAnva87{8|e^IlxoV|Z5`CP;ieS7o zdgQ64QUu?+3CbaLe2NRta$3(UOqrt32+OJPsdLr2?}coijdm8vQ)2pZfm&7T>lyk) zzW$+?wXy?(Gtz!*QN6eeJXQ94r3@**zEOlb8r|hJ^PIO}?wqLi$j9ctwk)%Ym<~pa zaOURb<~WzAhdmZLr!lWpO_{2E0H-` zy*{0?p`z9|Rc&JEGWuSrbGrO@4%}pBo94Xwnsb~nCfgb#DNKG_clCLQbDS~mTQNPW zKgVh77m~>#igTPjx`!BfUYF&x--@;OlogFPNcEmQU9|T|ROJm|aznDc8@aFe8)e-& z&iH;ML9Amcs_NJkGaZJ$ODqxnKO>*!VU}2fZKJHGkR?y{Ps!2#WX=&CUUIYq{hyJa zWJBE2AzBfMu5)IO$XSwq$v>3}7E1k;DJhhSrCh)(y%?@ZM_WuQ|9z)E{FiKG^B|qF z|LXmmo6`NQC%_n)mcC^s{O9Chb+KlZI+v!NY#i~A-Py5cS+f_O72nZf>BI*5Kdpu& z1N@wS?9Nra$CI(@aA2h;+Mh|)&-4-h;H`;`skqtLZq{JM&1cD-WZ7X2Ps5y_)!Y^1 zgMO@b$`tiv=+qhV%%T(`YXueqxMj<$I1GWmyIehGhf37SFfL_pWJT*w(Eq(x9AHOA z^zWZrS+v&JMPJ*j&%pZS9AjUz;0&tgwL|!WD(bRhn&T{U*&}B$%l-DXQSXh9QE+4o zI7hDnbanKJT5s4F6j570#+BGrUmF{v?#TFquaB*(Kfg~|IQ6+gk=y8#p?`jrG3Ib3 z>$*M@z;opOa(U1IYeK($E?ce8Vs0FtdQa6o}!j4JdJ?$OHD}Ro<25;vtr27IZ2`d4`?q@|8;X7ov-??bNYyX`iA=I8xmprhZ#RT%;x{;$k9V7h5d6xMgRv;qK{r4>C))`%=rD^ zy8omXhDyv+H{nQ?jD1yUvwEyr%;NNxi20+()Ntf=Y75tzC`b2PX>w*xZB&^>M|Go} z+<2F+O$MCBwO-nFh$>@P%{+Jgz4*DhZ!uO&ZnUR!nA z@z1IsgZ?j5drJRw>h@bZpwp(Adlr3{g%R-^rhSuy)Lp08*!S9T6UqA@IemL1d93D+ znGVPGjC3SRsK2@#_q{Flo%O>HDXZP1M*Ytu?JuF#MT%x6+oiC&>aV;%@i(LY&)k3bo6)C4{V%`2@HeAh2GXD5a{HUnXSqF& zkjB3meX9SL+ulC?m+}Aq&FKF-`d?FMHFaBmIPQP%w3XxwAa?VW=j-J~1J$c$>MvgC zCsby~zIUOYhnU^y=Oy{c((pV*>PTvm?|bpL#;R2R+`s05H@mt=6AB3n30}h0gb?BT zgm>QQ>i&T6C&HJ6LHoM8ziJDaT(=H7)P3%NL)~wtAL>2<`~~3<;R=GI|Do=de#CvL z(@9z@%pA!5VTZbReEm@OWUzr?5bh^Z`C)Lltv zKUJrbv{pEC#G&pBCqU2mL){M&-Xk;-PUGIQSL^U1`1cM!>mv=bNVn0JR<8RJrrGlR zz1n)BNyBMOPim65%vk$mTkqFoiIa z;3h00TuN9$XdvA8*rD#bo;=k3FyRHldj#XDL)~8`j3b;+s3KfL_zvMg!Vbb)gwF|I zX+P9GnovTxl+Z+IBm9`KneZFJCxl}+9qJxIIG1n{;R?b{gnuV&G($VISl9oT@!5Z{ zc7C)4ee}=J{VHTV=_pRk4SKEc8L@dV2TvEu^&xU&rb#?O9%) z9JYr%7IyU;Ah%})LOCi_}jy**t&Lv4y49|LxlGyEH!+0l1r z4!7Q(m$ICM2>k}T#G4I#8M7+kW~H}bRgYWh#oq~c?euVTO#H@Erf5t^ zNk4Nxy8i60<)t&Cv<>S*zp>be`yQ^rXUh`)<}C0}CW{)pljNNT24UJRAj$Kh% znaiA$%O`-xlA>{iyc4Xpl8@l=MdOv|&jtRo%NLK!AFrg{Mw8jjMEb{#GfU{vhy=!@ z%Ac=mPL@6G>;2EU2d@2`7czWu%@^Gpx!%zAMfW~1{m>WPSu4|wQ@{M8`>t7rF%8@Z z)`5G#?}J_7!{9KNVLT5`1wR9qf+ux<(Y+e{26z|vFW}7=8phH6ySg`mK5!4XF}d~SXcK3@ZvMN zy0>0z7~_WHp8yAD^LvS5oH~l%;0d{1-C0WwW9ZnfZZ~*pURSpt>;i8CcjXg5D$RIg zSyy-6=rm&|*hTx_2Z!+qv-2yux~GDdfJ?zTa5Z>4co+C2xDnh3?g5uACqMXoa2Wh~ z6`Tt8t0X^o0=ODH1>6W<)_{A!eP9=OTow7s3}ZYv6}$~x3T_2ggCBr*fq5SCgFbK% zXjGFQJQo~xo?+YsP6ZzVmx6o1)!@_>0^bIULBorj zf>(k!gAX(yub}e^>H{wYyTEneunP?1?nd%~onRF>JU~8h`IY1Ye*o?V_cW0Y{Ax4# z<{QT1RpbM|4OW4>t|A|J+|^y(4}hb=o#1)k2Ves@cmeza$Af3A#@`1%0IminUPC*< z#o$)Z2krxJ1=ANA#?QbkaM-nsC-5S$4!jn;8N45S0DKbM3GN0z06W3Ki+K0T8vKl4 zHs}T?f_2~p;LYF;@B#4CwX_#}`#RbSe(ieNyO{LgRB%4H6s!kVgExV9fj|9rz;)m{@Luo-;0E-~xk2axw}RNN)p}1-=0m%ZK%DB|rEza2+`L z+q4_J7~BaqgCBsmfrBgQKX5d-5p;up0{vk6ZOjMY-QY&>Yq!&G@LI47ycZmX!TKyX z72F3d1qXfyzJXcbU0^e~5!?yx0W;^T0Q7D!2?>3SI@S2JZsz0v`i6g2tWX z2eZNSYQ`;?1#Se3!B4;{Fz>sx8=MZ_3%(BS1m6We08joN?OuUi1xJH^&<(bNb>MB_ z&EQsW1NhQi)C)$yF7QimSPlL0FVGEcxSM*x<^M`P@Mquy;Lv|VKEWyAC!h-)Qp-FE zP6ZGCJNdvN_d+k22i^-_2JQrJ0zUxn1P5P6{or`;Q*a@8)(`0?uo%1ztOhrLw}QLD zhrmz3SHU5d8^!@}Jb1#7$Pea%e(*f-HgGAp0lXF54Z81x&vnQRm<8Ssy1{KApJq0e z-A_L7DsTgM8@L;M4EzM#4Gviez2JCo$d9QP%me+P8@vr{1vi4XfqTHW!Ss6cF_;CO z`XBT!SPWKymx1fRHt=5XKftZvPH-Ri2AJ+ePJTlFf~BAvtO4u5Tfm#az2FA$LvT0v zIrs@U@B!#V;P*g3_y~9#IPj;?4GsbKfYZS)@H}wX73e2$D!36`3cdiY z2Hybh0^bEUg6^M@AG{Rol6Y{K5Bu#w@`H20rC=?%8hjPJ7tDQ#c7yZ5ec&=My%Bi@ zv%oq33E#ke{{`Q`Tfm#a$v>yv;A(IW_*<|G`~V#0$G+S^z2Mr%$OjfaNj|U*+yE|r zihSVDz%Fn%I4nRvgHypF?a&KO23LcNz`MXoa3gpHxCdMdc7cy=g5E0`r(iL-53B+Y zfa}1;n`tjt18xQX4crHw`ZVLBiTM^B4es7fKY^J$=qK=P@Gda-8R`Yy;2!WYunTMk zhc(k*&r&b=9k2@A0ImZ!gZF|%o}*rH8MqI;225XN7*B&);IF`9aLP{P3v_`ugV%!( zfM33Ve1U_1g?xcO0*75i|ASM(pS?)E;8t)Qco4i79Q_jYf{Vd@;A$}aYQ{A<8hrg_ z+6&IvO?yENxB>hbxEtIJegb|74p|LYg;LcxDFF5oK>IL5i_ka_B1E0Ye;IM1S4^9RB;8O4ga5Xq= z5B&sQ`&-%z-UaRhH-PDD&^KTfc<1k^7u*Ndf&KQvXYe@i0q|?!PH-*w0eCAocrEk7 zo3s}k{1)v6AAOs8!G?FJ7o4$=dcj-3ec*xLlkYmpeV6uv*MV;EH((w32k>Ulc#nF) zDd0}98T}YT__%h#T z4|P8P-U{vp-vB=WPdMgK_mCSIhv0bddT=5580ZI&K90Rba2U7|YzFs$w}4&Xo8YkZ ztZ�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 {PxoPD*q@UWYRj>SZyi?$_eWUO1 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�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

-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

=UB$yHcjgxTivo#2C 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 From 10faa7b05281a4ce9760ddc867181a5731b82af6 Mon Sep 17 00:00:00 2001 From: shenwei41 Date: Thu, 11 Mar 2021 17:38:45 +0800 Subject: [PATCH 17/59] change --- CMakeLists.txt | 6 ++---- inc/external/acl/acl.h | 8 ++++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fb21e5e6..947fb016 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,8 +82,8 @@ if (ENABLE_OPEN_SRC) elseif(ENABLE_GE_COV OR ENABLE_GE_UT) add_subdirectory(tests) else() - find_module(slog libalog.so ${ASCEND_ATC_DIR}) - find_module(static_mmpa libmmpa.a ${ASCEND_ATC_DIR}) + find_module(slog libalog.so ${ASCEND_ATC_DIR} ${ASCEND_DRIVER_COMMON_DIR}) + find_module(static_mmpa libmmpa.a ${ASCEND_ATC_DIR} ${ASCEND_RUNTIME_DIR}) if(PLATFORM STREQUAL "train") find_module(adump_server libadump_server.a ${ASCEND_RUNTIME_DIR}) find_module(runtime libruntime.so ${ASCEND_RUNTIME_DIR}) @@ -136,7 +136,6 @@ elseif (ENABLE_D OR ENABLE_ACL) # common libraries find_module(slog libalog.so ${ASCEND_MS_RUNTIME_PATH} ${ATLAS_MS_RUNTIME_PATH}) - find_module(error_manager liberror_manager.so ${ASCEND_MS_RUNTIME_PATH} ${ATLAS_MS_RUNTIME_PATH}) find_module(static_mmpa libmmpa.a ${ASCEND_MS_RUNTIME_PATH} ${ATLAS_MS_RUNTIME_PATH}) if (ENABLE_D) @@ -156,7 +155,6 @@ elseif(ENABLE_MS_TESTCASES) # common libraries find_module(slog libalog.so ${ASCEND_MS_RUNTIME_PATH} ${ATLAS_MS_RUNTIME_PATH}) - find_module(error_manager liberror_manager.so ${ASCEND_MS_RUNTIME_PATH} ${ATLAS_MS_RUNTIME_PATH}) find_module(static_mmpa libmmpa.a ${ASCEND_MS_RUNTIME_PATH} ${ATLAS_MS_RUNTIME_PATH}) set(METADEF_DIR ${CMAKE_CURRENT_LIST_DIR}/metadef) diff --git a/inc/external/acl/acl.h b/inc/external/acl/acl.h index eae87835..ef5b4772 100644 --- a/inc/external/acl/acl.h +++ b/inc/external/acl/acl.h @@ -26,9 +26,9 @@ extern "C" { #endif // Current version is 1.0.0 -#define ACL_MAJOR_VERSION 1 -#define ACL_MINOR_VERSION 0 -#define ACL_PATCH_VERSION 0 +#define ACL_MAJOR_VERSION 1 +#define ACL_MINOR_VERSION 0 +#define ACL_PATCH_VERSION 0 /** * @ingroup AscendCL @@ -70,4 +70,4 @@ ACL_FUNC_VISIBILITY aclError aclrtGetVersion(int32_t *majorVersion, int32_t *min } #endif -#endif // INC_EXTERNAL_ACL_ACL_H_ +#endif // INC_EXTERNAL_ACL_ACL_H_ From 54a48678aeeb7153633ac56df8eaf9307ab97663 Mon Sep 17 00:00:00 2001 From: shenwei41 Date: Fri, 12 Mar 2021 12:18:57 +0800 Subject: [PATCH 18/59] update include headers 0311 --- inc/external/acl/error_codes/ge_error_codes.h | 6 +- inc/external/acl/ops/acl_dvpp.h | 531 ++++++++++-------- scripts/format_source_code.sh | 0 .../fwkacllib/inc/ops/avg_pool_1d_ops.h | 58 ++ .../inc/ops/elewise_calculation_ops.h | 19 + third_party/fwkacllib/inc/ops/image_ops.h | 166 ++++++ third_party/fwkacllib/inc/ops/list_ops.h | 274 +++++++++ third_party/fwkacllib/inc/ops/math_ops.h | 59 ++ .../inc/ops/matrix_calculation_ops.h | 30 + third_party/fwkacllib/inc/ops/nn_norm_ops.h | 54 ++ third_party/fwkacllib/inc/ops/nn_ops.h | 55 ++ .../fwkacllib/inc/ops/nn_pooling_ops.h | 4 +- .../fwkacllib/inc/ops/nonlinear_fuc_ops.h | 28 + third_party/fwkacllib/inc/ops/pad_ops.h | 2 +- third_party/fwkacllib/inc/ops/selection_ops.h | 56 ++ third_party/fwkacllib/inc/runtime/base.h | 2 +- third_party/fwkacllib/inc/runtime/config.h | 23 + third_party/fwkacllib/inc/runtime/kernel.h | 8 +- third_party/fwkacllib/inc/runtime/rt_model.h | 22 +- third_party/fwkacllib/inc/runtime/stream.h | 22 + .../inc/toolchain/tuning_tool/tune_api.h | 82 --- 21 files changed, 1178 insertions(+), 323 deletions(-) mode change 100644 => 100755 scripts/format_source_code.sh create mode 100644 third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h diff --git a/inc/external/acl/error_codes/ge_error_codes.h b/inc/external/acl/error_codes/ge_error_codes.h index b477a18c..cafc5a64 100644 --- a/inc/external/acl/error_codes/ge_error_codes.h +++ b/inc/external/acl/error_codes/ge_error_codes.h @@ -53,9 +53,9 @@ static const uint32_t ACL_ERROR_GE_AIPP_MODE_INVALID = 145016; static const uint32_t ACL_ERROR_GE_OP_TASK_TYPE_INVALID = 145017; static const uint32_t ACL_ERROR_GE_OP_KERNEL_TYPE_INVALID = 145018; static const uint32_t ACL_ERROR_GE_PLGMGR_PATH_INVALID = 145019; -static const uint32_t ACL_ERROR_GE_TRANSSHAPE_FORMAT_INVALID = 145020; -static const uint32_t ACL_ERROR_GE_TRANSSHAPE_SHAPE_INVALID = 145021; -static const uint32_t ACL_ERROR_GE_TRANSSHAPE_DATATYPE_INVALID = 145022; +static const uint32_t ACL_ERROR_GE_FORMAT_INVALID = 145020; +static const uint32_t ACL_ERROR_GE_SHAPE_INVALID = 145021; +static const uint32_t ACL_ERROR_GE_DATATYPE_INVALID = 145022; static const uint32_t ACL_ERROR_GE_MEMORY_ALLOCATION = 245000; static const uint32_t ACL_ERROR_GE_MEMORY_OPERATE_FAILED = 245001; static const uint32_t ACL_ERROR_GE_INTERNAL_ERROR = 545000; diff --git a/inc/external/acl/ops/acl_dvpp.h b/inc/external/acl/ops/acl_dvpp.h index 42ec4a8d..dcaa3936 100644 --- a/inc/external/acl/ops/acl_dvpp.h +++ b/inc/external/acl/ops/acl_dvpp.h @@ -53,123 +53,109 @@ typedef void (*aclvencCallback)(acldvppPicDesc *input, acldvppStreamDesc *output // Supported Pixel Format enum acldvppPixelFormat { - PIXEL_FORMAT_YUV_400 = 0, // 0 - PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1, // 1 - PIXEL_FORMAT_YVU_SEMIPLANAR_420 = 2, // 2 - PIXEL_FORMAT_YUV_SEMIPLANAR_422 = 3, // 3 - PIXEL_FORMAT_YVU_SEMIPLANAR_422 = 4, // 4 - PIXEL_FORMAT_YUV_SEMIPLANAR_444 = 5, // 5 - PIXEL_FORMAT_YVU_SEMIPLANAR_444 = 6, // 6 - PIXEL_FORMAT_YUYV_PACKED_422 = 7, // 7 - PIXEL_FORMAT_UYVY_PACKED_422 = 8, // 8 - PIXEL_FORMAT_YVYU_PACKED_422 = 9, // 9 - PIXEL_FORMAT_VYUY_PACKED_422 = 10, // 10 - PIXEL_FORMAT_YUV_PACKED_444 = 11, // 11 - PIXEL_FORMAT_RGB_888 = 12, // 12 - PIXEL_FORMAT_BGR_888 = 13, // 13 - PIXEL_FORMAT_ARGB_8888 = 14, // 14 - PIXEL_FORMAT_ABGR_8888 = 15, // 15 - PIXEL_FORMAT_RGBA_8888 = 16, // 16 - PIXEL_FORMAT_BGRA_8888 = 17, // 17 - PIXEL_FORMAT_YUV_SEMI_PLANNER_420_10BIT = 18, // 18 - PIXEL_FORMAT_YVU_SEMI_PLANNER_420_10BIT = 19, // 19 - PIXEL_FORMAT_YVU_PLANAR_420 = 20, // 20 - PIXEL_FORMAT_YVU_PLANAR_422, - PIXEL_FORMAT_YVU_PLANAR_444, - PIXEL_FORMAT_RGB_444 = 23, - PIXEL_FORMAT_BGR_444, - PIXEL_FORMAT_ARGB_4444, - PIXEL_FORMAT_ABGR_4444, - PIXEL_FORMAT_RGBA_4444, - PIXEL_FORMAT_BGRA_4444, - PIXEL_FORMAT_RGB_555, - PIXEL_FORMAT_BGR_555, - PIXEL_FORMAT_RGB_565, - PIXEL_FORMAT_BGR_565, - PIXEL_FORMAT_ARGB_1555, - PIXEL_FORMAT_ABGR_1555, - PIXEL_FORMAT_RGBA_1555, - PIXEL_FORMAT_BGRA_1555, - PIXEL_FORMAT_ARGB_8565, - PIXEL_FORMAT_ABGR_8565, - PIXEL_FORMAT_RGBA_8565, - PIXEL_FORMAT_BGRA_8565, - PIXEL_FORMAT_RGB_BAYER_8BPP = 50, - PIXEL_FORMAT_RGB_BAYER_10BPP, - PIXEL_FORMAT_RGB_BAYER_12BPP, - PIXEL_FORMAT_RGB_BAYER_14BPP, - PIXEL_FORMAT_RGB_BAYER_16BPP, - PIXEL_FORMAT_BGR_888_PLANAR = 70, - PIXEL_FORMAT_HSV_888_PACKAGE, - PIXEL_FORMAT_HSV_888_PLANAR, - PIXEL_FORMAT_LAB_888_PACKAGE, - PIXEL_FORMAT_LAB_888_PLANAR, - PIXEL_FORMAT_S8C1, - PIXEL_FORMAT_S8C2_PACKAGE, - PIXEL_FORMAT_S8C2_PLANAR, - PIXEL_FORMAT_S16C1, - PIXEL_FORMAT_U8C1, - PIXEL_FORMAT_U16C1, - PIXEL_FORMAT_S32C1, - PIXEL_FORMAT_U32C1, - PIXEL_FORMAT_U64C1, - PIXEL_FORMAT_S64C1, - PIXEL_FORMAT_YUV_SEMIPLANAR_440 = 1000, - PIXEL_FORMAT_YVU_SEMIPLANAR_440, - PIXEL_FORMAT_FLOAT32, - PIXEL_FORMAT_BUTT, - PIXEL_FORMAT_UNKNOWN = 10000 + PIXEL_FORMAT_YUV_400 = 0, // 0 + PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1, // 1 + PIXEL_FORMAT_YVU_SEMIPLANAR_420 = 2, // 2 + PIXEL_FORMAT_YUV_SEMIPLANAR_422 = 3, // 3 + PIXEL_FORMAT_YVU_SEMIPLANAR_422 = 4, // 4 + PIXEL_FORMAT_YUV_SEMIPLANAR_444 = 5, // 5 + PIXEL_FORMAT_YVU_SEMIPLANAR_444 = 6, // 6 + PIXEL_FORMAT_YUYV_PACKED_422 = 7, // 7 + PIXEL_FORMAT_UYVY_PACKED_422 = 8, // 8 + PIXEL_FORMAT_YVYU_PACKED_422 = 9, // 9 + PIXEL_FORMAT_VYUY_PACKED_422 = 10, // 10 + PIXEL_FORMAT_YUV_PACKED_444 = 11, // 11 + PIXEL_FORMAT_RGB_888 = 12, // 12 + PIXEL_FORMAT_BGR_888 = 13, // 13 + PIXEL_FORMAT_ARGB_8888 = 14, // 14 + PIXEL_FORMAT_ABGR_8888 = 15, // 15 + PIXEL_FORMAT_RGBA_8888 = 16, // 16 + PIXEL_FORMAT_BGRA_8888 = 17, // 17 + PIXEL_FORMAT_YUV_SEMI_PLANNER_420_10BIT = 18, // 18 + PIXEL_FORMAT_YVU_SEMI_PLANNER_420_10BIT = 19, // 19 + PIXEL_FORMAT_YVU_PLANAR_420 = 20, // 20 + PIXEL_FORMAT_YVU_PLANAR_422, + PIXEL_FORMAT_YVU_PLANAR_444, + PIXEL_FORMAT_RGB_444 = 23, + PIXEL_FORMAT_BGR_444, + PIXEL_FORMAT_ARGB_4444, + PIXEL_FORMAT_ABGR_4444, + PIXEL_FORMAT_RGBA_4444, + PIXEL_FORMAT_BGRA_4444, + PIXEL_FORMAT_RGB_555, + PIXEL_FORMAT_BGR_555, + PIXEL_FORMAT_RGB_565, + PIXEL_FORMAT_BGR_565, + PIXEL_FORMAT_ARGB_1555, + PIXEL_FORMAT_ABGR_1555, + PIXEL_FORMAT_RGBA_1555, + PIXEL_FORMAT_BGRA_1555, + PIXEL_FORMAT_ARGB_8565, + PIXEL_FORMAT_ABGR_8565, + PIXEL_FORMAT_RGBA_8565, + PIXEL_FORMAT_BGRA_8565, + PIXEL_FORMAT_RGB_BAYER_8BPP = 50, + PIXEL_FORMAT_RGB_BAYER_10BPP, + PIXEL_FORMAT_RGB_BAYER_12BPP, + PIXEL_FORMAT_RGB_BAYER_14BPP, + PIXEL_FORMAT_RGB_BAYER_16BPP, + PIXEL_FORMAT_BGR_888_PLANAR = 70, + PIXEL_FORMAT_HSV_888_PACKAGE, + PIXEL_FORMAT_HSV_888_PLANAR, + PIXEL_FORMAT_LAB_888_PACKAGE, + PIXEL_FORMAT_LAB_888_PLANAR, + PIXEL_FORMAT_S8C1, + PIXEL_FORMAT_S8C2_PACKAGE, + PIXEL_FORMAT_S8C2_PLANAR, + PIXEL_FORMAT_S16C1, + PIXEL_FORMAT_U8C1, + PIXEL_FORMAT_U16C1, + PIXEL_FORMAT_S32C1, + PIXEL_FORMAT_U32C1, + PIXEL_FORMAT_U64C1, + PIXEL_FORMAT_S64C1, + PIXEL_FORMAT_YUV_SEMIPLANAR_440 = 1000, + PIXEL_FORMAT_YVU_SEMIPLANAR_440, + PIXEL_FORMAT_FLOAT32, + PIXEL_FORMAT_BUTT, + PIXEL_FORMAT_UNKNOWN = 10000 }; // Stream Format -enum acldvppStreamFormat { - H265_MAIN_LEVEL = 0, - H264_BASELINE_LEVEL, - H264_MAIN_LEVEL, - H264_HIGH_LEVEL -}; +enum acldvppStreamFormat { H265_MAIN_LEVEL = 0, H264_BASELINE_LEVEL, H264_MAIN_LEVEL, H264_HIGH_LEVEL }; // Supported Channel Mode -enum acldvppChannelMode { - DVPP_CHNMODE_VPC = 1, - DVPP_CHNMODE_JPEGD = 2, - DVPP_CHNMODE_JPEGE = 4 -}; +enum acldvppChannelMode { DVPP_CHNMODE_VPC = 1, DVPP_CHNMODE_JPEGD = 2, DVPP_CHNMODE_JPEGE = 4 }; // Supported Border Type -enum acldvppBorderType { - BORDER_CONSTANT = 0, - BORDER_REPLICATE, - BORDER_REFLECT, - BORDER_REFLECT_101 -}; +enum acldvppBorderType { BORDER_CONSTANT = 0, BORDER_REPLICATE, BORDER_REFLECT, BORDER_REFLECT_101 }; // Venc parameter type enum aclvencChannelDescParamType { - ACL_VENC_THREAD_ID_UINT64 = 0, - ACL_VENC_CALLBACK_PTR, - ACL_VENC_PIXEL_FORMAT_UINT32, - ACL_VENC_ENCODE_TYPE_UINT32, - ACL_VENC_PIC_WIDTH_UINT32, - ACL_VENC_PIC_HEIGHT_UINT32, - ACL_VENC_KEY_FRAME_INTERVAL_UINT32, - ACL_VENC_BUF_ADDR_PTR, - ACL_VENC_BUF_SIZE_UINT32, - ACL_VENC_RC_MODE_UINT32, - ACL_VENC_SRC_RATE_UINT32, - ACL_VENC_MAX_BITRATE_UINT32, - ACL_VENC_MAX_IP_PROP_UINT32 + ACL_VENC_THREAD_ID_UINT64 = 0, + ACL_VENC_CALLBACK_PTR, + ACL_VENC_PIXEL_FORMAT_UINT32, + ACL_VENC_ENCODE_TYPE_UINT32, + ACL_VENC_PIC_WIDTH_UINT32, + ACL_VENC_PIC_HEIGHT_UINT32, + ACL_VENC_KEY_FRAME_INTERVAL_UINT32, + ACL_VENC_BUF_ADDR_PTR, + ACL_VENC_BUF_SIZE_UINT32, + ACL_VENC_RC_MODE_UINT32, + ACL_VENC_SRC_RATE_UINT32, + ACL_VENC_MAX_BITRATE_UINT32, + ACL_VENC_MAX_IP_PROP_UINT32 }; // Jpeg picture format enum acldvppJpegFormat { - ACL_JPEG_CSS_444 = 0, - ACL_JPEG_CSS_422, - ACL_JPEG_CSS_420, - ACL_JPEG_CSS_GRAY, - ACL_JPEG_CSS_440, - ACL_JPEG_CSS_411, - ACL_JPEG_CSS_UNKNOWN = 1000 + ACL_JPEG_CSS_444 = 0, + ACL_JPEG_CSS_422, + ACL_JPEG_CSS_420, + ACL_JPEG_CSS_GRAY, + ACL_JPEG_CSS_440, + ACL_JPEG_CSS_411, + ACL_JPEG_CSS_UNKNOWN = 1000 }; /** @@ -523,9 +509,7 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescRetCode(const acldvppPicDesc *picD * @retval null for failed. * @retval other success */ -ACL_FUNC_VISIBILITY acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, - uint32_t right, - uint32_t top, +ACL_FUNC_VISIBILITY acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, uint32_t right, uint32_t top, uint32_t bottom); /** @@ -604,10 +588,7 @@ ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfigBottom(acldvppRoiConfig *config, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfig(acldvppRoiConfig *config, - uint32_t left, - uint32_t right, - uint32_t top, +ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfig(acldvppRoiConfig *config, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom); /** @@ -1096,7 +1077,8 @@ ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescMaxBitRate(aclvencChannelDesc * @retval ACL_SUCCESS for success, other for failure */ ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescParam(aclvencChannelDesc *channelDesc, - aclvencChannelDescParamType paramType, size_t length, const void *param); + aclvencChannelDescParamType paramType, size_t length, + const void *param); /** * @ingroup AscendCL @@ -1245,7 +1227,8 @@ ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescMaxBitRate(const aclvencChanne * @retval ACL_SUCCESS for success, other for failure */ ACL_FUNC_VISIBILITY aclError aclvencGetChannelDescParam(const aclvencChannelDesc *channelDesc, - aclvencChannelDescParamType paramType, size_t length, size_t *paramRetSize, void *param); + aclvencChannelDescParamType paramType, size_t length, + size_t *paramRetSize, void *param); /** * @ingroup AscendCL @@ -1545,10 +1528,7 @@ ACL_FUNC_VISIBILITY aclError aclvdecDestroyFrameConfig(aclvdecFrameConfig *vdecF * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, - uint32_t size, - uint32_t *width, - uint32_t *height, +ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, uint32_t size, uint32_t *width, uint32_t *height, int32_t *components); /** @@ -1565,11 +1545,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, - uint32_t size, - uint32_t *width, - uint32_t *height, - int32_t *components, +ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, uint32_t size, uint32_t *width, + uint32_t *height, int32_t *components, acldvppJpegFormat *format); /** @@ -1584,8 +1561,7 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictEncSize(const acldvppPicDesc *inputDesc, - const acldvppJpegeConfig *config, - uint32_t *size); + const acldvppJpegeConfig *config, uint32_t *size); /** * @ingroup AscendCL @@ -1599,10 +1575,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictEncSize(const acldvppPicDesc *inp * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, - uint32_t dataSize, - acldvppPixelFormat outputPixelFormat, - uint32_t *decSize); +ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, uint32_t dataSize, + acldvppPixelFormat outputPixelFormat, uint32_t *decSize); /** * @ingroup AscendCL @@ -1617,11 +1591,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, - uint32_t dataSize, - uint32_t *width, - uint32_t *height, - int32_t *components); +ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, uint32_t dataSize, uint32_t *width, + uint32_t *height, int32_t *components); /** * @ingroup AscendCL @@ -1635,10 +1606,8 @@ ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppPngPredictDecSize(const void *data, - uint32_t dataSize, - acldvppPixelFormat outputPixelFormat, - uint32_t *decSize); +ACL_FUNC_VISIBILITY aclError acldvppPngPredictDecSize(const void *data, uint32_t dataSize, + acldvppPixelFormat outputPixelFormat, uint32_t *decSize); /** * @ingroup AscendCL @@ -1702,10 +1671,8 @@ ACL_FUNC_VISIBILITY aclError acldvppDestroyChannel(acldvppChannelDesc *channelDe * @see acldvppCreateChannel | acldvppCreatePicDesc * | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - acldvppResizeConfig *resizeConfig, +ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppResizeConfig *resizeConfig, aclrtStream stream); /** @@ -1714,7 +1681,7 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDe * * @par Function * crop the input picture according to the specified area, - * and then store the picture in the output memory as the output picture + * and then store the picture in the output memory as the output picture * * @par Restriction * Width alignment requirements: @@ -1732,21 +1699,57 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDe * @li The height of the input image is aligned to 2. * High stride minimum 6 and maximum 4096. * - * @param channelDesc [IN] the channel destruction - * @param inputDesc [IN] crop input picture destruction - * @param outputDesc [IN|OUT] crop output picture destruction - * @param cropArea [IN] crop area config - * @param stream [IN] crop task stream + * @param channelDesc [IN] the channel destruction + * @param inputDesc [IN] crop input picture destruction + * @param outputDesc [IN|OUT] crop output picture destruction + * @param cropArea [IN] crop area config + * @param stream [IN] crop task stream * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - acldvppRoiConfig *cropArea, +ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, aclrtStream stream); +/** + * @ingroup AscendCL + * @brief dvpp vpc crop and resize config. + * + * @par Function + * crop the input picture with resize config according to the specified area, + * and then store the picture in the output memory as the output picture + * + * @par Restriction + * Width alignment requirements: + * @li The minimum stride is 32 and the maximum is 4096 * 4 + * (that is, an image in argb format with a width of 4096); + * @li For 8K scaling, widthStride is required to be aligned to 2; + * @li For non 8K scaling, the calculation formula for widthStride + * is different for different image formats: + * @li yuv400sp, yuv420sp, yuv422sp, yuv444sp: input image width aligned to 16 + * @li yuv422packed: input image width * 2 and then align to 16 + * @li yuv444packed, rgb888: input image width alignment * 3, alignment to 16 + * @li xrgb8888: input image width * 4, align to 16 + * @li HFBC:input image width + * Height alignment requirements: + * @li The height of the input image is aligned to 2. + * High stride minimum 6 and maximum 4096. + * + * @param channelDesc [IN] the channel destruction + * @param inputDesc [IN] crop input picture destruction + * @param outputDesc [IN|OUT] crop output picture destruction + * @param cropArea [IN] crop area config + * @param resizeConfig [IN] resize config + * @param stream [IN] crop and resize config task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, + acldvppResizeConfig *resizeConfig, aclrtStream stream); + /** * @ingroup AscendCL * @brief dvpp vpc batch crop. @@ -1769,12 +1772,37 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, - uint32_t *roiNums, - uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, - acldvppRoiConfig *cropAreas[], - aclrtStream stream); + acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, + uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc batch crop and resize config. + * + * @par Function + * crop the input batch picture with resize config according to the specified area + * as the output batch pictures + * + * @param channelDesc [IN] the channel destruction + * @param srcBatchPicDescs [IN] crop input batch picture destruction + * @param roiNums [IN] roi config numbers + * @param size [IN] roiNum size + * @param dstBatchPicDescs [IN|OUT] crop output batch picture destruction + * @param cropAreas [IN] crop area configs + * @param resizeConfig [IN] resize config + * @param stream [IN] crop batch and resize config task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateDvppConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeAsync(acldvppChannelDesc *channelDesc, + acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, + uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + acldvppResizeConfig *resizeConfig, aclrtStream stream); /** * @ingroup AscendCL @@ -1797,12 +1825,36 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channe * * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateRoiConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - acldvppRoiConfig *cropArea, - acldvppRoiConfig *pasteArea, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, + acldvppRoiConfig *pasteArea, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc crop, resize config and paste. + * + * @par Function + * crop the input picture with resize config according to the specified area, + * and paste the picture to the specified position of the target picture + * as the output picture + * + * @param channelDesc [IN] thechannel destruction + * @param inputDesc [IN] crop and paste input picture destruction + * @param outputDesc [IN|OUT] crop and paste output picture destruction + * @param cropArea [IN] crop area config + * @param pasteArea [IN] paste area config + * @param resizeConfig [IN] resize config + * @param stream [IN] crop, paste and resize task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizePasteAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, + acldvppRoiConfig *pasteArea, + acldvppResizeConfig *resizeConfig, aclrtStream stream); /** * @ingroup AscendCL @@ -1827,14 +1879,40 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *cha * * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig */ - ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, - uint32_t *roiNums, - uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, - acldvppRoiConfig *cropAreas[], - acldvppRoiConfig *pasteAreas[], - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *channelDesc, + acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, + uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + acldvppRoiConfig *pasteAreas[], aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc batch crop, resize config and paste. + * + * @par Function + * crop the input batch picture with resize config according to the specified area, + * and paste the pictures to the specified position of the target pictures + * as the output batch pictures + * + * @param channelDesc [IN] the channel destruction + * @param srcBatchPicDescs [IN] crop input batch picture destruction + * @param roiNums [IN] roi config numbers + * @param size [IN] roiNum size + * @param dstBatchPicDescs [IN|OUT] crop output batch picture destruction + * @param cropAreas [IN] crop area configs + * @param pasteAreas [IN] paste area configs + * @param resizeConfig [IN] resize config + * @param stream [IN] crop batch and resize config task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizePasteAsync( + acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], acldvppRoiConfig *pasteAreas[], + acldvppResizeConfig *resizeConfig, aclrtStream stream); /** * @ingroup AscendCL @@ -1862,11 +1940,8 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *cha * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, - const void *data, - uint32_t size, - acldvppPicDesc *outputDesc, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, + acldvppPicDesc *outputDesc, aclrtStream stream); /** * @ingroup AscendCL @@ -1884,11 +1959,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelD * * @see acldvppCreateChannel | acldvppCreateJpegeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - const void *data, - uint32_t *size, - acldvppJpegeConfig *config, +ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + const void *data, uint32_t *size, acldvppJpegeConfig *config, aclrtStream stream); /** @@ -1906,11 +1978,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelD * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppPngDecodeAsync(acldvppChannelDesc *channelDesc, - const void *data, - uint32_t size, - acldvppPicDesc *outputDesc, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppPngDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, + acldvppPicDesc *outputDesc, aclrtStream stream); /** * @ingroup AscendCL @@ -1965,11 +2034,8 @@ ACL_FUNC_VISIBILITY aclError aclvdecDestroyChannel(aclvdecChannelDesc *channelDe * * @see aclvdecCreateChannel | acldvppCreateStreamDesc | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, - acldvppStreamDesc *input, - acldvppPicDesc *output, - aclvdecFrameConfig *config, - void *userData); +ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, acldvppStreamDesc *input, + acldvppPicDesc *output, aclvdecFrameConfig *config, void *userData); /** * @ingroup AscendCL @@ -1988,10 +2054,8 @@ ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, * * @see aclvdecCreateChannel | acldvppCreateStreamDesc | acldvppCreatePicDesc | aclvdecSendFrame */ -ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channelDesc, - acldvppStreamDesc *input, - aclvdecFrameConfig *config, - void *userData); +ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channelDesc, acldvppStreamDesc *input, + aclvdecFrameConfig *config, void *userData); /** * @ingroup AscendCL @@ -2012,10 +2076,8 @@ ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channel * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, aclrtStream stream); /** * @ingroup AscendCL @@ -2037,11 +2099,8 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *cha * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - void *reserve, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, void *reserve, aclrtStream stream); /** * @ingroup AscendCL @@ -2053,8 +2112,7 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelD * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetChannelDescMode(acldvppChannelDesc *channelDesc, - uint32_t mode); +ACL_FUNC_VISIBILITY aclError acldvppSetChannelDescMode(acldvppChannelDesc *channelDesc, uint32_t mode); /** * @ingroup AscendCL @@ -2089,8 +2147,7 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetResizeConfigInterpolation(const acldvppRe * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutMode(aclvdecChannelDesc *channelDesc, - uint32_t outMode); +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutMode(aclvdecChannelDesc *channelDesc, uint32_t outMode); /** * @ingroup AscendCL @@ -2187,9 +2244,7 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetLutMapDims(const acldvppLutMap *lutMap); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, - uint32_t dim, - uint8_t **data, +ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, uint32_t dim, uint8_t **data, uint32_t *len); /** * @ingroup AscendCL @@ -2207,10 +2262,8 @@ ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, * @see acldvppCreateChannel|acldvppCreatePicDesc|acldvppCreateLutMap */ ACL_FUNC_VISIBILITY aclError acldvppVpcEqualizeHistAsync(const acldvppChannelDesc *channelDesc, - const acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - const acldvppLutMap *lutMap, - aclrtStream stream); + const acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, + const acldvppLutMap *lutMap, aclrtStream stream); /** * @ingroup AscendCL @@ -2231,8 +2284,7 @@ ACL_FUNC_VISIBILITY acldvppBorderConfig *acldvppCreateBorderConfig(); * * @retval ACL_SUCCESS for success, other for failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigValue(acldvppBorderConfig *borderConfig, - uint32_t index, +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigValue(acldvppBorderConfig *borderConfig, uint32_t index, double value); /** @@ -2377,10 +2429,8 @@ ACL_FUNC_VISIBILITY aclError acldvppDestroyBorderConfig(acldvppBorderConfig *bor * @see acldvppCreateChannel|acldvppCreatePicDesc|acldvppCreateBorderConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcMakeBorderAsync(const acldvppChannelDesc *channelDesc, - const acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - const acldvppBorderConfig *borderConfig, - aclrtStream stream); + const acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, + const acldvppBorderConfig *borderConfig, aclrtStream stream); /** * @ingroup AscendCL @@ -2397,11 +2447,8 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcMakeBorderAsync(const acldvppChannelDesc * * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateHist */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *srcPicDesc, - acldvppHist *hist, - void *reserve, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *srcPicDesc, + acldvppHist *hist, void *reserve, aclrtStream stream); /** * @ingroup AscendCL @@ -2410,7 +2457,7 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channel * @retval null for failed. * @retval OtherValues success. */ -ACL_FUNC_VISIBILITY acldvppHist* acldvppCreateHist(); +ACL_FUNC_VISIBILITY acldvppHist *acldvppCreateHist(); /** * @ingroup AscendCL @@ -2467,7 +2514,7 @@ ACL_FUNC_VISIBILITY aclError acldvppGetHistData(acldvppHist *hist, uint32_t dim, * * @see acldvppCreateHist | acldvppVpcCalcHistAsync */ -ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist* hist); +ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist *hist); /** * @ingroup AscendCL @@ -2486,8 +2533,36 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist* hist); */ ACL_FUNC_VISIBILITY aclError acldvppClearHist(acldvppHist *hist); +/** + * @ingroup AscendCL + * @brief dvpp vpc batch crop, resize config and make border. + * + * @par Function + * crop the input batch picture with resize config and border configs according to the specified area + * as the output batch pictures + * + * @param channelDesc [IN] the channel destruction + * @param srcBatchPicDescs [IN] crop input batch picture destruction + * @param roiNums [IN] roi config numbers + * @param size [IN] roiNum size + * @param dstBatchPicDescs [IN|OUT] crop output batch picture destruction + * @param cropAreas [IN] crop area configs + * @param borderCfgs [IN] border configs + * @param resizeConfig [IN] resize config + * @param stream [IN] crop batch, resize config and make border task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeMakeBorderAsync( + acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], acldvppBorderConfig *borderCfgs[], + acldvppResizeConfig *resizeConfig, aclrtStream stream); + #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ diff --git a/scripts/format_source_code.sh b/scripts/format_source_code.sh old mode 100644 new mode 100755 diff --git a/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h b/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h new file mode 100644 index 00000000..d0800a08 --- /dev/null +++ b/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h @@ -0,0 +1,58 @@ +/** + * Copyright 2019 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. + */ + +/*! + * \file avg_pool_1d_ops.h + * \brief + */ +#ifndef OPS_BUILT_IN_OP_PROTO_INC_AVGPOOL1DOPS_H_ +#define OPS_BUILT_IN_OP_PROTO_INC_AVGPOOL1DOPS_H_ +#include "graph/operator_reg.h" + +namespace ge { +/** +*@brief Generate an auxiliary matrix . \n + +*@par Inputs: +* @li x: A tensor. Must be one of the following types:uint8, int8,int16, int32, + int64, float16, float, double.The format must be NHWC NCHW NC1HWC0. + +*@par Attributes: +*@li ksize: Kernel size. Input type is int. +*@li strides: Input type is int. +*@li pads: Input type is listInt . +*@li ceil_mode: Bool, default value is false. +*@li count_include_pad: Bool, default value is false. \n + +*@par Outputs: +*y_tensor: A tensor with the same types as "x" . \n +*@par Third-party framework compatibility + +*Compatible with the TensorFlow operator Unbatch. +*/ +REG_OP(AvgPool1DAvgMatrix) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT16, DT_UINT8, + DT_INT32, DT_INT64, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT16, DT_UINT8, + DT_INT32, DT_INT64, DT_DOUBLE})) + .REQUIRED_ATTR(ksize, Int) + .REQUIRED_ATTR(strides, Int) + .REQUIRED_ATTR(pads, ListInt) + .ATTR(ceil_mode, Bool, false) + .ATTR(count_include_pad, Bool, false) + .OP_END_FACTORY_REG(AvgPool1DAvgMatrix) +} +#endif \ No newline at end of file diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index 6207c917..0ec15367 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -2454,6 +2454,25 @@ REG_OP(Eltwise) .ATTR(coeff, ListFloat, {}) .OP_END_FACTORY_REG(Eltwise) +/** + *@brief Computes the inverse error function of each element of input. \n + + *@par Inputs: + *One inputs, including: + * @li input_x: A tensor. Must be one of the following types: + * float16, float32. \n + + *@par Outputs: + *y: A Tensor with the same type and shape of input_x's. \n + + *@par Third-party framework compatibility + *Compatible with the Pytorch operator Erfinv. \n + */ +REG_OP(Erfinv) + .INPUT(input_x, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(output_y, TensorType({DT_FLOAT, DT_FLOAT16})) + .OP_END_FACTORY_REG(Erfinv) + /** *@brief Computes element-wise population count. \n diff --git a/third_party/fwkacllib/inc/ops/image_ops.h b/third_party/fwkacllib/inc/ops/image_ops.h index 4703705b..6ae1613c 100644 --- a/third_party/fwkacllib/inc/ops/image_ops.h +++ b/third_party/fwkacllib/inc/ops/image_ops.h @@ -1516,6 +1516,96 @@ REG_OP(DenseImageWarp) .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) .OP_END_FACTORY_REG(DenseImageWarp) +/** +*@brief Calculate the resize_d function. \n + +*@par Inputs: +*One inputs, including: +* @li x: A tensor. Must be one of the following types: +* float16, float32. \n + +*@par Attributes: +*@li sizes: An optional listInt. \n +*@li scales: An optional listFloat. + Defaults to none. \n +*@li roi: An optional listInt. + Defaults to none. \n +*@li coordinate_transformation_mode: An optional String. + Defaults to "half_pixel". \n +*@li cubic_coeff_a: An optional float. + Defaults to -0.75. \n +*@li exclude_outside: An optional int. + Defaults to 0. \n +*@li extrapolation_value: An optional float. + Defaults to 0.0. \n +*@li mode: An optional String. + Defaults to "nearest". \n +*@li nearest_mode: An optional String. + Defaults to "round_prefer_floor". \n + +*@par Outputs: +*y: A Tensor with the same type of x's, + shape depends on x and sizes. \n +*/ +REG_OP(ResizeD) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(sizes, ListInt) + .ATTR(scales, ListFloat, {}) + .ATTR(roi, ListInt, {}) + .ATTR(coordinate_transformation_mode, String, "half_pixel") + .ATTR(cubic_coeff_a, Float, -0.75) + .ATTR(exclude_outside, Int, 0) + .ATTR(extrapolation_value, Float, 0.0) + .ATTR(mode, String, "nearest") + .ATTR(nearest_mode, String, "round_prefer_floor") + .OP_END_FACTORY_REG(ResizeD) + +/** +*@brief Calculate the resize_grad_d function. \n + +*@par Inputs: +*One inputs, including: +* @li grads: A tensor. Must be one of the following types: +* float16, float32. \n + +*@par Attributes: +*@li original_size: An optional listInt. \n +*@li roi: An optional listInt. + Defaults to none. \n +*@li scales: An optional listFloat. + Defaults to none. \n +*@li coordinate_transformation_mode: An optional String. + Defaults to "half_pixel". \n +*@li cubic_coeff_a: An optional float. + Defaults to -0.75. \n +*@li exclude_outside: An optional int. + Defaults to 0. \n +*@li extrapolation_value: An optional float. + Defaults to 0.0. \n +*@li mode: An optional String. + Defaults to "nearest". \n +*@li nearest_mode: An optional String. + Defaults to "round_prefer_floor". \n + +*@par Outputs: +*y: A Tensor with the same type of x's, + shape depends on x and sizes. \n +*/ +REG_OP(ResizeGradD) + .INPUT(grads, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(original_size, ListInt) + .ATTR(roi, ListInt, {}) + .ATTR(scales, ListFloat, {}) + .ATTR(coordinate_transformation_mode, String, "half_pixel") + .ATTR(cubic_coeff_a, Float, -0.75) + .ATTR(exclude_outside, Int, 0) + .ATTR(extrapolation_value, Float, 0.0) + .ATTR(mode, String, "nearest") + .ATTR(nearest_mode, String, "round_prefer_floor") + .OP_END_FACTORY_REG(ResizeGradD) + /** *@brief Computes the gradients of DenseImageWarp with respect to image and flow. \n @@ -1535,5 +1625,81 @@ REG_OP(DenseImageWarpGrad) .OUTPUT(grad_image, TensorType({DT_FLOAT, DT_FLOAT16})) .OUTPUT(grad_flow, TensorType({DT_FLOAT, DT_FLOAT16})) .OP_END_FACTORY_REG(DenseImageWarpGrad) + +/** +*@brief This operation samples input X by using interpolation based on flow field grid, + which is usually gennerated by affine_grid. The grid of shape [N, H, W, 2] is the concatenation of + (x, y) coordinates with shape [N, H, W] each, where x is indexing the 4th dimension (in width dimension) of + input data x and y is indexng the 3rd dimention (in height dimension), finally results is + the interpolation value of 4 nearest corner points. The output tensor shape will be [N, C, H, W]. + +*@par Inputs: +*@li x: 4-D Tensor with shape `[batch, channels, height, width]`. +*@li grid: flow field grid, 4-D Tensor with shape `[batch, height, width, 2]`. + +*@par Attributes: +*@li interpolation_mode: An optional string specifying the interpolation method. Only 'bilinear' is + supported for now . +*@li padding_mode: An optional string specifying the pad method. Only 'zeros' is supported for now . +*@li align_corners: An optional bool. If "true", the centers of the corner + pixels of the input and output tensors are aligned. Defaults to "false" . + +*@par Outputs: +*y: Returns 4-D Tensor with the same dtype as `X`. + +*@par Third-party framework compatibility +*Compatible with pytorch GridSampler2D operator. +*/ +REG_OP(GridSampler2D) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(grid, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(interpolation_mode, String, "bilinear") + .ATTR(padding_mode, String, "zeros") + .ATTR(align_corners, Bool, false) + .OP_END_FACTORY_REG(GridSampler2D) + +/** +*@brief This operation unnormalize input Grid, which is usually gennerated by affine_grid. + +*@par Inputs: +*@li grid: flow field grid, 4-D Tensor with shape `[batch, height, width, 2]`. +*@li assist: Assist matrix, a 4-D tensor of type float16. + +*@par Attributes: +*@li align_corners: An optional bool. If "true", the centers of the corner + pixels of the input and output tensors are aligned. Defaults to "false" . + +*@par Outputs: +*diff: Returns 4-D Tensor with the same shape and dtype as `grid`. +*position: Returns 4-D Tensor with the same shape as `grid`. +*/ +REG_OP(GridUnnormal) + .INPUT(grid, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(assist, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(diff, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(position, TensorType({DT_INT32})) + .ATTR(align_corners, Bool, false) + .OP_END_FACTORY_REG(GridUnnormal) + +/** +*@brief This operation unfold input X based on unnormalized grid, which is gennerated by GridUnnormal. + +*@par Inputs: +*@li x: 4-D Tensor with shape `[batch, channels, height, width]`. +*@li position: 4-D Tensor with shape `[batch, output_height, output_width, 2]`. + +*@par Attributes: +*@li padding_mode: An optional string specifying the pad method. Only 'zeros' is supported for now . + +*@par Outputs: +*y: Returns 4-D Tensor with the same dtype as `x`. +*/ +REG_OP(ImageUnfold) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(position, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(padding_mode, String, "zeros") + .OP_END_FACTORY_REG(ImageUnfold) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_IMAGE_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/list_ops.h b/third_party/fwkacllib/inc/ops/list_ops.h index 33270ea8..a1b622e9 100644 --- a/third_party/fwkacllib/inc/ops/list_ops.h +++ b/third_party/fwkacllib/inc/ops/list_ops.h @@ -225,6 +225,280 @@ REG_OP(TensorListSetItem) .ATTR(element_dtype, Type, DT_INT32) .OP_END_FACTORY_REG(TensorListSetItem) +/** +*@brief Push tensor to list. \n + +*@par Inputs: +*@li input_handles: The input tensor lists. +*@li tensor: The tensor push into tensor list. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li output_handles: The output tensor lists. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListPushBackBatch operator. +*/ +REG_OP(TensorListPushBackBatch) + .INPUT(input_handles, TensorType({DT_VARIANT})) + .INPUT(tensor, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .OUTPUT(output_handles, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListPushBackBatch) + +/** +*@brief Stacks all tensors in the list. \n + +*@par Inputs: +*@li input_handle: The input tensor list. +*@li element_shape: A shape compatible with that of elements in the tensor. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. +*@li num_elements: The number of elements in the list. \n + +*@par Outputs: +*@li tensor: The tensor of list. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListStack operator. +*/ +REG_OP(TensorListStack) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(element_shape, TensorType({DT_INT32})) + .OUTPUT(tensor, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .ATTR(element_dtype, Type, DT_INT32) + .ATTR(num_elements, Int, -1) + .OP_END_FACTORY_REG(TensorListStack) + +/** +*@brief Concats all tensors in the list along the 0th dimension. +Requires that all tensors have the same shape except the first dimension. \n + +*@par Inputs: +*@li input_handle: The input list. +*@li element_shape: The shape of the uninitialized elements in the list. +If the first dimension is not -1, it is assumed that all list elements have +the same leading dim. +*@li leading_dims: The list of leading dims of uninitialized list elements. Used if +the leading dim of input_handle.element_shape or the element_shape input arg +is not already set. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li tensor: The concated result. +*@li lengths: Output tensor containing sizes of the 0th dimension of tensors +in the list, used for computing the gradient. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListConcatV2 operator. +*/ +REG_OP(TensorListConcatV2) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(element_shape, TensorType({DT_INT32,DT_INT64})) + .INPUT(leading_dims, TensorType({DT_INT64})) + .OUTPUT(tensor, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .OUTPUT(lengths, TensorType({DT_INT64})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListConcatV2) + +/** +*@brief Splits a tensor into a list. \n + +*@par Inputs: +*@li tensor: The input tensor. +*@li element_shape: A shape compatible with that of elements in the tensor. +*@li lengths: Vector of sizes of the 0th dimension of tensors in the list. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li output_handle: The list. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListSplit operator. +*/ +REG_OP(TensorListSplit) + .INPUT(tensor, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .INPUT(element_shape, TensorType({DT_INT32,DT_INT64})) + .INPUT(lengths, TensorType({DT_INT64})) + .OUTPUT(output_handle, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListSplit) + +/** +*@brief Creates a TensorList which, when stacked, has the value of `tensor`. \n + +*@par Inputs: +*@li tensor: The input tensor. +*@li element_shape: The shape of elements in the list. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li output_handle: An output tensor list . \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListFromTensor operator. +*/ +REG_OP(TensorListFromTensor) + .INPUT(tensor, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .INPUT(element_shape, TensorType({DT_INT32,DT_INT64})) + .OUTPUT(output_handle, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListFromTensor) + +/** +*@brief Resizes the list. \n + +*@par Inputs: +*@li input_handle: The input tensor list. +*@li size: size of the output list. \n + +*@par Outputs: +*@li output_handle: The output tensor list. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListResize operator. +*/ +REG_OP(TensorListResize) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(size, TensorType({DT_INT32})) + .OUTPUT(output_handle, TensorType({DT_VARIANT})) + .OP_END_FACTORY_REG(TensorListResize) + +/** +*@brief Creates a Tensor by indexing into the TensorList. \n + +*@par Inputs: +*@li input_handle: The input tensor list. +*@li indices: The indices used to index into the list. +*@li element_shape: The shape of elements in the list. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li values: The tensor. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListGather operator. +*/ +REG_OP(TensorListGather) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(indices, TensorType({DT_INT32})) + .INPUT(element_shape, TensorType({DT_INT32})) + .OUTPUT(values, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListGather) + +/** +*@brief Creates a TensorList by indexing into a Tensor. \n + +*@par Inputs: +*@li tensor: The input tensor. +*@li indices: The indices used to index into the list. +*@li element_shape: The shape of the elements in the list (can be less specified than +the shape of the tensor). +*@li num_elements: The size of the output list. Must be large enough to accommodate +the largest index in indices. If -1, the list is just large enough to include +the largest index in indices. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li output_handle: The TensorList. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListScatterV2 operator. +*/ +REG_OP(TensorListScatterV2) + .INPUT(tensor, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .INPUT(indices, TensorType({DT_INT32})) + .INPUT(element_shape, TensorType({DT_INT32,DT_INT64})) + .INPUT(num_elements, TensorType({DT_INT32})) + .OUTPUT(output_handle, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListScatterV2) + +/** +*@brief Scatters tensor at indices in an input list. \n + +*@par Inputs: +*@li input_handle: The input tensor list. +*@li tensor: The input tensor. +*@li indices: The indices used to index into the list. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li output_handle: The TensorList. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListScatterIntoExistingList operator. +*/ +REG_OP(TensorListScatterIntoExistingList) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(tensor, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .INPUT(indices, TensorType({DT_INT32})) + .OUTPUT(output_handle, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListScatterIntoExistingList) + +/** +*@brief Concat two tensor lists to a new tensor list. \n + +*@par Inputs: +*@li input_a: The input tensor list A. +*@li input_b: The input tensor list B. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li output: The output list. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListConcatLists operator. +*/ +REG_OP(TensorListConcatLists) + .INPUT(input_a, TensorType({DT_VARIANT})) + .INPUT(input_b, TensorType({DT_VARIANT})) + .OUTPUT(output, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListConcatLists) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_LIST_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/math_ops.h b/third_party/fwkacllib/inc/ops/math_ops.h index bd30e50c..28f7f0aa 100644 --- a/third_party/fwkacllib/inc/ops/math_ops.h +++ b/third_party/fwkacllib/inc/ops/math_ops.h @@ -982,6 +982,65 @@ REG_OP(SoftMarginLossGrad) .ATTR(reduction, String, "mean") .OP_END_FACTORY_REG(SoftMarginLossGrad) +/** + *@brief Computes batched the p-norm distance between each pair of + *the two collections of row vectors. \n + + *@par Inputs: + *Two inputs, including: + * @li x1: A tensor with shpae: BxPXM. Must be one of the following types: + * float16, float32. \n + * @li x2: A tensor with shpae: BxRxM. Must be one of the following types: + * float16, float32. \n + + *@par Attributes: + * @li p: An optional float >= 0 or inf. Defaults to 2.0. \n + + *@par Outputs: + * y: A Tensor with the same type of x1's and with shape BxPxR. \n + + *@par Third-party framework compatibility + *Compatible with the Pytorch operator Cdist. \n + */ +REG_OP(Cdist) + .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(p, Float, 2.0) + .OP_END_FACTORY_REG(Cdist) + +/** +*@brief Computes the grad of x1 in cdist. \n + +*@par Inputs: +*Four inputs, including: + * @li grad: Grad with shape BxPxR. Must be one of the following types: +* float16, float32. \n +* @li x1: A tensor with shpae: BxPXM. Must be one of the following types: +* float16, float32. \n +* @li x2: A tensor with shpae: BxRxM. Must be one of the following types: +* float16, float32. \n +* @li cdist: Output tensor of cdist forward with shpae: BxPXR. +* Must be one of the following types: float16, float32. \n + +*@par Attributes: +* @li p: An optional float >= 0 or inf. Defaults to 2.0. \n + +*@par Outputs: +* y: A Tensor with the same type and shape of x1's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator Cdist Backward. \n +*/ +REG_OP(CdistGrad) + .INPUT(grad, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(x1, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(x2, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(cdist, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT})) + .ATTR(p, Float, 2.0) + .OP_END_FACTORY_REG(CdistGrad) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATH_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index 32631f14..49a49931 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -1065,7 +1065,37 @@ REG_OP(Tril) .ATTR(diagonal, Int, 0) .OUTPUT(y, TensorType::BasicType()) .OP_END_FACTORY_REG(Tril) +/** +*@brief Concatenates a list of N tensors along the first dimension. +*@par Inputs: +* Two inputs, including: +* @li values: A list of Tensors. Must be one of the following types: int32, float16, float32. +* Tensors to be concatenated. All must have size 1 in the first dimension and same shape. +* It's a dynamic input. +* @li shape: A Tensor of the same type as "x". +* The final shape of the result. Should be equal to the shapes of any input +* but with the number of input values in the first dimension . \n +*@par Attributes: +*equation: The subscripts for the Einstein summation. \n +*tensor_size: tensor size of input \n + +*@par Outputs: +*@li y: Sums the product of the elements of the input operands along dimensions specified + using a notation based on the Einstein summation convention. \n + +*@attention Constraints: +*Input tensor_size must be Int. \n + +*@par Third-party framework compatibility +*Compatible with Pytorch einsum operator. +*/ +REG_OP(EinSum) + .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .REQUIRED_ATTR(equation, String) + .REQUIRED_ATTR(tensor_size, Int) + .OP_END_FACTORY_REG(EinSum) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATRIX_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index 041aa765..7d38beb5 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -427,6 +427,33 @@ REG_OP(MVN) .ATTR(eps, Float, 1e-9) .OP_END_FACTORY_REG(MVN) +/** +*@brief Normalizes the input . \n + +*@par Inputs: +* One input: +*x: An NCHW tensor of type float16 or float32 . \n + +*@par Attributes: +*@li eps: An optional float32 epsilon for not dividing by zero. Defaults to "1e-9" . \n +*@li axes: A list of Intefers, along which axis to reduce. Defaults to "[0, 2, 3]" . \n + +*@par Outputs: +*y: An NCHW tensor of type float16 or float32 . \n + +*@attention Constraints: +* The input tensor must have the NCHW format, whose shape length must be 4. +*@par Third-party framework compatibility +* Compatible with the ONNX operator MeanVarianceNormalization. +*/ + +REG_OP(MVNV2) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) /* "First operand." */ + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) /* "Result, has same element type as inputs" */ + .ATTR(eps, Float, 1e-9) + .ATTR(axes, ListInt, {0, 2, 3}) + .OP_END_FACTORY_REG(MVNV2) + /** *@brief Normalizes the input "x1" . \n @@ -1205,6 +1232,33 @@ REG_OP(Centralization) .ATTR(axes, ListInt, {-1}) .OP_END_FACTORY_REG(Centralization) +/** +*@brief Roll the tensor along the given dimension(s). +* Elements that are shifted beyond the last position are re-introduced at the first position. +* If a dimension is not specified, the tensor will be flattened before rolling and then restored to the original shape. \n + +*@par Inputs: +*One inputs, including: +* @li x: A tensor . Must be one of the following types: +* float16, float32, int32, uint32, int8, uint8. \n + +*@par Attributes: +* @li shifts: The number of places by which the elements of the tensor are shifted. \n +* @li dims: Axis along which to roll. \n + +*@par Outputs: +* y: A Tensor with the same type and shape of x's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator Roll. \n +*/ +REG_OP(Roll) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_UINT32,DT_INT8,DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_UINT32,DT_INT8,DT_UINT8})) + .REQUIRED_ATTR(shifts, ListInt) + .ATTR(dims, ListInt, {}) + .OP_END_FACTORY_REG(Roll) + /** *@brief Calculate the loss. Creates a criterion that optimizes a two-class classification logistic loss between input_x and input_y (containing 1 or -1). \n diff --git a/third_party/fwkacllib/inc/ops/nn_ops.h b/third_party/fwkacllib/inc/ops/nn_ops.h index 820aa00d..f7dd6795 100644 --- a/third_party/fwkacllib/inc/ops/nn_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_ops.h @@ -49,5 +49,60 @@ REG_OP(InTopKV2) .INPUT(k, TensorType({IndexNumberType})) .OUTPUT(precision, TensorType({DT_BOOL})) .OP_END_FACTORY_REG(InTopKV2) + +/** +*@brief Performs batch normalization . \n + +*@par Inputs: +* Five inputs, including: (NHWC, NCHW, or NC1HWC0 supported) +*@li x: A 4D or 5D Tensor of type float16 or float32, with format NHWC or NCHW for 4D or NC1HWC0 for 5D. +*@li scale: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D +if input "x" is with format NC1HWC0. Specifies the scaling factor. +*@li offset: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D +if input "x" is with format NC1HWC0. Specifies the offset. +*@li mean: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D +if input "x" is with format NC1HWC0. Specifies the mean used for inference. Must be "None" if the +operation is used for training. +*@li variance: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be +5D if input "x" is with format NC1HWC0. Specifies the variance used for inference. Must be "None" +if the operation is used for training . \n + +*@par Attributes: +*@li epsilon: An optional float32, specifying the small value added to variance to avoid dividing by zero. Defaults to "0.0001". +*@li data_format: An optional string, specifying the format of "x". Defaults to "NHWC". +*@li is_training: An optional bool, specifying if the operation is used for training or inference. Defaults to "True" . \n + +*@par Outputs: +* Five outputs, including: (NHWC, NCHW, or NC1HWC0 supported) +*@li y: A 4D or 5D Tensor of type float16 or float32 for the normalized "x", with format NHWC or NCHW for 4D or NC1HWC0 for 5D. +*@li batch_mean: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D +if input "x" is with format NC1HWC0. Specifies the mean of "x". +*@li batch_variance: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. +Must be 5D if input "x" is with format NC1HWC0. Specifies the variance of "x". +*@li reserve_space_1: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. +Must be 5D if input "x" is with format NC1HWC0. Specifies the mean of "x" for gradient computation. Pass "None" to skip this output. +*@li reserve_space_2: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. +Must be 5D if input "x" is with format NC1HWC0. Specifies the variance of "x" for gradient computation. Pass "None" to skip this output . \n + +*@attention Constraints: +*@li If the operation is used for inference and outputs "reserve_space_1" and "reserve_space_2" are available, +then "reserve_space_1" has the same value as "mean" and "reserve_space_2" has the same value as "variance". +*@li For Ascend 310, the result accuracy fails to reach 1‰ due to the square root instruction . \n +*/ +REG_OP(FusedBatchNormV2) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(scale, TensorType({DT_FLOAT})) + .INPUT(offset, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(mean, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(variance, TensorType({DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(batch_mean, TensorType({DT_FLOAT})) + .OUTPUT(batch_variance, TensorType({DT_FLOAT})) + .OUTPUT(reserve_space_1, TensorType({DT_FLOAT})) + .OUTPUT(reserve_space_2, TensorType({DT_FLOAT})) + .ATTR(epsilon, Float, 0.0001) + .ATTR(data_format, String, "NHWC") + .ATTR(is_training, Bool, true) + .OP_END_FACTORY_REG(FusedBatchNormV2) }// namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h index 9f191ebe..32eb148b 100644 --- a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h @@ -1502,14 +1502,14 @@ REG_OP(AdaptiveAvgPool2d) * @brief Compute gradients of adaptive averagev2 pooling function. * @par Inputs: -* @li input_grad: A NCHW Tensor. Must be one of the following data types: +* @li input_grad: A Tensor. Must be one of the following data types: * float16, float32. * @par Attributes: * @li orig_input_shape: A required tuple or list of type int32. * @par Outputs: -* @li output_grad: A tensor with the same shape and type as "orig_input_shape". +* @li output_grad: A tensor with the same type as "input_grad". * @par Third-party framework compatibility * Compatible with the Pytorch operator AdaptiveAvgPool2dGrad. diff --git a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h index a911fa51..0d0be241 100644 --- a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h +++ b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h @@ -530,6 +530,34 @@ REG_OP(Elu) .ATTR(alpha, Float, 1.0) .OP_END_FACTORY_REG(Elu) +/** +*@brief Continuously Differentiable Exponential Linear Uints: +* Perform the linear uint element-wise on the input tensor X using formula: +* max(0, x) + min(0, alpha * (exp(x/alpha) - 1)). \n + +*@par Inputs: +*x: A float16, float32 or double, for the input data type . \n + +*@par Attributes: +*alpha: A float32. Defines at which negative value the ELU saturates. Defaults to "1.0" . \n + +*@par Outputs: +*y: A float16, float32 or double, for the normalized result . \n + +*@attention Constraints: +*@li The input is of type float16 or float32 . \n + +*@par Multiple batches supported or not +*Supported +*@par Third-party framework compatibility +*@li Compatible with ONNX's Celu operator +*/ +REG_OP(Celu) + .INPUT(x, TensorType::FloatingDataType()) + .OUTPUT(y, TensorType::FloatingDataType()) + .ATTR(alpha, Float, 1.0) + .OP_END_FACTORY_REG(Celu) + /** *@brief Computes gradients for the exponential linear (Elu) operation. * diff --git a/third_party/fwkacllib/inc/ops/pad_ops.h b/third_party/fwkacllib/inc/ops/pad_ops.h index 8d71c5cd..50eb98c8 100644 --- a/third_party/fwkacllib/inc/ops/pad_ops.h +++ b/third_party/fwkacllib/inc/ops/pad_ops.h @@ -101,7 +101,7 @@ REG_OP(FillD) */ REG_OP(BroadcastTo) .INPUT(x, TensorType::BasicType()) - .INPUT(shape, TensorType({DT_INT32})) + .INPUT(shape, TensorType({DT_INT32,DT_INT64})) .OUTPUT(y, TensorType::BasicType()) .OP_END_FACTORY_REG(BroadcastTo) diff --git a/third_party/fwkacllib/inc/ops/selection_ops.h b/third_party/fwkacllib/inc/ops/selection_ops.h index 0aff5a81..7fe05b1e 100644 --- a/third_party/fwkacllib/inc/ops/selection_ops.h +++ b/third_party/fwkacllib/inc/ops/selection_ops.h @@ -239,6 +239,30 @@ REG_OP(GatherV2D) .REQUIRED_ATTR(axis, Int) .OP_END_FACTORY_REG(GatherV2D) +/** +*@Gathers values along an axis specified by dim . \n + +*@par Inputs: +*@li x: A Tensor. Must be one of the following types: float16, float32, int32, int64. +*@li index: A Tensor. Must be one of the following types: int64 . \n + +*@par Attributes: +* dim: the axis along which to index . \n + +*@par Outputs: +* y: A Tensor. Has the same type as "x" . \n + +*@par Third-party framework compatibility +*Compatible with the PyTorch operator Gather. +*/ + +REG_OP(GatherElements) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT64})) + .INPUT(index, TensorType({DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT64})) + .ATTR(dim, Int, 0) + .OP_END_FACTORY_REG(GatherElements) + /** *@brief Extracts a strided slice of a tensor. Roughly speaking, this op extracts a slice of size (end-begin)/stride from the given input tensor. @@ -486,6 +510,38 @@ REG_OP(UnsortedSegmentSum) .OUTPUT(y, TensorType::NumberType()) .OP_END_FACTORY_REG(UnsortedSegmentSum) +/** +*@brief Creates a one-dimensional tensor of size steps whose values are evenly spaced from start to +* end, inclusive, on a logarithmic scale with base base. \n + +*@par Inputs: +*One inputs, including: +* @li assist: A tensor. Must be one of the following types: +* float16, float32. \n + +* @par Attributes: +* @li start: An required float. Used to select the start. \n +* @li end: An required float. Used to select the end. \n +* @li steps: An optional int.Defaults to 100. \n +* @li base: An optional float.Defaults to 10.0. \n +* @li dtype: An optional int.Defaults to 1. \n + +*@par Outputs: +*y: A Tensor with the same type and shape of input_x's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator logspaced. \n +*/ +REG_OP(LogSpaceD) + .INPUT(assist, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .REQUIRED_ATTR (start, Float) + .REQUIRED_ATTR (end, Float) + .ATTR(steps, Int, 100) + .ATTR(base, Float, 10.0) + .ATTR(dtype, Int, 1) + .OP_END_FACTORY_REG(LogSpaceD) + /** *@brief Computes the sum along segments of a tensor . \n diff --git a/third_party/fwkacllib/inc/runtime/base.h b/third_party/fwkacllib/inc/runtime/base.h index 5b246eed..1b264843 100644 --- a/third_party/fwkacllib/inc/runtime/base.h +++ b/third_party/fwkacllib/inc/runtime/base.h @@ -339,7 +339,7 @@ RTS_API rtError_t rtLabelCreateEx(rtLabel_t *label, rtStream_t stream); * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -rtError_t rtLabelCreateExV2(rtLabel_t *label, rtModel_t model, rtStream_t stream); +RTS_API rtError_t rtLabelCreateExV2(rtLabel_t *label, rtModel_t model, rtStream_t stream); /** * @ingroup dvrt_base diff --git a/third_party/fwkacllib/inc/runtime/config.h b/third_party/fwkacllib/inc/runtime/config.h index fed7341a..66ae36ef 100644 --- a/third_party/fwkacllib/inc/runtime/config.h +++ b/third_party/fwkacllib/inc/runtime/config.h @@ -132,6 +132,11 @@ typedef struct tagRtPlatformConfig { uint32_t platformConfig; } rtPlatformConfig_t; +typedef enum tagRTTaskTimeoutType { + RT_TIMEOUT_TYPE_OP_WAIT = 0, + RT_TIMEOUT_TYPE_OP_EXECUTE, +} rtTaskTimeoutType_t; + /** * @ingroup * @brief get AI core count @@ -203,6 +208,24 @@ RTS_API rtError_t rtGetRuntimeVersion(uint32_t *runtimeVersion); */ RTS_API rtError_t rtGetDeviceCapability(int32_t deviceId, int32_t moduleType, int32_t featureType, int32_t *value); +/** + * @ingroup + * @brief set event wait task timeout time. + * @param [in] timeout + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtSetOpWaitTimeOut(uint32_t timeout); + +/** + * @ingroup + * @brief set op execute task timeout time. + * @param [in] timeout + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtSetOpExecuteTimeOut(uint32_t timeout); + #if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) } #endif diff --git a/third_party/fwkacllib/inc/runtime/kernel.h b/third_party/fwkacllib/inc/runtime/kernel.h index 754f069a..cf5347cb 100644 --- a/third_party/fwkacllib/inc/runtime/kernel.h +++ b/third_party/fwkacllib/inc/runtime/kernel.h @@ -188,7 +188,7 @@ typedef void (*rtCallback_t)(void *fnData); /** * @ingroup rt_kernel * @brief kernel mode - */ +**/ #define RT_DEFAULT_KERNEL_MODE (0x00) #define RT_NORMAL_KERNEL_MODE (0x01) #define RT_ALL_KERNEL_MODE (0x02) @@ -211,7 +211,7 @@ RTS_API rtError_t rtDevBinaryRegister(const rtDevBinary_t *bin, void **handle); /** * @ingroup rt_kernel - * @brief register device binary + * @brief register device binary with all kernel * @param [in] bin device binary description * @param [out] handle device binary handle * @return RT_ERROR_NONE for ok @@ -330,7 +330,7 @@ RTS_API rtError_t rtKernelLaunch(const void *stubFunc, uint32_t blockDim, void * * @ingroup rt_kernel * @brief launch kernel with handle to device * @param [in] handle program - * @param [in] devFunc device function description + * @param [in] devFunc device function description. * @param [in] blockDim block dimentions * @param [in] args argments address for kernel function * @param [in] argsSize argements size @@ -341,7 +341,7 @@ RTS_API rtError_t rtKernelLaunch(const void *stubFunc, uint32_t blockDim, void * * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtKernelLaunchWithHandle(void *handle, const void *devFunc, uint32_t blockDim, void *args, uint32_t argsSize, - rtSmDesc_t *smDesc, rtStream_t stream, const void *kernelInfo); + rtSmDesc_t *smDesc, rtStream_t stream_, const void *kernelInfo); /** * @ingroup rt_kernel diff --git a/third_party/fwkacllib/inc/runtime/rt_model.h b/third_party/fwkacllib/inc/runtime/rt_model.h index 798f63ae..df2eddc9 100644 --- a/third_party/fwkacllib/inc/runtime/rt_model.h +++ b/third_party/fwkacllib/inc/runtime/rt_model.h @@ -133,12 +133,13 @@ typedef struct tagAllKernelTaskInfo { uint16_t argsCount; uint16_t argsSize; uint16_t reserved; - const void *dev_func; + void *devfunc; void *handle; uint8_t *smDesc; uint8_t *args; uint16_t *argsOffset; } rtAllKernelTaskInfo_t; + typedef struct tagKernelTaskInfoEx { uint32_t flags; uint32_t argsSize; @@ -263,7 +264,7 @@ typedef struct tagTaskInfo { union { rtKernelTaskInfoEx_t kernelTaskEx; rtKernelTaskInfo_t kernelTask; - rtAllKernelTaskInfo_t allkernelTask; + rtAllKernelTaskInfo_t allKernelTask; rtEventTaskInfo_t eventTask; rtStreamSwitchTaskInfo_t streamSwitchTask; rtStreamActiveTaskInfo_t streamActiveTask; @@ -285,10 +286,27 @@ typedef struct tagTaskInfo { } u; } rtTaskInfo_t; +typedef struct tagNodeInfo_t { + uint32_t nodeIdx; + uint32_t reserved[1]; +} rtNodeInfo; + +typedef struct tagHwtsInfo_t { + uint16_t taskId; + uint16_t sqExeHead; + uint16_t streamExeHead; + uint16_t reserved[2]; +} rtHwtsInfo; + typedef struct tagLabelDevInfo_t { uint16_t modelId; uint16_t streamId; uint16_t labelId; + union { + rtNodeInfo nodeInfo; + rtHwtsInfo hwtsInfo; + uint16_t reserved[5]; + }u; }rtLabelDevInfo; typedef rtError_t (*rtTaskGenCallback)(rtModel_t model, rtTaskInfo_t *taskInfo); diff --git a/third_party/fwkacllib/inc/runtime/stream.h b/third_party/fwkacllib/inc/runtime/stream.h index 6b9f80ae..f9981514 100644 --- a/third_party/fwkacllib/inc/runtime/stream.h +++ b/third_party/fwkacllib/inc/runtime/stream.h @@ -189,6 +189,28 @@ RTS_API rtError_t rtStreamActive(rtStream_t activeStream, rtStream_t stream); */ RTS_API rtError_t rtStreamSwitchN(void *ptr, uint32_t size, void *valuePtr, rtStream_t *trueStreamPtr, uint32_t elementSize, rtStream_t stream, rtSwitchDataType_t dataType); + +/* + * @ingroup dvrt_stream + * @brief enable debug for dump overflow exception with stream + * @param [in] addr: ddr address of kernel exception dumpped + * @param [in] stream: stream handle + * @param [in] flag: debug flag + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtDebugRegisterForStream(rtStream_t stream, uint32_t flag, const void *addr, + uint32_t *streamId, uint32_t *taskId); + +/* + * @ingroup rt_model + * @brief disable debug for dump overflow exception with stream + * @param [in] stream: stream handle + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtDebugUnRegisterForStream(rtStream_t stream); + #if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) } #endif diff --git a/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h b/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h index 47c41c48..3634b8a8 100644 --- a/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h +++ b/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h @@ -11,93 +11,11 @@ /** @defgroup aoe aoe调优接口 */ #ifndef TUNE_API_H #define TUNE_API_H -#include #include #include -#include "graph/graph.h" #include "ge/ge_api.h" #include "aoe_types.h" -/** - * @ingroup aoe - * - * aoe status - */ -enum MsTuneStatus { - MSTUNE_SUCCESS, /** tune success */ - MSTUNE_FAILED, /** tune failed */ -}; - -// Option key: for train options sets -const std::string MSTUNE_SELF_KEY = "mstune"; -const std::string MSTUNE_GEINIT_KEY = "initialize"; -const std::string MSTUNE_GESESS_KEY = "session"; - -#ifdef __cplusplus -extern "C" { -#endif - -struct RunnerInitConfig { - // onilne online - std::string profPath; - std::string parserPath; - // ncs only - std::vector devList; -}; - -struct RunnerOpInfo { - std::string opName; - uint64_t opCostTime; - uint64_t aicoreCostTime; - // gradient_split only - std::string modelName; - std::string opType; - std::vector start; - std::vector end; -}; - -struct RunnerModelInfo { - uint64_t totalCostTime; -}; - -struct RunnerRunResult { - std::vector modelInfo; - std::vector opInfo; -}; - -struct RunnerResult { - uint64_t totalCostTime; - std::map opCostTime; - std::map aicoreCostTime; -}; - -struct RunnerDataBuf { - void *ptr = nullptr; - size_t size = 0; -}; - -struct AOEBufferData { - std::shared_ptr data = nullptr; - uint64_t length; -}; - -struct RunnerConfig { - bool isProf; - uint32_t loop; - // offline only - std::vector input; - std::vector output; - std::string modelPath; - RunnerDataBuf modelData; - // online only - uint32_t devId; - std::vector> inputs; - std::vector dependGraph; // run graph (for training) -}; -#ifdef __cplusplus -} -#endif - /** * @ingroup aoe * @par 描述: 命令行调优 From 948000fe5ba81acaceedb52b016e2cbffe990764 Mon Sep 17 00:00:00 2001 From: shenwei41 Date: Fri, 12 Mar 2021 15:58:02 +0800 Subject: [PATCH 19/59] fix ge Compile Error --- ge/ge_runtime/runtime_model.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/ge/ge_runtime/runtime_model.cc b/ge/ge_runtime/runtime_model.cc index 71147a4b..2c1f2d3b 100644 --- a/ge/ge_runtime/runtime_model.cc +++ b/ge/ge_runtime/runtime_model.cc @@ -21,6 +21,7 @@ #include "common/ge_inner_error_codes.h" #include "common/types.h" #include "common/util.h" +#include "common/math/math_util.h" #include "framework/common/debug/ge_log.h" #include "framework/common/op/op_parser_util.h" #include "graph/types.h" From 6a82dd1947647373621b4617e40c2f712602940c Mon Sep 17 00:00:00 2001 From: shenwei41 Date: Sat, 13 Mar 2021 14:51:55 +0800 Subject: [PATCH 20/59] update ge --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 947fb016..3f97d245 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -150,6 +150,7 @@ elseif(ENABLE_MS_TESTCASES) include(cmake/external_libs/protobuf_static.cmake) include(cmake/external_libs/protoc.cmake) include(cmake/external_libs/securec.cmake) + include(cmake/external_libs/json.cmake) include(cmake/FindModule.cmake) include(cmake/intf_pub_linux.cmake) From d6308151e0afa90834c9bdea72e018ff47c2a5fc Mon Sep 17 00:00:00 2001 From: zhoufeng Date: Mon, 18 Jan 2021 15:10:16 +0800 Subject: [PATCH 21/59] reuse workspace memory of hccl op Signed-off-by: zhoufeng --- ge/ge_runtime/task/hccl_task.cc | 16 ++-------------- inc/framework/ge_runtime/task_info.h | 5 ++++- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/ge/ge_runtime/task/hccl_task.cc b/ge/ge_runtime/task/hccl_task.cc index 06165053..c3040697 100644 --- a/ge/ge_runtime/task/hccl_task.cc +++ b/ge/ge_runtime/task/hccl_task.cc @@ -52,15 +52,7 @@ HcclTask::HcclTask(const ModelContext &model_context, const std::shared_ptrworkspace_size() > 0) { - rtError_t rt_ret = rtMalloc(&workspace_mem_, task_info_->workspace_size(), RT_MEMORYINFO_HBM); - if (rt_ret != RT_ERROR_NONE) { - GELOGE(RT_FAILED, "Call rt api failed, ret: 0x%X", rt_ret); - return false; - } + workspace_mem_ = task_info_->workspace_addr(); } GELOGI("HcclTaskInfo Distribute Start. begin to call function LoadTask in hccl."); diff --git a/inc/framework/ge_runtime/task_info.h b/inc/framework/ge_runtime/task_info.h index f59c6454..4530bff7 100644 --- a/inc/framework/ge_runtime/task_info.h +++ b/inc/framework/ge_runtime/task_info.h @@ -271,13 +271,14 @@ class FusionEndTaskInfo : public TaskInfo { class HcclTaskInfo : public TaskInfo { public: HcclTaskInfo(const std::string &op_name, uint32_t stream_id, const std::string hccl_type, void *input_data_addr, - void *output_data_addr, int64_t workspace_size, int64_t hccl_stream_num, + void *output_data_addr, void *workspace_addr, int64_t workspace_size, int64_t hccl_stream_num, const std::vector &private_def, void *ops_kernel_store, int32_t count, int64_t root_id, int64_t op_type, int64_t data_type, const std::string &group, bool dump_flag) : TaskInfo(op_name, stream_id, TaskInfoType::HCCL, dump_flag), hccl_type_(hccl_type), input_data_addr_(input_data_addr), output_data_addr_(output_data_addr), + workspace_addr_(workspace_addr), workspace_size_(workspace_size), hccl_stream_num_(hccl_stream_num), private_def_(private_def), @@ -292,6 +293,7 @@ class HcclTaskInfo : public TaskInfo { const std::string &hccl_type() const { return hccl_type_; } void *input_data_addr() const { return input_data_addr_; } void *output_data_addr() const { return output_data_addr_; } + void *workspace_addr() const { return workspace_addr_; } int64_t workspace_size() const { return workspace_size_; } int64_t hccl_stream_num() const { return hccl_stream_num_; } const std::vector &private_def() const { return private_def_; } @@ -306,6 +308,7 @@ class HcclTaskInfo : public TaskInfo { std::string hccl_type_; void *input_data_addr_; void *output_data_addr_; + void *workspace_addr_; int64_t workspace_size_; int64_t hccl_stream_num_; std::vector private_def_; From 55f1e609698fe6c03dff8496a3365f43a90e1b50 Mon Sep 17 00:00:00 2001 From: dingpeifei Date: Tue, 20 Apr 2021 15:14:17 +0800 Subject: [PATCH 22/59] code_sync_0420 --- metadef | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metadef b/metadef index fcebf37d..99627af3 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit fcebf37d7428caf4e0bd6e6c3a4f8143f6eac8b7 +Subproject commit 99627af3e039343ee972701acaf9a6f376a6ca77 From 4d0b6f9d9a1b212c0be65b3406ca4b538d2d4616 Mon Sep 17 00:00:00 2001 From: dingpeifei Date: Tue, 20 Apr 2021 17:06:36 +0800 Subject: [PATCH 23/59] code_sync_0420 --- ge/ge_runtime/CMakeLists.txt | 1 + ge/ge_runtime/task/label_goto_task.cc | 98 ++++++++----------- ge/ge_runtime/task/label_goto_task.h | 16 ++-- ge/ge_runtime/task/label_manager.cc | 119 ++++++++++++++++++++++++ ge/ge_runtime/task/label_manager.h | 54 +++++++++++ ge/ge_runtime/task/label_switch_task.cc | 55 +++-------- ge/ge_runtime/task/label_switch_task.h | 6 +- 7 files changed, 242 insertions(+), 107 deletions(-) create mode 100644 ge/ge_runtime/task/label_manager.cc create mode 100644 ge/ge_runtime/task/label_manager.h diff --git a/ge/ge_runtime/CMakeLists.txt b/ge/ge_runtime/CMakeLists.txt index b00dd5b3..40113285 100644 --- a/ge/ge_runtime/CMakeLists.txt +++ b/ge/ge_runtime/CMakeLists.txt @@ -16,6 +16,7 @@ set(GE_SRC_LIST "task/label_goto_task.cc" "task/label_set_task.cc" "task/label_switch_task.cc" + "task/label_manager.cc" ) add_library(ge_runtime SHARED ${GE_SRC_LIST}) diff --git a/ge/ge_runtime/task/label_goto_task.cc b/ge/ge_runtime/task/label_goto_task.cc index ad93a98f..c04bd5cf 100644 --- a/ge/ge_runtime/task/label_goto_task.cc +++ b/ge/ge_runtime/task/label_goto_task.cc @@ -16,99 +16,83 @@ #include "ge_runtime/task/label_goto_task.h" #include "ge_runtime/task/task_factory.h" -#include "framework/common/util.h" namespace ge { namespace model_runner { LabelGotoTask::LabelGotoTask(const ModelContext &model_context, const std::shared_ptr &task_info) - : TaskRepeater(model_context, task_info), task_info_(task_info) { + : TaskRepeater(model_context, task_info), + task_info_(task_info), + stream_(nullptr), + index_value_(nullptr) { if (task_info_ == nullptr) { GELOGW("task_info_ is null!"); return; } auto stream_list = model_context.stream_list(); auto label_list = model_context.label_list(); + rt_model_handle_ = model_context.rt_model_handle(); uint32_t stream_id = task_info->stream_id(); - uint32_t label_id = task_info->label_id(); + label_id_ = task_info->label_id(); GELOGI("Stream list size:%zu, stream id:%u.", stream_list.size(), stream_id); - GELOGI("Label list size:%zu, label id:%u.", label_list.size(), label_id); - if (stream_id >= stream_list.size() || label_id >= label_list.size()) { + GELOGI("Label list size:%zu, label id:%u.", label_list.size(), label_id_); + if (stream_id >= stream_list.size() || label_id_ >= label_list.size()) { GELOGW("Stream/Label id invalid."); return; } stream_ = stream_list[stream_id]; - label_ = label_list[label_id]; + label_manager_ = LabelManager::GetInstance(); + if (label_manager_ == nullptr) { + GELOGW("Get label manager instance failed."); + return; + } + label_info_ = label_manager_->GetLabelInfo(rt_model_handle_, {label_id_}, label_list); } LabelGotoTask::~LabelGotoTask() { - GE_FREE_RT_LOG(label_info_); - GE_FREE_RT_LOG(index_value_); + if (index_value_ != nullptr) { + rtError_t rt_ret = rtFree(index_value_); + if (rt_ret != RT_ERROR_NONE) { + GELOGE(RT_FAILED, "rtFree index_value_ failed! ret: 0x%X.", rt_ret); + } + index_value_ = nullptr; + } } bool LabelGotoTask::Distribute() { GELOGI("LabelGotoTask Distribute start."); - if (!CheckParamValid()) { - return false; - } - - const std::vector label_list = { label_ }; - rtError_t rt_ret = rtMalloc(&index_value_, sizeof(uint64_t), RT_MEMORY_HBM); - if (rt_ret != RT_ERROR_NONE) { - GELOGE(RT_FAILED, "Call rt api failed, ret: %#x", rt_ret); - return false; - } - - uint64_t branch_index = 0; - rt_ret = rtMemcpy(index_value_, sizeof(uint64_t), &branch_index, sizeof(uint64_t), RT_MEMCPY_HOST_TO_DEVICE); - if (rt_ret != RT_ERROR_NONE) { - GELOGE(RT_FAILED, "Call rt api failed, ret: %#x", rt_ret); - return false; - } - - uint32_t label_info_size = sizeof(rtLabelDevInfo) * label_list.size(); - rt_ret = rtMalloc(&label_info_, label_info_size, RT_MEMORY_HBM); - if (rt_ret != RT_ERROR_NONE) { - GELOGE(RT_FAILED, "Call rt api failed, ret: %#x", rt_ret); - return false; - } - - rt_ret = rtLabelListCpy(label_list.data(), label_list.size(), label_info_, label_info_size); - if (rt_ret != RT_ERROR_NONE) { - GELOGE(RT_FAILED, "Call rt api failed, ret: %#x", rt_ret); - return false; - } - - rt_ret = rtLabelSwitchByIndex(index_value_, label_list.size(), label_info_, stream_); - if (rt_ret != RT_ERROR_NONE) { - GELOGE(RT_FAILED, "Call rt api failed, ret: %#x", rt_ret); - return false; - } - - GELOGI("DistributeTask end."); - return true; -} - -bool LabelGotoTask::CheckParamValid() { if (stream_ == nullptr) { GELOGE(PARAM_INVALID, "stream is null!"); return false; } - if (label_ == nullptr) { - GELOGE(PARAM_INVALID, "label is null!"); + if (label_info_ == nullptr) { + GELOGE(PARAM_INVALID, "label info is null!"); return false; } - if (label_info_ != nullptr) { - GELOGE(PARAM_INVALID, "label_info_ has dirty data."); - return false; + if (index_value_ == nullptr) { + rtError_t rt_ret = rtMalloc(&index_value_, sizeof(uint64_t), RT_MEMORY_HBM); + if (rt_ret != RT_ERROR_NONE) { + GELOGE(RT_FAILED, "Call rt api failed, ret: 0x%X", rt_ret); + return false; + } + + uint64_t index = 0; + rt_ret = rtMemcpy(index_value_, sizeof(uint64_t), &index, sizeof(index), RT_MEMCPY_HOST_TO_DEVICE); + if (rt_ret != RT_ERROR_NONE) { + GELOGE(RT_FAILED, "Call rt api failed, ret: 0x%X", rt_ret); + return false; + } } - if (index_value_ != nullptr) { - GELOGE(PARAM_INVALID, "index_value_ has dirty data."); + void *label_info = label_info_->GetLabelInfo(); + rtError_t rt_ret = rtLabelSwitchByIndex(index_value_, 1, label_info, stream_); + if (rt_ret != RT_ERROR_NONE) { + GELOGE(RT_FAILED, "Call rt api failed, ret: 0x%X", rt_ret); return false; } + GELOGI("DistributeTask end."); return true; } diff --git a/ge/ge_runtime/task/label_goto_task.h b/ge/ge_runtime/task/label_goto_task.h index addbb700..e579c683 100644 --- a/ge/ge_runtime/task/label_goto_task.h +++ b/ge/ge_runtime/task/label_goto_task.h @@ -18,7 +18,11 @@ #define GE_GE_RUNTIME_TASK_LABEL_GOTO_TASK_H_ #include +#include +#include +#include #include "ge_runtime/task/task.h" +#include "ge_runtime/task/label_manager.h" namespace ge { namespace model_runner { @@ -31,13 +35,13 @@ class LabelGotoTask : public TaskRepeater { bool Distribute() override; private: - bool CheckParamValid(); - std::shared_ptr task_info_; - void *stream_{nullptr}; - void *label_{nullptr}; - void *label_info_{nullptr}; - void *index_value_{nullptr}; + void *stream_; + std::shared_ptr label_info_; + void *index_value_; + uint32_t label_id_; + rtModel_t rt_model_handle_; + std::shared_ptr label_manager_; }; } // namespace model_runner } // namespace ge diff --git a/ge/ge_runtime/task/label_manager.cc b/ge/ge_runtime/task/label_manager.cc new file mode 100644 index 00000000..a2b0c3aa --- /dev/null +++ b/ge/ge_runtime/task/label_manager.cc @@ -0,0 +1,119 @@ +/** + * Copyright 2021 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 "ge_runtime/task/label_manager.h" +#include +#include +#include "runtime/mem.h" +#include "runtime/rt_model.h" +#include "common/ge_inner_error_codes.h" +#include "framework/common/debug/ge_log.h" + +namespace ge { +namespace model_runner { +std::weak_ptr LabelManager::instance_; +std::mutex LabelManager::instance_mutex_; + +template +static std::string GetVectorString(const std::vector &vec) { + std::string ret; + for (size_t i = 0; i < vec.size(); ++i) { + if (i != 0) { + ret.push_back(','); + } + ret += std::to_string(vec[i]); + } + return ret; +} + +LabelGuard::~LabelGuard() { + void *label_info = GetLabelInfo(); + if (label_info != nullptr) { + rtError_t rt_ret = rtFree(label_info); + if (rt_ret != RT_ERROR_NONE) { + GELOGE(RT_FAILED, "rtFree label_info failed! ret: 0x%X.", rt_ret); + } + } +} + +std::shared_ptr LabelManager::GetInstance() { + std::lock_guard lock(instance_mutex_); + auto instance = instance_.lock(); + if (instance != nullptr) { + return instance; + } + + instance = std::make_shared(); + instance_ = instance; + return instance; +} + +std::shared_ptr LabelManager::GetLabelInfo(rtModel_t model, const std::vector &label_ids, + const std::vector &all_label) { + std::lock_guard lock(model_info_mapping_mutex_); + rtError_t rt_ret; + auto model_iter = model_info_mapping_.find(model); + if (model_iter == model_info_mapping_.end()) { + model_info_mapping_.emplace(model, std::map>()); + model_iter = model_info_mapping_.find(model); + } + + std::string label_id_str = GetVectorString(label_ids); + auto &label_map = model_iter->second; + auto label_iter = label_map.find(label_id_str); + if (label_iter != label_map.end()) { + auto label_guard = label_iter->second.lock(); + if (label_guard != nullptr) { + GELOGI("model %p find same label id %s.", model, label_id_str.c_str()); + return label_guard; + } + } + + GELOGI("Alloc label id %s for model %p.", label_id_str.c_str(), model); + void *label_info; + std::vector label_list; + bool status = true; + std::transform(label_ids.begin(), label_ids.end(), std::back_inserter(label_list), + [&all_label, &status](uint32_t idx) -> void * { + if (idx >= all_label.size()) { + GELOGE(PARAM_INVALID, "Invalid label id %u, all label list size %zu.", idx, all_label.size()); + status = false; + return nullptr; + } + return all_label[idx]; + }); + if (!status) { + GELOGE(PARAM_INVALID, "Get label info failed."); + return nullptr; + } + uint32_t label_info_size = sizeof(rtLabelDevInfo) * label_list.size(); + rt_ret = rtMalloc(&label_info, label_info_size, RT_MEMORY_HBM); + if (rt_ret != RT_ERROR_NONE) { + GELOGE(RT_FAILED, "Call rt api failed, ret: 0x%X", rt_ret); + return nullptr; + } + + rt_ret = rtLabelListCpy(label_list.data(), label_list.size(), label_info, label_info_size); + if (rt_ret != RT_ERROR_NONE) { + GELOGE(RT_FAILED, "Call rt api failed, ret: 0x%X", rt_ret); + return nullptr; + } + + auto label_guard = std::make_shared(label_info); + label_map.emplace(label_id_str, label_guard); + return label_guard; +} +} // namespace model_runner +} // namespace ge diff --git a/ge/ge_runtime/task/label_manager.h b/ge/ge_runtime/task/label_manager.h new file mode 100644 index 00000000..f2c42c29 --- /dev/null +++ b/ge/ge_runtime/task/label_manager.h @@ -0,0 +1,54 @@ +/** + * Copyright 2021 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. + */ +#ifndef GE_GE_RUNTIME_TASK_LABEL_MANAGER_H_ +#define GE_GE_RUNTIME_TASK_LABEL_MANAGER_H_ + +#include +#include +#include +#include +#include + +namespace ge { +namespace model_runner { +class LabelGuard { + public: + explicit LabelGuard(void *label_info) : label_info_(reinterpret_cast(label_info)) {} + ~LabelGuard(); + void *GetLabelInfo() { return reinterpret_cast(label_info_); } + + private: + uintptr_t label_info_; +}; + +class LabelManager { + public: + static std::shared_ptr GetInstance(); + std::shared_ptr GetLabelInfo(rtModel_t model, const std::vector &label_ids, + const std::vector &all_label); + + private: + std::mutex model_info_mapping_mutex_; + std::map>> model_info_mapping_; + + static std::weak_ptr instance_; + static std::mutex instance_mutex_; +}; + + +} // namespace model_runner +} // namespace ge +#endif // GE_GE_RUNTIME_TASK_LABEL_MANAGER_H_ \ No newline at end of file diff --git a/ge/ge_runtime/task/label_switch_task.cc b/ge/ge_runtime/task/label_switch_task.cc index a3c2d41a..1f913d74 100644 --- a/ge/ge_runtime/task/label_switch_task.cc +++ b/ge/ge_runtime/task/label_switch_task.cc @@ -24,14 +24,14 @@ LabelSwitchTask::LabelSwitchTask(const ModelContext &model_context, : TaskRepeater(model_context, task_info), task_info_(task_info), stream_(nullptr), - all_label_resource_(), label_info_(nullptr) { if (task_info_ == nullptr) { GELOGW("task_info_ is null!"); return; } - all_label_resource_ = model_context.label_list(); + rt_model_handle_ = model_context.rt_model_handle(); + auto all_label_resource = model_context.label_list(); auto stream_list = model_context.stream_list(); uint32_t stream_id = task_info->stream_id(); GELOGI("Stream list size:%zu, stream id:%u.", stream_list.size(), stream_id); @@ -40,52 +40,24 @@ LabelSwitchTask::LabelSwitchTask(const ModelContext &model_context, return; } stream_ = stream_list[stream_id]; -} - -LabelSwitchTask::~LabelSwitchTask() { - if (label_info_ != nullptr) { - rtError_t rt_ret = rtFree(label_info_); - if (rt_ret != RT_ERROR_NONE) { - GELOGE(RT_FAILED, "rtFree fwkOpBuf failed! ret: 0x%X.", rt_ret); - } - label_info_ = nullptr; + label_manager_ = LabelManager::GetInstance(); + if (label_manager_ == nullptr) { + GELOGW("Get label manager instance failed."); + return; } + label_info_ = label_manager_->GetLabelInfo(rt_model_handle_, task_info_->label_list(), all_label_resource); } +LabelSwitchTask::~LabelSwitchTask() {} + bool LabelSwitchTask::Distribute() { GELOGI("LabelSwitchTask Distribute start."); if (!CheckParamValid()) { return false; } - const std::vector &label_index_list = task_info_->label_list(); - std::vector label_list(task_info_->label_size(), nullptr); - - for (size_t i = 0; i < task_info_->label_size(); ++i) { - uint32_t label_index = label_index_list[i]; - if (label_index >= all_label_resource_.size()) { - GELOGE(PARAM_INVALID, "label %zu index is %u, but there are %zu labels in total.", i, label_index, - all_label_resource_.size()); - return false; - } - label_list[i] = all_label_resource_[label_index]; - GELOGI("Case %zu: label id %zu.", i, label_index); - } - - uint32_t label_info_size = sizeof(rtLabelDevInfo) * task_info_->label_size(); - rtError_t rt_ret = rtMalloc(&label_info_, label_info_size, RT_MEMORY_HBM); - if (rt_ret != RT_ERROR_NONE) { - GELOGE(RT_FAILED, "Call rt api failed, ret: 0x%X", rt_ret); - return false; - } - - rt_ret = rtLabelListCpy(label_list.data(), label_list.size(), label_info_, label_info_size); - if (rt_ret != RT_ERROR_NONE) { - GELOGE(RT_FAILED, "Call rt api failed, ret: 0x%X", rt_ret); - return false; - } - - rt_ret = rtLabelSwitchByIndex(task_info_->cond(), label_list.size(), label_info_, stream_); + void *label_info = label_info_->GetLabelInfo(); + rtError_t rt_ret = rtLabelSwitchByIndex(task_info_->cond(), task_info_->label_size(), label_info, stream_); if (rt_ret != RT_ERROR_NONE) { GELOGE(RT_FAILED, "Call rt api failed, ret: 0x%X", rt_ret); return false; @@ -117,8 +89,8 @@ bool LabelSwitchTask::CheckParamValid() { return false; } - if (label_info_ != nullptr) { - GELOGE(PARAM_INVALID, "label_info_ has dirty data."); + if (label_info_ == nullptr) { + GELOGE(PARAM_INVALID, "CopyLabelList failed, label info is null."); return false; } @@ -126,6 +98,5 @@ bool LabelSwitchTask::CheckParamValid() { } REGISTER_TASK(TaskInfoType::LABEL_SWITCH, LabelSwitchTask, LabelSwitchTaskInfo); - } // namespace model_runner } // namespace ge diff --git a/ge/ge_runtime/task/label_switch_task.h b/ge/ge_runtime/task/label_switch_task.h index 463faa31..cfa6877c 100644 --- a/ge/ge_runtime/task/label_switch_task.h +++ b/ge/ge_runtime/task/label_switch_task.h @@ -19,6 +19,7 @@ #include #include "ge_runtime/task/task.h" +#include "ge_runtime/task/label_manager.h" namespace ge { namespace model_runner { @@ -35,8 +36,9 @@ class LabelSwitchTask : public TaskRepeater { std::shared_ptr task_info_; void *stream_; - std::vector all_label_resource_; - void *label_info_; + rtModel_t rt_model_handle_; + std::shared_ptr label_info_; + std::shared_ptr label_manager_; }; } // namespace model_runner } // namespace ge From 5b9393e3239a09da75c5b3a529cbdcb60a7488f5 Mon Sep 17 00:00:00 2001 From: dingpeifei Date: Wed, 21 Apr 2021 16:19:27 +0800 Subject: [PATCH 24/59] code_sync_0420_inc --- inc/external/acl/acl.h | 17 +- inc/external/acl/acl_base.h | 9 + inc/external/acl/acl_mdl.h | 15 + inc/external/acl/acl_op_compiler.h | 20 +- inc/external/acl/acl_rt.h | 11 + inc/external/acl/error_codes/rt_error_codes.h | 1 + inc/external/acl/ops/acl_dvpp.h | 425 +++++++++++------- inc/external/hccl/hccl.h | 9 + inc/external/runtime/rt_error_codes.h | 1 + .../inc/external/runtime/rt_error_codes.h | 0 third_party/fwkacllib/inc/mmpa/mmpa_api.h | 1 + .../fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h | 4 + .../fwkacllib/inc/mmpa/sub_inc/mmpa_win.h | 4 + .../inc/ops/elewise_calculation_ops.h | 36 ++ third_party/fwkacllib/inc/ops/image_ops.h | 98 ++++ third_party/fwkacllib/inc/ops/linalg_ops.h | 47 ++ third_party/fwkacllib/inc/ops/math_ops.h | 23 + .../inc/ops/matrix_calculation_ops.h | 154 +++++-- third_party/fwkacllib/inc/ops/nn_detect_ops.h | 289 +++++++----- third_party/fwkacllib/inc/ops/nn_norm_ops.h | 140 +++++- .../fwkacllib/inc/ops/nn_pooling_ops.h | 109 ++++- .../fwkacllib/inc/ops/nonlinear_fuc_ops.h | 29 +- third_party/fwkacllib/inc/ops/pad_ops.h | 4 +- third_party/fwkacllib/inc/ops/parsing_ops.h | 240 ++++++++++ third_party/fwkacllib/inc/ops/quantize_ops.h | 20 + third_party/fwkacllib/inc/ops/random_ops.h | 33 ++ third_party/fwkacllib/inc/ops/reduce_ops.h | 27 +- third_party/fwkacllib/inc/ops/rnn.h | 118 +++++ third_party/fwkacllib/inc/ops/selection_ops.h | 45 +- third_party/fwkacllib/inc/ops/string_ops.h | 337 ++++++++++++++ .../fwkacllib/inc/ops/transformation_ops.h | 8 +- third_party/fwkacllib/inc/runtime/base.h | 10 +- third_party/fwkacllib/inc/runtime/event.h | 12 + third_party/fwkacllib/inc/runtime/rt.h | 1 + third_party/fwkacllib/inc/runtime/rt_model.h | 9 + third_party/fwkacllib/inc/runtime/rt_stars.h | 29 ++ .../fwkacllib/inc/toolchain/prof_reporter.h | 70 +-- .../inc/toolchain/tuning_tool/tune_api.h | 37 +- 38 files changed, 2051 insertions(+), 391 deletions(-) mode change 100755 => 100644 third_party/fwkacllib/inc/external/runtime/rt_error_codes.h create mode 100644 third_party/fwkacllib/inc/runtime/rt_stars.h diff --git a/inc/external/acl/acl.h b/inc/external/acl/acl.h index ef5b4772..a53d029d 100644 --- a/inc/external/acl/acl.h +++ b/inc/external/acl/acl.h @@ -26,9 +26,9 @@ extern "C" { #endif // Current version is 1.0.0 -#define ACL_MAJOR_VERSION 1 -#define ACL_MINOR_VERSION 0 -#define ACL_PATCH_VERSION 0 +#define ACL_MAJOR_VERSION 1 +#define ACL_MINOR_VERSION 0 +#define ACL_PATCH_VERSION 0 /** * @ingroup AscendCL @@ -66,8 +66,17 @@ ACL_FUNC_VISIBILITY aclError aclFinalize(); */ ACL_FUNC_VISIBILITY aclError aclrtGetVersion(int32_t *majorVersion, int32_t *minorVersion, int32_t *patchVersion); +/** + * @ingroup AscendCL + * @brief get recent error message + * + * @retval null for failed + * @retval OtherValues success +*/ +ACL_FUNC_VISIBILITY const char *aclGetRecentErrMsg(); + #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_H_ +#endif // INC_EXTERNAL_ACL_ACL_H_ diff --git a/inc/external/acl/acl_base.h b/inc/external/acl/acl_base.h index 657bf67c..417a80c8 100644 --- a/inc/external/acl/acl_base.h +++ b/inc/external/acl/acl_base.h @@ -626,6 +626,15 @@ ACL_FUNC_VISIBILITY aclError aclSetTensorPlaceMent(aclTensorDesc *desc, aclMemTy ACL_FUNC_VISIBILITY void aclAppLog(aclLogLevel logLevel, const char *func, const char *file, uint32_t line, const char *fmt, ...); +/** + * @ingroup AscendCL + * @brief get soc name + * + * @retval null for failed + * @retval OtherValues success +*/ +ACL_FUNC_VISIBILITY const char *aclrtGetSocName(); + #define ACL_APP_LOG(level, fmt, ...) \ aclAppLog(level, __FUNCTION__, __FILE__, __LINE__, fmt, ##__VA_ARGS__) diff --git a/inc/external/acl/acl_mdl.h b/inc/external/acl/acl_mdl.h index 3a62ce32..e2f95a56 100644 --- a/inc/external/acl/acl_mdl.h +++ b/inc/external/acl/acl_mdl.h @@ -280,6 +280,21 @@ ACL_FUNC_VISIBILITY aclError aclmdlDestroyDataset(const aclmdlDataset *dataset); */ ACL_FUNC_VISIBILITY aclError aclmdlAddDatasetBuffer(aclmdlDataset *dataset, aclDataBuffer *dataBuffer); +/** + * @ingroup AscendCL + * @brief Set aclTensorDesc to aclmdlDataset + * + * @param dataset [OUT] aclmdlDataset address of aclDataBuffer to be added + * @param tensorDesc [IN] aclTensorDesc address to be added + * @param index [IN] index of tensorDesc which to be added + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetDatasetTensorDesc(aclmdlDataset *dataset, + aclTensorDesc *tensorDesc, + size_t index); + /** * @ingroup AscendCL * @brief Get the number of aclDataBuffer in aclmdlDataset diff --git a/inc/external/acl/acl_op_compiler.h b/inc/external/acl/acl_op_compiler.h index 6bbb855c..353d2a1a 100644 --- a/inc/external/acl/acl_op_compiler.h +++ b/inc/external/acl/acl_op_compiler.h @@ -38,9 +38,15 @@ typedef enum { ACL_OP_DEBUG_LEVEL, ACL_DEBUG_DIR, ACL_OP_COMPILER_CACHE_MODE, - ACL_OP_COMPILER_CACHE_DIR + ACL_OP_COMPILER_CACHE_DIR, + ACL_OP_PERFORMANCE_MODE } aclCompileOpt; +typedef enum aclCompileFlag { + ACL_OP_COMPILE_DEFAULT, + ACL_OP_COMPILE_FUZZ +} aclOpCompileFlag; + /** * @ingroup AscendCL * @brief compile op @@ -108,6 +114,18 @@ ACL_FUNC_VISIBILITY aclError aclopCompileAndExecute(const char *opType, */ ACL_FUNC_VISIBILITY aclError aclSetCompileopt(aclCompileOpt opt, const char *value); +/** + * @ingroup AscendCL + * @brief set compile flag + * + * @param flag [IN] compile flag, ACL_OP_COMPILE_DEFAULT means compile with default mode + * ACL_OP_COMPILE_FUZZ means compile with fuzz mode + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopSetCompileFlag(aclOpCompileFlag flag); + #ifdef __cplusplus } #endif diff --git a/inc/external/acl/acl_rt.h b/inc/external/acl/acl_rt.h index 703ca4ca..3c777ecc 100644 --- a/inc/external/acl/acl_rt.h +++ b/inc/external/acl/acl_rt.h @@ -957,6 +957,17 @@ ACL_FUNC_VISIBILITY aclError aclrtDeviceDisablePeerAccess(int32_t peerDeviceId); */ ACL_FUNC_VISIBILITY aclError aclrtGetMemInfo(aclrtMemAttr attr, size_t *free, size_t *total); +/** + * @ingroup AscendCL + * @brief Set the timeout interval for waitting of op + * + * @param timeout [IN] op wait timeout + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtSetOpWaitTimeout(uint32_t timeout); + #ifdef __cplusplus } #endif diff --git a/inc/external/acl/error_codes/rt_error_codes.h b/inc/external/acl/error_codes/rt_error_codes.h index 47f16d9f..02a357fc 100644 --- a/inc/external/acl/error_codes/rt_error_codes.h +++ b/inc/external/acl/error_codes/rt_error_codes.h @@ -94,6 +94,7 @@ static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error +static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect #ifdef __cplusplus } diff --git a/inc/external/acl/ops/acl_dvpp.h b/inc/external/acl/ops/acl_dvpp.h index dcaa3936..90dc70e8 100644 --- a/inc/external/acl/ops/acl_dvpp.h +++ b/inc/external/acl/ops/acl_dvpp.h @@ -53,109 +53,123 @@ typedef void (*aclvencCallback)(acldvppPicDesc *input, acldvppStreamDesc *output // Supported Pixel Format enum acldvppPixelFormat { - PIXEL_FORMAT_YUV_400 = 0, // 0 - PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1, // 1 - PIXEL_FORMAT_YVU_SEMIPLANAR_420 = 2, // 2 - PIXEL_FORMAT_YUV_SEMIPLANAR_422 = 3, // 3 - PIXEL_FORMAT_YVU_SEMIPLANAR_422 = 4, // 4 - PIXEL_FORMAT_YUV_SEMIPLANAR_444 = 5, // 5 - PIXEL_FORMAT_YVU_SEMIPLANAR_444 = 6, // 6 - PIXEL_FORMAT_YUYV_PACKED_422 = 7, // 7 - PIXEL_FORMAT_UYVY_PACKED_422 = 8, // 8 - PIXEL_FORMAT_YVYU_PACKED_422 = 9, // 9 - PIXEL_FORMAT_VYUY_PACKED_422 = 10, // 10 - PIXEL_FORMAT_YUV_PACKED_444 = 11, // 11 - PIXEL_FORMAT_RGB_888 = 12, // 12 - PIXEL_FORMAT_BGR_888 = 13, // 13 - PIXEL_FORMAT_ARGB_8888 = 14, // 14 - PIXEL_FORMAT_ABGR_8888 = 15, // 15 - PIXEL_FORMAT_RGBA_8888 = 16, // 16 - PIXEL_FORMAT_BGRA_8888 = 17, // 17 - PIXEL_FORMAT_YUV_SEMI_PLANNER_420_10BIT = 18, // 18 - PIXEL_FORMAT_YVU_SEMI_PLANNER_420_10BIT = 19, // 19 - PIXEL_FORMAT_YVU_PLANAR_420 = 20, // 20 - PIXEL_FORMAT_YVU_PLANAR_422, - PIXEL_FORMAT_YVU_PLANAR_444, - PIXEL_FORMAT_RGB_444 = 23, - PIXEL_FORMAT_BGR_444, - PIXEL_FORMAT_ARGB_4444, - PIXEL_FORMAT_ABGR_4444, - PIXEL_FORMAT_RGBA_4444, - PIXEL_FORMAT_BGRA_4444, - PIXEL_FORMAT_RGB_555, - PIXEL_FORMAT_BGR_555, - PIXEL_FORMAT_RGB_565, - PIXEL_FORMAT_BGR_565, - PIXEL_FORMAT_ARGB_1555, - PIXEL_FORMAT_ABGR_1555, - PIXEL_FORMAT_RGBA_1555, - PIXEL_FORMAT_BGRA_1555, - PIXEL_FORMAT_ARGB_8565, - PIXEL_FORMAT_ABGR_8565, - PIXEL_FORMAT_RGBA_8565, - PIXEL_FORMAT_BGRA_8565, - PIXEL_FORMAT_RGB_BAYER_8BPP = 50, - PIXEL_FORMAT_RGB_BAYER_10BPP, - PIXEL_FORMAT_RGB_BAYER_12BPP, - PIXEL_FORMAT_RGB_BAYER_14BPP, - PIXEL_FORMAT_RGB_BAYER_16BPP, - PIXEL_FORMAT_BGR_888_PLANAR = 70, - PIXEL_FORMAT_HSV_888_PACKAGE, - PIXEL_FORMAT_HSV_888_PLANAR, - PIXEL_FORMAT_LAB_888_PACKAGE, - PIXEL_FORMAT_LAB_888_PLANAR, - PIXEL_FORMAT_S8C1, - PIXEL_FORMAT_S8C2_PACKAGE, - PIXEL_FORMAT_S8C2_PLANAR, - PIXEL_FORMAT_S16C1, - PIXEL_FORMAT_U8C1, - PIXEL_FORMAT_U16C1, - PIXEL_FORMAT_S32C1, - PIXEL_FORMAT_U32C1, - PIXEL_FORMAT_U64C1, - PIXEL_FORMAT_S64C1, - PIXEL_FORMAT_YUV_SEMIPLANAR_440 = 1000, - PIXEL_FORMAT_YVU_SEMIPLANAR_440, - PIXEL_FORMAT_FLOAT32, - PIXEL_FORMAT_BUTT, - PIXEL_FORMAT_UNKNOWN = 10000 + PIXEL_FORMAT_YUV_400 = 0, // 0 + PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1, // 1 + PIXEL_FORMAT_YVU_SEMIPLANAR_420 = 2, // 2 + PIXEL_FORMAT_YUV_SEMIPLANAR_422 = 3, // 3 + PIXEL_FORMAT_YVU_SEMIPLANAR_422 = 4, // 4 + PIXEL_FORMAT_YUV_SEMIPLANAR_444 = 5, // 5 + PIXEL_FORMAT_YVU_SEMIPLANAR_444 = 6, // 6 + PIXEL_FORMAT_YUYV_PACKED_422 = 7, // 7 + PIXEL_FORMAT_UYVY_PACKED_422 = 8, // 8 + PIXEL_FORMAT_YVYU_PACKED_422 = 9, // 9 + PIXEL_FORMAT_VYUY_PACKED_422 = 10, // 10 + PIXEL_FORMAT_YUV_PACKED_444 = 11, // 11 + PIXEL_FORMAT_RGB_888 = 12, // 12 + PIXEL_FORMAT_BGR_888 = 13, // 13 + PIXEL_FORMAT_ARGB_8888 = 14, // 14 + PIXEL_FORMAT_ABGR_8888 = 15, // 15 + PIXEL_FORMAT_RGBA_8888 = 16, // 16 + PIXEL_FORMAT_BGRA_8888 = 17, // 17 + PIXEL_FORMAT_YUV_SEMI_PLANNER_420_10BIT = 18, // 18 + PIXEL_FORMAT_YVU_SEMI_PLANNER_420_10BIT = 19, // 19 + PIXEL_FORMAT_YVU_PLANAR_420 = 20, // 20 + PIXEL_FORMAT_YVU_PLANAR_422, + PIXEL_FORMAT_YVU_PLANAR_444, + PIXEL_FORMAT_RGB_444 = 23, + PIXEL_FORMAT_BGR_444, + PIXEL_FORMAT_ARGB_4444, + PIXEL_FORMAT_ABGR_4444, + PIXEL_FORMAT_RGBA_4444, + PIXEL_FORMAT_BGRA_4444, + PIXEL_FORMAT_RGB_555, + PIXEL_FORMAT_BGR_555, + PIXEL_FORMAT_RGB_565, + PIXEL_FORMAT_BGR_565, + PIXEL_FORMAT_ARGB_1555, + PIXEL_FORMAT_ABGR_1555, + PIXEL_FORMAT_RGBA_1555, + PIXEL_FORMAT_BGRA_1555, + PIXEL_FORMAT_ARGB_8565, + PIXEL_FORMAT_ABGR_8565, + PIXEL_FORMAT_RGBA_8565, + PIXEL_FORMAT_BGRA_8565, + PIXEL_FORMAT_RGB_BAYER_8BPP = 50, + PIXEL_FORMAT_RGB_BAYER_10BPP, + PIXEL_FORMAT_RGB_BAYER_12BPP, + PIXEL_FORMAT_RGB_BAYER_14BPP, + PIXEL_FORMAT_RGB_BAYER_16BPP, + PIXEL_FORMAT_BGR_888_PLANAR = 70, + PIXEL_FORMAT_HSV_888_PACKAGE, + PIXEL_FORMAT_HSV_888_PLANAR, + PIXEL_FORMAT_LAB_888_PACKAGE, + PIXEL_FORMAT_LAB_888_PLANAR, + PIXEL_FORMAT_S8C1, + PIXEL_FORMAT_S8C2_PACKAGE, + PIXEL_FORMAT_S8C2_PLANAR, + PIXEL_FORMAT_S16C1, + PIXEL_FORMAT_U8C1, + PIXEL_FORMAT_U16C1, + PIXEL_FORMAT_S32C1, + PIXEL_FORMAT_U32C1, + PIXEL_FORMAT_U64C1, + PIXEL_FORMAT_S64C1, + PIXEL_FORMAT_YUV_SEMIPLANAR_440 = 1000, + PIXEL_FORMAT_YVU_SEMIPLANAR_440, + PIXEL_FORMAT_FLOAT32, + PIXEL_FORMAT_BUTT, + PIXEL_FORMAT_UNKNOWN = 10000 }; // Stream Format -enum acldvppStreamFormat { H265_MAIN_LEVEL = 0, H264_BASELINE_LEVEL, H264_MAIN_LEVEL, H264_HIGH_LEVEL }; +enum acldvppStreamFormat { + H265_MAIN_LEVEL = 0, + H264_BASELINE_LEVEL, + H264_MAIN_LEVEL, + H264_HIGH_LEVEL +}; // Supported Channel Mode -enum acldvppChannelMode { DVPP_CHNMODE_VPC = 1, DVPP_CHNMODE_JPEGD = 2, DVPP_CHNMODE_JPEGE = 4 }; +enum acldvppChannelMode { + DVPP_CHNMODE_VPC = 1, + DVPP_CHNMODE_JPEGD = 2, + DVPP_CHNMODE_JPEGE = 4 +}; // Supported Border Type -enum acldvppBorderType { BORDER_CONSTANT = 0, BORDER_REPLICATE, BORDER_REFLECT, BORDER_REFLECT_101 }; +enum acldvppBorderType { + BORDER_CONSTANT = 0, + BORDER_REPLICATE, + BORDER_REFLECT, + BORDER_REFLECT_101 +}; // Venc parameter type enum aclvencChannelDescParamType { - ACL_VENC_THREAD_ID_UINT64 = 0, - ACL_VENC_CALLBACK_PTR, - ACL_VENC_PIXEL_FORMAT_UINT32, - ACL_VENC_ENCODE_TYPE_UINT32, - ACL_VENC_PIC_WIDTH_UINT32, - ACL_VENC_PIC_HEIGHT_UINT32, - ACL_VENC_KEY_FRAME_INTERVAL_UINT32, - ACL_VENC_BUF_ADDR_PTR, - ACL_VENC_BUF_SIZE_UINT32, - ACL_VENC_RC_MODE_UINT32, - ACL_VENC_SRC_RATE_UINT32, - ACL_VENC_MAX_BITRATE_UINT32, - ACL_VENC_MAX_IP_PROP_UINT32 + ACL_VENC_THREAD_ID_UINT64 = 0, + ACL_VENC_CALLBACK_PTR, + ACL_VENC_PIXEL_FORMAT_UINT32, + ACL_VENC_ENCODE_TYPE_UINT32, + ACL_VENC_PIC_WIDTH_UINT32, + ACL_VENC_PIC_HEIGHT_UINT32, + ACL_VENC_KEY_FRAME_INTERVAL_UINT32, + ACL_VENC_BUF_ADDR_PTR, + ACL_VENC_BUF_SIZE_UINT32, + ACL_VENC_RC_MODE_UINT32, + ACL_VENC_SRC_RATE_UINT32, + ACL_VENC_MAX_BITRATE_UINT32, + ACL_VENC_MAX_IP_PROP_UINT32 }; // Jpeg picture format enum acldvppJpegFormat { - ACL_JPEG_CSS_444 = 0, - ACL_JPEG_CSS_422, - ACL_JPEG_CSS_420, - ACL_JPEG_CSS_GRAY, - ACL_JPEG_CSS_440, - ACL_JPEG_CSS_411, - ACL_JPEG_CSS_UNKNOWN = 1000 + ACL_JPEG_CSS_444 = 0, + ACL_JPEG_CSS_422, + ACL_JPEG_CSS_420, + ACL_JPEG_CSS_GRAY, + ACL_JPEG_CSS_440, + ACL_JPEG_CSS_411, + ACL_JPEG_CSS_UNKNOWN = 1000 }; /** @@ -509,7 +523,9 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescRetCode(const acldvppPicDesc *picD * @retval null for failed. * @retval other success */ -ACL_FUNC_VISIBILITY acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, uint32_t right, uint32_t top, +ACL_FUNC_VISIBILITY acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, + uint32_t right, + uint32_t top, uint32_t bottom); /** @@ -588,7 +604,10 @@ ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfigBottom(acldvppRoiConfig *config, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfig(acldvppRoiConfig *config, uint32_t left, uint32_t right, uint32_t top, +ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfig(acldvppRoiConfig *config, + uint32_t left, + uint32_t right, + uint32_t top, uint32_t bottom); /** @@ -1077,8 +1096,7 @@ ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescMaxBitRate(aclvencChannelDesc * @retval ACL_SUCCESS for success, other for failure */ ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescParam(aclvencChannelDesc *channelDesc, - aclvencChannelDescParamType paramType, size_t length, - const void *param); + aclvencChannelDescParamType paramType, size_t length, const void *param); /** * @ingroup AscendCL @@ -1227,8 +1245,7 @@ ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescMaxBitRate(const aclvencChanne * @retval ACL_SUCCESS for success, other for failure */ ACL_FUNC_VISIBILITY aclError aclvencGetChannelDescParam(const aclvencChannelDesc *channelDesc, - aclvencChannelDescParamType paramType, size_t length, - size_t *paramRetSize, void *param); + aclvencChannelDescParamType paramType, size_t length, size_t *paramRetSize, void *param); /** * @ingroup AscendCL @@ -1528,7 +1545,10 @@ ACL_FUNC_VISIBILITY aclError aclvdecDestroyFrameConfig(aclvdecFrameConfig *vdecF * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, uint32_t size, uint32_t *width, uint32_t *height, +ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, + uint32_t size, + uint32_t *width, + uint32_t *height, int32_t *components); /** @@ -1545,8 +1565,11 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, uint32_t * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, uint32_t size, uint32_t *width, - uint32_t *height, int32_t *components, +ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, + uint32_t size, + uint32_t *width, + uint32_t *height, + int32_t *components, acldvppJpegFormat *format); /** @@ -1561,7 +1584,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, uint32_ * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictEncSize(const acldvppPicDesc *inputDesc, - const acldvppJpegeConfig *config, uint32_t *size); + const acldvppJpegeConfig *config, + uint32_t *size); /** * @ingroup AscendCL @@ -1575,8 +1599,10 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictEncSize(const acldvppPicDesc *inp * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, uint32_t dataSize, - acldvppPixelFormat outputPixelFormat, uint32_t *decSize); +ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, + uint32_t dataSize, + acldvppPixelFormat outputPixelFormat, + uint32_t *decSize); /** * @ingroup AscendCL @@ -1591,8 +1617,11 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, uint32_ * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, uint32_t dataSize, uint32_t *width, - uint32_t *height, int32_t *components); +ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, + uint32_t dataSize, + uint32_t *width, + uint32_t *height, + int32_t *components); /** * @ingroup AscendCL @@ -1606,8 +1635,10 @@ ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, uint32_t d * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppPngPredictDecSize(const void *data, uint32_t dataSize, - acldvppPixelFormat outputPixelFormat, uint32_t *decSize); +ACL_FUNC_VISIBILITY aclError acldvppPngPredictDecSize(const void *data, + uint32_t dataSize, + acldvppPixelFormat outputPixelFormat, + uint32_t *decSize); /** * @ingroup AscendCL @@ -1671,8 +1702,10 @@ ACL_FUNC_VISIBILITY aclError acldvppDestroyChannel(acldvppChannelDesc *channelDe * @see acldvppCreateChannel | acldvppCreatePicDesc * | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, acldvppResizeConfig *resizeConfig, +ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + acldvppResizeConfig *resizeConfig, aclrtStream stream); /** @@ -1708,8 +1741,10 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDe * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, +ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + acldvppRoiConfig *cropArea, aclrtStream stream); /** @@ -1746,9 +1781,13 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, - acldvppResizeConfig *resizeConfig, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizeAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + acldvppRoiConfig *cropArea, + acldvppResizeConfig *resizeConfig, + aclrtStream stream); + /** * @ingroup AscendCL @@ -1772,9 +1811,12 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizeAsync(acldvppChannelDesc *chann * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, - uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, - acldvppRoiConfig *cropAreas[], aclrtStream stream); + acldvppBatchPicDesc *srcBatchPicDescs, + uint32_t *roiNums, + uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + aclrtStream stream); /** * @ingroup AscendCL @@ -1799,10 +1841,13 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channe * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateDvppConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, - uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, + acldvppBatchPicDesc *srcBatchPicDescs, + uint32_t *roiNums, + uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], - acldvppResizeConfig *resizeConfig, aclrtStream stream); + acldvppResizeConfig *resizeConfig, + aclrtStream stream); /** * @ingroup AscendCL @@ -1825,9 +1870,12 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeAsync(acldvppChannelDesc * * * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateRoiConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, - acldvppRoiConfig *pasteArea, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + acldvppRoiConfig *cropArea, + acldvppRoiConfig *pasteArea, + aclrtStream stream); /** * @ingroup AscendCL @@ -1851,10 +1899,13 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *cha * * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizePasteAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, +ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizePasteAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + acldvppRoiConfig *cropArea, acldvppRoiConfig *pasteArea, - acldvppResizeConfig *resizeConfig, aclrtStream stream); + acldvppResizeConfig *resizeConfig, + aclrtStream stream); /** * @ingroup AscendCL @@ -1879,11 +1930,14 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizePasteAsync(acldvppChannelDesc * * * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, - uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, - acldvppRoiConfig *cropAreas[], - acldvppRoiConfig *pasteAreas[], aclrtStream stream); + ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *channelDesc, + acldvppBatchPicDesc *srcBatchPicDescs, + uint32_t *roiNums, + uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + acldvppRoiConfig *pasteAreas[], + aclrtStream stream); /** * @ingroup AscendCL @@ -1909,10 +1963,16 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc * * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizePasteAsync( - acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], acldvppRoiConfig *pasteAreas[], - acldvppResizeConfig *resizeConfig, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizePasteAsync(acldvppChannelDesc *channelDesc, + acldvppBatchPicDesc *srcBatchPicDescs, + uint32_t *roiNums, + uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + acldvppRoiConfig *pasteAreas[], + acldvppResizeConfig *resizeConfig, + aclrtStream stream); + /** * @ingroup AscendCL @@ -1940,8 +2000,11 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizePasteAsync( * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, - acldvppPicDesc *outputDesc, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, + const void *data, + uint32_t size, + acldvppPicDesc *outputDesc, + aclrtStream stream); /** * @ingroup AscendCL @@ -1959,8 +2022,11 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelD * * @see acldvppCreateChannel | acldvppCreateJpegeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - const void *data, uint32_t *size, acldvppJpegeConfig *config, +ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + const void *data, + uint32_t *size, + acldvppJpegeConfig *config, aclrtStream stream); /** @@ -1978,8 +2044,11 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelD * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppPngDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, - acldvppPicDesc *outputDesc, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppPngDecodeAsync(acldvppChannelDesc *channelDesc, + const void *data, + uint32_t size, + acldvppPicDesc *outputDesc, + aclrtStream stream); /** * @ingroup AscendCL @@ -2034,8 +2103,11 @@ ACL_FUNC_VISIBILITY aclError aclvdecDestroyChannel(aclvdecChannelDesc *channelDe * * @see aclvdecCreateChannel | acldvppCreateStreamDesc | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, acldvppStreamDesc *input, - acldvppPicDesc *output, aclvdecFrameConfig *config, void *userData); +ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, + acldvppStreamDesc *input, + acldvppPicDesc *output, + aclvdecFrameConfig *config, + void *userData); /** * @ingroup AscendCL @@ -2054,8 +2126,10 @@ ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, a * * @see aclvdecCreateChannel | acldvppCreateStreamDesc | acldvppCreatePicDesc | aclvdecSendFrame */ -ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channelDesc, acldvppStreamDesc *input, - aclvdecFrameConfig *config, void *userData); +ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channelDesc, + acldvppStreamDesc *input, + aclvdecFrameConfig *config, + void *userData); /** * @ingroup AscendCL @@ -2076,8 +2150,10 @@ ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channel * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + aclrtStream stream); /** * @ingroup AscendCL @@ -2099,8 +2175,11 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *cha * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, void *reserve, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + void *reserve, + aclrtStream stream); /** * @ingroup AscendCL @@ -2112,7 +2191,8 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelD * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetChannelDescMode(acldvppChannelDesc *channelDesc, uint32_t mode); +ACL_FUNC_VISIBILITY aclError acldvppSetChannelDescMode(acldvppChannelDesc *channelDesc, + uint32_t mode); /** * @ingroup AscendCL @@ -2147,7 +2227,8 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetResizeConfigInterpolation(const acldvppRe * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutMode(aclvdecChannelDesc *channelDesc, uint32_t outMode); +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutMode(aclvdecChannelDesc *channelDesc, + uint32_t outMode); /** * @ingroup AscendCL @@ -2244,7 +2325,9 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetLutMapDims(const acldvppLutMap *lutMap); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, uint32_t dim, uint8_t **data, +ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, + uint32_t dim, + uint8_t **data, uint32_t *len); /** * @ingroup AscendCL @@ -2262,8 +2345,10 @@ ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, u * @see acldvppCreateChannel|acldvppCreatePicDesc|acldvppCreateLutMap */ ACL_FUNC_VISIBILITY aclError acldvppVpcEqualizeHistAsync(const acldvppChannelDesc *channelDesc, - const acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, - const acldvppLutMap *lutMap, aclrtStream stream); + const acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + const acldvppLutMap *lutMap, + aclrtStream stream); /** * @ingroup AscendCL @@ -2284,7 +2369,8 @@ ACL_FUNC_VISIBILITY acldvppBorderConfig *acldvppCreateBorderConfig(); * * @retval ACL_SUCCESS for success, other for failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigValue(acldvppBorderConfig *borderConfig, uint32_t index, +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigValue(acldvppBorderConfig *borderConfig, + uint32_t index, double value); /** @@ -2429,8 +2515,10 @@ ACL_FUNC_VISIBILITY aclError acldvppDestroyBorderConfig(acldvppBorderConfig *bor * @see acldvppCreateChannel|acldvppCreatePicDesc|acldvppCreateBorderConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcMakeBorderAsync(const acldvppChannelDesc *channelDesc, - const acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, - const acldvppBorderConfig *borderConfig, aclrtStream stream); + const acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + const acldvppBorderConfig *borderConfig, + aclrtStream stream); /** * @ingroup AscendCL @@ -2447,8 +2535,11 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcMakeBorderAsync(const acldvppChannelDesc * * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateHist */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *srcPicDesc, - acldvppHist *hist, void *reserve, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *srcPicDesc, + acldvppHist *hist, + void *reserve, + aclrtStream stream); /** * @ingroup AscendCL @@ -2457,7 +2548,7 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channel * @retval null for failed. * @retval OtherValues success. */ -ACL_FUNC_VISIBILITY acldvppHist *acldvppCreateHist(); +ACL_FUNC_VISIBILITY acldvppHist* acldvppCreateHist(); /** * @ingroup AscendCL @@ -2514,7 +2605,7 @@ ACL_FUNC_VISIBILITY aclError acldvppGetHistData(acldvppHist *hist, uint32_t dim, * * @see acldvppCreateHist | acldvppVpcCalcHistAsync */ -ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist *hist); +ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist* hist); /** * @ingroup AscendCL @@ -2533,6 +2624,7 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist *hist); */ ACL_FUNC_VISIBILITY aclError acldvppClearHist(acldvppHist *hist); + /** * @ingroup AscendCL * @brief dvpp vpc batch crop, resize config and make border. @@ -2556,13 +2648,18 @@ ACL_FUNC_VISIBILITY aclError acldvppClearHist(acldvppHist *hist); * * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeMakeBorderAsync( - acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], acldvppBorderConfig *borderCfgs[], - acldvppResizeConfig *resizeConfig, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeMakeBorderAsync(acldvppChannelDesc *channelDesc, + acldvppBatchPicDesc *srcBatchPicDescs, + uint32_t *roiNums, + uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + acldvppBorderConfig *borderCfgs[], + acldvppResizeConfig *resizeConfig, + aclrtStream stream); #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ diff --git a/inc/external/hccl/hccl.h b/inc/external/hccl/hccl.h index 311e78f2..cc4bea8e 100644 --- a/inc/external/hccl/hccl.h +++ b/inc/external/hccl/hccl.h @@ -118,6 +118,15 @@ HcclReduceOp op, HcclComm comm, aclrtStream stream); extern HcclResult HcclAllGather(void *sendBuf, void *recvBuf, uint64_t sendCount, HcclDataType dataType, HcclComm comm, aclrtStream stream); +/** + * @brief Barrier operator. + * + * @param comm A pointer identifying the communication resource based on. + * @param stream A pointer identifying the stream information. + * @return HcclResult + */ +extern HcclResult HcclBarrier(HcclComm comm, aclrtStream stream); + /** * @brief Destroy HCCL comm * diff --git a/inc/external/runtime/rt_error_codes.h b/inc/external/runtime/rt_error_codes.h index 47f16d9f..02a357fc 100644 --- a/inc/external/runtime/rt_error_codes.h +++ b/inc/external/runtime/rt_error_codes.h @@ -94,6 +94,7 @@ static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error +static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect #ifdef __cplusplus } diff --git a/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h b/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h old mode 100755 new mode 100644 diff --git a/third_party/fwkacllib/inc/mmpa/mmpa_api.h b/third_party/fwkacllib/inc/mmpa/mmpa_api.h index 38a689ee..f8d5ccf3 100644 --- a/third_party/fwkacllib/inc/mmpa/mmpa_api.h +++ b/third_party/fwkacllib/inc/mmpa/mmpa_api.h @@ -56,6 +56,7 @@ #include #include #include +#include #include #include diff --git a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h index 993f36ba..3d196e41 100644 --- a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h +++ b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h @@ -550,6 +550,10 @@ MMPA_FUNC_VISIBILITY mmFileHandle mmShmOpen(const CHAR *name, INT32 oflag, mmMod MMPA_FUNC_VISIBILITY INT32 mmShmUnlink(const CHAR *name); MMPA_FUNC_VISIBILITY VOID *mmMmap(mmFd_t fd, mmSize_t size, mmOfft_t offset, mmFd_t *extra, INT32 prot, INT32 flags); MMPA_FUNC_VISIBILITY INT32 mmMunMap(VOID *data, mmSize_t size, mmFd_t *extra); + +MMPA_FUNC_VISIBILITY mmSize mmGetPageSize(); +MMPA_FUNC_VISIBILITY VOID *mmAlignMalloc(mmSize mallocSize, mmSize alignSize); +MMPA_FUNC_VISIBILITY VOID mmAlignFree(VOID *addr); #define MMPA_DLL_API #ifdef __cplusplus diff --git a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h index 49e97a5d..e6b6f71e 100644 --- a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h +++ b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h @@ -557,6 +557,10 @@ MMPA_FUNC_VISIBILITY mmFileHandle mmShmOpen(const CHAR *name, INT32 oflag, mmMod MMPA_FUNC_VISIBILITY INT32 mmShmUnlink(const CHAR *name); MMPA_FUNC_VISIBILITY VOID *mmMmap(mmFd_t fd, mmSize_t size, mmOfft_t offset, mmFd_t *extra, INT32 prot, INT32 flags); MMPA_FUNC_VISIBILITY INT32 mmMunMap(VOID *data, mmSize_t size, mmFd_t *extra); + +MMPA_FUNC_VISIBILITY mmSize mmGetPageSize(); +MMPA_FUNC_VISIBILITY VOID *mmAlignMalloc(mmSize mallocSize, mmSize alignSize); +MMPA_FUNC_VISIBILITY VOID mmAlignFree(VOID *addr); #ifdef __cplusplus #if __cplusplus } diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index 0ec15367..209967bd 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -146,6 +146,8 @@ REG_OP(Cast) /** *@brief Returns the truth value of (x1 >= x2) element-wise. \n +*when input is int32 and (x2 - x1) > 2**31 or < -2**31 +*aicore accuracy is not guaranteed \n *@par Inputs: *Two inputs, including: @@ -167,6 +169,8 @@ REG_OP(GreaterEqual) /** *@brief Returns the truth value of (x1 < x2) element-wise. \n +*when input is int32 and (x2 - x1) > 2**31 or < -2**31 +*aicore accuracy is not guaranteed \n *@par Inputs: *Two inputs, including: @@ -567,6 +571,8 @@ REG_OP(InvGrad) /** *@brief: Returns the truth value of (x <= y) element-wise. \n +*when input is int32 and (x2 - x1) > 2**31 or < -2**31 +*aicore accuracy is not guaranteed \n *@par Inputs: * Two inputs, including: @@ -1464,6 +1470,8 @@ REG_OP(ReciprocalGrad) /** *@brief Returns the truth value of (x1 > x2) element-wise. \n +*when input is int32 and (x2 - x1) > 2**31 or < -2**31 +*aicore accuracy is not guaranteed \n *@par Inputs: *@li x1: A Tensor of type float16, float32, double, int64, int32, int16, int8, @@ -3800,6 +3808,34 @@ REG_OP(ArgMaxGradD) .REQUIRED_ATTR(dimension, Int) .OP_END_FACTORY_REG(ArgMaxGradD) +/** +*@brief Calculates the reversed outputs of the function "AddMatMatElements" +* c = c * beta + alpha * a * b + +*@par Inputs: +*Three inputs, including: +* @li c: A mutable Tensor. Must be one of the following types: +* float16, float32. +* @li a: A mutable Tensor of the same type as "c". +* @li b: A mutable Tensor of the same type as "c". +* @li beta: A mutable scalar of the same type as "c". +* @li alpha: A mutable scalar of the same type as "c". \n + +*@par Outputs: +* @li c: A mutable Tensor. Has the same type as "c". \n + +*@par Third-party framework compatibility +* Compatible with the TensorFlow operator AddMatMatElements. +*/ +REG_OP(AddMatMatElements) + .INPUT(c, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(a, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(b, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(beta, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(alpha, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(c, TensorType({DT_FLOAT, DT_FLOAT16})) + .OP_END_FACTORY_REG(AddMatMatElements) + /** *@brief Returns cosine similarity between x1 and x2,computed along dim. \n diff --git a/third_party/fwkacllib/inc/ops/image_ops.h b/third_party/fwkacllib/inc/ops/image_ops.h index 6ae1613c..3ef4d95e 100644 --- a/third_party/fwkacllib/inc/ops/image_ops.h +++ b/third_party/fwkacllib/inc/ops/image_ops.h @@ -24,6 +24,22 @@ #include "graph/operator_reg.h" namespace ge { +/** +*@brief Decode the frame(s) of a GIF-encoded image to a uint8 tensor . \n + +*@par Inputs: +*@li contents:A Tensor of type string. 0-D. The GIF-encoded image. \n + +*@par Outputs: +*image:A Tensor of type uint8. \n + +*@par Third-party framework compatibility +*Compatible with tensorflow DecodeGif operator. +*/ +REG_OP(DecodeGif) + .INPUT(contents, TensorType({DT_STRING})) + .OUTPUT(image, TensorType({DT_UINT8})) + .OP_END_FACTORY_REG(DecodeGif) /** *@brief Adjust the hue of one or more images . \n @@ -1071,6 +1087,88 @@ REG_OP(EncodePng) .ATTR(compression, Int, -1) .OP_END_FACTORY_REG(EncodePng) + +/** +*@brief PNG-decode an image. +*@par Inputs: +*contents: 0-D. PNG-decoded image . + +*@par Attributes: +*channels: graph channels \n +*dtype: type of image + +*@par Outputs: +*image: is a 3-D uint8 or uint16 Tensor of shape [height, width, channels] +where channels is: 1: for grayscale; 2: for grayscale + alpha; 3: for RGB; +4: for RGBA . \n + +*@par Third-party framework compatibility +*Compatible with tensorflow DecodePng operator. +*/ +REG_OP(DecodePng) + .INPUT(contents, TensorType({DT_STRING})) + .OUTPUT(image, TensorType({DT_UINT8, DT_UINT16})) + .ATTR(dtype, Type, DT_UINT8) + .ATTR(channels, Int, 0) + .OP_END_FACTORY_REG(DecodePng) + +/** +*@brief Bmp-decode an image. \n + +*@par Inputs: +*@li contents: A Tensor of type string. 0-D. The BMP-encoded image. \n + +*@par Attributes: +*@li channels: Decode the desired number of color channels of the image. \n + +*@par Outputs: +*image: A Tensor dtype of uint8. + +* @par Third-party framework compatibility +* Compatible with tensorflow DecodeBmp operator. +*/ + +REG_OP(DecodeBmp) + .INPUT(contents, TensorType({DT_STRING})) + .OUTPUT(image, TensorType({DT_UINT8})) + .ATTR(channels, Int, 0) + .OP_END_FACTORY_REG(DecodeBmp) + +/* +*@brief Function parse image from string to int. \n + +*@par Inputs: +*@li contents: A Tensor of type string. 0-D. The JPEG-encoded image. \n +*@li crop_window: 1-D. The crop window: [crop_y, crop_x, crop_height, crop_width]. \n + +*@par Attributes: +*@li channels: An optional int. Defaults to 0. Number of color channels for the +*decoded image. +*@li ratio: An optional int. Defaults to 1. Downscaling ratio. +*@li fancy_upscaling: An optional bool. Defaults to True. If true use a slower +*but nicer upscaling of the chroma planes +*@li try_recover_truncated: An optional bool. Defaults to False. If true try to +*recover an image from truncated input. +*@li acceptable_fraction: An optional float. Defaults to 1. The minimum required +fraction of lines before a truncated input is accepted. +*@li dct_method: An optional string. Defaults to "". string specifying a hint +*about the algorithm used for decompression. \n + +*@par Outputs: +*image: A Tensor dtype of uint8. +*/ +REG_OP(DecodeAndCropJpeg) + .INPUT(contents, TensorType({DT_STRING})) + .INPUT(crop_window, TensorType({DT_INT32})) + .OUTPUT(image, TensorType({DT_UINT8})) + .ATTR(channels, Int, 0) + .ATTR(ratio, Int, 1) + .ATTR(fancy_upscaling, Bool, true) + .ATTR(try_recover_truncated, Bool, false) + .ATTR(acceptable_fraction, Float, 1.0) + .ATTR(dct_method, String, "") + .OP_END_FACTORY_REG(DecodeAndCropJpeg) + /** *@brief Resizes "images" to "size" using bilinear interpolation . \n diff --git a/third_party/fwkacllib/inc/ops/linalg_ops.h b/third_party/fwkacllib/inc/ops/linalg_ops.h index 1a59d88e..532a641d 100644 --- a/third_party/fwkacllib/inc/ops/linalg_ops.h +++ b/third_party/fwkacllib/inc/ops/linalg_ops.h @@ -82,6 +82,25 @@ REG_OP(Cholesky) DT_FLOAT16, DT_COMPLEX64, DT_COMPLEX128})) .OP_END_FACTORY_REG(Cholesky) +/** +*@brief Computes the outer product of two 1D vectors . \n + +*@par Inputs: +*The input x1 and x2 has to be a 1D vector.Inputs include: +*@li x1:A Tensor. Must be one of the following types: float16, float32. +Shape is [N] . \n +*@li x2:A Tensor. Must have the same type as x. Shape is [M] . \n + +*@par Outputs: +*y:A Tensor. Has the same type as x . \n +*/ + +REG_OP(Ger) + .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(Ger) + /** *@brief Computes the sign and the log of the absolute value of the determinant of one or more square matrices . \n @@ -327,6 +346,34 @@ REG_OP(SelfAdjointEig) .ATTR(compute_v, Bool, true) .OP_END_FACTORY_REG(SelfAdjointEig) +/** +*@brief Computes the sign and the log of the absolute value of the determinant +of one or more square matrices . \n + +*@par Inputs: +*The input x is a tensor of shape [N, M, M] whose inner-most 2 dimensions +form square matrices. Inputs include: +*x:A Tensor. Must be one of the following types: double, float32, float16 +Shape is [..., M, M] . \n + +*@par Outputs: +*@li y:A Tensor. Has the same type as x. +*@li sign:A Tensor. Has the same type as x . \n + +*@attention Constraints: +*The input x is a tensor of shape [N, M, M] whose inner-most 2 dimensions +form square matrices. \n + +*@par Third-party framework compatibility +*Compatible with tensorflow LogMatrixDeterminant operator. +*/ + +REG_OP(Slogdet) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(sign, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OP_END_FACTORY_REG(Slogdet) + /** *@brief Computes the singular value decompositions of one or more matrices . \n diff --git a/third_party/fwkacllib/inc/ops/math_ops.h b/third_party/fwkacllib/inc/ops/math_ops.h index 28f7f0aa..4a44d744 100644 --- a/third_party/fwkacllib/inc/ops/math_ops.h +++ b/third_party/fwkacllib/inc/ops/math_ops.h @@ -533,6 +533,29 @@ REG_OP(NextAfter) .OUTPUT(output, TensorType({DT_FLOAT, DT_DOUBLE})) .OP_END_FACTORY_REG(NextAfter) +/** +*@brief Calculate the P-norm distance between vectors function. \n + +*@par Inputs: +*One inputs, including: +* @li input_x: A tensor. Must be one of the following types: +* float16, float32. \n + +*@par Attributes: +*@li p: An optional float.Defaults to 2. \n + +*@par Outputs: +*y: A Tensor with the same type and shape of input_x's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator Pdist. \n +*/ +REG_OP(Pdist) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(p, Float, 2.0) + .OP_END_FACTORY_REG(Pdist) + /** *@brief Compute element-wise finiteness, return a boolean tensor. diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index 49a49931..3340007c 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -91,6 +91,36 @@ REG_OP(MatMulV2) .ATTR(offset_x, Int, 0) .OP_END_FACTORY_REG(MatMulV2) +/** +*@brief Multiplies matrix "a" by matrix "b", producing "a * b" . \n + +*@par Inputs: +*Two inputs, including: +* @li x1: A matrix Tensor. 2D. Must be one of the following types: int8. +* @li x2: A matrix Tensor. 2D. Must be one of the following types: int8. +* @li compress_index: A compress index matrix of type int8. +* @li bias: A 1D Tensor. Must be one of the following types: int32, float16. + +*@par Attributes: +*@li transpose_x1: A bool. If True, changes the shape of "x1" from [M, K] to [K, M]. +*@li transpose_x2: A bool. If True, changes the shape of "x2" from [M, K] to [K, M] . \n + +*@par Outputs: +*y: The result matrix Tensor. 2D. Must be one of the following types: float16, +* int32. \n + +*/ +REG_OP(MatMulV2Compress) + .INPUT(x1, TensorType({DT_INT8})) + .INPUT(x2, TensorType({DT_INT8})) + .INPUT(compress_index, TensorType({DT_INT8})) + .OPTIONAL_INPUT(bias, TensorType({DT_INT32, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_INT32, DT_FLOAT16})) + .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8})) + .ATTR(transpose_x1, Bool, false) + .ATTR(transpose_x2, Bool, false) + .ATTR(offset_x, Int, 0) + .OP_END_FACTORY_REG(MatMulV2Compress) /** *@brief Performs Matrix-to-matrix Multiply, producing c=alpha[0]*a*b+beta[0]*c . \n @@ -189,8 +219,8 @@ REG_OP(BatchMatMul) * float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ] . \n * @par Attributes: -* @li adj_x: A bool. If True, changes the shape of "x1" from [B, M, K] to [B, K, M]. -* @li adj_y: A bool. If True, changes the shape of "x2" from [B, M, K] to [B, K, M] . \n +* @li adj_x1: A bool. If True, changes the shape of "x1" from [B, M, K] to [B, K, M]. +* @li adj_x2: A bool. If True, changes the shape of "x2" from [B, M, K] to [B, K, M] . \n * @par Outputs: * y: The result matrix Tensor. 2D or higher. Must be one of the following types: float16, @@ -201,15 +231,16 @@ REG_OP(BatchMatMul) */ REG_OP(BatchMatMulV2) - .INPUT(x1, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) - .INPUT(x2, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .INPUT(x1, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) + .INPUT(x2, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8})) .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) .ATTR(adj_x1, Bool, false) .ATTR(adj_x2, Bool, false) + .ATTR(offset_x, Int, 0) .OP_END_FACTORY_REG(BatchMatMulV2) - /** *@brief Computes half the L2 norm of a tensor without the sqrt . \n @@ -369,7 +400,7 @@ REG_OP(MatrixSetDiagD) * int64, complex64, qint8, quint8, qint32, uint16, complex128, half, uint32, * uint64 *@li indices: An ND Tensor. -*Must be one of the following types: int32, int64 +*Must be one of the following types: int32 or int64 *@li updates: An ND Tensor. *Must be one of the following types: float16, float32, int8, uint8, double, * int64, complex64, qint8, quint8, qint32, uint16, complex128, half, uint32, @@ -429,7 +460,7 @@ REG_OP(TensorScatterUpdate) *@li var: An ND Tensor . \n *Must be one of the following types: float16, float32, int32, int8, uint8 -*@li indices: An ND Tensor of type int32 or int64. +*@li indices: An ND Tensor of type int32 or int64 *@li updates: An Tensor. format:NCHW, NHWC . \n @@ -447,10 +478,10 @@ REG_OP(TensorScatterUpdate) * Compatible with the TensorFlow operator ScatterAdd. */ REG_OP(ScatterAdd) - .INPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .INPUT(indices, TensorType::IndexNumberType()) - .INPUT(updates, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .OUTPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterAdd) @@ -463,7 +494,7 @@ REG_OP(ScatterAdd) *Must be one of the following types: float16, float, int32, int8, uint8 *@li indices: An ND Tensor. -*Must be one of the following types: int32 +*Must be one of the following types: int32 or int64 *@li updates: An ND Tensor. *Must be one of the following types: float16, float, int32, int8, uint8 @@ -478,10 +509,10 @@ REG_OP(ScatterAdd) * Compatible with the TensorFlow operator ScatterDiv. */ REG_OP(ScatterDiv) - .INPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .INPUT(indices, TensorType({DT_INT32})) - .INPUT(updates, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .OUTPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(indices, TensorType::IndexNumberType()) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterDiv) @@ -493,7 +524,7 @@ REG_OP(ScatterDiv) *@li var: An ND Tensor. *Must be one of the following types: float16, float, int32, int8, uint8 *@li indices: An ND Tensor. -*Must be one of the following types: int32 +*Must be one of the following types: int32 or int64 *@li updates: An ND Tensor. *Must be one of the following types: float16, float, int32, int8, uint8 *@par Attributes: @@ -507,10 +538,10 @@ REG_OP(ScatterDiv) * Compatible with the TensorFlow operator ScatterNdAdd. */ REG_OP(ScatterNdAdd) - .INPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .INPUT(indices, TensorType::IndexNumberType()) - .INPUT(updates, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .OUTPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterNdAdd) @@ -550,7 +581,7 @@ REG_OP(TensorScatterAdd) *@li var: An ND Tensor. *Must be one of the following types: float16, float, int32, int8, uint8 *@li indices: An ND Tensor. -*Must be one of the following types: int32, int64 +*Must be one of the following types: int32 or int64 *@li updates: An ND Tensor. *Must be one of the following types: float16, float, int32, int8, uint8 @@ -565,10 +596,10 @@ REG_OP(TensorScatterAdd) * Compatible with the TensorFlow operator ScatterNdSub. */ REG_OP(ScatterNdSub) - .INPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .INPUT(indices, TensorType::IndexNumberType()) - .INPUT(updates, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .OUTPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterNdSub) @@ -608,7 +639,7 @@ REG_OP(TensorScatterSub) *@li var: An ND Tensor. *Must be one of the following types: float16, float, int32, int8, uint8 *@li indices: An ND Tensor. -*Must be one of the following types: int32, int64 +*Must be one of the following types: int32 or int64 *@li updates: An ND Tensor. *Must be one of the following types: float16, float, int32, int8, uint8 *@par Attributes: @@ -622,10 +653,10 @@ REG_OP(TensorScatterSub) * Compatible with the TensorFlow operator ScatterSub. */ REG_OP(ScatterSub) - .INPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .INPUT(indices, TensorType::IndexNumberType()) - .INPUT(updates, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .OUTPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterSub) @@ -796,7 +827,7 @@ REG_OP(ConfusionMatrix) *@li var: An ND Tensor. *Must be one of the following types: float16, float, int32, int8, uint8 *@li indices: An ND Tensor. -*Must be one of the following types: int32 +*Must be one of the following types: int32 or int64 *@li updates: An ND Tensor . \n *Must be one of the following types: float16, float, int32, int8, uint8 @@ -813,7 +844,7 @@ REG_OP(ConfusionMatrix) */ REG_OP(ScatterMul) .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .INPUT(indices, TensorType({DT_INT32})) + .INPUT(indices, TensorType::IndexNumberType()) .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .ATTR(use_locking, Bool, false) @@ -826,13 +857,13 @@ REG_OP(ScatterMul) *@par Inputs: * Three inputs, including: *@li var: An ND Tensor. -*Must be one of the following types: float16, float, int32 +*Must be one of the following types: float16, float, int32, int8, uint8 *@li indices: An ND Tensor. -*Must be one of the following types: int32 +*Must be one of the following types: int32 or int64 *@li updates: An ND Tensor. -*Must be one of the following types: float16, float, int32 +*Must be one of the following types: float16, float, int32, int8, uint8 *@par Attributes: *use_locking: An optional bool. Defaults to "False". If "True", the operation @@ -845,10 +876,10 @@ REG_OP(ScatterMul) * Compatible with the TensorFlow operator ScatterMin. */ REG_OP(ScatterMin) - .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32})) - .INPUT(indices, TensorType({DT_INT32})) - .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32})) - .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32})) + .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(indices, TensorType::IndexNumberType()) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterMin) @@ -859,13 +890,13 @@ REG_OP(ScatterMin) * Three inputs, including: *@li var: An ND Tensor . \n -*Must be one of the following types: float16, float, int32 +*Must be one of the following types: float16, float, int32, int8, uint8 *@li indices: An NCHW, NHWC, or ND Tensor . \n -*Must be one of the following types: int32 +*Must be one of the following types: int32 or int64 *@li updates: An NCHW, NHWC, or ND Tensor . \n -*Must be one of the following types: float16, float, int32 +*Must be one of the following types: float16, float, int32, int8, uint8 *@par Attributes: *use_locking: An optional bool. Defaults to "False". @@ -878,10 +909,10 @@ REG_OP(ScatterMin) * Compatible with the TensorFlow operator ScatterMax. */ REG_OP(ScatterMax) - .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32})) - .INPUT(indices, TensorType({DT_INT32})) - .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32})) - .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32})) + .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(indices, TensorType::IndexNumberType()) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterMax) @@ -895,7 +926,7 @@ REG_OP(ScatterMax) *Must be one of the following types: float16, float, int32, int8, uint8 *@li indices: An ND Tensor . \n -*Must be one of the following types: int32 +*Must be one of the following types: int32 or int64 *@li updates: An ND Tensor . \n *Must be one of the following types: float16, float, int32, int8, uint8 @@ -911,10 +942,10 @@ REG_OP(ScatterMax) * Compatible with the TensorFlow operator ScatterUpdate. */ REG_OP(ScatterUpdate) - .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT8,DT_UINT8})) - .INPUT(indices, TensorType({DT_INT32})) - .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT8,DT_UINT8})) - .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT8,DT_UINT8})) + .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(indices, TensorType::IndexNumberType()) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterUpdate) @@ -1096,6 +1127,33 @@ REG_OP(EinSum) .REQUIRED_ATTR(equation, String) .REQUIRED_ATTR(tensor_size, Int) .OP_END_FACTORY_REG(EinSum) + +/** +*@brief Returns a 2-D tensor with ones on the diagonal and zeros elsewhere. \n + +*@par Inputs: +*No inputs + +*@par Attributes: +*@li num_rows: An required int. \n +*@li num_columns: An optional int.Defaults to 0. \n +*@li batch_shape: An optional ListInt.Defaults to []. \n +*@li dtype: An optional int.Defaults to 0. \n + +*@par Outputs: +*y: A Tensor with targeted type and shape. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator Eye. \n +*/ +REG_OP(Eye) + .OUTPUT(y, TensorType::BasicType()) /* "Result, has targeted element type" */ + .REQUIRED_ATTR(num_rows, Int) + .ATTR(num_columns, Int, 0) + .ATTR(batch_shape, ListInt, {}) + .ATTR(dtype, Int, 0) + .OP_END_FACTORY_REG(Eye) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATRIX_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_detect_ops.h b/third_party/fwkacllib/inc/ops/nn_detect_ops.h index af59b4e2..33148e62 100644 --- a/third_party/fwkacllib/inc/ops/nn_detect_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_detect_ops.h @@ -254,22 +254,22 @@ is min_size/sqrt(aspect_ratio), the width is min_size*sqrt(aspect_ratio). Defaul *@par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. */ - REG_OP(PriorBox) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(img, TensorType({DT_FLOAT16, DT_FLOAT})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) - .REQUIRED_ATTR(min_size, ListFloat) - .REQUIRED_ATTR(max_size, ListFloat) - .REQUIRED_ATTR(aspect_ratio, ListFloat) - .ATTR(img_h, Int, 0) - .ATTR(img_w, Int, 0) - .ATTR(step_h, Float, 0.0) - .ATTR(step_w, Float, 0.0) - .ATTR(flip, Bool, true) - .ATTR(clip, Bool, false) - .ATTR(offset, Float, 0.5) - .ATTR(variance, ListFloat, {0.1}) - .OP_END_FACTORY_REG(PriorBox); +REG_OP(PriorBox) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(img, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(min_size, ListFloat) + .REQUIRED_ATTR(max_size, ListFloat) + .REQUIRED_ATTR(aspect_ratio, ListFloat) + .ATTR(img_h, Int, 0) + .ATTR(img_w, Int, 0) + .ATTR(step_h, Float, 0.0) + .ATTR(step_w, Float, 0.0) + .ATTR(flip, Bool, true) + .ATTR(clip, Bool, false) + .ATTR(offset, Float, 0.5) + .ATTR(variance, ListFloat, {0.1}) + .OP_END_FACTORY_REG(PriorBox); /** *@brief Performs SSD prior box detection, with four additional matrices and the "aspect_ratio" attribute deleted compared to PriorBox . \n @@ -306,25 +306,25 @@ is min_size/sqrt(aspect_ratio), the width is min_size*sqrt(aspect_ratio). Defaul *@par Restrictions: *Warning: THIS FUNCTION IS DEPRECATED. Please use PriorBox instead. */ - REG_OP(PriorBoxD) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(img, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(data_h, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(data_w, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(box_height, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(box_width, TensorType({DT_FLOAT16, DT_FLOAT})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) - .REQUIRED_ATTR(min_size, ListFloat) - .REQUIRED_ATTR(max_size, ListFloat) - .ATTR(img_h, Int, 0) - .ATTR(img_w, Int, 0) - .ATTR(step_h, Float, 0.0) - .ATTR(step_w, Float, 0.0) - .ATTR(flip, Bool, true) - .ATTR(clip, Bool, false) - .ATTR(offset, Float, 0.5) - .ATTR(variance, ListFloat, {0.1}) - .OP_END_FACTORY_REG(PriorBoxD); +REG_OP(PriorBoxD) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(img, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(data_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(data_w, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(box_height, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(box_width, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(min_size, ListFloat) + .REQUIRED_ATTR(max_size, ListFloat) + .ATTR(img_h, Int, 0) + .ATTR(img_w, Int, 0) + .ATTR(step_h, Float, 0.0) + .ATTR(step_w, Float, 0.0) + .ATTR(flip, Bool, true) + .ATTR(clip, Bool, false) + .ATTR(offset, Float, 0.5) + .ATTR(variance, ListFloat, {0.1}) + .OP_END_FACTORY_REG(PriorBoxD); /** *@brief Performs SSD prior box detection, with four additional matrices and the "aspect_ratio" attribute deleted compared to PriorBox . \n @@ -358,22 +358,22 @@ is min_size/sqrt(aspect_ratio), the width is min_size*sqrt(aspect_ratio). Defaul *@par Restrictions: *Warning: THIS FUNCTION IS DEPRECATED. Please use PriorBox instead. */ - REG_OP(PriorBoxDV2) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(img, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(boxes, TensorType({DT_FLOAT16, DT_FLOAT})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) - .REQUIRED_ATTR(min_size, ListFloat) - .REQUIRED_ATTR(max_size, ListFloat) - .ATTR(img_h, Int, 0) - .ATTR(img_w, Int, 0) - .ATTR(step_h, Float, 0.0) - .ATTR(step_w, Float, 0.0) - .ATTR(flip, Bool, true) - .ATTR(clip, Bool, false) - .ATTR(offset, Float, 0.5) - .ATTR(variance, ListFloat, {0.1}) - .OP_END_FACTORY_REG(PriorBoxDV2); +REG_OP(PriorBoxDV2) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(img, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(boxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(min_size, ListFloat) + .REQUIRED_ATTR(max_size, ListFloat) + .ATTR(img_h, Int, 0) + .ATTR(img_w, Int, 0) + .ATTR(step_h, Float, 0.0) + .ATTR(step_w, Float, 0.0) + .ATTR(flip, Bool, true) + .ATTR(clip, Bool, false) + .ATTR(offset, Float, 0.5) + .ATTR(variance, ListFloat, {0.1}) + .OP_END_FACTORY_REG(PriorBoxDV2); /** *@brief Performs Position Sensitive ROI Pooling . \n @@ -531,10 +531,10 @@ as xx...xyy...yww...whh...hbb...bc0c0..c0c1c1...c1......cncn...cn . \n * It is a custom operator. It has no corresponding operator in Caffe. */ REG_OP(Yolo) - .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) - .OUTPUT(coord_data, TensorType({DT_FLOAT16,DT_FLOAT})) - .OUTPUT(obj_prob, TensorType({DT_FLOAT16,DT_FLOAT})) - .OUTPUT(classes_prob, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(coord_data, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(obj_prob, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(classes_prob, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(boxes, Int, 3) .ATTR(coords, Int, 4) .ATTR(classes, Int, 80) @@ -584,10 +584,10 @@ REG_OP(Yolo) * It is a custom operator. It has no corresponding operator in Caffe. */ REG_OP(YoloV2DetectionOutput) - .INPUT(coord_data, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(obj_prob, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(classes_prob, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(img_info, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(coord_data, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(obj_prob, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(classes_prob, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(img_info, TensorType({DT_FLOAT16, DT_FLOAT})) .REQUIRED_ATTR(biases, ListFloat) .ATTR(boxes, Int, 5) .ATTR(coords, Int, 4) @@ -598,7 +598,7 @@ REG_OP(YoloV2DetectionOutput) .ATTR(score_threshold, Float, 0.5) .ATTR(iou_threshold, Float, 0.45) .ATTR(pre_nms_topn, Int, 512) - .OUTPUT(box_out, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(box_out, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(box_out_num, TensorType({DT_INT32})) .OP_END_FACTORY_REG(YoloV2DetectionOutput) @@ -647,12 +647,12 @@ REG_OP(YoloV2DetectionOutput) *Warning: THIS FUNCTION IS DEPRECATED. Please use YoloV2DetectionOutput instead. */ REG_OP(YoloV2DetectionOutputD) - .INPUT(coord_data, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(obj_prob, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(classes_prob, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(img_info, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(windex, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(hindex, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(coord_data, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(obj_prob, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(classes_prob, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(img_info, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(windex, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(hindex, TensorType({DT_FLOAT16, DT_FLOAT})) .REQUIRED_ATTR(biases, ListFloat) .ATTR(boxes, Int, 5) .ATTR(coords, Int, 4) @@ -663,7 +663,7 @@ REG_OP(YoloV2DetectionOutputD) .ATTR(score_threshold, Float, 0.5) .ATTR(iou_threshold, Float, 0.45) .ATTR(pre_nms_topn, Int, 512) - .OUTPUT(box_out, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(box_out, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(box_out_num, TensorType({DT_INT32})) .OP_END_FACTORY_REG(YoloV2DetectionOutputD) @@ -707,16 +707,16 @@ REG_OP(YoloV2DetectionOutputD) * It is a custom operator. It has no corresponding operator in Caffe. */ REG_OP(YoloV3DetectionOutput) - .INPUT(coord_data_low, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(coord_data_mid, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(coord_data_high, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(obj_prob_low, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(obj_prob_mid, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(obj_prob_high, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(classes_prob_low, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(classes_prob_mid, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(classes_prob_high, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(img_info, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(coord_data_low, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(coord_data_mid, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(coord_data_high, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(obj_prob_low, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(obj_prob_mid, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(obj_prob_high, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(classes_prob_low, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(classes_prob_mid, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(classes_prob_high, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(img_info, TensorType({DT_FLOAT16, DT_FLOAT})) .REQUIRED_ATTR(biases_low, ListFloat) .REQUIRED_ATTR(biases_mid, ListFloat) .REQUIRED_ATTR(biases_high, ListFloat) @@ -729,7 +729,7 @@ REG_OP(YoloV3DetectionOutput) .ATTR(score_threshold, Float, 0.5) .ATTR(iou_threshold, Float, 0.45) .ATTR(pre_nms_topn, Int, 512) - .OUTPUT(box_out, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(box_out, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(box_out_num, TensorType({DT_INT32})) .OP_END_FACTORY_REG(YoloV3DetectionOutput) @@ -776,22 +776,22 @@ s *Warning: THIS FUNCTION IS DEPRECATED. Please use YoloV3DetectionOutput instead. */ REG_OP(YoloV3DetectionOutputD) - .INPUT(coord_data_low, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(coord_data_mid, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(coord_data_high, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(obj_prob_low, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(obj_prob_mid, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(obj_prob_high, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(classes_prob_low, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(classes_prob_mid, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(classes_prob_high, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(img_info, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(windex1, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(windex2, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(windex3, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(hindex1, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(hindex2, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(hindex3, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(coord_data_low, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(coord_data_mid, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(coord_data_high, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(obj_prob_low, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(obj_prob_mid, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(obj_prob_high, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(classes_prob_low, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(classes_prob_mid, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(classes_prob_high, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(img_info, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(windex1, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(windex2, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(windex3, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(hindex1, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(hindex2, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(hindex3, TensorType({DT_FLOAT16, DT_FLOAT})) .REQUIRED_ATTR(biases_low, ListFloat) .REQUIRED_ATTR(biases_mid, ListFloat) .REQUIRED_ATTR(biases_high, ListFloat) @@ -804,7 +804,7 @@ REG_OP(YoloV3DetectionOutputD) .ATTR(score_threshold, Float, 0.5) .ATTR(iou_threshold, Float, 0.45) .ATTR(pre_nms_topn, Int, 512) - .OUTPUT(box_out, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(box_out, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(box_out_num, TensorType({DT_INT32})) .OP_END_FACTORY_REG(YoloV3DetectionOutputD) @@ -848,7 +848,7 @@ There are three Yolo operators at Yolov3DetectionOutput's preceding layer on Yol * It is a custom operator. It has no corresponding operator in Caffe. */ REG_OP(YoloV3DetectionOutputV2) - .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) .REQUIRED_ATTR(biases, ListFloat) .ATTR(boxes, Int, 3) .ATTR(coords, Int, 4) @@ -862,7 +862,7 @@ REG_OP(YoloV3DetectionOutputV2) .ATTR(N, Int, 10) .ATTR(resize_origin_img_to_net, Bool, false) .ATTR(out_box_dim, Int, 3) - .OUTPUT(box_out, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(box_out, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(box_out_num, TensorType({DT_INT32})) .OP_END_FACTORY_REG(YoloV3DetectionOutputV2) @@ -910,9 +910,9 @@ REG_OP(YoloV3DetectionOutputV2) * Warning: THIS FUNCTION IS DEPRECATED. Please use YoloV3DetectionOutputV2 instead. */ REG_OP(YoloV3DetectionOutputV2D) - .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) - .DYNAMIC_INPUT(windex, TensorType({DT_FLOAT16,DT_FLOAT})) - .DYNAMIC_INPUT(hindex, TensorType({DT_FLOAT16,DT_FLOAT})) + .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .DYNAMIC_INPUT(windex, TensorType({DT_FLOAT16, DT_FLOAT})) + .DYNAMIC_INPUT(hindex, TensorType({DT_FLOAT16, DT_FLOAT})) .REQUIRED_ATTR(biases, ListFloat) .ATTR(boxes, Int, 3) .ATTR(coords, Int, 4) @@ -926,7 +926,7 @@ REG_OP(YoloV3DetectionOutputV2D) .ATTR(N, Int, 10) .ATTR(resize_origin_img_to_net, Bool, false) .ATTR(out_box_dim, Int, 3) - .OUTPUT(box_out, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(box_out, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(box_out_num, TensorType({DT_INT32})) .OP_END_FACTORY_REG(YoloV3DetectionOutputV2D) @@ -1466,9 +1466,9 @@ REG_OP(NormalizeBBox) * y: A Tensor. Must have the same type as box_predictions. */ REG_OP(DecodeBboxV2) - .INPUT(boxes, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(anchors, TensorType({DT_FLOAT16,DT_FLOAT})) - .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(boxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(anchors, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(scales, ListFloat, {1.0, 1.0, 1.0, 1.0}) .ATTR(decode_clip, Float, 0.0) .ATTR(reversed_box, Bool, false) @@ -1592,7 +1592,6 @@ selected indices from the boxes tensor, where M <= max_output_size. \n *Compatible with onnx NonMaxSuppression operator. */ - REG_OP(NonMaxSuppressionV7) .INPUT(boxes, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(scores, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -1641,7 +1640,7 @@ REG_OP(RoiExtractor) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(finest_scale, Int, 56) .ATTR(roi_scale_factor, Float, 0) - .ATTR(spatial_scale, ListFloat, { 1.f/4, 1.f/8, 1.f/16, 1.f/32 }) + .ATTR(spatial_scale, ListFloat, {1.f / 4, 1.f / 8, 1.f / 16, 1.f / 32}) .ATTR(pooled_height, Int, 7) .ATTR(pooled_width, Int, 7) .ATTR(sample_num, Int, 0) @@ -1649,6 +1648,84 @@ REG_OP(RoiExtractor) .ATTR(aligned, Bool, true) .OP_END_FACTORY_REG(RoiExtractor) +/** +*@brief Performs Position Sensitive PS ROI Pooling . \n + +*@par Inputs: +* Two inputs, including: +*@li x: An NC1HWC0 tensor of type float16 or float32, describing the feature +* map, dimension C1 must be equal to +* (int(output_dim+15)/C0))*group_size*group_size. +*@li rois: A tensor of type float16 or float32, with shape +* [batch, 5, rois_num], describing the ROIs, each ROI consists of five +* elements: "batch_id", "x1", "y1", "x2", and "y2", which "batch_id" indicates +* the index of the input feature map, "x1", "y1", "x2", or "y2" must be +* greater than or equal to "0.0" . \n + +*@par Attributes: +*@li output_dim: A required int32, specifying the number of output channels, +* must be greater than 0. +*@li group_size: A required int32, specifying the number of groups to encode +* position-sensitive score maps, must be within the range (0, 128). +*@li spatial_scale: A required float32, scaling factor for mapping the input +* coordinates to the ROI coordinates . \n + +*@par Outputs: +*y: An NC1HWC0 tensor of type float16 or float32, describing the result +* feature map . \n + +*@attention Constraints: +* HC1HWC0: channel must be Group_size squared, rois_num is a multiple of 16 +*/ +REG_OP(PSROIPoolingV2) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(rois, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(spatial_scale, Float) + .REQUIRED_ATTR(output_dim, Int) + .REQUIRED_ATTR(group_size, Int) + .OP_END_FACTORY_REG(PSROIPoolingV2) + +/** +*@brief Performs Position Sensitive PS ROI Pooling Grad . \n + +*@par Inputs: +* Two inputs, including: +*@li x: An NC1HWC0 tensor of type float16 or float32, describing the result +* feature map . \n +*@li rois: A tensor of type float16 or float32, with shape +* [batch, 5, rois_num], describing the ROIs, each ROI consists of five +* elements: "batch_id", "x1", "y1", "x2", and "y2", which "batch_id" indicates +* the index of the input feature map, "x1", "y1", "x2", or "y2" must be +* greater than or equal to "0.0" . \n + +*@par Attributes: +*@li output_dim: A required int32, specifying the number of output channels, +* must be greater than 0. +*@li group_size: A required int32, specifying the number of groups to encode +* position-sensitive score maps, must be within the range (0, 128). +*@li spatial_scale: A required float32, scaling factor for mapping the input +* coordinates to the ROI coordinates . \n +*@li input_size: A required listInt, mapping the gradinput size: (H, W) + +*@par Outputs: +*y: An NC1HWC0 tensor of type float16 or float32, describing the feature +* map, dimension C1 must be equal to +* (int(output_dim+15)/C0))*group_size*group_size. + +*@attention Constraints: +* HC1HWC0: channel must be Group_size squared, rois_num is a multiple of 16 +*/ +REG_OP(PSROIPoolingGradV2D) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(rois, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(spatial_scale, Float) + .REQUIRED_ATTR(output_dim, Int) + .REQUIRED_ATTR(group_size, Int) + .REQUIRED_ATTR(input_size, ListInt) + .OP_END_FACTORY_REG(PSROIPoolingGradV2D) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_DETECT_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index 7d38beb5..a0251d88 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -525,6 +525,31 @@ REG_OP(LayerNorm) .ATTR(epsilon, Float, 0.0000001) .OP_END_FACTORY_REG(LayerNorm) +/** +*@brief Returns a tensor where each sub-tensor of input along dimension +* dim is normalized such that the p-norm of the sub-tensor is lower than the value maxnorm. \n + +*@par Inputs: +*One input, including: +* @li x: A Tensor. Must be one of the following types: float16, float32 . \n + +*@par Attributes: +* @li p: Specify L_p norm, the type is float. +* @li dim: The processed dim, the type is int. +* @li maxnorm: Threshold for comparison, the type is float. \n + +*@par Outputs: +*One outputs, including: +* @li y: shape and dtype of output, should be same shape and type as input. +*/ +REG_OP(Renorm) + .INPUT(x, TensorType::BasicType()) + .OUTPUT(y, TensorType::BasicType()) + .REQUIRED_ATTR(p, Float) + .REQUIRED_ATTR(dim, Int) + .REQUIRED_ATTR(maxnorm, Float) + .OP_END_FACTORY_REG(Renorm) + /** *@brief LayerNormGrad operator interface implementation * calculating: dy, x, variance, mean, gamma @@ -683,7 +708,68 @@ REG_OP(DropOutDoMask) .INPUT(keep_prob, TensorType({DT_FLOAT, DT_FLOAT16})) .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) .OP_END_FACTORY_REG(DropOutDoMask) - + +/** +*@brief Return "output" according to the algorithm of dropout_do_mask: +* scale_x = x *(1 / keep_prob) +* output = select(mask == 1, scale_x, 0) + +*@par Inputs: +*Three inputs, including: +* @li x: A mutable Tensor. Must be one of the following types: +* float16, float32 +* @li mask: A mutable Tensor. Must met all of the following rules: +* shape of mask should be 1D. +* dtype of mask should be uint8. +* value of shape should met the following algorithm: +* value = (size(x) + 128 - 1) // 128 * 128 +* @li keep_prob: A mutable Tensor. Must met all of the following rules: +* shape of "keep_prob" should be (1,) or [1,]. +* Has the same type as "x" . \n + +*@par Output: +*y: A mutable Tensor. Has the same type as "x". +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(DropOutDoMaskV3) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(mask, TensorType({DT_UINT8})) + .INPUT(keep_prob, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .OP_END_FACTORY_REG(DropOutDoMaskV3) + +/** +*@brief Return "output" according to the algorithm of dropout_do_mask: +* scale_x = x *(1 / keep_prob) +* output = select(mask == 1, scale_x, 0) + +*@par Inputs: +*Two inputs, including: +* @li x: A mutable Tensor. Must be one of the following types: +* float16, float32 +* @li mask: A mutable Tensor. Must met all of the following rules: +* shape of mask should be 1D. +* dtype of mask should be uint8. +* value of shape should met the following algorithm: +* value = (size(x) + 128 - 1) // 128 * 128 +*@par Attributes: +* @li keep_prob: A mutable Tensor. Must met all of the following rules: +* shape of "keep_prob" should be (1,) or [1,]. +* Has the same type as "x" . \n + +*@par Output: +*y: A mutable Tensor. Has the same type as "x". +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(DropOutDoMaskV3D) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(mask, TensorType({DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .REQUIRED_ATTR(keep_prob, Float) + .OP_END_FACTORY_REG(DropOutDoMaskV3D) + /** *@brief Scales the input . \n @@ -1356,6 +1442,58 @@ REG_OP(PoissonNllLoss) .ATTR(eps, Float, 1e-8) .ATTR(reduction, String, "mean") .OP_END_FACTORY_REG(PoissonNllLoss) +/** + *@brief rnn_gen_mask + * @par Inputs: + * @li seq_length: A ND Tensor of type int32. Recoed the current length of each batch.\n + * + * @par Attributes: + * @li num_step: A required int.\n + * @li hidden_size: A required int. \n + * + * + * @par Output: + * y: A mutable Tensor of type int32, with the shape of [num_step, batch_size, hidden_size]. \n + * + */ +REG_OP(RnnGenMask) + .INPUT(seq_length, TensorType({DT_INT32})) + .OUTPUT(seq_mask, TensorType({DT_INT32})) + .REQUIRED_ATTR(num_step, Int) + .REQUIRED_ATTR(hidden_size, Int) + .OP_END_FACTORY_REG(RnnGenMask) + +/** +* @brief Creates a criterion that optimizes a multi-class multi-classification hinge loss (margin-based loss) +* between input x (a 2D mini-batch Tensor) and output y (which is a 2D Tensor of target class indices) \n + +* @par Inputs: +* Two inputs, including: +* @li x: A tensor. Must be one of the following types: +* float16, float32. \n +* +* @par Inputs: +* @li target: A tensor. Must be the following types: +* int32. \n + +* @par Attributes: +* @li reduction: An optional string. Defaults to "mean" \n + +* @par Outputs: +* y: A Tensor has same element type as input x. \n +* is_target: A Tensor has same element type as input target. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator MultiLabelMarginLoss. \n +*/ +REG_OP(MultilabelMarginLoss) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(target, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(is_target, TensorType({DT_INT32})) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(MultilabelMarginLoss) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_NORM_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h index 32eb148b..743c28b7 100644 --- a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h @@ -397,8 +397,8 @@ No default value. specifying the stride of the sliding window for each dimension of the input tensor. No default value. *@li padding: A required string type of float16. -*@li pads: A list type of int32. Default value {0, 0, 0}. -*@li dilation: A list type of int32. Default value {1, 1, 1}. +*@li pads: A list type of int32. Default value {0,0,0,0,0,0}. +*@li dilation: A list type of int32. Default value {1,1,1,1,1,1}. *@li ceil_mode: A ceil mode number of int32 . Default value 0. *@li data_format: An optional string. Defaults to "NDHWC" . \n @@ -421,8 +421,8 @@ REG_OP(MaxPool3D) .REQUIRED_ATTR(ksize, ListInt) .REQUIRED_ATTR(strides, ListInt) .REQUIRED_ATTR(padding, String) - .ATTR(pads, ListInt, {0,0,0}) - .ATTR(dilation, ListInt, {1,1,1}) + .ATTR(pads, ListInt, {0,0,0,0,0,0}) + .ATTR(dilation, ListInt, {1,1,1,1,1,1}) .ATTR(ceil_mode, Int, 0) .ATTR(data_format, String, "NDHWC") .OP_END_FACTORY_REG(MaxPool3D) @@ -1184,6 +1184,7 @@ REG_OP(MaxPool3DGrad) .OUTPUT(y, TensorType::RealNumberType()) .REQUIRED_ATTR(ksize, ListInt) .REQUIRED_ATTR(strides, ListInt) + .ATTR(padding, String, "SAME") .REQUIRED_ATTR(pads, ListInt) .ATTR(data_format, String, "NDHWC") .OP_END_FACTORY_REG(MaxPool3DGrad) @@ -1440,12 +1441,11 @@ REG_OP(MaxPoolV3Grad) .OP_END_FACTORY_REG(MaxPoolV3Grad) /** -*@brief Performs dilation2d on the input . \n +*@brief Performs Dilation2D on the input . \n *@par Inputs: *x: A tensor of shape is 4d, format is support NHWC. -*filter: A tensor of shape is 3d, the type is same with x, -and the c dimension is same with x. \n +*filter: A tensor of shape is 3d, the type is same with x, and the c dimension is same with x. \n *@par Attributes: *@li strides: A required list of 4 ints, specifying the stride of the sliding window. The strides of the N and C dimensions are 1. @@ -1473,6 +1473,84 @@ REG_OP(Dilation2D) .ATTR(data_format, String, "NHWC") .OP_END_FACTORY_REG(Dilation2D) +/** +*@brief Performs Dilation2DBackpropFilter on the input. \n + +*@par Inputs: +*x: A tensor of shape is 4d, format is support NHWC. +*filter: A tensor of shape is 3d, the type is same with x, and the c dimension is same with x. +*out_backprop: Has the same type and format as input x and the c dimension is same with x. \n + +*@par Attributes +*@li strides: A required list of 4 ints, specifying the stride of the sliding window. The strides of the N and C dimension are 1. +*@li rates: A required list of 4 ints, the rates of the N and C dimensions are 1. +*@li padding_mode: A optional string. Defaults to "SAME", it support SAME and VALID. +*@li pads: A optional list of 4 ints. +*@li ceil_mode: An optional bool. Defaults to "false". Use ceil or floor to calculate the output size when padding_mode is "CALCULATED". +*@li data_format: An optional string, specifying the data format of "rates" and "strides", either "NCHW" or "NHWC" (default). \n + +*@par Outputs: +*y: The output tensor. Has the same type and format as input "filter" . \n + +*@par Third-party framework compatibility +* Compatible with the TensorFlow operator Dilation2DBackpropFilter. +*/ + +REG_OP(Dilation2DBackpropFilter) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .INPUT(filter, + TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .INPUT(out_backprop, + TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .OUTPUT(y, + TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(rates, ListInt) + .ATTR(padding_mode, String, "SAME") + .ATTR(pads, ListInt, {0, 0, 0, 0}) + .ATTR(ceil_mode, Bool, false) + .ATTR(data_format, String, "NHWC") + .OP_END_FACTORY_REG(Dilation2DBackpropFilter) + +/** +*@brief Performs Dilation2DBackpropInput on the input. \n + +*@par Inputs: +*x: A tensor of shape is 4d, format is support NHWC. +*filter: A tensor of shape is 3d, the type is same with x, and the c dimension is same with x. +*out_backprop: Has the same type and format as input x and the c dimension is same with x. \n + +*@par Attributes +*@li strides: A required list of 4 ints, specifying the stride of the sliding window. The strides of the N and C dimension are 1. +*@li rates: A required list of 4 ints, the rates of the N and C dimensions are 1. +*@li padding_mode: A optional string. Defaults to "SAME", it support SAME and VALID. +*@li pads: A optional list of 4 ints. +*@li ceil_mode: An optional bool. Defaults to "false". Use ceil or floor to calculate the output size when padding_mode is "CALCULATED". +*@li data_format: An optional string, specifying the data format of "rates" and "strides", either "NCHW" or "NHWC" (default). \n + +*@par Outputs: +*y: The output tensor. Has the same type and format as input "x" . \n + +*@par Third-party framework compatibility +* Compatible with the TensorFlow operator Dilation2DBackpropInput. +*/ + +REG_OP(Dilation2DBackpropInput) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .INPUT(filter, + TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .INPUT(out_backprop, + TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .OUTPUT(y, + TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(rates, ListInt) + .ATTR(padding_mode, String, "SAME") + .ATTR(pads, ListInt, {0, 0, 0, 0}) + .ATTR(ceil_mode, Bool, false) + .ATTR(data_format, String, "NHWC") + .OP_END_FACTORY_REG(Dilation2DBackpropInput) + /** * @brief Applies a 2D adaptive average pooling over * an input signal composed of several input planes. \n @@ -1604,5 +1682,22 @@ REG_OP(MaxPoolWithArgmaxV1) .ATTR(ceil_mode, Bool, false) .OP_END_FACTORY_REG(MaxPoolWithArgmaxV1) +// SubSample +REG_OP(SubSample) + .INPUT(labels, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_INT32})) + .REQUIRED_ATTR(batch_size_per_images, Int) + .REQUIRED_ATTR(positive_fraction, Float) + .OP_END_FACTORY_REG(SubSample) + +// SubSampleLabels +REG_OP(SubSampleLabels) + .INPUT(labels, TensorType({DT_INT32})) + .INPUT(shuffle_matrix, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_INT32})) + .REQUIRED_ATTR(batch_size_per_images, Int) + .REQUIRED_ATTR(positive_fraction, Float) + .OP_END_FACTORY_REG(SubSampleLabels) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_POOLING_OPS_H diff --git a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h index 0d0be241..4cbe4057 100644 --- a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h +++ b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h @@ -836,7 +836,7 @@ REG_OP(HardShrink) *backprops: A Tensor with the same type and shape of features's. \n * *@par Attributes: -*@li lambda: An optional float.Defaults to 0.5. \n +*@li lambd: An optional float.Defaults to 0.5. \n * *@par Third-party framework compatibility *Compatible with the Pytorch operator Hardshrink_backward. \n @@ -845,7 +845,7 @@ REG_OP(HardShrink) .INPUT(gradients, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(features, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(backprops, TensorType({DT_FLOAT16, DT_FLOAT})) - .ATTR(lambda, Float, 0.5) + .ATTR(lambd, Float, 0.5) .OP_END_FACTORY_REG(HardShrinkGrad) /** @@ -920,7 +920,30 @@ REG_OP(SoftShrinkGrad) .OUTPUT(output_y, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(lambd, Float, 0.5) .OP_END_FACTORY_REG(SoftShrinkGrad) - + +/** +*@brief Calculate the gradient of log simoid. \n + +*@par Inputs: +*Two inputs, including: +* @li grads: A tensor, gradient of previous layer. Must be one of the following types: +* float16, float32. \n +* @li features: A tensor, input of log sigmoid. Must be one of the following types: +* float16, float32. \n + +*@par Outputs: +*One outputs, including: +* @li backprops: A tensor with the same type of and shape of grads. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator LogSigmoidBackward. \n +*/ +REG_OP(LogSigmoidGrad) + .INPUT(grads, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(features, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(backprops, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(LogSigmoidGrad) + /** *@brief Calculate -ln(1+e^(-x)). \n diff --git a/third_party/fwkacllib/inc/ops/pad_ops.h b/third_party/fwkacllib/inc/ops/pad_ops.h index 50eb98c8..42da3828 100644 --- a/third_party/fwkacllib/inc/ops/pad_ops.h +++ b/third_party/fwkacllib/inc/ops/pad_ops.h @@ -418,7 +418,7 @@ REG_OP(EmbeddingRankId) */ REG_OP(FillV2) .INPUT(dims, TensorType({DT_INT16, DT_INT32, DT_INT64})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT, DT_DOUBLE, DT_INT8, DT_INT16, DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT8, DT_INT16, DT_INT32, DT_INT64})) .ATTR(value, Float, 0) .OP_END_FACTORY_REG(FillV2) @@ -437,7 +437,7 @@ REG_OP(FillV2) * Compatible with the ONNX operator ConstantOfShape. */ REG_OP(FillV2D) - .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT, DT_DOUBLE, DT_INT8, DT_UINT8, DT_INT16, DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT8, DT_UINT8, DT_INT16, DT_INT32, DT_INT64})) .ATTR(value, Float, 0) .REQUIRED_ATTR(dims, ListInt) .OP_END_FACTORY_REG(FillV2D) diff --git a/third_party/fwkacllib/inc/ops/parsing_ops.h b/third_party/fwkacllib/inc/ops/parsing_ops.h index 9a5cf504..452961a9 100644 --- a/third_party/fwkacllib/inc/ops/parsing_ops.h +++ b/third_party/fwkacllib/inc/ops/parsing_ops.h @@ -51,6 +51,246 @@ REG_OP(StringToNumber) .ATTR(out_type, Type, DT_FLOAT) .OP_END_FACTORY_REG(StringToNumber) +/** +*@brief Convert serialized tensorflow.TensorProto prototype to Tensor. +*@brief Parse an Example prototype. +*@par Input: +*serialized: A Tensor of type string. +*dense_defaults: DYNAMIC INPUT Tensor type as string, float, int64. \n + +*@par Attributes: +*num_sparse: type int num of inputs sparse_indices , sparse_values, sparse_shapes +*out_type: output type +*sparse_keys: ListString +*sparse_types: types of sparse_values +*dense_keys: ListString +*dense_shapes: output of dense_defaults shape +*dense_types: output of dense_defaults type \n + +*@par Outputs: +*sparse_indices: A Tensor of type string. +*sparse_values: Has the same type as sparse_types. +*sparse_shapes: A Tensor of type int64 +*dense_values: Has the same type as dense_defaults. + +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +**/ +REG_OP(ParseSingleExample) + .INPUT(serialized, TensorType({DT_STRING})) + .DYNAMIC_INPUT(dense_defaults, TensorType({DT_STRING,DT_FLOAT,DT_INT64})) + .DYNAMIC_OUTPUT(sparse_indices, TensorType({DT_INT64})) + .DYNAMIC_OUTPUT(sparse_values, TensorType({DT_STRING,DT_FLOAT,DT_INT64})) + .DYNAMIC_OUTPUT(sparse_shapes, TensorType({DT_INT64})) + .DYNAMIC_OUTPUT(dense_values, TensorType({DT_STRING,DT_FLOAT,DT_INT64})) + .ATTR(num_sparse, Int, 0) + .ATTR(sparse_keys, ListString, {}) + .ATTR(dense_keys, ListString, {}) + .ATTR(sparse_types, ListType, {}) + .ATTR(dense_types, ListType, {}) + .ATTR(dense_shapes, ListListInt, {}) + .OP_END_FACTORY_REG(ParseSingleExample) + +/** +*@brief Decodes raw file into tensor . \n +*@par Input: +*bytes: A Tensor of type string. + +*@par Attributes: +*little_endian: bool ture +*out_type: output type + +*@par Outputs: +*Output: A Tensor +**/ +REG_OP(DecodeRaw) + .INPUT(bytes, TensorType({DT_STRING})) + .OUTPUT(output, TensorType({DT_BOOL,DT_FLOAT16,DT_DOUBLE,DT_FLOAT, + DT_INT64,DT_INT32,DT_INT8,DT_UINT8,DT_INT16, + DT_UINT16,DT_COMPLEX64,DT_COMPLEX128})) + .ATTR(out_type, Type, DT_FLOAT) + .ATTR(little_endian, Bool, true) + .OP_END_FACTORY_REG(DecodeRaw) + +/** +*@brief Convert serialized tensorflow.TensorProto prototype to Tensor. \n + +*@par Inputs: +*serialized: A Tensor of string type. Scalar string containing serialized +*TensorProto prototype. \n + +*@par Attributes: +*out_type: The type of the serialized tensor. The provided type must match the +*type of the serialized tensor and no implicit conversion will take place. \n + +*@par Outputs: +*output: A Tensor of type out_type. \n + +*@attention Constraints: +*The implementation for StringToNumber on Ascend uses AICPU, +*with badperformance. \n + +*@par Third-party framework compatibility +*@li compatible with tensorflow ParseTensor operator. +*/ +REG_OP(ParseTensor) + .INPUT(serialized, TensorType({DT_STRING})) + .OUTPUT(output, TensorType(DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT16, + DT_UINT16, DT_UINT8, DT_INT32, DT_INT64, DT_UINT32, + DT_UINT64, DT_BOOL, DT_DOUBLE, DT_STRING, + DT_COMPLEX64, DT_COMPLEX128})) + .ATTR(out_type, Type, DT_FLOAT) + .OP_END_FACTORY_REG(ParseTensor) + +/** +*@brief Converts each string in the input Tensor to the specified numeric +*type . \n + +*@par Inputs: +*Inputs include: +*records: Each string is a record/row in the csv and all records should have the +*same format. \n +*record_defaults: One tensor per column of the input record, with either a +*scalar default value for that column or an empty vector if the column is +*required. \n + +*@par Attributes: +*OUT_TYPE: The numeric type to interpret each string in string_tensor as . \n +*field_delim: char delimiter to separate fields in a record. \n +*use_quote_delim: If false, treats double quotation marks as regular characters +*inside of the string fields (ignoring RFC 4180, Section 2, Bullet 5). \n +*na_value: Additional string to recognize as NA/NaN. \n + +*@par Outputs: +*output: A Tensor. Has the same type as x . \n + +*@attention Constraints: +*The implementation for StringToNumber on Ascend uses AICPU, with bad +*performance. \n + +*@par Third-party framework compatibility +*@li compatible with tensorflow StringToNumber operator. +*/ +REG_OP(DecodeCSV) + .INPUT(records, TensorType({DT_STRING})) + .DYNAMIC_INPUT(record_defaults, TensorType({DT_FLOAT, DT_DOUBLE, DT_INT32, + DT_INT64, DT_STRING, DT_RESOURCE})) + .DYNAMIC_OUTPUT(output, TensorType({DT_FLOAT, DT_DOUBLE, DT_INT32, + DT_INT64, DT_STRING, DT_RESOURCE})) + .ATTR(OUT_TYPE, ListType, {}) + .ATTR(field_delim, String, ",") + .ATTR(use_quote_delim, Bool, true) + .ATTR(na_value, String, ",") + .ATTR(select_cols, ListInt, {}) + .OP_END_FACTORY_REG(DecodeCSV) + +/** +*@brief Convert serialized tensorflow.TensorProto prototype to Tensor. +*@brief Parse an Example prototype. +*@par Input: +*serialized: A Tensor of type string. \n +*name:A Tensor of type string. \n +*sparse_keys: Dynamic input tensor of string. \n +*dense_keys: Dynamic input tensor of string \n +*dense_defaults: Dynamic input tensor type as string, float, int64. \n + +*@par Attributes: +*Nsparse: Number of sparse_keys, sparse_indices and sparse_shapes \n +*Ndense: Number of dense_keys \n +*sparse_types: types of sparse_values \n +*Tdense: Type of dense_defaults dense_defaults and dense_values \n +*dense_shapes: output of dense_defaults shape \n + +*@par Outputs: +*sparse_indices: A Tensor of type string. \n +*sparse_values: Has the same type as sparse_types. \n +*sparse_shapes: A Tensor of type int64 \n +*dense_values: Has the same type as dense_defaults. \n +*@par Third-party framework compatibility \n +*@li compatible with tensorflow StringToNumber operator. \n +*/ +REG_OP(ParseExample) + .INPUT(serialized, TensorType({DT_STRING})) + .INPUT(name, TensorType({DT_STRING})) + .DYNAMIC_INPUT(sparse_keys, TensorType({DT_STRING})) + .DYNAMIC_INPUT(dense_keys, TensorType({DT_STRING})) + .DYNAMIC_INPUT(dense_defaults, TensorType({DT_FLOAT, DT_INT64, DT_STRING})) + .DYNAMIC_OUTPUT(sparse_indices, TensorType({DT_INT64})) + .DYNAMIC_OUTPUT(sparse_values, TensorType({DT_FLOAT, DT_INT64, DT_STRING})) + .DYNAMIC_OUTPUT(sparse_shapes, TensorType({DT_INT64})) + .DYNAMIC_OUTPUT(dense_values, TensorType({DT_FLOAT, DT_INT64, DT_STRING})) + .ATTR(Nsparse, Int, 0) + .ATTR(Ndense, Int, 0) + .ATTR(sparse_types, ListType, {}) + .ATTR(Tdense, ListType, {}) + .ATTR(dense_shapes, ListListInt, {}) + .OP_END_FACTORY_REG(ParseExample) + +/** +*@brief Transforms a scalar brain.SequenceExample proto (as strings) into typed +*tensors. +*@par Input: +*serialized: A Tensor of type string. \n +*feature_list_dense_missing_assumed_empty:A Tensor of type string. \n +*context_sparse_keys: Dynamic input tensor of string. \n +*context_dense_keys: Dynamic input tensor of string \n +*feature_list_sparse_keys: Dynamic input tensor of string \n +*feature_list_dense_keys: Dynamic input tensor of string \n +*context_dense_defaults: Dynamic input tensor of string, float, int64 \n +*debug_name: A Tensor of type string. \n + +*@par Attributes: +*Ncontext_sparse: Number of context_sparse_keys, context_sparse_indices and context_sparse_shapes \n +*Ncontext_dense: Number of context_dense_keys \n +*Nfeature_list_sparse: Number of feature_list_sparse_keys \n +*Nfeature_list_dense: Number of feature_list_dense_keys \n +*context_sparse_types: Types of context_sparse_values \n +*Tcontext_dense: Number of dense_keys \n +*feature_list_dense_types: Types of feature_list_dense_values \n +*context_dense_shapes: Shape of context_dense \n +*feature_list_sparse_types: Type of feature_list_sparse_values \n +*feature_list_dense_shapes: Shape of feature_list_dense \n + +*@par Outputs: +*context_sparse_indices: Dynamic output tensor of type int64. \n +*context_sparse_values: Dynamic output tensor of type string, float, int64. \n +*context_sparse_shapes: Dynamic output tensor of type int64 \n +*context_dense_values: Dynamic output tensor of type string, float, int64. \n +*feature_list_sparse_indices: Dynamic output tensor of type int64. \n +*feature_list_sparse_values: Dynamic output tensor of type string, float, int64. \n +*feature_list_sparse_shapes: Dynamic output tensor of type int64 \n +*feature_list_dense_values: Dynamic output tensor of type string, float, int64. \n +*@par Third-party framework compatibility \n +*@li compatible with tensorflow StringToNumber operator. \n +*/ +REG_OP(ParseSingleSequenceExample) + .INPUT(serialized, TensorType({DT_STRING})) + .INPUT(feature_list_dense_missing_assumed_empty, TensorType({DT_STRING})) + .DYNAMIC_INPUT(context_sparse_keys, TensorType({DT_STRING})) + .DYNAMIC_INPUT(context_dense_keys, TensorType({DT_STRING})) + .DYNAMIC_INPUT(feature_list_sparse_keys, TensorType({DT_STRING})) + .DYNAMIC_INPUT(feature_list_dense_keys, TensorType({DT_STRING})) + .DYNAMIC_INPUT(context_dense_defaults, TensorType({DT_FLOAT, DT_INT64, DT_STRING})) + .INPUT(debug_name, TensorType({DT_STRING})) + .DYNAMIC_OUTPUT(context_sparse_indices, TensorType({DT_INT64})) + .DYNAMIC_OUTPUT(context_sparse_values, TensorType({DT_FLOAT, DT_INT64, DT_STRING})) + .DYNAMIC_OUTPUT(context_sparse_shapes, TensorType({DT_INT64})) + .DYNAMIC_OUTPUT(context_dense_values, TensorType({DT_FLOAT, DT_INT64, DT_STRING})) + .DYNAMIC_OUTPUT(feature_list_sparse_indices, TensorType({DT_INT64})) + .DYNAMIC_OUTPUT(feature_list_sparse_values, TensorType({DT_FLOAT, DT_INT64, DT_STRING})) + .DYNAMIC_OUTPUT(feature_list_sparse_shapes, TensorType({DT_INT64})) + .DYNAMIC_OUTPUT(feature_list_dense_values, TensorType({DT_FLOAT, DT_INT64, DT_STRING})) + .ATTR(Ncontext_sparse, Int, 0) + .ATTR(Ncontext_dense, Int, 0) + .ATTR(Nfeature_list_sparse, Int, 0) + .ATTR(Nfeature_list_dense, Int, 0) + .REQUIRED_ATTR(context_sparse_types, ListType) + .REQUIRED_ATTR(Tcontext_dense, ListType) + .REQUIRED_ATTR(feature_list_dense_types, ListType) + .REQUIRED_ATTR(context_dense_shapes, ListListInt) + .REQUIRED_ATTR(feature_list_sparse_types, ListType) + .REQUIRED_ATTR(feature_list_dense_shapes, ListListInt) + .OP_END_FACTORY_REG(ParseSingleSequenceExample) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_PARSING_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/quantize_ops.h b/third_party/fwkacllib/inc/ops/quantize_ops.h index 806e28df..eafc8cc4 100644 --- a/third_party/fwkacllib/inc/ops/quantize_ops.h +++ b/third_party/fwkacllib/inc/ops/quantize_ops.h @@ -60,6 +60,26 @@ REG_OP(Dequantize) .ATTR(mode, String, "MIN_COMBINED") .OP_END_FACTORY_REG(Dequantize) +/** +*@brief Quantizes the input . \n +*@par Inputs: +*x: shape and dtype of input_x. \n +*scales: shape and dtype of input_scales. \n +*zero_points: shape and dtype of input_zero_points \n +*@par Attributes: +*@li axis: the processed dim. \n +*@par Outputs: +*y: shape and dtype of output_y, should be same shape as input, dtype is same as the quantified type . \n +*/ +REG_OP(Quantize) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(scales, TensorType({DT_FLOAT})) + .INPUT(zero_points, TensorType({DT_INT8,DT_UINT8,DT_INT32})) + .OUTPUT(y, TensorType({DT_INT8,DT_UINT8,DT_INT32})) + .REQUIRED_ATTR(dtype, String) + .ATTR(axis, Int, 1) + .OP_END_FACTORY_REG(Quantize) + /** *@brief Quantizes the input . \n diff --git a/third_party/fwkacllib/inc/ops/random_ops.h b/third_party/fwkacllib/inc/ops/random_ops.h index e2b00ce3..8104cb01 100644 --- a/third_party/fwkacllib/inc/ops/random_ops.h +++ b/third_party/fwkacllib/inc/ops/random_ops.h @@ -356,6 +356,39 @@ REG_OP(DropOutGenMask) .ATTR(seed2, Int, 0) .OP_END_FACTORY_REG(DropOutGenMask) + +/** +*@brief Generate random uint8 mask for dropout v3 . \n + +*@par Inputs: +include: +*@li shape:The shape of the output tensor. +*@li prob:0-D. Prob of 1 . \n + +*@par Attributes: +*@li seed:If either seed or seed2 are set to be non-zero, the random number +*generator is seeded by the given seed. Otherwise, it is seeded by a random seed. +*@li seed2:A second seed to avoid seed collision . \n + +*@par Outputs: +*y:Output (1-D) random number using uint8 data format . \n + +*@attention Constraints: +*The output is aligned with 16 + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. + +*@see DropOutGenMaskV3() +*/ +REG_OP(DropOutGenMaskV3) + .INPUT(shape, TensorType({ DT_INT32, DT_INT64 })) + .INPUT(prob, TensorType({ DT_FLOAT16, DT_FLOAT })) + .OUTPUT(y, TensorType({ DT_UINT8 })) + .ATTR(seed, Int, 0) + .ATTR(seed2, Int, 0) + .OP_END_FACTORY_REG(DropOutGenMaskV3) + /** *@brief Generates values in an interval . \n diff --git a/third_party/fwkacllib/inc/ops/reduce_ops.h b/third_party/fwkacllib/inc/ops/reduce_ops.h index 5b97d226..7d9e6df1 100644 --- a/third_party/fwkacllib/inc/ops/reduce_ops.h +++ b/third_party/fwkacllib/inc/ops/reduce_ops.h @@ -898,14 +898,14 @@ REG_OP(Reduction) *@brief Computes the euclidean norm of elements across dimensions of a tensor . \n *@par Inputs: -*@li input_tensor: A Tensor. Must be one of the following types: float16, float32, int32. +*@li x: A Tensor. Must be one of the following types: float16, float32, int32. *@li axes: A Tensor of type int8 or int32. Specifies the dimensions to reduce. Defaults to "None" . \n *@par Attributes: *keep_dims: An optional bool. If "True", reduced dimensions will be retained. Defaults to "False" . \n *@par Outputs: -*output_tensor: A Tensor. Must be one of the following types: float16, float32, int32 . \n +*y: A Tensor. Must be one of the following types: float16, float32, int32 . \n *@attention Constraints: * If "axes = None", all dimensions will be reduced. "axes" must be in the range [-rank(input_shape), rank(input_shape)) . \n @@ -1133,6 +1133,29 @@ REG_OP(GNTrainingUpdate) .OUTPUT(batch_variance, TensorType({DT_FLOAT})) .OP_END_FACTORY_REG(GNTrainingUpdate) +/** +*@brief Joins a string Tensor across the given dimensions. \n + +*@par Inputs: +include: +*@li input:A Tensor of type string. The text to be processed. +*@li reduction_indices:A Tensor of type int. The text to be processed. + +*@par Attributes: +*@li keep_dims:A bool, An optional bool. Defaults to False. If True, retain reduced dimensions with length 1.. +*@li separator:string. + +*@par output: +*@li output::A Tensor of type string.. +*/ +REG_OP(ReduceJoin) + .INPUT(input, TensorType({DT_STRING})) + .INPUT(reduction_indices, TensorType({DT_INT32})) + .OUTPUT(output, TensorType({DT_STRING})) + .ATTR(keep_dims, Bool, true) + .ATTR(separator, String, "") + .OP_END_FACTORY_REG(ReduceJoin) + /** * @brief Calculates the standard deviation and average value of Tensors. diff --git a/third_party/fwkacllib/inc/ops/rnn.h b/third_party/fwkacllib/inc/ops/rnn.h index 12bb0ee8..d4b3b102 100644 --- a/third_party/fwkacllib/inc/ops/rnn.h +++ b/third_party/fwkacllib/inc/ops/rnn.h @@ -256,6 +256,83 @@ REG_OP(DynamicRNN) .ATTR(is_training, Bool, true) .OP_END_FACTORY_REG(DynamicRNN) +/** +*@brief: DynamicRNNV3 calculation. +*@par Inputs: +*ten inputs: +*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li w:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. +*@li seq_length:A optional 1D Tensor. Must be one of the following types: int32. The format must be ND. +*@li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li wcf:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li wco:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li mask:A 1D optional Tensor. Must be one of the following types: uint8. The format must be ND . \n +*@li real_mask:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li project:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. + +*@par Attributes: +*@li cell_type:An string identifying the cell type in the op. Default to "LSTM". Only LSTM is currently supported. +*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. +*@li cell_depth:An integer identifying the cell depth in the op. Default to 1. +*@li use_peephole:An bool identifying if use peephole in the op. Default to false. +*@li keep_prob:An float identifying the keep prob in the op. Default to 1. +*@li cell_clip:An float identifying the cell clip in the op. Default to -1. +*@li num_proj:An integer identifying the num projection in the op. Default to 0. +*@li time_major:An bool identifying the time major in the op. Default to true. +*@li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported. +*@li forget_bias:An float identifying the forget bias in the op. Default to 0. +*@li is_training:An bool identifying is training in the op. Default to true . \n + +*@par Outputs: +*eight outputs: +*@li y:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li output_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li output_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li i:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li j:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li f:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li o:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@par Third-party framework compatibility: +* Compatible with the TF operator LSTM. +*/ +REG_OP(DynamicRNNV3) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(w, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(b, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32})) + .OPTIONAL_INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(init_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wci, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wcf, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wco, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(mask, TensorType({DT_UINT8})) + .OPTIONAL_INPUT(real_mask, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(project, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(i, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(j, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(f, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(o, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(tanhc, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(cell_type, String, "LSTM") + .ATTR(direction, String, "UNIDIRECTIONAL") + .ATTR(cell_depth, Int, 1) + .ATTR(use_peephole, Bool, false) + .ATTR(keep_prob, Float, 1.0) + .ATTR(cell_clip, Float, -1.0) + .ATTR(num_proj, Int, 0) + .ATTR(time_major, Bool, true) + .ATTR(activation, String, "tanh") + .ATTR(forget_bias, Float, 0.0) + .ATTR(is_training, Bool, true) + .OP_END_FACTORY_REG(DynamicRNNV3) + /** *@brief: DynamicLSTMV2 calculation. *@par Inputs: @@ -960,6 +1037,47 @@ REG_OP(CommonGRU) .REQUIRED_ATTR(hidden_size, Int) .ATTR(linear_before_reset , Int, 0) .OP_END_FACTORY_REG(CommonGRU) +/** +* @brief Calculates the reversed outputs of the function "embedding". \n + +* @par Inputs: +* Four inputs, including: +* @li weight: A mutable Tensor of word grad. Must be one of the following types: +* float32. +* @li indices: A mutable word index Tensor of the int32 type.\n +* @li offsets: A mutable word index Tensor of the int32 type.\n +* @li per_sample_weights: to indicate all weights should be taken to be 1. +* If specified, per_sample_weights must have exactly the same shape as input +* and is treated as having the same offsets, if those are not None. +* Only supported for mode='sum'..\n + +* @par Attributes: +* @li mode: An string attr which use "sum"``, ``"mean"`` or ``"max"``. Specifies the way to reduce the bag.. \n + +* @li scale_grad_by_freq: An optional bool. Defaults to "False". +* If "True", "grad_weight" will be scale by word_frequency. +* If "False", "grad_weight" will not be scale by word_frequency. \n +* @li sparse: if True, gradient w.r.t.attr weight matrix will be a sparse tensor. \n +* @li include_last_offset: if True, attr offsets has one additional element, where the last element +* is equivalent to the size of indices. This matches the CSR format.. \n + +* @par Outputs: +* @li grad_weight: A mutable output Tensor of new word grad has the same type as "grads". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator EmbeddingBag. +*/ +REG_OP(EmbeddingBag) + .INPUT(weight, TensorType({ DT_FLOAT32 })) + .INPUT(indices, TensorType({ DT_INT32 })) + .OPTIONAL_INPUT(offsets, TensorType({DT_INT32})) + .OPTIONAL_INPUT(per_sample_weights, TensorType({DT_FLOAT32})) + .OUTPUT(y, TensorType({ DT_FLOAT32 })) + .ATTR(mode, String, "mean") + .ATTR(scale_grad_by_freq, Bool, false) + .ATTR(sparse, Bool, false) + .ATTR(include_last_offset, Bool, false) + .OP_END_FACTORY_REG(EmbeddingBag) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_RNN_H_ diff --git a/third_party/fwkacllib/inc/ops/selection_ops.h b/third_party/fwkacllib/inc/ops/selection_ops.h index 7fe05b1e..da5bdb6a 100644 --- a/third_party/fwkacllib/inc/ops/selection_ops.h +++ b/third_party/fwkacllib/inc/ops/selection_ops.h @@ -1006,9 +1006,9 @@ REG_OP(TopK) *@par Inputs: *Inputs including: -* @li indices: A required index tensor. Must be one of the following types: float32, float16, int32, int8, uint8. -* @li x: A required slice tensor. Must be one of the following types: float32, float16, int32, int8, uint8. -* @li shape: A required list of int32, specifying the output shape. +* @li indices: A required index tensor. Must be one of the following types: int32 or int64. +* @li x: A required slice tensor. Must be one of the following types: float32, float16, int32, int8, uint8... +* @li shape: A required list of int32 or int64, specifying the output shape. *@par Outputs: *y:A output Tensor with same datatype as "updates" . \n @@ -1019,7 +1019,7 @@ REG_OP(TopK) * Compatible with the TensorFlow operator ScatterNd. */ REG_OP(ScatterNd) - .INPUT(indices, TensorType::BasicType()) + .INPUT(indices, TensorType::IndexNumberType()) .INPUT(x, TensorType::BasicType()) .INPUT(shape, TensorType::IndexNumberType()) .OUTPUT(y, TensorType::BasicType()) @@ -1032,11 +1032,11 @@ REG_OP(ScatterNd) *@par Inputs: *Inputs including: * @li indices: A required index tensor. Must be one of the following types: - * float, float16, int32, int16. format:ND. + * int32 or int64. format:ND. * @li x: A required slice tensor. Must be one of the following types: - * float, float16, int32, int16. format:ND. + * float16, float, int32, int8, uint8. format:ND. *@par Attributes: -* @li shape: A required list of int32, specifying the output shape. +* @li shape: A required list of int32 or int64, specifying the output shape. *@par Outputs: *y: A Tensor. Has the same type as "x". format:ND . \n @@ -1051,8 +1051,8 @@ REG_OP(ScatterNd) */ REG_OP(ScatterNdD) .INPUT(indices, TensorType::IndexNumberType()) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT16})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT16})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) .REQUIRED_ATTR(shape, ListInt) .OP_END_FACTORY_REG(ScatterNdD) @@ -1876,6 +1876,33 @@ REG_OP(Crop) .REQUIRED_ATTR(offsets, ListInt) .OP_END_FACTORY_REG(Crop) +/** +*@brief Returns a namedtuple (values, indices) where values is the cumulative +* the cumulative minimum of elements of input in the dimension dim. +* And indices is the index location of each maximum value found in the dimension dim. \n + +*@par Inputs: +*One inputs, including: +* @li x: A tensor . Must be one of the following types: +* float16, float32, int32, uint32, int8, uint8. \n + +*@par Attributes: +* @li axis: Axis along which to cummin. \n + +*@par Outputs: +* y: A Tensor with the same type and shape of x's. \n +* indices: A Tensor with the int32 type and the same shape of x's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator Cummin. \n +*/ +REG_OP(Cummin) + .INPUT(x, TensorType::BasicType()) + .OUTPUT(y, TensorType::BasicType()) + .OUTPUT(indices, TensorType::BasicType()) + .REQUIRED_ATTR(axis, Int) + .OP_END_FACTORY_REG(Cummin) + /** *@brief Extends the input with copies of data along a specified dimension. For example: *(1) If x = [[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]]], with shape (2, 3, 2); diff --git a/third_party/fwkacllib/inc/ops/string_ops.h b/third_party/fwkacllib/inc/ops/string_ops.h index 29aec302..d7233906 100644 --- a/third_party/fwkacllib/inc/ops/string_ops.h +++ b/third_party/fwkacllib/inc/ops/string_ops.h @@ -25,6 +25,233 @@ #include "graph/operator_reg.h" namespace ge { +/** +*@brief Creates ngrams from ragged string data . \n + +*@par Inputs: +include: +*@li data:1-D.The values tensor of the ragged string tensor to make ngrams out of. +*@li data_splits:The splits tensor of the ragged string tensor to make ngrams out of . \n + +*@par Attributes: +* separator:The string to append between elements of the token. Use "" for no separator. +* ngram_widths:The sizes of the ngrams to create. +* left_pad:The string to use to pad the left side of the ngram sequence. Only used if pad_width != 0. +* right_pad:The string to use to pad the right side of the ngram sequence. Only used if pad_width != 0. +* pad_width:The number of padding elements to add to each side of each sequence. +* preserve_short_sequences: Preserve short sequences. \n + +*@par Outputs: +*@li ngrams:The values tensor of the output ngrams ragged tensor. +*@li ngrams_splits:The splits tensor of the output ngrams ragged tensor. \n + +*@see StringNGrams() + +*@par Third-party framework compatibility +*compatible with StringNGrams op of tensorflow + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(StringNGrams) + .INPUT(data, TensorType({DT_STRING})) + .INPUT(data_splits, TensorType({DT_INT32, DT_INT64})) + .OUTPUT(ngrams, TensorType({DT_STRING})) + .OUTPUT(ngrams_splits, TensorType({DT_INT32, DT_INT64})) + .REQUIRED_ATTR(separator, String) + .ATTR(ngram_widths, ListInt, {}) + .REQUIRED_ATTR(left_pad, String) + .REQUIRED_ATTR(right_pad, String) + .REQUIRED_ATTR(pad_width, Int) + .REQUIRED_ATTR(preserve_short_sequences, Bool) + .OP_END_FACTORY_REG(StringNGrams) + +/** +*@brief Decodes each string in `input` into a sequence of Unicode code points . \n + +*@par Inputs: +include: +*@li input:The text to be decoded. Can have any shape. Note that the output is flattened +to a vector of char values. \n + +*@par Attributes: +* input_encoding:Text encoding of the input strings. This is any of the encodings supported +by ICU ucnv algorithmic converters. Examples: `"UTF-16", "US ASCII", "UTF-8"`. +* errors:Error handling policy when there is invalid formatting found in the input. +The value of 'strict' will cause the operation to produce a InvalidArgument +error on any invalid input formatting. A value of 'replace' (the default) will +cause the operation to replace any invalid formatting in the input with the +`replacement_char` codepoint. A value of 'ignore' will cause the operation to +skip any invalid formatting in the input and produce no corresponding output +character. +* replacement_char:The replacement character codepoint to be used in place of any invalid +formatting in the input when `errors='replace'`. Any valid unicode codepoint may +be used. The default value is the default unicode replacement character is +0xFFFD or U+65533. +* replace_control_characters:Whether to replace the C0 control characters (00-1F) with the +`replacement_char`. Default is false. \n + +*@par Outputs: +*@li row_splits:A 1D tensor containing the row splits. +*@li char_values:A 1D tensor containing the decoded codepoints. +*@li char_to_byte_starts:A 1D int32 Tensor containing the byte index in the input string where each +character in `char_values` starts. \n + +*@see UnicodeDecodeWithOffsets() + +*@par Third-party framework compatibility +*compatible with UnicodeDecodeWithOffsets op of tensorflow + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(UnicodeDecodeWithOffsets) + .INPUT(input, TensorType({DT_STRING})) + .OUTPUT(row_splits, TensorType({DT_INT64})) + .OUTPUT(char_values, TensorType({DT_INT32})) + .OUTPUT(char_to_byte_starts, TensorType({DT_INT64})) + .REQUIRED_ATTR(input_encoding, String) + .ATTR(errors, String, "replace") + .ATTR(replacement_char, Int, 65533) + .ATTR(replace_control_characters, Bool, false) + .OP_END_FACTORY_REG(UnicodeDecodeWithOffsets) + +/** +*@brief Decodes each string in `input` into a sequence of Unicode code points. \n + +*@par Inputs: +include: +*@li input:The text to be decoded. Can have any shape. Note that the output is flattened +to a vector of char values. \n + +*@par Attributes: +* input_encoding:Text encoding of the input strings. This is any of the encodings supported +by ICU ucnv algorithmic converters. Examples: `"UTF-16", "US ASCII", "UTF-8"`. +* errors:Error handling policy when there is invalid formatting found in the input. +The value of 'strict' will cause the operation to produce a InvalidArgument +error on any invalid input formatting. A value of 'replace' (the default) will +cause the operation to replace any invalid formatting in the input with the +`replacement_char` codepoint. A value of 'ignore' will cause the operation to +skip any invalid formatting in the input and produce no corresponding output +character. +* replacement_char:The replacement character codepoint to be used in place of any invalid +formatting in the input when `errors='replace'`. Any valid unicode codepoint may +be used. The default value is the default unicode replacement character is +0xFFFD or U+65533. +* replace_control_characters:Whether to replace the C0 control characters (00-1F) with the +`replacement_char`. Default is false. \n + +*@par Outputs: +*@li row_splits:A 1D tensor containing the row splits. +*@li char_values:A 1D tensor containing the decoded codepoints. \n + +*@see UnicodeDecode() + +*@par Third-party framework compatibility +*compatible with UnicodeDecode op of tensorflow + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(UnicodeDecode) + .INPUT(input, TensorType({DT_STRING})) + .OUTPUT(row_splits, TensorType({DT_INT64})) + .OUTPUT(char_values, TensorType({DT_INT32})) + .REQUIRED_ATTR(input_encoding, String) + .ATTR(errors, String, "replace") + .ATTR(replacement_char, Int, 65533) + .ATTR(replace_control_characters, Bool, false) + .OP_END_FACTORY_REG(UnicodeDecode) + +/** +*@brief Transcode the input text from a source encoding to a destination encoding. \n + +*@par Inputs: +include: +*@li input:The text to be processed. Can have any shape. \n + +*@par Attributes: +* input_encoding:Text encoding of the input strings. This is any of the encodings supported +by ICU ucnv algorithmic converters. Examples: `"UTF-16", "US ASCII", "UTF-8"`. +* output_encoding:The unicode encoding to use in the output. Must be one of `"UTF-8", "UTF-16-BE", "UTF-32-BE"`. +Multi-byte encodings will be big-endian. +* errors:Error handling policy when there is invalid formatting found in the input. +The value of 'strict' will cause the operation to produce a InvalidArgument +error on any invalid input formatting. A value of 'replace' (the default) will +cause the operation to replace any invalid formatting in the input with the +`replacement_char` codepoint. A value of 'ignore' will cause the operation to +skip any invalid formatting in the input and produce no corresponding output +character. +* replacement_char:The replacement character codepoint to be used in place of any invalid +formatting in the input when `errors='replace'`. Any valid unicode codepoint may +be used. The default value is the default unicode replacement character is +0xFFFD or U+65533. +* replace_control_characters:Whether to replace the C0 control characters (00-1F) with the +`replacement_char`. Default is false. \n + +*@par Outputs: +*@li output:A string tensor containing unicode text encoded using `output_encoding`. \n + +*@see UnicodeTranscode() + +*@par Third-party framework compatibility +*compatible with UnicodeTranscode op of tensorflow + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(UnicodeTranscode) + .INPUT(input, TensorType({DT_STRING})) + .OUTPUT(output, TensorType({DT_STRING})) + .REQUIRED_ATTR(input_encoding, String) + .ATTR(output_encoding, String, "UTF-8") + .ATTR(errors, String, "replace") + .ATTR(replacement_char, Int, 65533) + .ATTR(replace_control_characters, Bool, false) + .OP_END_FACTORY_REG(UnicodeTranscode) + +/** +*@brief Encode a tensor of ints into unicode strings. \n + +*@par Inputs: +include: +*@li input_values:A 1D tensor containing the unicode codepoints that should be encoded. +*@li input_splits:A 1D tensor specifying how the unicode codepoints should be split into strings. \n + +*@par Attributes: +* output_encoding:The unicode encoding to use in the output. Must be one of `"UTF-8", "UTF-16-BE", "UTF-32-BE"`. +Multi-byte encodings will be big-endian. +* errors:Error handling policy when there is invalid formatting found in the input. +The value of 'strict' will cause the operation to produce a InvalidArgument +error on any invalid input formatting. A value of 'replace' (the default) will +cause the operation to replace any invalid formatting in the input with the +`replacement_char` codepoint. A value of 'ignore' will cause the operation to +skip any invalid formatting in the input and produce no corresponding output +character. +* replacement_char:The replacement character codepoint to be used in place of any invalid +formatting in the input when `errors='replace'`. Any valid unicode codepoint may +be used. The default value is the default unicode replacement character is +0xFFFD or U+65533. \n + +*@par Outputs: +*@li output:The 1-D Tensor of strings encoded from the provided unicode codepoints. \n + +*@see UnicodeEncode() + +*@par Third-party framework compatibility +*compatible with UnicodeEncode op of tensorflow + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(UnicodeEncode) + .INPUT(input_values, TensorType({DT_INT32})) + .INPUT(input_splits, TensorType({DT_INT32, DT_INT64})) + .OUTPUT(output, TensorType({DT_STRING})) + .ATTR(errors, String, "replace") + .ATTR(output_encoding, String, "UTF-8") + .ATTR(replacement_char, Int, 65533) + .OP_END_FACTORY_REG(UnicodeEncode) /** *@brief Split elements of input based on delimiter into a SparseTensor . \n @@ -61,6 +288,116 @@ REG_OP(StringSplit) .ATTR(skip_empty, Bool, true) .OP_END_FACTORY_REG(StringSplit) +/** +*@brief Replaces the match of pattern in input with rewrite. \n + +*@par Inputs: +include: +*@li input:A Tensor of type string. The text to be processed. \n + +*@par Attributes: +*@li pattern:A string. The regular expression to match the input. +*@li rewrite:A string. The rewrite to be applied to the matched expression. +*@li replace_global:An optional bool. Defaults to True. If True, the replacement is global, +otherwise the replacement is done only on the first match. + +*@par output: +*@li output::A Tensor of type string. +*/ +REG_OP(StaticRegexReplace) + .INPUT(input, TensorType({DT_STRING})) + .OUTPUT(output, TensorType({DT_STRING})) + .ATTR(pattern, String, "") + .ATTR(rewrite, String, "") + .ATTR(replace_global, Bool, true) + .OP_END_FACTORY_REG(StaticRegexReplace) + +/** +*@brief The input is a string tensor of any shape. The pattern is the +*regular expression to be matched with every element of the input tensor. +*The boolean values (True or False) of the output tensor indicate +*if the input matches the regex pattern provided. + +*@par Inputs: +include: +*@li input:A Tensor of type string. The text to be processed. \n + +*@par Attributes: +*@li pattern:A string. The regular expression to match the input. + +*@par output: +*@li output::A bool tensor with the same shape as `input`. +*/ +REG_OP(StaticRegexFullMatch) + .INPUT(input, TensorType({DT_STRING})) + .OUTPUT(output, TensorType({DT_BOOL})) + .ATTR(pattern, String, "") + .OP_END_FACTORY_REG(StaticRegexFullMatch) + +/** +*@brief A Tensor of type string. The input to be joined. \n + +*@par Inputs: +include: +*@li input:A Tensor of type string. The text to be processed. +*@li segment_ids:A Tensor. Must be one of the following types: int32, int64. +*A tensor whose shape is a prefix of data.shape. Negative segment ids are not supported. +*@li num_segments:A Tensor. Must be one of the following types: int32, int64. A scalar. + +*@par Attributes: +*@li separator:An optional string. Defaults to "". The separator to use when joining. + +*@par output: +*@li output::A Tensor of type string.. +*/ +REG_OP(UnsortedSegmentJoin) + .INPUT(input, TensorType({DT_STRING})) + .INPUT(segment_ids, TensorType({DT_INT32,DT_INT64})) + .INPUT(num_segments, TensorType({DT_INT32,DT_INT64})) + .OUTPUT(output, TensorType({DT_STRING})) + .ATTR(separator, String, "") + .OP_END_FACTORY_REG(UnsortedSegmentJoin) + +/** +*@brief Inputs to TensorFlow operations are outputs of another TensorFlow operation. +*This method is used to obtain a symbolic handle that represents the computation of the input. + +*@par Inputs: +include: +*@li input:A Tensor of type string. The text to be processed. + +*@par Attributes: +*@li encoding:An optional string. Defaults to "". + +*@par output: +*@li output::A Tensor of type string.. +*/ +REG_OP(StringLower) + .INPUT(input, TensorType({DT_STRING})) + .OUTPUT(output, TensorType({DT_STRING})) + .ATTR(encoding, String, "") + .OP_END_FACTORY_REG(StringLower) + +/** +*@brief Inputs to TensorFlow operations are outputs of another TensorFlow operation. +*This method is used to obtain a symbolic handle that represents the computation of the input. + +*@par Inputs: +include: +*@li input:A Tensor of type string. The text to be processed. + +*@par Attributes: +*@li encoding:An optional string. Defaults to "". + +*@par output: +*@li output::A Tensor of type string.. +*/ +REG_OP(StringUpper) + .INPUT(input, TensorType({DT_STRING})) + .OUTPUT(output, TensorType({DT_STRING})) + .ATTR(encoding, String, "") + .OP_END_FACTORY_REG(StringUpper) + /** *@brief Split elements of source based on sep into a SparseTensor . \n diff --git a/third_party/fwkacllib/inc/ops/transformation_ops.h b/third_party/fwkacllib/inc/ops/transformation_ops.h index 32baf56c..48a094f7 100644 --- a/third_party/fwkacllib/inc/ops/transformation_ops.h +++ b/third_party/fwkacllib/inc/ops/transformation_ops.h @@ -418,12 +418,8 @@ REG_OP(BatchToSpace) * Warning: THIS FUNCTION IS DEPRECATED. Please use BatchToSpace instead. */ REG_OP(BatchToSpaceD) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT64, DT_INT32, DT_UINT8, - DT_UINT16, DT_UINT32, DT_UINT64, DT_INT8, DT_INT16, DT_COMPLEX64, - DT_COMPLEX128, DT_QINT8, DT_QUINT8, DT_QINT16, DT_QUINT16, DT_QINT32})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT64, DT_INT32, DT_UINT8, - DT_UINT16, DT_UINT32, DT_UINT64, DT_INT8, DT_INT16, DT_COMPLEX64, - DT_COMPLEX128, DT_QINT8, DT_QUINT8, DT_QINT16, DT_QUINT16, DT_QINT32})) + .INPUT(x, TensorType::BasicType()) + .OUTPUT(y, TensorType::BasicType()) .REQUIRED_ATTR(block_size, Int) .REQUIRED_ATTR(crops, ListInt) .OP_END_FACTORY_REG(BatchToSpaceD) diff --git a/third_party/fwkacllib/inc/runtime/base.h b/third_party/fwkacllib/inc/runtime/base.h index 1b264843..7fc1cdea 100644 --- a/third_party/fwkacllib/inc/runtime/base.h +++ b/third_party/fwkacllib/inc/runtime/base.h @@ -154,6 +154,12 @@ RTS_API rtError_t rtProfilerStop(uint64_t profConfig, int32_t numsDev, uint32_t */ RTS_API rtError_t rtProfilerTrace(uint64_t id, bool notify, uint32_t flags, rtStream_t stream); +/** + * @ingroup profiling_base + * @brief ts send keypoint profiler log. + */ +RTS_API rtError_t rtProfilerTraceEx(uint64_t id, uint64_t modelId, uint16_t tagId, rtStream_t stream); + /** * @ingroup profiling_base * @brief ts set profiling reporter callback. @@ -200,7 +206,7 @@ RTS_API rtError_t rtRegDeviceStateCallback(const char *regName, rtDeviceStateCal /** * @ingroup dvrt_base - * @brief register callback for fail task + * @brief register callback for fail task * @param [in] uniName unique register name, can't be null * @param [in] callback fail task callback function * @param [out] NA @@ -343,7 +349,7 @@ RTS_API rtError_t rtLabelCreateExV2(rtLabel_t *label, rtModel_t model, rtStream_ /** * @ingroup dvrt_base - * @brief get current thread last stream id and task id + * @brief get current thread last stream id and task id * @param [out] stream id and task id * @param [in] null * @return RT_ERROR_NONE for ok diff --git a/third_party/fwkacllib/inc/runtime/event.h b/third_party/fwkacllib/inc/runtime/event.h index d4219559..9e555230 100644 --- a/third_party/fwkacllib/inc/runtime/event.h +++ b/third_party/fwkacllib/inc/runtime/event.h @@ -181,6 +181,18 @@ RTS_API rtError_t rtNotifyRecord(rtNotify_t notify, rtStream_t stream); */ RTS_API rtError_t rtNotifyWait(rtNotify_t notify, rtStream_t stream); +/** + * @ingroup dvrt_event + * @brief Wait for a notify with time out + * @param [in] notify_ notify to be wait + * @param [in] stream_ input stream + * @param [in] timeOut input timeOut + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + * @return RT_ERROR_STREAM_CONTEXT for stream is not in current ctx + */ +RTS_API rtError_t rtNotifyWaitWithTimeOut(rtNotify_t notify_, rtStream_t stream_, uint32_t timeOut); + /** * @ingroup dvrt_event * @brief Name a notify diff --git a/third_party/fwkacllib/inc/runtime/rt.h b/third_party/fwkacllib/inc/runtime/rt.h index 83cafa3c..fb6e2e20 100644 --- a/third_party/fwkacllib/inc/runtime/rt.h +++ b/third_party/fwkacllib/inc/runtime/rt.h @@ -27,5 +27,6 @@ #include "mem.h" #include "rt_model.h" #include "stream.h" +#include "rt_stars.h" #endif // __CCE_RUNTIME_RT_H__ diff --git a/third_party/fwkacllib/inc/runtime/rt_model.h b/third_party/fwkacllib/inc/runtime/rt_model.h index df2eddc9..8c93fbd5 100644 --- a/third_party/fwkacllib/inc/runtime/rt_model.h +++ b/third_party/fwkacllib/inc/runtime/rt_model.h @@ -51,6 +51,7 @@ typedef enum tagModelTaskType { RT_MODEL_TASK_STREAM_LABEL_GOTO, RT_MODEL_TASK_MODEL_EXIT, RT_MODEL_TASK_ALL_KERNEL, + RT_MODEL_TASK_PROFILER_TRACE_EX, } rtModelTaskType_t; typedef enum tagModelStreamType { @@ -197,6 +198,13 @@ typedef struct tagProfilerTraceTaskInfo { uint32_t reserved[6]; } rtProfilerTrace_t; +typedef struct tagProfilerTraceExTaskInfo { + uint64_t profilerTraceId; + uint64_t modelId; + uint16_t tagId; + uint8_t reserved[22]; +} rtProfilerTraceEx_t; + typedef struct tagrtMemcpyAsyncTaskInfo { void *dst; uint64_t destMax; @@ -272,6 +280,7 @@ typedef struct tagTaskInfo { rtLabelSwitchTaskInfo_t labelSwitchTask; rtLabelGotoTaskInfo_t labelGotoTask; rtProfilerTrace_t profilertraceTask; + rtProfilerTraceEx_t profilertraceExTask; rtMemcpyAsyncTaskInfo_t memcpyAsyncTask; rtNotifyTaskInfo_t notifyTask; rtReduceAsyncTaskInfo_t reduceAsyncTask; diff --git a/third_party/fwkacllib/inc/runtime/rt_stars.h b/third_party/fwkacllib/inc/runtime/rt_stars.h new file mode 100644 index 00000000..3b944065 --- /dev/null +++ b/third_party/fwkacllib/inc/runtime/rt_stars.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + * Description: + */ + +#ifndef __CCE_RUNTIME_STARS_H +#define __CCE_RUNTIME_STARS_H + +#include "base.h" + +#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +extern "C" { +#endif + +/** + * @ingroup rt_stars + * @brief launch stars task. + * used for send star sqe directly. + * @param [in] taskSqe stars task sqe + * @param [in] sqeLen stars task sqe length + * @param [in] stream associated stream + * @return RT_ERROR_NONE for ok, others failed + */ +RTS_API rtError_t rtStarsTaskLaunch(const void *taskSqe, uint32_t sqeLen, rtStream_t stream); + +#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +} +#endif +#endif // __CCE_RUNTIME_STARS_H diff --git a/third_party/fwkacllib/inc/toolchain/prof_reporter.h b/third_party/fwkacllib/inc/toolchain/prof_reporter.h index ff91351b..d5ed7569 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_reporter.h +++ b/third_party/fwkacllib/inc/toolchain/prof_reporter.h @@ -41,42 +41,44 @@ namespace Engine { * the Reporter class .used to send data to profiling */ class MSVP_PROF_API Reporter { - public: - virtual ~Reporter() {} +public: + virtual ~Reporter() {} - public: - /** - * @ingroup reporter - * @name : Report - * @brief : API of libmsprof, report data to libmsprof, it's a non-blocking function \n - The data will be firstly appended to cache, if the cache is full, data will be ignored - * @param data [IN] const ReporterData * the data send to libmsporf - * @retval PROFILING_SUCCESS 0 (success) - * @retval PROFILING_FAILED -1 (failed) - * - * @par depend: - * @li libmsprof - * @li prof_reporter.h - * @since c60 - * @see Flush - */ - virtual int Report(const ReporterData *data) = 0; +public: + /** + * @ingroup reporter + * @name : Report + * @brief : API of libmsprof, report data to libmsprof, it's a non-blocking function \n + The data will be firstly appended to cache, if the cache is full, data will be ignored + * @param data [IN] const ReporterData * the data send to libmsporf + * @retval PROFILING_SUCCESS 0 (success) + * @retval PROFILING_FAILED -1 (failed) + * + * @par depend: + * @li libmsprof + * @li prof_reporter.h + * @since c60 + * @see Flush + */ + virtual int Report(const ReporterData *data) = 0; - /** - * @ingroup reporter - * @name : Flush - * @brief : API of libmsprof, notify libmsprof send data over, it's a blocking function \n - The all datas of cache will be write to file or send to host - * @retval PROFILING_SUCCESS 0 (success) - * @retval PROFILING_FAILED -1 (failed) - * - * @par depend: - * @li libmsprof - * @li prof_reporter.h - * @since c60 - * @see ProfMgrStop - */ - virtual int Flush() = 0; + /** + * @ingroup reporter + * @name : Flush + * @brief : API of libmsprof, notify libmsprof send data over, it's a blocking function \n + The all datas of cache will be write to file or send to host + * @retval PROFILING_SUCCESS 0 (success) + * @retval PROFILING_FAILED -1 (failed) + * + * @par depend: + * @li libmsprof + * @li prof_reporter.h + * @since c60 + * @see ProfMgrStop + */ + virtual int Flush() = 0; + + virtual uint32_t GetReportDataMaxLen() = 0; }; } // namespace Engine diff --git a/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h b/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h index 3634b8a8..71226d87 100644 --- a/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h +++ b/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h @@ -55,7 +55,40 @@ extern "C" MsTuneStatus MsTrainTuning(ge::Graph &tuningGraph, std::vector &option); + +/** + * @ingroup aoe + * @par 描述: 调优去初始化 + * + * @attention 无 + * @param 无 + * @retval #AOE_SUCCESS 执行成功 + * @retval #AOE_FAILED 执行失败 + * @par 依赖: + * @li tune_api.cpp:该接口所属的开发包。 + * @li tune_api.h:该接口声明所在的头文件。 + * @see 无 + * @since + */ +extern "C" AoeStatus AoeOnlineFinalize(); + +/** + * @ingroup aoe + * @par 描述: 调优处理 * * @attention 无 * @param tuningGraph [IN] 调优图 @@ -71,5 +104,5 @@ extern "C" MsTuneStatus MsTrainTuning(ge::Graph &tuningGraph, std::vector &dependGraph, - ge::Session *session, const std::map> &option); + ge::Session *session, const std::map &option); #endif From 38621eb9ed4394d6f9c778257e54fa20e0b4730d Mon Sep 17 00:00:00 2001 From: dingpeifei Date: Wed, 28 Apr 2021 17:52:06 +0800 Subject: [PATCH 25/59] code_sync_0428 --- inc/external/acl/acl.h | 10 +- inc/external/acl/acl_base.h | 91 ++-- inc/external/acl/acl_mdl.h | 359 +++++++-------- inc/external/acl/acl_op.h | 119 ++--- inc/external/acl/acl_op_compiler.h | 54 +-- inc/external/acl/acl_prof.h | 46 +- inc/external/acl/acl_rt.h | 142 +++--- inc/external/acl/acl_tdt.h | 31 +- inc/external/acl/error_codes/rt_error_codes.h | 138 +++--- inc/external/acl/ops/acl_cblas.h | 179 ++------ inc/external/acl/ops/acl_dvpp.h | 425 +++++++----------- inc/external/acl/ops/acl_fv.h | 14 +- inc/external/hccl/hccl.h | 35 +- inc/external/hccl/hccl_types.h | 84 ++-- inc/external/runtime/rt_error_codes.h | 138 +++--- 15 files changed, 780 insertions(+), 1085 deletions(-) diff --git a/inc/external/acl/acl.h b/inc/external/acl/acl.h index a53d029d..8d261201 100644 --- a/inc/external/acl/acl.h +++ b/inc/external/acl/acl.h @@ -26,9 +26,9 @@ extern "C" { #endif // Current version is 1.0.0 -#define ACL_MAJOR_VERSION 1 -#define ACL_MINOR_VERSION 0 -#define ACL_PATCH_VERSION 0 +#define ACL_MAJOR_VERSION 1 +#define ACL_MINOR_VERSION 0 +#define ACL_PATCH_VERSION 0 /** * @ingroup AscendCL @@ -72,11 +72,11 @@ ACL_FUNC_VISIBILITY aclError aclrtGetVersion(int32_t *majorVersion, int32_t *min * * @retval null for failed * @retval OtherValues success -*/ + */ ACL_FUNC_VISIBILITY const char *aclGetRecentErrMsg(); #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_H_ +#endif // INC_EXTERNAL_ACL_ACL_H_ diff --git a/inc/external/acl/acl_base.h b/inc/external/acl/acl_base.h index 417a80c8..64d4bd81 100644 --- a/inc/external/acl/acl_base.h +++ b/inc/external/acl/acl_base.h @@ -136,50 +136,49 @@ static const int ACL_ERROR_PROFILING_FAILURE = 500005; #define ACL_UNKNOWN_RANK 0xFFFFFFFFFFFFFFFE typedef enum { - ACL_DT_UNDEFINED = -1, - ACL_FLOAT = 0, - ACL_FLOAT16 = 1, - ACL_INT8 = 2, - ACL_INT32 = 3, - ACL_UINT8 = 4, - ACL_INT16 = 6, - ACL_UINT16 = 7, - ACL_UINT32 = 8, - ACL_INT64 = 9, - ACL_UINT64 = 10, - ACL_DOUBLE = 11, - ACL_BOOL = 12, - ACL_STRING = 13, + ACL_DT_UNDEFINED = -1, + ACL_FLOAT = 0, + ACL_FLOAT16 = 1, + ACL_INT8 = 2, + ACL_INT32 = 3, + ACL_UINT8 = 4, + ACL_INT16 = 6, + ACL_UINT16 = 7, + ACL_UINT32 = 8, + ACL_INT64 = 9, + ACL_UINT64 = 10, + ACL_DOUBLE = 11, + ACL_BOOL = 12, + ACL_STRING = 13, } aclDataType; typedef enum { - ACL_FORMAT_UNDEFINED = -1, - ACL_FORMAT_NCHW = 0, - ACL_FORMAT_NHWC = 1, - ACL_FORMAT_ND = 2, - ACL_FORMAT_NC1HWC0 = 3, - ACL_FORMAT_FRACTAL_Z = 4, - ACL_FORMAT_NC1HWC0_C04 = 12, - ACL_FORMAT_NDHWC = 27, - ACL_FORMAT_FRACTAL_NZ = 29, - ACL_FORMAT_NCDHW = 30, - ACL_FORMAT_NDC1HWC0 = 32, - ACL_FRACTAL_Z_3D = 33 + ACL_FORMAT_UNDEFINED = -1, + ACL_FORMAT_NCHW = 0, + ACL_FORMAT_NHWC = 1, + ACL_FORMAT_ND = 2, + ACL_FORMAT_NC1HWC0 = 3, + ACL_FORMAT_FRACTAL_Z = 4, + ACL_FORMAT_NC1HWC0_C04 = 12, + ACL_FORMAT_NDHWC = 27, + ACL_FORMAT_FRACTAL_NZ = 29, + ACL_FORMAT_NCDHW = 30, + ACL_FORMAT_NDC1HWC0 = 32, + ACL_FRACTAL_Z_3D = 33 } aclFormat; typedef enum { - ACL_DEBUG = 0, - ACL_INFO = 1, - ACL_WARNING = 2, - ACL_ERROR = 3, + ACL_DEBUG = 0, + ACL_INFO = 1, + ACL_WARNING = 2, + ACL_ERROR = 3, } aclLogLevel; typedef enum { - ACL_MEMTYPE_DEVICE = 0, - ACL_MEMTYPE_HOST = 1, + ACL_MEMTYPE_DEVICE = 0, + ACL_MEMTYPE_HOST = 1, } aclMemType; - /** * @ingroup AscendCL * @brief Converts data of type aclFloat16 to data of type float @@ -312,9 +311,7 @@ ACL_FUNC_VISIBILITY size_t aclDataTypeSize(aclDataType dataType); * @retval aclTensorDesc pointer. * @retval nullptr if param is invalid or run out of memory */ -ACL_FUNC_VISIBILITY aclTensorDesc *aclCreateTensorDesc(aclDataType dataType, - int numDims, - const int64_t *dims, +ACL_FUNC_VISIBILITY aclTensorDesc *aclCreateTensorDesc(aclDataType dataType, int numDims, const int64_t *dims, aclFormat format); /** @@ -336,8 +333,7 @@ ACL_FUNC_VISIBILITY void aclDestroyTensorDesc(const aclTensorDesc *desc); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclSetTensorShapeRange(aclTensorDesc* desc, - size_t dimsCount, +ACL_FUNC_VISIBILITY aclError aclSetTensorShapeRange(aclTensorDesc *desc, size_t dimsCount, int64_t dimsRange[][ACL_TENSOR_SHAPE_RANGE_NUM]); /** @@ -434,9 +430,7 @@ ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimV2(const aclTensorDesc *desc, si * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimRange(const aclTensorDesc *desc, - size_t index, - size_t dimRangeNum, +ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimRange(const aclTensorDesc *desc, size_t index, size_t dimRangeNum, int64_t *dimRange); /** @@ -473,7 +467,7 @@ ACL_FUNC_VISIBILITY const char *aclGetTensorDescName(aclTensorDesc *desc); * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclTransTensorDescFormat(const aclTensorDesc *srcDesc, aclFormat dstFormat, - aclTensorDesc **dstDesc); + aclTensorDesc **dstDesc); /** * @ingroup AscendCL @@ -561,7 +555,7 @@ ACL_FUNC_VISIBILITY aclError aclSetTensorOriginShape(aclTensorDesc *desc, int nu * * @retval null for failed. * @retval OtherValues success. -*/ + */ ACL_FUNC_VISIBILITY aclTensorDesc *aclGetTensorDescByIndex(aclTensorDesc *desc, size_t index); /** @@ -572,7 +566,7 @@ ACL_FUNC_VISIBILITY aclTensorDesc *aclGetTensorDescByIndex(aclTensorDesc *desc, * * @retval null for failed * @retval OtherValues success -*/ + */ ACL_FUNC_VISIBILITY void *aclGetTensorDescAddress(const aclTensorDesc *desc); /** @@ -624,7 +618,7 @@ ACL_FUNC_VISIBILITY aclError aclSetTensorPlaceMent(aclTensorDesc *desc, aclMemTy * @param ... [IN] the value of current log */ ACL_FUNC_VISIBILITY void aclAppLog(aclLogLevel logLevel, const char *func, const char *file, uint32_t line, - const char *fmt, ...); + const char *fmt, ...); /** * @ingroup AscendCL @@ -632,14 +626,13 @@ ACL_FUNC_VISIBILITY void aclAppLog(aclLogLevel logLevel, const char *func, const * * @retval null for failed * @retval OtherValues success -*/ + */ ACL_FUNC_VISIBILITY const char *aclrtGetSocName(); -#define ACL_APP_LOG(level, fmt, ...) \ - aclAppLog(level, __FUNCTION__, __FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define ACL_APP_LOG(level, fmt, ...) aclAppLog(level, __FUNCTION__, __FILE__, __LINE__, fmt, ##__VA_ARGS__) #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_BASE_H_ +#endif // INC_EXTERNAL_ACL_ACL_BASE_H_ diff --git a/inc/external/acl/acl_mdl.h b/inc/external/acl/acl_mdl.h index e2f95a56..88f85cb3 100644 --- a/inc/external/acl/acl_mdl.h +++ b/inc/external/acl/acl_mdl.h @@ -27,19 +27,19 @@ extern "C" { #endif -#define ACL_MAX_DIM_CNT 128 -#define ACL_MAX_TENSOR_NAME_LEN 128 -#define ACL_MAX_BATCH_NUM 128 -#define ACL_MAX_HW_NUM 128 -#define ACL_MAX_SHAPE_COUNT 128 -#define ACL_INVALID_NODE_INDEX 0xFFFFFFFF - -#define ACL_MDL_LOAD_FROM_FILE 1 -#define ACL_MDL_LOAD_FROM_FILE_WITH_MEM 2 -#define ACL_MDL_LOAD_FROM_MEM 3 -#define ACL_MDL_LOAD_FROM_MEM_WITH_MEM 4 -#define ACL_MDL_LOAD_FROM_FILE_WITH_Q 5 -#define ACL_MDL_LOAD_FROM_MEM_WITH_Q 6 +#define ACL_MAX_DIM_CNT 128 +#define ACL_MAX_TENSOR_NAME_LEN 128 +#define ACL_MAX_BATCH_NUM 128 +#define ACL_MAX_HW_NUM 128 +#define ACL_MAX_SHAPE_COUNT 128 +#define ACL_INVALID_NODE_INDEX 0xFFFFFFFF + +#define ACL_MDL_LOAD_FROM_FILE 1 +#define ACL_MDL_LOAD_FROM_FILE_WITH_MEM 2 +#define ACL_MDL_LOAD_FROM_MEM 3 +#define ACL_MDL_LOAD_FROM_MEM_WITH_MEM 4 +#define ACL_MDL_LOAD_FROM_FILE_WITH_Q 5 +#define ACL_MDL_LOAD_FROM_MEM_WITH_Q 6 #define ACL_DYNAMIC_TENSOR_NAME "ascend_mbatch_shape_data" #define ACL_DYNAMIC_AIPP_NAME "ascend_dynamic_aipp_data" @@ -51,123 +51,123 @@ typedef struct aclAippExtendInfo aclAippExtendInfo; typedef struct aclmdlConfigHandle aclmdlConfigHandle; typedef enum { - ACL_YUV420SP_U8 = 1, - ACL_XRGB8888_U8, - ACL_RGB888_U8, - ACL_YUV400_U8, - ACL_NC1HWC0DI_FP16, - ACL_NC1HWC0DI_S8, - ACL_ARGB8888_U8, - ACL_YUYV_U8, - ACL_YUV422SP_U8, - ACL_AYUV444_U8, - ACL_RAW10, - ACL_RAW12, - ACL_RAW16, - ACL_RAW24, - ACL_AIPP_RESERVED = 0xffff, + ACL_YUV420SP_U8 = 1, + ACL_XRGB8888_U8, + ACL_RGB888_U8, + ACL_YUV400_U8, + ACL_NC1HWC0DI_FP16, + ACL_NC1HWC0DI_S8, + ACL_ARGB8888_U8, + ACL_YUYV_U8, + ACL_YUV422SP_U8, + ACL_AYUV444_U8, + ACL_RAW10, + ACL_RAW12, + ACL_RAW16, + ACL_RAW24, + ACL_AIPP_RESERVED = 0xffff, } aclAippInputFormat; typedef enum { - ACL_MDL_PRIORITY_INT32 = 0, - ACL_MDL_LOAD_TYPE_SIZET, - ACL_MDL_PATH_PTR, /**< pointer to model load path with deep copy */ - ACL_MDL_MEM_ADDR_PTR, /**< pointer to model memory with shallow copy */ - ACL_MDL_MEM_SIZET, - ACL_MDL_WEIGHT_ADDR_PTR, /**< pointer to weight memory of model with shallow copy */ - ACL_MDL_WEIGHT_SIZET, - ACL_MDL_WORKSPACE_ADDR_PTR, /**< pointer to worksapce memory of model with shallow copy */ - ACL_MDL_WORKSPACE_SIZET, - ACL_MDL_INPUTQ_NUM_SIZET, - ACL_MDL_INPUTQ_ADDR_PTR, /**< pointer to inputQ with shallow copy */ - ACL_MDL_OUTPUTQ_NUM_SIZET, - ACL_MDL_OUTPUTQ_ADDR_PTR /**< pointer to outputQ with shallow copy */ + ACL_MDL_PRIORITY_INT32 = 0, + ACL_MDL_LOAD_TYPE_SIZET, + ACL_MDL_PATH_PTR, /**< pointer to model load path with deep copy */ + ACL_MDL_MEM_ADDR_PTR, /**< pointer to model memory with shallow copy */ + ACL_MDL_MEM_SIZET, + ACL_MDL_WEIGHT_ADDR_PTR, /**< pointer to weight memory of model with shallow copy */ + ACL_MDL_WEIGHT_SIZET, + ACL_MDL_WORKSPACE_ADDR_PTR, /**< pointer to worksapce memory of model with shallow copy */ + ACL_MDL_WORKSPACE_SIZET, + ACL_MDL_INPUTQ_NUM_SIZET, + ACL_MDL_INPUTQ_ADDR_PTR, /**< pointer to inputQ with shallow copy */ + ACL_MDL_OUTPUTQ_NUM_SIZET, + ACL_MDL_OUTPUTQ_ADDR_PTR /**< pointer to outputQ with shallow copy */ } aclmdlConfigAttr; typedef enum { - ACL_DATA_WITHOUT_AIPP = 0, - ACL_DATA_WITH_STATIC_AIPP, - ACL_DATA_WITH_DYNAMIC_AIPP, - ACL_DYNAMIC_AIPP_NODE + ACL_DATA_WITHOUT_AIPP = 0, + ACL_DATA_WITH_STATIC_AIPP, + ACL_DATA_WITH_DYNAMIC_AIPP, + ACL_DYNAMIC_AIPP_NODE } aclmdlInputAippType; typedef struct aclmdlIODims { - char name[ACL_MAX_TENSOR_NAME_LEN]; /**< tensor name */ - size_t dimCount; /**< dim array count */ - int64_t dims[ACL_MAX_DIM_CNT]; /**< dim data array */ + char name[ACL_MAX_TENSOR_NAME_LEN]; /**< tensor name */ + size_t dimCount; /**< dim array count */ + int64_t dims[ACL_MAX_DIM_CNT]; /**< dim data array */ } aclmdlIODims; typedef struct aclAippDims { - aclmdlIODims srcDims; /**< input dims before model transform */ - size_t srcSize; /**< input size before model transform */ - aclmdlIODims aippOutdims; /**< aipp output dims */ - size_t aippOutSize; /**< aipp output size */ + aclmdlIODims srcDims; /**< input dims before model transform */ + size_t srcSize; /**< input size before model transform */ + aclmdlIODims aippOutdims; /**< aipp output dims */ + size_t aippOutSize; /**< aipp output size */ } aclAippDims; typedef struct aclmdlBatch { - size_t batchCount; /**< batch array count */ - uint64_t batch[ACL_MAX_BATCH_NUM]; /**< batch data array */ + size_t batchCount; /**< batch array count */ + uint64_t batch[ACL_MAX_BATCH_NUM]; /**< batch data array */ } aclmdlBatch; typedef struct aclmdlHW { - size_t hwCount; /**< height&width array count */ - uint64_t hw[ACL_MAX_HW_NUM][2]; /**< height&width data array */ + size_t hwCount; /**< height&width array count */ + uint64_t hw[ACL_MAX_HW_NUM][2]; /**< height&width data array */ } aclmdlHW; typedef struct aclAippInfo { - aclAippInputFormat inputFormat; - int32_t srcImageSizeW; - int32_t srcImageSizeH; - int8_t cropSwitch; - int32_t loadStartPosW; - int32_t loadStartPosH; - int32_t cropSizeW; - int32_t cropSizeH; - int8_t resizeSwitch; - int32_t resizeOutputW; - int32_t resizeOutputH; - int8_t paddingSwitch; - int32_t leftPaddingSize; - int32_t rightPaddingSize; - int32_t topPaddingSize; - int32_t bottomPaddingSize; - int8_t cscSwitch; - int8_t rbuvSwapSwitch; - int8_t axSwapSwitch; - int8_t singleLineMode; - int32_t matrixR0C0; - int32_t matrixR0C1; - int32_t matrixR0C2; - int32_t matrixR1C0; - int32_t matrixR1C1; - int32_t matrixR1C2; - int32_t matrixR2C0; - int32_t matrixR2C1; - int32_t matrixR2C2; - int32_t outputBias0; - int32_t outputBias1; - int32_t outputBias2; - int32_t inputBias0; - int32_t inputBias1; - int32_t inputBias2; - int32_t meanChn0; - int32_t meanChn1; - int32_t meanChn2; - int32_t meanChn3; - float minChn0; - float minChn1; - float minChn2; - float minChn3; - float varReciChn0; - float varReciChn1; - float varReciChn2; - float varReciChn3; - aclFormat srcFormat; - aclDataType srcDatatype; - size_t srcDimNum; - size_t shapeCount; - aclAippDims outDims[ACL_MAX_SHAPE_COUNT]; - aclAippExtendInfo *aippExtend; /**< reserved parameters, current version needs to be null */ + aclAippInputFormat inputFormat; + int32_t srcImageSizeW; + int32_t srcImageSizeH; + int8_t cropSwitch; + int32_t loadStartPosW; + int32_t loadStartPosH; + int32_t cropSizeW; + int32_t cropSizeH; + int8_t resizeSwitch; + int32_t resizeOutputW; + int32_t resizeOutputH; + int8_t paddingSwitch; + int32_t leftPaddingSize; + int32_t rightPaddingSize; + int32_t topPaddingSize; + int32_t bottomPaddingSize; + int8_t cscSwitch; + int8_t rbuvSwapSwitch; + int8_t axSwapSwitch; + int8_t singleLineMode; + int32_t matrixR0C0; + int32_t matrixR0C1; + int32_t matrixR0C2; + int32_t matrixR1C0; + int32_t matrixR1C1; + int32_t matrixR1C2; + int32_t matrixR2C0; + int32_t matrixR2C1; + int32_t matrixR2C2; + int32_t outputBias0; + int32_t outputBias1; + int32_t outputBias2; + int32_t inputBias0; + int32_t inputBias1; + int32_t inputBias2; + int32_t meanChn0; + int32_t meanChn1; + int32_t meanChn2; + int32_t meanChn3; + float minChn0; + float minChn1; + float minChn2; + float minChn3; + float varReciChn0; + float varReciChn1; + float varReciChn2; + float varReciChn3; + aclFormat srcFormat; + aclDataType srcDatatype; + size_t srcDimNum; + size_t shapeCount; + aclAippDims outDims[ACL_MAX_SHAPE_COUNT]; + aclAippExtendInfo *aippExtend; /**< reserved parameters, current version needs to be null */ } aclAippInfo; /** @@ -291,8 +291,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlAddDatasetBuffer(aclmdlDataset *dataset, aclD * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclmdlSetDatasetTensorDesc(aclmdlDataset *dataset, - aclTensorDesc *tensorDesc, +ACL_FUNC_VISIBILITY aclError aclmdlSetDatasetTensorDesc(aclmdlDataset *dataset, aclTensorDesc *tensorDesc, size_t index); /** @@ -354,8 +353,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFile(const char *modelPath, uint32_t * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMem(const void *model, size_t modelSize, - uint32_t *modelId); +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMem(const void *model, size_t modelSize, uint32_t *modelId); /** * @ingroup AscendCL @@ -377,9 +375,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMem(const void *model, size_t modelS * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithMem(const char *modelPath, - uint32_t *modelId, void *workPtr, size_t workSize, - void *weightPtr, size_t weightSize); +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithMem(const char *modelPath, uint32_t *modelId, void *workPtr, + size_t workSize, void *weightPtr, size_t weightSize); /** * @ingroup AscendCL @@ -402,9 +399,9 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithMem(const char *modelPath, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithMem(const void *model, size_t modelSize, - uint32_t *modelId, void *workPtr, size_t workSize, - void *weightPtr, size_t weightSize); +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithMem(const void *model, size_t modelSize, uint32_t *modelId, + void *workPtr, size_t workSize, void *weightPtr, + size_t weightSize); /** * @ingroup AscendCL @@ -439,8 +436,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithQ(const char *modelPath, uint * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithQ(const void *model, size_t modelSize, uint32_t *modelId, - const uint32_t *inputQ, size_t inputQNum, - const uint32_t *outputQ, size_t outputQNum); + const uint32_t *inputQ, size_t inputQNum, const uint32_t *outputQ, + size_t outputQNum); /** * @ingroup AscendCL @@ -470,8 +467,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlExecute(uint32_t modelId, const aclmdlDataset * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem */ -ACL_FUNC_VISIBILITY aclError aclmdlExecuteAsync(uint32_t modelId, const aclmdlDataset *input, - aclmdlDataset *output, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclmdlExecuteAsync(uint32_t modelId, const aclmdlDataset *input, aclmdlDataset *output, + aclrtStream stream); /** * @ingroup AscendCL @@ -846,11 +843,11 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPInputFormat(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, int8_t csc_switch, - int16_t cscMatrixR0C0, int16_t cscMatrixR0C1, int16_t cscMatrixR0C2, - int16_t cscMatrixR1C0, int16_t cscMatrixR1C1, int16_t cscMatrixR1C2, - int16_t cscMatrixR2C0, int16_t cscMatrixR2C1, int16_t cscMatrixR2C2, + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, int8_t csc_switch, int16_t cscMatrixR0C0, + int16_t cscMatrixR0C1, int16_t cscMatrixR0C2, int16_t cscMatrixR1C0, + int16_t cscMatrixR1C1, int16_t cscMatrixR1C2, int16_t cscMatrixR2C0, + int16_t cscMatrixR2C1, int16_t cscMatrixR2C2, uint8_t cscOutputBiasR0, uint8_t cscOutputBiasR1, uint8_t cscOutputBiasR2, uint8_t cscInputBiasR0, uint8_t cscInputBiasR1, uint8_t cscInputBiasR2); @@ -866,7 +863,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, in * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPRbuvSwapSwitch(aclmdlAIPP *aippParmsSet, int8_t rbuvSwapSwitch); /** @@ -880,7 +877,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPRbuvSwapSwitch(aclmdlAIPP *aippParmsSe * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPAxSwapSwitch(aclmdlAIPP *aippParmsSet, int8_t axSwapSwitch); /** @@ -895,7 +892,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPAxSwapSwitch(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPSrcImageSize(aclmdlAIPP *aippParmsSet, int32_t srcImageSizeW, int32_t srcImageSizeH); @@ -915,14 +912,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPSrcImageSize(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPScfParams(aclmdlAIPP *aippParmsSet, - int8_t scfSwitch, - int32_t scfInputSizeW, - int32_t scfInputSizeH, - int32_t scfOutputSizeW, - int32_t scfOutputSizeH, - uint64_t batchIndex); + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPScfParams(aclmdlAIPP *aippParmsSet, int8_t scfSwitch, int32_t scfInputSizeW, + int32_t scfInputSizeH, int32_t scfOutputSizeW, + int32_t scfOutputSizeH, uint64_t batchIndex); /** * @ingroup AscendCL @@ -940,13 +933,9 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPScfParams(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCropParams(aclmdlAIPP *aippParmsSet, - int8_t cropSwitch, - int32_t cropStartPosW, - int32_t cropStartPosH, - int32_t cropSizeW, - int32_t cropSizeH, + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCropParams(aclmdlAIPP *aippParmsSet, int8_t cropSwitch, int32_t cropStartPosW, + int32_t cropStartPosH, int32_t cropSizeW, int32_t cropSizeH, uint64_t batchIndex); /** @@ -965,7 +954,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCropParams(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPaddingParams(aclmdlAIPP *aippParmsSet, int8_t paddingSwitch, int32_t paddingSizeTop, int32_t paddingSizeBottom, int32_t paddingSizeLeft, int32_t paddingSizeRight, @@ -986,13 +975,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPaddingParams(aclmdlAIPP *aippParmsSet * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMean(aclmdlAIPP *aippParmsSet, - int16_t dtcPixelMeanChn0, - int16_t dtcPixelMeanChn1, - int16_t dtcPixelMeanChn2, - int16_t dtcPixelMeanChn3, - uint64_t batchIndex); + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMean(aclmdlAIPP *aippParmsSet, int16_t dtcPixelMeanChn0, + int16_t dtcPixelMeanChn1, int16_t dtcPixelMeanChn2, + int16_t dtcPixelMeanChn3, uint64_t batchIndex); /** * @ingroup AscendCL @@ -1009,13 +995,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMean(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMin(aclmdlAIPP *aippParmsSet, - float dtcPixelMinChn0, - float dtcPixelMinChn1, - float dtcPixelMinChn2, - float dtcPixelMinChn3, - uint64_t batchIndex); + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMin(aclmdlAIPP *aippParmsSet, float dtcPixelMinChn0, + float dtcPixelMinChn1, float dtcPixelMinChn2, + float dtcPixelMinChn3, uint64_t batchIndex); /** * @ingroup AscendCL @@ -1032,13 +1015,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMin(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPixelVarReci(aclmdlAIPP *aippParmsSet, - float dtcPixelVarReciChn0, - float dtcPixelVarReciChn1, - float dtcPixelVarReciChn2, - float dtcPixelVarReciChn3, - uint64_t batchIndex); + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPixelVarReci(aclmdlAIPP *aippParmsSet, float dtcPixelVarReciChn0, + float dtcPixelVarReciChn1, float dtcPixelVarReciChn2, + float dtcPixelVarReciChn3, uint64_t batchIndex); /** * @ingroup AscendCL @@ -1054,10 +1034,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPixelVarReci(aclmdlAIPP *aippParmsSet, * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetInputAIPP(uint32_t modelId, - aclmdlDataset *dataset, - size_t index, + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetInputAIPP(uint32_t modelId, aclmdlDataset *dataset, size_t index, const aclmdlAIPP *aippParmsSet); /** @@ -1074,10 +1052,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetInputAIPP(uint32_t modelId, * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPByInputIndex(uint32_t modelId, - aclmdlDataset *dataset, - size_t index, + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPByInputIndex(uint32_t modelId, aclmdlDataset *dataset, size_t index, const aclmdlAIPP *aippParmsSet); /** @@ -1095,10 +1071,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPByInputIndex(uint32_t modelId, * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, - size_t index, - aclmdlInputAippType *type, + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, size_t index, aclmdlInputAippType *type, size_t *dynamicAttachedDataIndex); /** @@ -1115,7 +1089,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlGetFirstAippInfo(uint32_t modelId, size_t index, aclAippInfo *aippinfo); /** @@ -1134,10 +1108,11 @@ ACL_FUNC_VISIBILITY aclError aclmdlGetFirstAippInfo(uint32_t modelId, size_t ind * * @retval ACL_SUCCESS The function is successfully executed * @retval OtherValues Failure -*/ -ACL_FUNC_VISIBILITY aclError aclmdlCreateAndGetOpDesc(uint32_t deviceId, uint32_t streamId, - uint32_t taskId, char *opName, size_t opNameLen, aclTensorDesc **inputDesc, size_t *numInputs, - aclTensorDesc **outputDesc, size_t *numOutputs); + */ +ACL_FUNC_VISIBILITY aclError aclmdlCreateAndGetOpDesc(uint32_t deviceId, uint32_t streamId, uint32_t taskId, + char *opName, size_t opNameLen, aclTensorDesc **inputDesc, + size_t *numInputs, aclTensorDesc **outputDesc, + size_t *numOutputs); /** * @ingroup AscendCL @@ -1145,7 +1120,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlCreateAndGetOpDesc(uint32_t deviceId, uint32_ * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlInitDump(); /** @@ -1156,7 +1131,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlInitDump(); * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlSetDump(const char *dumpCfgPath); /** @@ -1165,7 +1140,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetDump(const char *dumpCfgPath); * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlFinalizeDump(); /** @@ -1177,7 +1152,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlFinalizeDump(); * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlLoadWithConfig(const aclmdlConfigHandle *handle, uint32_t *modelId); /** @@ -1187,7 +1162,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadWithConfig(const aclmdlConfigHandle *hand * @retval the aclmdlConfigHandle pointer * * @see aclmdlDestroyConfigHandle -*/ + */ ACL_FUNC_VISIBILITY aclmdlConfigHandle *aclmdlCreateConfigHandle(); /** @@ -1216,7 +1191,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlDestroyConfigHandle(aclmdlConfigHandle *handl * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclmdlSetConfigOpt(aclmdlConfigHandle *handle, aclmdlConfigAttr attr, - const void *attrValue, size_t valueSize); + const void *attrValue, size_t valueSize); /** * @ingroup AscendCL @@ -1234,4 +1209,4 @@ ACL_FUNC_VISIBILITY const char *aclmdlGetTensorRealName(const aclmdlDesc *modelD } #endif -#endif // INC_EXTERNAL_ACL_ACL_MODEL_H_ +#endif // INC_EXTERNAL_ACL_ACL_MODEL_H_ diff --git a/inc/external/acl/acl_op.h b/inc/external/acl/acl_op.h index b1be0d6e..d2e59bfb 100644 --- a/inc/external/acl/acl_op.h +++ b/inc/external/acl/acl_op.h @@ -33,9 +33,9 @@ typedef void (*aclDataDeallocator)(void *data, size_t length); static const int ACL_COMPILE_FLAG_BIN_SELECTOR = 1; typedef enum aclEngineType { - ACL_ENGINE_SYS, - ACL_ENGINE_AICORE, - ACL_ENGINE_VECTOR, + ACL_ENGINE_SYS, + ACL_ENGINE_AICORE, + ACL_ENGINE_VECTOR, } aclopEngineType; /** @@ -148,7 +148,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrString(aclopAttr *attr, const char *att * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListBool(aclopAttr *attr, const char *attrName, int numValues, - const uint8_t *values); + const uint8_t *values); /** * @ingroup AscendCL @@ -163,7 +163,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListBool(aclopAttr *attr, const char *a * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListInt(aclopAttr *attr, const char *attrName, int numValues, - const int64_t *values); + const int64_t *values); /** * @ingroup AscendCL @@ -178,7 +178,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListInt(aclopAttr *attr, const char *at * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListFloat(aclopAttr *attr, const char *attrName, int numValues, - const float *values); + const float *values); /** * @ingroup AscendCL @@ -193,7 +193,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListFloat(aclopAttr *attr, const char * * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListString(aclopAttr *attr, const char *attrName, int numValues, - const char **values); + const char **values); /** * @ingroup AscendCL @@ -208,11 +208,8 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListString(aclopAttr *attr, const char * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, - const char *attrName, - int numLists, - const int *numValues, - const int64_t *const values[]); +ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, const char *attrName, int numLists, + const int *numValues, const int64_t *const values[]); /** * @ingroup AscendCL @@ -242,15 +239,10 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, * @retval OtherValues Failure */ ACL_DEPRECATED_MESSAGE("aclopExecute is deprecated, use aclopExecuteV2 instead") -ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, - int numInputs, - const aclTensorDesc *const inputDesc[], - const aclDataBuffer *const inputs[], - int numOutputs, - const aclTensorDesc *const outputDesc[], - aclDataBuffer *const outputs[], - const aclopAttr *attr, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], + const aclDataBuffer *const inputs[], int numOutputs, + const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], + const aclopAttr *attr, aclrtStream stream); /** * @ingroup AscendCL @@ -280,15 +272,9 @@ ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, - int numInputs, - aclTensorDesc *inputDesc[], - aclDataBuffer *inputs[], - int numOutputs, - aclTensorDesc *outputDesc[], - aclDataBuffer *outputs[], - aclopAttr *attr, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, int numInputs, aclTensorDesc *inputDesc[], + aclDataBuffer *inputs[], int numOutputs, aclTensorDesc *outputDesc[], + aclDataBuffer *outputs[], aclopAttr *attr, aclrtStream stream); /** * @ingroup AscendCL @@ -306,12 +292,9 @@ ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCreateHandle(const char *opType, - int numInputs, - const aclTensorDesc *const inputDesc[], - int numOutputs, - const aclTensorDesc *const outputDesc[], - const aclopAttr *opAttr, +ACL_FUNC_VISIBILITY aclError aclopCreateHandle(const char *opType, int numInputs, + const aclTensorDesc *const inputDesc[], int numOutputs, + const aclTensorDesc *const outputDesc[], const aclopAttr *opAttr, aclopHandle **handle); /** @@ -343,12 +326,9 @@ ACL_FUNC_VISIBILITY void aclopDestroyHandle(aclopHandle *handle); * * @see aclopCreateHandle | aclCreateDataBuffer */ -ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, - int numInputs, - const aclDataBuffer *const inputs[], - int numOutputs, - aclDataBuffer *const outputs[], - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, int numInputs, + const aclDataBuffer *const inputs[], int numOutputs, + aclDataBuffer *const outputs[], aclrtStream stream); /** * @ingroup AscendCL @@ -364,11 +344,8 @@ ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, - const aclDataBuffer *srcBuffer, - const aclTensorDesc *dstDesc, - aclDataBuffer *dstBuffer, - uint8_t truncate, +ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, const aclDataBuffer *srcBuffer, + const aclTensorDesc *dstDesc, aclDataBuffer *dstBuffer, uint8_t truncate, aclrtStream stream); /** @@ -383,12 +360,9 @@ ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, - aclTensorDesc *dstDesc, - uint8_t truncate, +ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, aclTensorDesc *dstDesc, uint8_t truncate, aclopHandle **handle); - /** * @ingroup AscendCL * @brief create kernel @@ -407,15 +381,10 @@ ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, * * @see aclopCompile */ -ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, - const char *kernelId, - const char *kernelName, - void *binData, - int binSize, - aclopEngineType enginetype, +ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, const char *kernelId, const char *kernelName, + void *binData, int binSize, aclopEngineType enginetype, aclDataDeallocator deallocator); - /** * @ingroup AscendCL * @brief create kernel @@ -430,11 +399,8 @@ ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -typedef aclError (*aclopCompileFunc)(int numInputs, - const aclTensorDesc *const inputDesc[], - int numOutputs, - const aclTensorDesc *const outputDesc[], - const aclopAttr *opAttr, +typedef aclError (*aclopCompileFunc)(int numInputs, const aclTensorDesc *const inputDesc[], int numOutputs, + const aclTensorDesc *const outputDesc[], const aclopAttr *opAttr, aclopKernelDesc *aclopKernelDesc); /** @@ -475,11 +441,8 @@ ACL_FUNC_VISIBILITY aclError aclopUnregisterCompileFunc(const char *opType); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopSetKernelArgs(aclopKernelDesc *kernelDesc, - const char *kernelId, - uint32_t blockDim, - const void *args, - uint32_t argSize); +ACL_FUNC_VISIBILITY aclError aclopSetKernelArgs(aclopKernelDesc *kernelDesc, const char *kernelId, uint32_t blockDim, + const void *args, uint32_t argSize); /** * @ingroup AscendCL @@ -510,12 +473,9 @@ ACL_FUNC_VISIBILITY aclError aclopSetKernelWorkspaceSizes(aclopKernelDesc *kerne * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, - int numInputs, - const aclTensorDesc *const inputDesc[], - int numOutputs, - const aclTensorDesc *const outputDesc[], - const aclopAttr *attr); +ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, int numInputs, + const aclTensorDesc *const inputDesc[], int numOutputs, + const aclTensorDesc *const outputDesc[], const aclopAttr *attr); /** * @ingroup AscendCL @@ -533,17 +493,12 @@ ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopInferShape(const char *opType, - int numInputs, - aclTensorDesc *inputDesc[], - aclDataBuffer *inputs[], - int numOutputs, - aclTensorDesc *outputDesc[], +ACL_FUNC_VISIBILITY aclError aclopInferShape(const char *opType, int numInputs, aclTensorDesc *inputDesc[], + aclDataBuffer *inputs[], int numOutputs, aclTensorDesc *outputDesc[], aclopAttr *attr); - #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_OP_H_ +#endif // INC_EXTERNAL_ACL_ACL_OP_H_ diff --git a/inc/external/acl/acl_op_compiler.h b/inc/external/acl/acl_op_compiler.h index 353d2a1a..d9d1b3da 100644 --- a/inc/external/acl/acl_op_compiler.h +++ b/inc/external/acl/acl_op_compiler.h @@ -24,28 +24,22 @@ extern "C" { #endif -typedef enum aclCompileType { - ACL_COMPILE_SYS, - ACL_COMPILE_UNREGISTERED -} aclopCompileType; +typedef enum aclCompileType { ACL_COMPILE_SYS, ACL_COMPILE_UNREGISTERED } aclopCompileType; typedef enum { - ACL_PRECISION_MODE, - ACL_AICORE_NUM, - ACL_AUTO_TUNE_MODE, - ACL_OP_SELECT_IMPL_MODE, - ACL_OPTYPELIST_FOR_IMPLMODE, - ACL_OP_DEBUG_LEVEL, - ACL_DEBUG_DIR, - ACL_OP_COMPILER_CACHE_MODE, - ACL_OP_COMPILER_CACHE_DIR, - ACL_OP_PERFORMANCE_MODE + ACL_PRECISION_MODE, + ACL_AICORE_NUM, + ACL_AUTO_TUNE_MODE, + ACL_OP_SELECT_IMPL_MODE, + ACL_OPTYPELIST_FOR_IMPLMODE, + ACL_OP_DEBUG_LEVEL, + ACL_DEBUG_DIR, + ACL_OP_COMPILER_CACHE_MODE, + ACL_OP_COMPILER_CACHE_DIR, + ACL_OP_PERFORMANCE_MODE } aclCompileOpt; -typedef enum aclCompileFlag { - ACL_OP_COMPILE_DEFAULT, - ACL_OP_COMPILE_FUZZ -} aclOpCompileFlag; +typedef enum aclCompileFlag { ACL_OP_COMPILE_DEFAULT, ACL_OP_COMPILE_FUZZ } aclOpCompileFlag; /** * @ingroup AscendCL @@ -65,15 +59,10 @@ typedef enum aclCompileFlag { * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, - int numInputs, - const aclTensorDesc *const inputDesc[], - int numOutputs, - const aclTensorDesc *const outputDesc[], - const aclopAttr *attr, - aclopEngineType engineType, - aclopCompileType compileFlag, - const char *opPath); +ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], + int numOutputs, const aclTensorDesc *const outputDesc[], + const aclopAttr *attr, aclopEngineType engineType, + aclopCompileType compileFlag, const char *opPath); /** * @ingroup AscendCL @@ -96,11 +85,10 @@ ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCompileAndExecute(const char *opType, - int numInputs, const aclTensorDesc *const inputDesc[], const aclDataBuffer *const inputs[], - int numOutputs, const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], - const aclopAttr *attr, aclopEngineType engineType, aclopCompileType compileFlag, - const char *opPath, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopCompileAndExecute( + const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], const aclDataBuffer *const inputs[], + int numOutputs, const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], const aclopAttr *attr, + aclopEngineType engineType, aclopCompileType compileFlag, const char *opPath, aclrtStream stream); /** * @ingroup AscendCL @@ -130,4 +118,4 @@ ACL_FUNC_VISIBILITY aclError aclopSetCompileFlag(aclOpCompileFlag flag); } #endif -#endif // INC_EXTERNAL_ACL_ACL_OP_COMPILER_H_ +#endif // INC_EXTERNAL_ACL_ACL_OP_COMPILER_H_ diff --git a/inc/external/acl/acl_prof.h b/inc/external/acl/acl_prof.h index 93bc3a9b..3784d8c6 100644 --- a/inc/external/acl/acl_prof.h +++ b/inc/external/acl/acl_prof.h @@ -23,24 +23,24 @@ extern "C" { #endif -#define ACL_PROF_ACL_API 0x0001 -#define ACL_PROF_TASK_TIME 0x0002 -#define ACL_PROF_AICORE_METRICS 0x0004 -#define ACL_PROF_AICPU 0x0008 +#define ACL_PROF_ACL_API 0x0001 +#define ACL_PROF_TASK_TIME 0x0002 +#define ACL_PROF_AICORE_METRICS 0x0004 +#define ACL_PROF_AICPU 0x0008 /** * @deprecated please use aclprofGetOpTypeLen and aclprofGetOpTNameLen instead */ -#define ACL_PROF_MAX_OP_NAME_LEN 257 -#define ACL_PROF_MAX_OP_TYPE_LEN 65 +#define ACL_PROF_MAX_OP_NAME_LEN 257 +#define ACL_PROF_MAX_OP_TYPE_LEN 65 typedef enum { - ACL_AICORE_ARITHMETIC_UTILIZATION = 0, - ACL_AICORE_PIPE_UTILIZATION = 1, - ACL_AICORE_MEMORY_BANDWIDTH = 2, - ACL_AICORE_L0B_AND_WIDTH = 3, - ACL_AICORE_RESOURCE_CONFLICT_RATIO = 4, - ACL_AICORE_NONE = 0xFF + ACL_AICORE_ARITHMETIC_UTILIZATION = 0, + ACL_AICORE_PIPE_UTILIZATION = 1, + ACL_AICORE_MEMORY_BANDWIDTH = 2, + ACL_AICORE_L0B_AND_WIDTH = 3, + ACL_AICORE_RESOURCE_CONFLICT_RATIO = 4, + ACL_AICORE_NONE = 0xFF } aclprofAicoreMetrics; typedef struct aclprofConfig aclprofConfig; @@ -101,7 +101,8 @@ ACL_FUNC_VISIBILITY aclError aclprofStart(const aclprofConfig *profilerConfig); * @see aclprofDestroyConfig */ ACL_FUNC_VISIBILITY aclprofConfig *aclprofCreateConfig(uint32_t *deviceIdList, uint32_t deviceNums, - aclprofAicoreMetrics aicoreMetrics, aclprofAicoreEvents *aicoreEvents, uint64_t dataTypeConfig); + aclprofAicoreMetrics aicoreMetrics, + aclprofAicoreEvents *aicoreEvents, uint64_t dataTypeConfig); /** * @ingroup AscendCL @@ -141,8 +142,7 @@ ACL_FUNC_VISIBILITY aclError aclprofStop(const aclprofConfig *profilerConfig); * * @see aclprofModelUnSubscribe */ -ACL_FUNC_VISIBILITY aclError aclprofModelSubscribe(uint32_t modelId, - const aclprofSubscribeConfig *profSubscribeConfig); +ACL_FUNC_VISIBILITY aclError aclprofModelSubscribe(uint32_t modelId, const aclprofSubscribeConfig *profSubscribeConfig); /** * @ingroup AscendCL @@ -170,7 +170,7 @@ ACL_FUNC_VISIBILITY aclError aclprofModelUnSubscribe(uint32_t modelId); * @see aclprofDestroySubscribeConfig */ ACL_FUNC_VISIBILITY aclprofSubscribeConfig *aclprofCreateSubscribeConfig(int8_t timeInfoSwitch, - aclprofAicoreMetrics aicoreMetrics, void *fd); + aclprofAicoreMetrics aicoreMetrics, void *fd); /** * @ingroup AscendCL @@ -222,7 +222,7 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpNum(const void *opInfo, size_t opInfoLe * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclprofGetOpTypeLen(const void *opInfo, size_t opInfoLen, uint32_t index, - size_t *opTypeLen); + size_t *opTypeLen); /** * @ingroup AscendCL @@ -237,8 +237,8 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpTypeLen(const void *opInfo, size_t opIn * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoLen, uint32_t index, - char *opType, size_t opTypeLen); +ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoLen, uint32_t index, char *opType, + size_t opTypeLen); /** * @ingroup AscendCL @@ -253,7 +253,7 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoL * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclprofGetOpNameLen(const void *opInfo, size_t opInfoLen, uint32_t index, - size_t *opNameLen); + size_t *opNameLen); /** * @ingroup AscendCL @@ -268,8 +268,8 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpNameLen(const void *opInfo, size_t opIn * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclprofGetOpName(const void *opInfo, size_t opInfoLen, uint32_t index, - char *opName, size_t opNameLen); +ACL_FUNC_VISIBILITY aclError aclprofGetOpName(const void *opInfo, size_t opInfoLen, uint32_t index, char *opName, + size_t opNameLen); /** * @ingroup AscendCL @@ -326,4 +326,4 @@ ACL_FUNC_VISIBILITY size_t aclprofGetModelId(const void *opInfo, size_t opInfoLe } #endif -#endif // INC_EXTERNAL_ACL_PROF_H_ +#endif // INC_EXTERNAL_ACL_PROF_H_ diff --git a/inc/external/acl/acl_rt.h b/inc/external/acl/acl_rt.h index 3c777ecc..5ee70724 100644 --- a/inc/external/acl/acl_rt.h +++ b/inc/external/acl/acl_rt.h @@ -28,63 +28,63 @@ extern "C" { #define ACL_EVENT_TIME_LINE 0x00000008u typedef enum aclrtRunMode { - ACL_DEVICE, - ACL_HOST, + ACL_DEVICE, + ACL_HOST, } aclrtRunMode; typedef enum aclrtTsId { - ACL_TS_ID_AICORE = 0, - ACL_TS_ID_AIVECTOR = 1, - ACL_TS_ID_RESERVED = 2, + ACL_TS_ID_AICORE = 0, + ACL_TS_ID_AIVECTOR = 1, + ACL_TS_ID_RESERVED = 2, } aclrtTsId; typedef enum aclrtEventStatus { - ACL_EVENT_STATUS_COMPLETE = 0, - ACL_EVENT_STATUS_NOT_READY = 1, - ACL_EVENT_STATUS_RESERVED = 2, + ACL_EVENT_STATUS_COMPLETE = 0, + ACL_EVENT_STATUS_NOT_READY = 1, + ACL_EVENT_STATUS_RESERVED = 2, } aclrtEventStatus; typedef enum aclrtCallbackBlockType { - ACL_CALLBACK_NO_BLOCK, - ACL_CALLBACK_BLOCK, + ACL_CALLBACK_NO_BLOCK, + ACL_CALLBACK_BLOCK, } aclrtCallbackBlockType; typedef enum aclrtMemcpyKind { - ACL_MEMCPY_HOST_TO_HOST, - ACL_MEMCPY_HOST_TO_DEVICE, - ACL_MEMCPY_DEVICE_TO_HOST, - ACL_MEMCPY_DEVICE_TO_DEVICE, + ACL_MEMCPY_HOST_TO_HOST, + ACL_MEMCPY_HOST_TO_DEVICE, + ACL_MEMCPY_DEVICE_TO_HOST, + ACL_MEMCPY_DEVICE_TO_DEVICE, } aclrtMemcpyKind; typedef enum aclrtMemMallocPolicy { - ACL_MEM_MALLOC_HUGE_FIRST, - ACL_MEM_MALLOC_HUGE_ONLY, - ACL_MEM_MALLOC_NORMAL_ONLY, - ACL_MEM_MALLOC_HUGE_FIRST_P2P, - ACL_MEM_MALLOC_HUGE_ONLY_P2P, - ACL_MEM_MALLOC_NORMAL_ONLY_P2P, + ACL_MEM_MALLOC_HUGE_FIRST, + ACL_MEM_MALLOC_HUGE_ONLY, + ACL_MEM_MALLOC_NORMAL_ONLY, + ACL_MEM_MALLOC_HUGE_FIRST_P2P, + ACL_MEM_MALLOC_HUGE_ONLY_P2P, + ACL_MEM_MALLOC_NORMAL_ONLY_P2P, } aclrtMemMallocPolicy; typedef enum aclrtMemAttr { - ACL_DDR_MEM, - ACL_HBM_MEM, - ACL_DDR_MEM_HUGE, - ACL_DDR_MEM_NORMAL, - ACL_HBM_MEM_HUGE, - ACL_HBM_MEM_NORMAL, - ACL_DDR_MEM_P2P_HUGE, - ACL_DDR_MEM_P2P_NORMAL, - ACL_HBM_MEM_P2P_HUGE, - ACL_HBM_MEM_P2P_NORMAL, + ACL_DDR_MEM, + ACL_HBM_MEM, + ACL_DDR_MEM_HUGE, + ACL_DDR_MEM_NORMAL, + ACL_HBM_MEM_HUGE, + ACL_HBM_MEM_NORMAL, + ACL_DDR_MEM_P2P_HUGE, + ACL_DDR_MEM_P2P_NORMAL, + ACL_HBM_MEM_P2P_HUGE, + ACL_HBM_MEM_P2P_NORMAL, } aclrtMemAttr; typedef enum aclrtGroupAttr { - ACL_GROUP_AICORE_INT, - ACL_GROUP_AIV_INT, - ACL_GROUP_AIC_INT, - ACL_GROUP_SDMANUM_INT, - ACL_GROUP_ASQNUM_INT, - ACL_GROUP_GROUPID_INT + ACL_GROUP_AICORE_INT, + ACL_GROUP_AIV_INT, + ACL_GROUP_AIC_INT, + ACL_GROUP_SDMANUM_INT, + ACL_GROUP_ASQNUM_INT, + ACL_GROUP_GROUPID_INT } aclrtGroupAttr; typedef struct tagRtGroupInfo aclrtGroupInfo; @@ -487,7 +487,7 @@ ACL_FUNC_VISIBILITY aclError aclrtRecordEvent(aclrtEvent event, aclrtStream stre */ ACL_FUNC_VISIBILITY aclError aclrtResetEvent(aclrtEvent event, aclrtStream stream); - /** +/** * @ingroup AscendCL * @brief Queries an event's status * @@ -549,9 +549,7 @@ ACL_FUNC_VISIBILITY aclError aclrtEventElapsedTime(float *ms, aclrtEvent start, * * @see aclrtFree | acldvppMalloc | aclrtMallocCached */ -ACL_FUNC_VISIBILITY aclError aclrtMalloc(void **devPtr, - size_t size, - aclrtMemMallocPolicy policy); +ACL_FUNC_VISIBILITY aclError aclrtMalloc(void **devPtr, size_t size, aclrtMemMallocPolicy policy); /** * @ingroup AscendCL @@ -574,9 +572,7 @@ ACL_FUNC_VISIBILITY aclError aclrtMalloc(void **devPtr, * * @see aclrtFree | aclrtMalloc */ -ACL_FUNC_VISIBILITY aclError aclrtMallocCached(void **devPtr, - size_t size, - aclrtMemMallocPolicy policy); +ACL_FUNC_VISIBILITY aclError aclrtMallocCached(void **devPtr, size_t size, aclrtMemMallocPolicy policy); /** * @ingroup AscendCL @@ -667,10 +663,7 @@ ACL_FUNC_VISIBILITY aclError aclrtFreeHost(void *hostPtr); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclrtMemcpy(void *dst, - size_t destMax, - const void *src, - size_t count, +ACL_FUNC_VISIBILITY aclError aclrtMemcpy(void *dst, size_t destMax, const void *src, size_t count, aclrtMemcpyKind kind); /** @@ -717,38 +710,31 @@ ACL_FUNC_VISIBILITY aclError aclrtMemset(void *devPtr, size_t maxCount, int32_t * * @see aclrtSynchronizeStream */ -ACL_FUNC_VISIBILITY aclError aclrtMemcpyAsync(void *dst, - size_t destMax, - const void *src, - size_t count, - aclrtMemcpyKind kind, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclrtMemcpyAsync(void *dst, size_t destMax, const void *src, size_t count, + aclrtMemcpyKind kind, aclrtStream stream); /** -* @ingroup AscendCL -* @brief Asynchronous initialize memory -* and set contents of memory to specified value async -* -* @par Function + * @ingroup AscendCL + * @brief Asynchronous initialize memory + * and set contents of memory to specified value async + * + * @par Function * The memory to be initialized is on the Host or device side, * and the system determines whether * it is host or device according to the address * -* @param devPtr [IN] destination address pointer -* @param maxCount [IN] Max length of destination address memory -* @param value [IN] set value -* @param count [IN] the number of byte to set -* @param stream [IN] asynchronized task stream -* -* @retval ACL_SUCCESS The function is successfully executed. -* @retval OtherValues Failure -* -* @see aclrtSynchronizeStream -*/ -ACL_FUNC_VISIBILITY aclError aclrtMemsetAsync(void *devPtr, - size_t maxCount, - int32_t value, - size_t count, + * @param devPtr [IN] destination address pointer + * @param maxCount [IN] Max length of destination address memory + * @param value [IN] set value + * @param count [IN] the number of byte to set + * @param stream [IN] asynchronized task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtSynchronizeStream + */ +ACL_FUNC_VISIBILITY aclError aclrtMemsetAsync(void *devPtr, size_t maxCount, int32_t value, size_t count, aclrtStream stream); /** @@ -894,11 +880,8 @@ ACL_FUNC_VISIBILITY aclError aclrtGetAllGroupInfo(aclrtGroupInfo *groupInfo); * * @see aclrtGetGroupCount | aclrtGetAllGroupInfo */ -ACL_FUNC_VISIBILITY aclError aclrtGetGroupInfoDetail(const aclrtGroupInfo *groupInfo, - int32_t groupIndex, - aclrtGroupAttr attr, - void *attrValue, - size_t valueLen, +ACL_FUNC_VISIBILITY aclError aclrtGetGroupInfoDetail(const aclrtGroupInfo *groupInfo, int32_t groupIndex, + aclrtGroupAttr attr, void *attrValue, size_t valueLen, size_t *paramRetSize); /** @@ -972,5 +955,4 @@ ACL_FUNC_VISIBILITY aclError aclrtSetOpWaitTimeout(uint32_t timeout); } #endif -#endif // INC_EXTERNAL_ACL_ACL_RT_H_ - +#endif // INC_EXTERNAL_ACL_ACL_RT_H_ diff --git a/inc/external/acl/acl_tdt.h b/inc/external/acl/acl_tdt.h index 61995121..c357518d 100644 --- a/inc/external/acl/acl_tdt.h +++ b/inc/external/acl/acl_tdt.h @@ -24,10 +24,10 @@ extern "C" { #endif enum acltdtTensorType { - ACL_TENSOR_DATA_UNDEFINED = -1, - ACL_TENSOR_DATA_TENSOR, - ACL_TENSOR_DATA_END_OF_SEQUENCE, - ACL_TENSOR_DATA_ABNORMAL + ACL_TENSOR_DATA_UNDEFINED = -1, + ACL_TENSOR_DATA_TENSOR, + ACL_TENSOR_DATA_END_OF_SEQUENCE, + ACL_TENSOR_DATA_ABNORMAL }; typedef struct acltdtDataItem acltdtDataItem; @@ -64,7 +64,7 @@ ACL_FUNC_VISIBILITY aclDataType acltdtGetDataTypeFromItem(const acltdtDataItem * * * @retval null for failed * @retval OtherValues success -*/ + */ ACL_FUNC_VISIBILITY void *acltdtGetDataAddrFromItem(const acltdtDataItem *dataItem); /** @@ -75,7 +75,7 @@ ACL_FUNC_VISIBILITY void *acltdtGetDataAddrFromItem(const acltdtDataItem *dataIt * * @retval 0 for failed * @retval OtherValues success -*/ + */ ACL_FUNC_VISIBILITY size_t acltdtGetDataSizeFromItem(const acltdtDataItem *dataItem); /** @@ -86,7 +86,7 @@ ACL_FUNC_VISIBILITY size_t acltdtGetDataSizeFromItem(const acltdtDataItem *dataI * * @retval 0 for failed * @retval OtherValues success -*/ + */ ACL_FUNC_VISIBILITY size_t acltdtGetDimNumFromItem(const acltdtDataItem *dataItem); /** @@ -118,12 +118,8 @@ ACL_FUNC_VISIBILITY aclError acltdtGetDimsFromItem(const acltdtDataItem *dataIte * * @see acltdtDestroyDataItem */ -ACL_FUNC_VISIBILITY acltdtDataItem *acltdtCreateDataItem(acltdtTensorType tdtType, - const int64_t *dims, - size_t dimNum, - aclDataType dataType, - void *data, - size_t size); +ACL_FUNC_VISIBILITY acltdtDataItem *acltdtCreateDataItem(acltdtTensorType tdtType, const int64_t *dims, size_t dimNum, + aclDataType dataType, void *data, size_t size); /** * @ingroup AscendCL @@ -254,8 +250,7 @@ ACL_FUNC_VISIBILITY aclError acltdtDestroyChannel(acltdtChannelHandle *handle); * * @see acltdtReceiveTensor */ -ACL_FUNC_VISIBILITY aclError acltdtSendTensor(const acltdtChannelHandle *handle, - const acltdtDataset *dataset, +ACL_FUNC_VISIBILITY aclError acltdtSendTensor(const acltdtChannelHandle *handle, const acltdtDataset *dataset, int32_t timeout); /** @@ -271,13 +266,11 @@ ACL_FUNC_VISIBILITY aclError acltdtSendTensor(const acltdtChannelHandle *handle, * * @see acltdtSendTensor */ -ACL_FUNC_VISIBILITY aclError acltdtReceiveTensor(const acltdtChannelHandle *handle, - acltdtDataset *dataset, +ACL_FUNC_VISIBILITY aclError acltdtReceiveTensor(const acltdtChannelHandle *handle, acltdtDataset *dataset, int32_t timeout); #ifdef __cplusplus } #endif -#endif //INC_EXTERNAL_ACL_ACL_TDT_H_ - +#endif // INC_EXTERNAL_ACL_ACL_TDT_H_ diff --git a/inc/external/acl/error_codes/rt_error_codes.h b/inc/external/acl/error_codes/rt_error_codes.h index 02a357fc..437a5544 100644 --- a/inc/external/acl/error_codes/rt_error_codes.h +++ b/inc/external/acl/error_codes/rt_error_codes.h @@ -23,81 +23,81 @@ extern "C" { #endif -static const int32_t ACL_RT_SUCCESS = 0; // success +static const int32_t ACL_RT_SUCCESS = 0; // success -static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid -static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id -static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null -static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context -static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context -static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal -static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned -static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed -static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed -static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream -static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread -static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set -static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create -static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream -static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type -static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle -static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type +static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid +static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id +static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null +static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context +static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context +static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal +static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned +static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed +static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed +static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream +static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread +static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set +static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create +static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream +static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type +static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle +static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type -static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support -static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error -static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error -static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow -static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device -static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail -static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission -static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource -static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource -static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource -static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource +static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support +static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error +static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error +static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow +static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device +static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail +static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission +static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource +static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource +static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource +static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource -static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error -static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error -static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error -static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect +static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error +static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error +static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect #ifdef __cplusplus } #endif -#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ +#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/inc/external/acl/ops/acl_cblas.h b/inc/external/acl/ops/acl_cblas.h index a2bd8c61..3d81eb2b 100644 --- a/inc/external/acl/ops/acl_cblas.h +++ b/inc/external/acl/ops/acl_cblas.h @@ -23,17 +23,9 @@ extern "C" { #endif -typedef enum aclTransType { - ACL_TRANS_N, - ACL_TRANS_T, - ACL_TRANS_NZ, - ACL_TRANS_NZ_T -} aclTransType; +typedef enum aclTransType { ACL_TRANS_N, ACL_TRANS_T, ACL_TRANS_NZ, ACL_TRANS_NZ_T } aclTransType; -typedef enum aclComputeType { - ACL_COMPUTE_HIGH_PRECISION, - ACL_COMPUTE_LOW_PRECISION -} aclComputeType; +typedef enum aclComputeType { ACL_COMPUTE_HIGH_PRECISION, ACL_COMPUTE_LOW_PRECISION } aclComputeType; /** * @ingroup AscendCL @@ -61,12 +53,11 @@ typedef enum aclComputeType { * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure -*/ -ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, - const void *alpha, const void *a, int lda, aclDataType dataTypeA, - const void *x, int incx, aclDataType dataTypeX, - const void *beta, void *y, int incy, aclDataType dataTypeY, - aclComputeType type, aclrtStream stream); + */ +ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, const void *alpha, const void *a, int lda, + aclDataType dataTypeA, const void *x, int incx, aclDataType dataTypeX, + const void *beta, void *y, int incy, aclDataType dataTypeY, + aclComputeType type, aclrtStream stream); /** * @ingroup AscendCL @@ -83,15 +74,10 @@ ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure -*/ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, - int m, - int n, - aclDataType dataTypeA, - aclDataType dataTypeX, - aclDataType dataTypeY, - aclComputeType type, - aclopHandle **handle); + */ +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, int m, int n, aclDataType dataTypeA, + aclDataType dataTypeX, aclDataType dataTypeY, + aclComputeType type, aclopHandle **handle); /** * @ingroup AscendCL @@ -115,18 +101,9 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, - int m, - int n, - const aclFloat16 *alpha, - const aclFloat16 *a, - int lda, - const aclFloat16 *x, - int incx, - const aclFloat16 *beta, - aclFloat16 *y, - int incy, - aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, int m, int n, const aclFloat16 *alpha, + const aclFloat16 *a, int lda, const aclFloat16 *x, int incx, + const aclFloat16 *beta, aclFloat16 *y, int incy, aclComputeType type, aclrtStream stream); /** @@ -142,10 +119,7 @@ ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, - int m, - int n, - aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, int m, int n, aclComputeType type, aclopHandle **handle); /** @@ -171,19 +145,9 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, - int m, - int n, - const int32_t *alpha, - const int8_t *a, - int lda, - const int8_t *x, - int incx, - const int32_t *beta, - int32_t *y, - int incy, - aclComputeType type, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, int m, int n, const int32_t *alpha, const int8_t *a, + int lda, const int8_t *x, int incx, const int32_t *beta, int32_t *y, + int incy, aclComputeType type, aclrtStream stream); /** * @ingroup AscendCL @@ -198,10 +162,7 @@ ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, - int m, - int n, - aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, int m, int n, aclComputeType type, aclopHandle **handle); /** @@ -233,26 +194,11 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, - aclTransType transB, - aclTransType transC, - int m, - int n, - int k, - const void *alpha, - const void *matrixA, - int lda, - aclDataType dataTypeA, - const void *matrixB, - int ldb, - aclDataType dataTypeB, - const void *beta, - void *matrixC, - int ldc, - aclDataType dataTypeC, - aclComputeType type, - aclrtStream stream); - +ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, + int k, const void *alpha, const void *matrixA, int lda, + aclDataType dataTypeA, const void *matrixB, int ldb, aclDataType dataTypeB, + const void *beta, void *matrixC, int ldc, aclDataType dataTypeC, + aclComputeType type, aclrtStream stream); /** * @ingroup AscendCL @@ -274,18 +220,10 @@ ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, - aclTransType transB, - aclTransType transC, - int m, - int n, - int k, - aclDataType dataTypeA, - aclDataType dataTypeB, - aclDataType dataTypeC, - aclComputeType type, - aclopHandle **handle); - +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, aclTransType transB, aclTransType transC, + int m, int n, int k, aclDataType dataTypeA, + aclDataType dataTypeB, aclDataType dataTypeC, + aclComputeType type, aclopHandle **handle); /** * @ingroup AscendCL @@ -313,22 +251,10 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, - aclTransType transB, - aclTransType transC, - int m, - int n, - int k, - const aclFloat16 *alpha, - const aclFloat16 *matrixA, - int lda, - const aclFloat16 *matrixB, - int ldb, - const aclFloat16 *beta, - aclFloat16 *matrixC, - int ldc, - aclComputeType type, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, + int k, const aclFloat16 *alpha, const aclFloat16 *matrixA, int lda, + const aclFloat16 *matrixB, int ldb, const aclFloat16 *beta, + aclFloat16 *matrixC, int ldc, aclComputeType type, aclrtStream stream); /** * @ingroup AscendCL @@ -346,13 +272,8 @@ ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, - aclTransType transB, - aclTransType transC, - int m, - int n, - int k, - aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, aclTransType transB, aclTransType transC, + int m, int n, int k, aclComputeType type, aclopHandle **handle); /** @@ -381,23 +302,10 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, - aclTransType transB, - aclTransType transC, - int m, - int n, - int k, - const int32_t *alpha, - const int8_t *matrixA, - int lda, - const int8_t *matrixB, - int ldb, - const int32_t *beta, - int32_t *matrixC, - int ldc, - aclComputeType type, - aclrtStream stream); - +ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, + int k, const int32_t *alpha, const int8_t *matrixA, int lda, + const int8_t *matrixB, int ldb, const int32_t *beta, int32_t *matrixC, + int ldc, aclComputeType type, aclrtStream stream); /** * @ingroup AscendCL @@ -415,17 +323,12 @@ ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemm(aclTransType transA, - aclTransType transB, - aclTransType transC, - int m, - int n, - int k, - aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemm(aclTransType transA, aclTransType transB, aclTransType transC, + int m, int n, int k, aclComputeType type, aclopHandle **handle); #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_CBLAS_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_CBLAS_H_ diff --git a/inc/external/acl/ops/acl_dvpp.h b/inc/external/acl/ops/acl_dvpp.h index 90dc70e8..dcaa3936 100644 --- a/inc/external/acl/ops/acl_dvpp.h +++ b/inc/external/acl/ops/acl_dvpp.h @@ -53,123 +53,109 @@ typedef void (*aclvencCallback)(acldvppPicDesc *input, acldvppStreamDesc *output // Supported Pixel Format enum acldvppPixelFormat { - PIXEL_FORMAT_YUV_400 = 0, // 0 - PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1, // 1 - PIXEL_FORMAT_YVU_SEMIPLANAR_420 = 2, // 2 - PIXEL_FORMAT_YUV_SEMIPLANAR_422 = 3, // 3 - PIXEL_FORMAT_YVU_SEMIPLANAR_422 = 4, // 4 - PIXEL_FORMAT_YUV_SEMIPLANAR_444 = 5, // 5 - PIXEL_FORMAT_YVU_SEMIPLANAR_444 = 6, // 6 - PIXEL_FORMAT_YUYV_PACKED_422 = 7, // 7 - PIXEL_FORMAT_UYVY_PACKED_422 = 8, // 8 - PIXEL_FORMAT_YVYU_PACKED_422 = 9, // 9 - PIXEL_FORMAT_VYUY_PACKED_422 = 10, // 10 - PIXEL_FORMAT_YUV_PACKED_444 = 11, // 11 - PIXEL_FORMAT_RGB_888 = 12, // 12 - PIXEL_FORMAT_BGR_888 = 13, // 13 - PIXEL_FORMAT_ARGB_8888 = 14, // 14 - PIXEL_FORMAT_ABGR_8888 = 15, // 15 - PIXEL_FORMAT_RGBA_8888 = 16, // 16 - PIXEL_FORMAT_BGRA_8888 = 17, // 17 - PIXEL_FORMAT_YUV_SEMI_PLANNER_420_10BIT = 18, // 18 - PIXEL_FORMAT_YVU_SEMI_PLANNER_420_10BIT = 19, // 19 - PIXEL_FORMAT_YVU_PLANAR_420 = 20, // 20 - PIXEL_FORMAT_YVU_PLANAR_422, - PIXEL_FORMAT_YVU_PLANAR_444, - PIXEL_FORMAT_RGB_444 = 23, - PIXEL_FORMAT_BGR_444, - PIXEL_FORMAT_ARGB_4444, - PIXEL_FORMAT_ABGR_4444, - PIXEL_FORMAT_RGBA_4444, - PIXEL_FORMAT_BGRA_4444, - PIXEL_FORMAT_RGB_555, - PIXEL_FORMAT_BGR_555, - PIXEL_FORMAT_RGB_565, - PIXEL_FORMAT_BGR_565, - PIXEL_FORMAT_ARGB_1555, - PIXEL_FORMAT_ABGR_1555, - PIXEL_FORMAT_RGBA_1555, - PIXEL_FORMAT_BGRA_1555, - PIXEL_FORMAT_ARGB_8565, - PIXEL_FORMAT_ABGR_8565, - PIXEL_FORMAT_RGBA_8565, - PIXEL_FORMAT_BGRA_8565, - PIXEL_FORMAT_RGB_BAYER_8BPP = 50, - PIXEL_FORMAT_RGB_BAYER_10BPP, - PIXEL_FORMAT_RGB_BAYER_12BPP, - PIXEL_FORMAT_RGB_BAYER_14BPP, - PIXEL_FORMAT_RGB_BAYER_16BPP, - PIXEL_FORMAT_BGR_888_PLANAR = 70, - PIXEL_FORMAT_HSV_888_PACKAGE, - PIXEL_FORMAT_HSV_888_PLANAR, - PIXEL_FORMAT_LAB_888_PACKAGE, - PIXEL_FORMAT_LAB_888_PLANAR, - PIXEL_FORMAT_S8C1, - PIXEL_FORMAT_S8C2_PACKAGE, - PIXEL_FORMAT_S8C2_PLANAR, - PIXEL_FORMAT_S16C1, - PIXEL_FORMAT_U8C1, - PIXEL_FORMAT_U16C1, - PIXEL_FORMAT_S32C1, - PIXEL_FORMAT_U32C1, - PIXEL_FORMAT_U64C1, - PIXEL_FORMAT_S64C1, - PIXEL_FORMAT_YUV_SEMIPLANAR_440 = 1000, - PIXEL_FORMAT_YVU_SEMIPLANAR_440, - PIXEL_FORMAT_FLOAT32, - PIXEL_FORMAT_BUTT, - PIXEL_FORMAT_UNKNOWN = 10000 + PIXEL_FORMAT_YUV_400 = 0, // 0 + PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1, // 1 + PIXEL_FORMAT_YVU_SEMIPLANAR_420 = 2, // 2 + PIXEL_FORMAT_YUV_SEMIPLANAR_422 = 3, // 3 + PIXEL_FORMAT_YVU_SEMIPLANAR_422 = 4, // 4 + PIXEL_FORMAT_YUV_SEMIPLANAR_444 = 5, // 5 + PIXEL_FORMAT_YVU_SEMIPLANAR_444 = 6, // 6 + PIXEL_FORMAT_YUYV_PACKED_422 = 7, // 7 + PIXEL_FORMAT_UYVY_PACKED_422 = 8, // 8 + PIXEL_FORMAT_YVYU_PACKED_422 = 9, // 9 + PIXEL_FORMAT_VYUY_PACKED_422 = 10, // 10 + PIXEL_FORMAT_YUV_PACKED_444 = 11, // 11 + PIXEL_FORMAT_RGB_888 = 12, // 12 + PIXEL_FORMAT_BGR_888 = 13, // 13 + PIXEL_FORMAT_ARGB_8888 = 14, // 14 + PIXEL_FORMAT_ABGR_8888 = 15, // 15 + PIXEL_FORMAT_RGBA_8888 = 16, // 16 + PIXEL_FORMAT_BGRA_8888 = 17, // 17 + PIXEL_FORMAT_YUV_SEMI_PLANNER_420_10BIT = 18, // 18 + PIXEL_FORMAT_YVU_SEMI_PLANNER_420_10BIT = 19, // 19 + PIXEL_FORMAT_YVU_PLANAR_420 = 20, // 20 + PIXEL_FORMAT_YVU_PLANAR_422, + PIXEL_FORMAT_YVU_PLANAR_444, + PIXEL_FORMAT_RGB_444 = 23, + PIXEL_FORMAT_BGR_444, + PIXEL_FORMAT_ARGB_4444, + PIXEL_FORMAT_ABGR_4444, + PIXEL_FORMAT_RGBA_4444, + PIXEL_FORMAT_BGRA_4444, + PIXEL_FORMAT_RGB_555, + PIXEL_FORMAT_BGR_555, + PIXEL_FORMAT_RGB_565, + PIXEL_FORMAT_BGR_565, + PIXEL_FORMAT_ARGB_1555, + PIXEL_FORMAT_ABGR_1555, + PIXEL_FORMAT_RGBA_1555, + PIXEL_FORMAT_BGRA_1555, + PIXEL_FORMAT_ARGB_8565, + PIXEL_FORMAT_ABGR_8565, + PIXEL_FORMAT_RGBA_8565, + PIXEL_FORMAT_BGRA_8565, + PIXEL_FORMAT_RGB_BAYER_8BPP = 50, + PIXEL_FORMAT_RGB_BAYER_10BPP, + PIXEL_FORMAT_RGB_BAYER_12BPP, + PIXEL_FORMAT_RGB_BAYER_14BPP, + PIXEL_FORMAT_RGB_BAYER_16BPP, + PIXEL_FORMAT_BGR_888_PLANAR = 70, + PIXEL_FORMAT_HSV_888_PACKAGE, + PIXEL_FORMAT_HSV_888_PLANAR, + PIXEL_FORMAT_LAB_888_PACKAGE, + PIXEL_FORMAT_LAB_888_PLANAR, + PIXEL_FORMAT_S8C1, + PIXEL_FORMAT_S8C2_PACKAGE, + PIXEL_FORMAT_S8C2_PLANAR, + PIXEL_FORMAT_S16C1, + PIXEL_FORMAT_U8C1, + PIXEL_FORMAT_U16C1, + PIXEL_FORMAT_S32C1, + PIXEL_FORMAT_U32C1, + PIXEL_FORMAT_U64C1, + PIXEL_FORMAT_S64C1, + PIXEL_FORMAT_YUV_SEMIPLANAR_440 = 1000, + PIXEL_FORMAT_YVU_SEMIPLANAR_440, + PIXEL_FORMAT_FLOAT32, + PIXEL_FORMAT_BUTT, + PIXEL_FORMAT_UNKNOWN = 10000 }; // Stream Format -enum acldvppStreamFormat { - H265_MAIN_LEVEL = 0, - H264_BASELINE_LEVEL, - H264_MAIN_LEVEL, - H264_HIGH_LEVEL -}; +enum acldvppStreamFormat { H265_MAIN_LEVEL = 0, H264_BASELINE_LEVEL, H264_MAIN_LEVEL, H264_HIGH_LEVEL }; // Supported Channel Mode -enum acldvppChannelMode { - DVPP_CHNMODE_VPC = 1, - DVPP_CHNMODE_JPEGD = 2, - DVPP_CHNMODE_JPEGE = 4 -}; +enum acldvppChannelMode { DVPP_CHNMODE_VPC = 1, DVPP_CHNMODE_JPEGD = 2, DVPP_CHNMODE_JPEGE = 4 }; // Supported Border Type -enum acldvppBorderType { - BORDER_CONSTANT = 0, - BORDER_REPLICATE, - BORDER_REFLECT, - BORDER_REFLECT_101 -}; +enum acldvppBorderType { BORDER_CONSTANT = 0, BORDER_REPLICATE, BORDER_REFLECT, BORDER_REFLECT_101 }; // Venc parameter type enum aclvencChannelDescParamType { - ACL_VENC_THREAD_ID_UINT64 = 0, - ACL_VENC_CALLBACK_PTR, - ACL_VENC_PIXEL_FORMAT_UINT32, - ACL_VENC_ENCODE_TYPE_UINT32, - ACL_VENC_PIC_WIDTH_UINT32, - ACL_VENC_PIC_HEIGHT_UINT32, - ACL_VENC_KEY_FRAME_INTERVAL_UINT32, - ACL_VENC_BUF_ADDR_PTR, - ACL_VENC_BUF_SIZE_UINT32, - ACL_VENC_RC_MODE_UINT32, - ACL_VENC_SRC_RATE_UINT32, - ACL_VENC_MAX_BITRATE_UINT32, - ACL_VENC_MAX_IP_PROP_UINT32 + ACL_VENC_THREAD_ID_UINT64 = 0, + ACL_VENC_CALLBACK_PTR, + ACL_VENC_PIXEL_FORMAT_UINT32, + ACL_VENC_ENCODE_TYPE_UINT32, + ACL_VENC_PIC_WIDTH_UINT32, + ACL_VENC_PIC_HEIGHT_UINT32, + ACL_VENC_KEY_FRAME_INTERVAL_UINT32, + ACL_VENC_BUF_ADDR_PTR, + ACL_VENC_BUF_SIZE_UINT32, + ACL_VENC_RC_MODE_UINT32, + ACL_VENC_SRC_RATE_UINT32, + ACL_VENC_MAX_BITRATE_UINT32, + ACL_VENC_MAX_IP_PROP_UINT32 }; // Jpeg picture format enum acldvppJpegFormat { - ACL_JPEG_CSS_444 = 0, - ACL_JPEG_CSS_422, - ACL_JPEG_CSS_420, - ACL_JPEG_CSS_GRAY, - ACL_JPEG_CSS_440, - ACL_JPEG_CSS_411, - ACL_JPEG_CSS_UNKNOWN = 1000 + ACL_JPEG_CSS_444 = 0, + ACL_JPEG_CSS_422, + ACL_JPEG_CSS_420, + ACL_JPEG_CSS_GRAY, + ACL_JPEG_CSS_440, + ACL_JPEG_CSS_411, + ACL_JPEG_CSS_UNKNOWN = 1000 }; /** @@ -523,9 +509,7 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescRetCode(const acldvppPicDesc *picD * @retval null for failed. * @retval other success */ -ACL_FUNC_VISIBILITY acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, - uint32_t right, - uint32_t top, +ACL_FUNC_VISIBILITY acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, uint32_t right, uint32_t top, uint32_t bottom); /** @@ -604,10 +588,7 @@ ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfigBottom(acldvppRoiConfig *config, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfig(acldvppRoiConfig *config, - uint32_t left, - uint32_t right, - uint32_t top, +ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfig(acldvppRoiConfig *config, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom); /** @@ -1096,7 +1077,8 @@ ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescMaxBitRate(aclvencChannelDesc * @retval ACL_SUCCESS for success, other for failure */ ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescParam(aclvencChannelDesc *channelDesc, - aclvencChannelDescParamType paramType, size_t length, const void *param); + aclvencChannelDescParamType paramType, size_t length, + const void *param); /** * @ingroup AscendCL @@ -1245,7 +1227,8 @@ ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescMaxBitRate(const aclvencChanne * @retval ACL_SUCCESS for success, other for failure */ ACL_FUNC_VISIBILITY aclError aclvencGetChannelDescParam(const aclvencChannelDesc *channelDesc, - aclvencChannelDescParamType paramType, size_t length, size_t *paramRetSize, void *param); + aclvencChannelDescParamType paramType, size_t length, + size_t *paramRetSize, void *param); /** * @ingroup AscendCL @@ -1545,10 +1528,7 @@ ACL_FUNC_VISIBILITY aclError aclvdecDestroyFrameConfig(aclvdecFrameConfig *vdecF * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, - uint32_t size, - uint32_t *width, - uint32_t *height, +ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, uint32_t size, uint32_t *width, uint32_t *height, int32_t *components); /** @@ -1565,11 +1545,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, - uint32_t size, - uint32_t *width, - uint32_t *height, - int32_t *components, +ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, uint32_t size, uint32_t *width, + uint32_t *height, int32_t *components, acldvppJpegFormat *format); /** @@ -1584,8 +1561,7 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictEncSize(const acldvppPicDesc *inputDesc, - const acldvppJpegeConfig *config, - uint32_t *size); + const acldvppJpegeConfig *config, uint32_t *size); /** * @ingroup AscendCL @@ -1599,10 +1575,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictEncSize(const acldvppPicDesc *inp * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, - uint32_t dataSize, - acldvppPixelFormat outputPixelFormat, - uint32_t *decSize); +ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, uint32_t dataSize, + acldvppPixelFormat outputPixelFormat, uint32_t *decSize); /** * @ingroup AscendCL @@ -1617,11 +1591,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, - uint32_t dataSize, - uint32_t *width, - uint32_t *height, - int32_t *components); +ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, uint32_t dataSize, uint32_t *width, + uint32_t *height, int32_t *components); /** * @ingroup AscendCL @@ -1635,10 +1606,8 @@ ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppPngPredictDecSize(const void *data, - uint32_t dataSize, - acldvppPixelFormat outputPixelFormat, - uint32_t *decSize); +ACL_FUNC_VISIBILITY aclError acldvppPngPredictDecSize(const void *data, uint32_t dataSize, + acldvppPixelFormat outputPixelFormat, uint32_t *decSize); /** * @ingroup AscendCL @@ -1702,10 +1671,8 @@ ACL_FUNC_VISIBILITY aclError acldvppDestroyChannel(acldvppChannelDesc *channelDe * @see acldvppCreateChannel | acldvppCreatePicDesc * | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - acldvppResizeConfig *resizeConfig, +ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppResizeConfig *resizeConfig, aclrtStream stream); /** @@ -1741,10 +1708,8 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDe * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - acldvppRoiConfig *cropArea, +ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, aclrtStream stream); /** @@ -1781,13 +1746,9 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizeAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - acldvppRoiConfig *cropArea, - acldvppResizeConfig *resizeConfig, - aclrtStream stream); - +ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, + acldvppResizeConfig *resizeConfig, aclrtStream stream); /** * @ingroup AscendCL @@ -1811,12 +1772,9 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizeAsync(acldvppChannelDesc *chann * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, - uint32_t *roiNums, - uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, - acldvppRoiConfig *cropAreas[], - aclrtStream stream); + acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, + uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], aclrtStream stream); /** * @ingroup AscendCL @@ -1841,13 +1799,10 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channe * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateDvppConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, - uint32_t *roiNums, - uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, + acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, + uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], - acldvppResizeConfig *resizeConfig, - aclrtStream stream); + acldvppResizeConfig *resizeConfig, aclrtStream stream); /** * @ingroup AscendCL @@ -1870,12 +1825,9 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeAsync(acldvppChannelDesc * * * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateRoiConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - acldvppRoiConfig *cropArea, - acldvppRoiConfig *pasteArea, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, + acldvppRoiConfig *pasteArea, aclrtStream stream); /** * @ingroup AscendCL @@ -1899,13 +1851,10 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *cha * * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizePasteAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - acldvppRoiConfig *cropArea, +ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizePasteAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, acldvppRoiConfig *pasteArea, - acldvppResizeConfig *resizeConfig, - aclrtStream stream); + acldvppResizeConfig *resizeConfig, aclrtStream stream); /** * @ingroup AscendCL @@ -1930,14 +1879,11 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizePasteAsync(acldvppChannelDesc * * * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig */ - ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, - uint32_t *roiNums, - uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, - acldvppRoiConfig *cropAreas[], - acldvppRoiConfig *pasteAreas[], - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *channelDesc, + acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, + uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + acldvppRoiConfig *pasteAreas[], aclrtStream stream); /** * @ingroup AscendCL @@ -1963,16 +1909,10 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizePasteAsync(acldvppChannelDesc * * * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizePasteAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, - uint32_t *roiNums, - uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, - acldvppRoiConfig *cropAreas[], - acldvppRoiConfig *pasteAreas[], - acldvppResizeConfig *resizeConfig, - aclrtStream stream); - +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizePasteAsync( + acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], acldvppRoiConfig *pasteAreas[], + acldvppResizeConfig *resizeConfig, aclrtStream stream); /** * @ingroup AscendCL @@ -2000,11 +1940,8 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizePasteAsync(acldvppChannelD * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, - const void *data, - uint32_t size, - acldvppPicDesc *outputDesc, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, + acldvppPicDesc *outputDesc, aclrtStream stream); /** * @ingroup AscendCL @@ -2022,11 +1959,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelD * * @see acldvppCreateChannel | acldvppCreateJpegeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - const void *data, - uint32_t *size, - acldvppJpegeConfig *config, +ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + const void *data, uint32_t *size, acldvppJpegeConfig *config, aclrtStream stream); /** @@ -2044,11 +1978,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelD * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppPngDecodeAsync(acldvppChannelDesc *channelDesc, - const void *data, - uint32_t size, - acldvppPicDesc *outputDesc, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppPngDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, + acldvppPicDesc *outputDesc, aclrtStream stream); /** * @ingroup AscendCL @@ -2103,11 +2034,8 @@ ACL_FUNC_VISIBILITY aclError aclvdecDestroyChannel(aclvdecChannelDesc *channelDe * * @see aclvdecCreateChannel | acldvppCreateStreamDesc | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, - acldvppStreamDesc *input, - acldvppPicDesc *output, - aclvdecFrameConfig *config, - void *userData); +ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, acldvppStreamDesc *input, + acldvppPicDesc *output, aclvdecFrameConfig *config, void *userData); /** * @ingroup AscendCL @@ -2126,10 +2054,8 @@ ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, * * @see aclvdecCreateChannel | acldvppCreateStreamDesc | acldvppCreatePicDesc | aclvdecSendFrame */ -ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channelDesc, - acldvppStreamDesc *input, - aclvdecFrameConfig *config, - void *userData); +ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channelDesc, acldvppStreamDesc *input, + aclvdecFrameConfig *config, void *userData); /** * @ingroup AscendCL @@ -2150,10 +2076,8 @@ ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channel * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, aclrtStream stream); /** * @ingroup AscendCL @@ -2175,11 +2099,8 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *cha * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - void *reserve, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, void *reserve, aclrtStream stream); /** * @ingroup AscendCL @@ -2191,8 +2112,7 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelD * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetChannelDescMode(acldvppChannelDesc *channelDesc, - uint32_t mode); +ACL_FUNC_VISIBILITY aclError acldvppSetChannelDescMode(acldvppChannelDesc *channelDesc, uint32_t mode); /** * @ingroup AscendCL @@ -2227,8 +2147,7 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetResizeConfigInterpolation(const acldvppRe * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutMode(aclvdecChannelDesc *channelDesc, - uint32_t outMode); +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutMode(aclvdecChannelDesc *channelDesc, uint32_t outMode); /** * @ingroup AscendCL @@ -2325,9 +2244,7 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetLutMapDims(const acldvppLutMap *lutMap); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, - uint32_t dim, - uint8_t **data, +ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, uint32_t dim, uint8_t **data, uint32_t *len); /** * @ingroup AscendCL @@ -2345,10 +2262,8 @@ ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, * @see acldvppCreateChannel|acldvppCreatePicDesc|acldvppCreateLutMap */ ACL_FUNC_VISIBILITY aclError acldvppVpcEqualizeHistAsync(const acldvppChannelDesc *channelDesc, - const acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - const acldvppLutMap *lutMap, - aclrtStream stream); + const acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, + const acldvppLutMap *lutMap, aclrtStream stream); /** * @ingroup AscendCL @@ -2369,8 +2284,7 @@ ACL_FUNC_VISIBILITY acldvppBorderConfig *acldvppCreateBorderConfig(); * * @retval ACL_SUCCESS for success, other for failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigValue(acldvppBorderConfig *borderConfig, - uint32_t index, +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigValue(acldvppBorderConfig *borderConfig, uint32_t index, double value); /** @@ -2515,10 +2429,8 @@ ACL_FUNC_VISIBILITY aclError acldvppDestroyBorderConfig(acldvppBorderConfig *bor * @see acldvppCreateChannel|acldvppCreatePicDesc|acldvppCreateBorderConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcMakeBorderAsync(const acldvppChannelDesc *channelDesc, - const acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - const acldvppBorderConfig *borderConfig, - aclrtStream stream); + const acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, + const acldvppBorderConfig *borderConfig, aclrtStream stream); /** * @ingroup AscendCL @@ -2535,11 +2447,8 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcMakeBorderAsync(const acldvppChannelDesc * * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateHist */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *srcPicDesc, - acldvppHist *hist, - void *reserve, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *srcPicDesc, + acldvppHist *hist, void *reserve, aclrtStream stream); /** * @ingroup AscendCL @@ -2548,7 +2457,7 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channel * @retval null for failed. * @retval OtherValues success. */ -ACL_FUNC_VISIBILITY acldvppHist* acldvppCreateHist(); +ACL_FUNC_VISIBILITY acldvppHist *acldvppCreateHist(); /** * @ingroup AscendCL @@ -2605,7 +2514,7 @@ ACL_FUNC_VISIBILITY aclError acldvppGetHistData(acldvppHist *hist, uint32_t dim, * * @see acldvppCreateHist | acldvppVpcCalcHistAsync */ -ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist* hist); +ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist *hist); /** * @ingroup AscendCL @@ -2624,7 +2533,6 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist* hist); */ ACL_FUNC_VISIBILITY aclError acldvppClearHist(acldvppHist *hist); - /** * @ingroup AscendCL * @brief dvpp vpc batch crop, resize config and make border. @@ -2648,18 +2556,13 @@ ACL_FUNC_VISIBILITY aclError acldvppClearHist(acldvppHist *hist); * * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeMakeBorderAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, - uint32_t *roiNums, - uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, - acldvppRoiConfig *cropAreas[], - acldvppBorderConfig *borderCfgs[], - acldvppResizeConfig *resizeConfig, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeMakeBorderAsync( + acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], acldvppBorderConfig *borderCfgs[], + acldvppResizeConfig *resizeConfig, aclrtStream stream); #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ diff --git a/inc/external/acl/ops/acl_fv.h b/inc/external/acl/ops/acl_fv.h index 40cd50cb..27dc367a 100644 --- a/inc/external/acl/ops/acl_fv.h +++ b/inc/external/acl/ops/acl_fv.h @@ -32,8 +32,8 @@ typedef struct aclfvSearchResult aclfvSearchResult; // search operation type enum aclfvSearchType { - SEARCH_1_N, // 1:N operation type - SEARCH_N_M // N:M operation type + SEARCH_1_N, // 1:N operation type + SEARCH_N_M // N:M operation type }; /** @@ -104,7 +104,8 @@ ACL_FUNC_VISIBILITY aclError aclfvSetNMTopNum(aclfvInitPara *initPara, uint32_t * @retval OtherValues success. */ ACL_FUNC_VISIBILITY aclfvFeatureInfo *aclfvCreateFeatureInfo(uint32_t id0, uint32_t id1, uint32_t offset, - uint32_t featureLen, uint32_t featureCount, uint8_t *featureData, uint32_t featureDataLen); + uint32_t featureLen, uint32_t featureCount, + uint8_t *featureData, uint32_t featureDataLen); /** * @ingroup AscendCL @@ -233,8 +234,9 @@ ACL_FUNC_VISIBILITY aclError aclfvDestroySearchInput(aclfvSearchInput *searchInp * @retval null for failed. OtherValues success */ ACL_FUNC_VISIBILITY aclfvSearchResult *aclfvCreateSearchResult(uint32_t queryCnt, uint32_t *resultNum, - uint32_t resultNumDataLen, uint32_t *id0, uint32_t *id1, uint32_t *resultOffset, float *resultDistance, - uint32_t dataLen); + uint32_t resultNumDataLen, uint32_t *id0, uint32_t *id1, + uint32_t *resultOffset, float *resultDistance, + uint32_t dataLen); /** * @ingroup AscendCL @@ -348,4 +350,4 @@ ACL_FUNC_VISIBILITY aclError aclfvSearch(aclfvSearchType type, aclfvSearchInput } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_RETR_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_RETR_H_ diff --git a/inc/external/hccl/hccl.h b/inc/external/hccl/hccl.h index cc4bea8e..9992a636 100644 --- a/inc/external/hccl/hccl.h +++ b/inc/external/hccl/hccl.h @@ -27,7 +27,7 @@ #ifdef __cplusplus extern "C" { -#endif // __cplusplus +#endif // __cplusplus /** * @brief Initialize HCCL. @@ -66,14 +66,15 @@ extern HcclResult HcclCommInitRootInfo(uint32_t nRanks, const HcclRootInfo *root * @param sendBuf A pointer identifying the input data address of the operator. * @param recvBuf A pointer identifying the output data address of the operator. * @param count An integer(u64) identifying the number of the output data. - * @param dataType The data type of the operator, must be one of the following types: int8, int16, int32, float16, float32. + * @param dataType The data type of the operator, must be one of the following types: int8, int16, int32, float16, + * float32. * @param op The reduction type of the operator, must be one of the following types: sum, min, max, prod. * @param comm A pointer identifying the communication resource based on. * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclAllReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType, -HcclReduceOp op, HcclComm comm, aclrtStream stream); +extern HcclResult HcclAllReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType, HcclReduceOp op, + HcclComm comm, aclrtStream stream); /** * @brief Broadcast operator. @@ -84,10 +85,10 @@ HcclReduceOp op, HcclComm comm, aclrtStream stream); * @param root An integer(u32) identifying the the root rank in the operator. * @param comm A pointer identifying the communication resource based on * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclBroadcast(void *buf, uint64_t count, HcclDataType dataType, uint32_t root, HcclComm comm, -aclrtStream stream); +extern HcclResult HcclBroadcast(void *buf, uint64_t count, HcclDataType dataType, uint32_t root, HcclComm comm, + aclrtStream stream); /** * @brief ReduceScatter operator. @@ -99,10 +100,10 @@ aclrtStream stream); * @param op The reduction type of the operator, must be one of the following types: sum, min, max, prod. * @param comm A pointer identifying the communication resource based on. * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclReduceScatter(void *sendBuf, void *recvBuf, uint64_t recvCount, HcclDataType dataType, -HcclReduceOp op, HcclComm comm, aclrtStream stream); +extern HcclResult HcclReduceScatter(void *sendBuf, void *recvBuf, uint64_t recvCount, HcclDataType dataType, + HcclReduceOp op, HcclComm comm, aclrtStream stream); /** * @brief AllGather operator. @@ -113,17 +114,17 @@ HcclReduceOp op, HcclComm comm, aclrtStream stream); * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. * @param comm A pointer identifying the communication resource based on. * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclAllGather(void *sendBuf, void *recvBuf, uint64_t sendCount, HcclDataType dataType, -HcclComm comm, aclrtStream stream); +extern HcclResult HcclAllGather(void *sendBuf, void *recvBuf, uint64_t sendCount, HcclDataType dataType, HcclComm comm, + aclrtStream stream); /** * @brief Barrier operator. * * @param comm A pointer identifying the communication resource based on. * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ extern HcclResult HcclBarrier(HcclComm comm, aclrtStream stream); @@ -138,5 +139,5 @@ extern HcclResult HcclCommDestroy(HcclComm comm); #ifdef __cplusplus } -#endif // __cplusplus -#endif // HCCL_H_ +#endif // __cplusplus +#endif // HCCL_H_ diff --git a/inc/external/hccl/hccl_types.h b/inc/external/hccl/hccl_types.h index 50a64795..0e832396 100644 --- a/inc/external/hccl/hccl_types.h +++ b/inc/external/hccl/hccl_types.h @@ -16,10 +16,10 @@ /** * @file hccl_types.h - * @brief HCCL data type definition - * + * @brief HCCL data type definition + * */ - + #ifndef HCCL_TYPES_H_ #define HCCL_TYPES_H_ @@ -27,33 +27,33 @@ #ifdef __cplusplus extern "C" { -#endif // __cplusplus +#endif // __cplusplus /** * @brief HCCL functions return value definition */ typedef enum { - HCCL_SUCCESS = 0, /**< success */ - HCCL_E_PARA = 1, /**< parameter error */ - HCCL_E_PTR = 2, /**< empty pointer */ - HCCL_E_MEMORY = 3, /**< memory error */ - HCCL_E_INTERNAL = 4, /**< internal error */ - HCCL_E_NOT_SUPPORT = 5, /**< not support feature */ - HCCL_E_NOT_FOUND = 6, /**< not found specific resource */ - HCCL_E_UNAVAIL = 7, /**< resource unavailable */ - HCCL_E_SYSCALL = 8, /**< call system interface error */ - HCCL_E_TIMEOUT = 9, /**< timeout */ - HCCL_E_OPEN_FILE_FAILURE = 10, /**< open file fail */ - HCCL_E_TCP_CONNECT = 11, /**< tcp connect fail */ - HCCL_E_ROCE_CONNECT = 12, /**< roce connect fail */ - HCCL_E_TCP_TRANSFER = 13, /**< tcp transfer fail */ - HCCL_E_ROCE_TRANSFER = 14, /**< roce transfer fail */ - HCCL_E_RUNTIME = 15, /**< call runtime api fail */ - HCCL_E_DRV = 16, /**< call driver api fail */ - HCCL_E_PROFILING = 17, /**< call profiling api fail */ - HCCL_E_CCE = 18, /**< call cce api fail */ - HCCL_E_NETWORK = 19, /**< call network api fail */ - HCCL_E_RESERVED /**< reserved */ + HCCL_SUCCESS = 0, /**< success */ + HCCL_E_PARA = 1, /**< parameter error */ + HCCL_E_PTR = 2, /**< empty pointer */ + HCCL_E_MEMORY = 3, /**< memory error */ + HCCL_E_INTERNAL = 4, /**< internal error */ + HCCL_E_NOT_SUPPORT = 5, /**< not support feature */ + HCCL_E_NOT_FOUND = 6, /**< not found specific resource */ + HCCL_E_UNAVAIL = 7, /**< resource unavailable */ + HCCL_E_SYSCALL = 8, /**< call system interface error */ + HCCL_E_TIMEOUT = 9, /**< timeout */ + HCCL_E_OPEN_FILE_FAILURE = 10, /**< open file fail */ + HCCL_E_TCP_CONNECT = 11, /**< tcp connect fail */ + HCCL_E_ROCE_CONNECT = 12, /**< roce connect fail */ + HCCL_E_TCP_TRANSFER = 13, /**< tcp transfer fail */ + HCCL_E_ROCE_TRANSFER = 14, /**< roce transfer fail */ + HCCL_E_RUNTIME = 15, /**< call runtime api fail */ + HCCL_E_DRV = 16, /**< call driver api fail */ + HCCL_E_PROFILING = 17, /**< call profiling api fail */ + HCCL_E_CCE = 18, /**< call cce api fail */ + HCCL_E_NETWORK = 19, /**< call network api fail */ + HCCL_E_RESERVED /**< reserved */ } HcclResult; /** @@ -65,37 +65,37 @@ typedef void *HcclComm; * @brief HCCL Reduction opperation */ typedef enum { - HCCL_REDUCE_SUM = 0, /**< sum */ - HCCL_REDUCE_PROD = 1, /**< prod */ - HCCL_REDUCE_MAX = 2, /**< max */ - HCCL_REDUCE_MIN = 3, /**< min */ - HCCL_REDUCE_RESERVED /**< reserved */ + HCCL_REDUCE_SUM = 0, /**< sum */ + HCCL_REDUCE_PROD = 1, /**< prod */ + HCCL_REDUCE_MAX = 2, /**< max */ + HCCL_REDUCE_MIN = 3, /**< min */ + HCCL_REDUCE_RESERVED /**< reserved */ } HcclReduceOp; /** * @brief HCCL data type */ typedef enum { - HCCL_DATA_TYPE_INT8 = 0, /**< int8 */ - HCCL_DATA_TYPE_INT16 = 1, /**< int16 */ - HCCL_DATA_TYPE_INT32 = 2, /**< int32 */ - HCCL_DATA_TYPE_FP16 = 3, /**< fp16 */ - HCCL_DATA_TYPE_FP32 = 4, /**< fp32 */ - HCCL_DATA_TYPE_INT64 = 5, /**< int64 */ - HCCL_DATA_TYPE_UINT64 = 6, /**< uint64 */ - HCCL_DATA_TYPE_RESERVED /**< reserved */ + HCCL_DATA_TYPE_INT8 = 0, /**< int8 */ + HCCL_DATA_TYPE_INT16 = 1, /**< int16 */ + HCCL_DATA_TYPE_INT32 = 2, /**< int32 */ + HCCL_DATA_TYPE_FP16 = 3, /**< fp16 */ + HCCL_DATA_TYPE_FP32 = 4, /**< fp32 */ + HCCL_DATA_TYPE_INT64 = 5, /**< int64 */ + HCCL_DATA_TYPE_UINT64 = 6, /**< uint64 */ + HCCL_DATA_TYPE_RESERVED /**< reserved */ } HcclDataType; -const uint32_t HCCL_ROOT_INFO_BYTES = 4108; // 4108: root info length +const uint32_t HCCL_ROOT_INFO_BYTES = 4108; // 4108: root info length /** * @brief HCCL root info */ typedef struct HcclRootInfoDef { - char internal[HCCL_ROOT_INFO_BYTES]; + char internal[HCCL_ROOT_INFO_BYTES]; } HcclRootInfo; #ifdef __cplusplus } -#endif // __cplusplus -#endif // HCCL_TYPES_H_ +#endif // __cplusplus +#endif // HCCL_TYPES_H_ diff --git a/inc/external/runtime/rt_error_codes.h b/inc/external/runtime/rt_error_codes.h index 02a357fc..437a5544 100644 --- a/inc/external/runtime/rt_error_codes.h +++ b/inc/external/runtime/rt_error_codes.h @@ -23,81 +23,81 @@ extern "C" { #endif -static const int32_t ACL_RT_SUCCESS = 0; // success +static const int32_t ACL_RT_SUCCESS = 0; // success -static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid -static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id -static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null -static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context -static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context -static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal -static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned -static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed -static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed -static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream -static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread -static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set -static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create -static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream -static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type -static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle -static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type +static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid +static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id +static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null +static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context +static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context +static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal +static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned +static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed +static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed +static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream +static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread +static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set +static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create +static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream +static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type +static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle +static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type -static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support -static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error -static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error -static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow -static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device -static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail -static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission -static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource -static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource -static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource -static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource +static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support +static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error +static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error +static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow +static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device +static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail +static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission +static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource +static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource +static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource +static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource -static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error -static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error -static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error -static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect +static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error +static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error +static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect #ifdef __cplusplus } #endif -#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ +#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ From 452ec62cb297fe61cab05c62a0ebd1176fe4e060 Mon Sep 17 00:00:00 2001 From: dingpeifei Date: Thu, 29 Apr 2021 16:10:37 +0800 Subject: [PATCH 26/59] code_sync_0428_inc --- inc/external/acl/error_codes/rt_error_codes.h | 71 ++++++++++--------- inc/external/runtime/rt_error_codes.h | 71 ++++++++++--------- third_party/fwkacllib/inc/ops/data_flow_ops.h | 16 +++++ .../inc/ops/elewise_calculation_ops.h | 14 ++-- third_party/fwkacllib/inc/ops/image_ops.h | 13 ++-- .../inc/ops/matrix_calculation_ops.h | 31 ++++++++ .../fwkacllib/inc/ops/nn_batch_norm_ops.h | 28 -------- .../fwkacllib/inc/ops/nn_calculation_ops.h | 3 + third_party/fwkacllib/inc/ops/nn_detect_ops.h | 53 +++++++------- third_party/fwkacllib/inc/ops/nn_norm_ops.h | 44 ++++++------ .../fwkacllib/inc/ops/nn_pooling_ops.h | 59 ++++++++++++--- .../fwkacllib/inc/ops/nn_training_ops.h | 49 +++++++++++++ third_party/fwkacllib/inc/ops/parsing_ops.h | 18 ++--- third_party/fwkacllib/inc/ops/random_ops.h | 2 + third_party/fwkacllib/inc/ops/rnn.h | 35 +++++---- third_party/fwkacllib/inc/ops/selection_ops.h | 27 +++++++ third_party/fwkacllib/inc/ops/string_ops.h | 2 + .../inc/toolchain/tuning_tool/tune_api.h | 30 ++------ 18 files changed, 353 insertions(+), 213 deletions(-) diff --git a/inc/external/acl/error_codes/rt_error_codes.h b/inc/external/acl/error_codes/rt_error_codes.h index 437a5544..1c196c48 100644 --- a/inc/external/acl/error_codes/rt_error_codes.h +++ b/inc/external/acl/error_codes/rt_error_codes.h @@ -57,40 +57,43 @@ static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream re static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource -static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout +static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error diff --git a/inc/external/runtime/rt_error_codes.h b/inc/external/runtime/rt_error_codes.h index 437a5544..1c196c48 100644 --- a/inc/external/runtime/rt_error_codes.h +++ b/inc/external/runtime/rt_error_codes.h @@ -57,40 +57,43 @@ static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream re static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource -static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout +static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error diff --git a/third_party/fwkacllib/inc/ops/data_flow_ops.h b/third_party/fwkacllib/inc/ops/data_flow_ops.h index 0043c027..05de1b0a 100644 --- a/third_party/fwkacllib/inc/ops/data_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/data_flow_ops.h @@ -2331,6 +2331,22 @@ REG_OP(CacheAllIndexToLocal) .REQUIRED_ATTR(dtype, Type) .OP_END_FACTORY_REG(CacheAllIndexToLocal) +/** +*@brief DynamicGetNext, dynamic get next data +*@par Inputs: +*x: the iterator, all types are available +*@par Outputs: +*y: the date in iterator, all types are available +*@par Attributes: +*output_types: types of all outputs +*output_shapes: shapes of all outputs +*_dynamic_graph_execute_mode: dynamic graph execution mode, +value is one of lazy_recompile and dynamic_execute +*_getnext_inputs_shape_range: shape ranges of outputs, +it works where _dynamic_graph_execute_mode is dynamic_execute +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ REG_OP(DynamicGetNext) .INPUT(x, TensorType::ALL()) .DYNAMIC_OUTPUT(y, TensorType::ALL()) diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index 209967bd..8c87cfe8 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -28,7 +28,7 @@ namespace ge { *@par Inputs: *Dynamic inputs, including: -* @li x: A list of Tensor objects, each with same shape and type. The supported types are: +*x: A list of Tensor objects, each with same shape and type. The supported types are: * float16, float32, double, int32, uint8, int16, int8, complex64, int64, * qint8, quint8, qint32, uint16, complex128, uint32, uint64. It's a dynamic input. \n @@ -330,8 +330,8 @@ REG_OP(Sub) *@brief computes the absolute value of a tensor. \n *@par Inputs: -*One inputs, including: -* @li x: A Tensor. Must be one of the following types: float16, float32, double, int32, int64. \n +*One input, including: \n +*x: A Tensor. Must be one of the following types: float16, float32, double, int32, int64. \n *@par Outputs: *y: A Tensor. Has the same type as "x". \n @@ -3243,9 +3243,11 @@ REG_OP(Fills) *@brief Add tensor with scale. \n *@par Inputs: -*Five inputs, including: -* @li x1: A Tensor. Must be one of the following types:int32,int16, float16, float32. -* @li x2: A scale. Must be float. \n +*One input, including: \n +*x: A Tensor. Must be one of the following types:int32,int16, float16, float32. \n + +*@par Attributes: +*value: A scale. Must be float. \n *@par Outputs: *@li y: A Tensor. Has the same type and shape as "x1". \n diff --git a/third_party/fwkacllib/inc/ops/image_ops.h b/third_party/fwkacllib/inc/ops/image_ops.h index 3ef4d95e..e6802c1e 100644 --- a/third_party/fwkacllib/inc/ops/image_ops.h +++ b/third_party/fwkacllib/inc/ops/image_ops.h @@ -1134,7 +1134,7 @@ REG_OP(DecodeBmp) .ATTR(channels, Int, 0) .OP_END_FACTORY_REG(DecodeBmp) -/* +/** *@brief Function parse image from string to int. \n *@par Inputs: @@ -1602,11 +1602,11 @@ REG_OP(DecodeJpeg) *@brief Image warping using per-pixel flow vectors. \n *@par Inputs: -*@li images: 4-D Tensor with shape `[batch, height, width, channels]`. +*@li image: 4-D Tensor with shape `[batch, height, width, channels]`. *@li flow: 4-D Tensor with shape `[batch, height, width, 2]`. \n *@par Outputs: -*y: Returns 4-D with the same shape and dtype as `images`. \n +*y: Returns 4-D with the same shape and dtype as `image`. \n */ REG_OP(DenseImageWarp) .INPUT(image, TensorType({DT_FLOAT, DT_FLOAT16})) @@ -1709,11 +1709,11 @@ REG_OP(ResizeGradD) *@par Inputs: *@li grad: gradients with respect to DenseImageWarp output. -*@li images: 4-D Tensor with shape `[batch, height, width, channels]`. +*@li image: 4-D Tensor with shape `[batch, height, width, channels]`. *@li flow: 4-D Tensor with shape `[batch, height, width, 2]`. \n *@par Outputs: -*grad_image: Returns 4-D with the same shape and dtype as `images`. +*grad_image: Returns 4-D with the same shape and dtype as `image`. *grad_flow: Returns 4-D with the same shape and dtype as `flow`. \n */ REG_OP(DenseImageWarpGrad) @@ -1747,6 +1747,9 @@ REG_OP(DenseImageWarpGrad) *@par Third-party framework compatibility *Compatible with pytorch GridSampler2D operator. + +*@par Restrictions: +*Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(GridSampler2D) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index 3340007c..083d4f9c 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -444,6 +444,9 @@ REG_OP(ScatterNdUpdate) *@par Third-party framework compatibility * Compatible with the TensorFlow operator TensorScatterUpdate. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(TensorScatterUpdate) .INPUT(x, TensorType::BasicType()) @@ -565,6 +568,9 @@ REG_OP(ScatterNdAdd) *@par Third-party framework compatibility * Compatible with the TensorFlow operator TensorScatterAdd. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(TensorScatterAdd) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) @@ -623,6 +629,9 @@ REG_OP(ScatterNdSub) *@par Third-party framework compatibility * Compatible with the TensorFlow operator TensorScatterSub. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(TensorScatterSub) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) @@ -1045,6 +1054,28 @@ REG_OP(MatrixDiagV2) .OUTPUT(output, TensorType::BasicType()) .OP_END_FACTORY_REG(MatrixDiagV2) +/** +* @brief Add updates to var_out according to axis and indices. + +* @par Inputs: +* Three inputs, including: +* @li var: A Tensor. Must be one of the following types: +* float16, float32, int32, int8, uint8. +* @li indices: A Tensor of the indices, type should be int32. +* @li updates: A Tensor of the same type as "var". + +* @par Attributes: +* @li axis: An required int to specify the axis to perform indices add. + +* @par Outputs: +* @li var_out: A Tensor. Same as input "var". + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator index_add. + +* @par Restrictions: +* Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ REG_OP(IndexAdd) .INPUT(var, TensorType({DT_INT32, DT_INT8, DT_UINT8, DT_FLOAT32, DT_FLOAT16})) .INPUT(indices, TensorType({DT_INT32})) diff --git a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h index ddd70bc8..9629976e 100644 --- a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h @@ -419,35 +419,7 @@ REG_OP(BNInference) .ATTR(use_global_stats, Bool,true) .ATTR(mode, Int,1) .OP_END_FACTORY_REG(BNInference) -/** -*@brief aicpu batch normalization host . \n - -*@par Inputs: -*@li mean: A Tensor of type float32 or float16. Must be 1D if input "x" Specifies the mean used for inference. -*@li variance: A Tensor of type float32 or float16 . Must be 1D if input "x" Specifies the variance used for inference. -*@li momentum: An optional float, mean and variance's Scale factor -*@par Attributes: -*@li epsilon: An optional float32, specifying the small value added to variance to avoid dividing by zero. Defaults to "0.00001". -*@li use_global_stats: mean inference mode , only can be "True". -*@li mode: An optional attr, not use -*@par Outputs: -*@li alpha: A Tensor of type float16 or float32 for the cpu calculate mean -*@li beta: A Tensor of type float16 or float32 for the cpu calculate variance -*/ -REG_OP(BnHost) - .INPUT(mean, TensorType({DT_FLOAT, DT_FLOAT16})) - .INPUT(variance, TensorType({DT_FLOAT, DT_FLOAT16})) - .INPUT(momentum, TensorType({DT_FLOAT16,DT_FLOAT})) - .OPTIONAL_INPUT(scale, TensorType({DT_FLOAT16,DT_FLOAT})) - .OPTIONAL_INPUT(offset, TensorType({DT_FLOAT16,DT_FLOAT})) - .ATTR(epsilon, Float, 0.00001) - .ATTR(mode, Int, 1) - .ATTR(use_global_stats, Bool, true) - .OUTPUT(alpha, TensorType({DT_FLOAT, DT_FLOAT16})) - .OUTPUT(beta, TensorType({DT_FLOAT, DT_FLOAT16})) - .OUTPUT(mu, TensorType({DT_FLOAT16,DT_FLOAT})) - .OP_END_FACTORY_REG(BnHost) /** *@brief Performs batch normalization . \n diff --git a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h index 8cbdf9ff..0eeeb511 100644 --- a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h @@ -989,6 +989,8 @@ REG_OP(Conv2DCompress) *@li deformable_groups: Optional. An integer of type int32. The number of * deformable group partitions. In_channels must be divisible by * "deformable_groups". Defaults to 1. +*@li modulated: Optional. Specify version of DeformableConv2D, true means v2, +* false means v1, currently only support v2. *\n *\n * The following value range restrictions must be met: @@ -1037,6 +1039,7 @@ REG_OP(DeformableConv2D) .ATTR(groups, Int, 1) .ATTR(data_format, String, "NHWC") .ATTR(deformable_groups, Int, 1) + .ATTR(modulated, Bool, true) .OP_END_FACTORY_REG(DeformableConv2D) /** diff --git a/third_party/fwkacllib/inc/ops/nn_detect_ops.h b/third_party/fwkacllib/inc/ops/nn_detect_ops.h index 33148e62..cc60f483 100644 --- a/third_party/fwkacllib/inc/ops/nn_detect_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_detect_ops.h @@ -1202,35 +1202,6 @@ REG_OP(RpnProposalsD) .OUTPUT(sorted_box, TensorType({DT_FLOAT16})) .OP_END_FACTORY_REG(RpnProposalsD) -/** -*@brief Computes Score Filte Pre-Sort function. - -*@par Inputs: -*Inputs include: -* @li rois: A Tensor. Must be float16. N-D with shape [N, 4]. -* @li cls_bg_prob: A Tensor. Must be float16. N-D with shape [N, 1]. - -*@par Attributes: -* @li score_threshold: required, float, threahold of topk process. -* @li k: required, Int, threahold of topk process. -* @li score_filter: bool, mark of score_filter. Defaults to "true" -* @li core_max_num: int, max number of core. Defaults to "8" -*@par Outputs: -* @li sorted_proposal: A Tensor. Must be float16. -* N-D with shape [8*6002, 8]. -* @li proposal_num: A Tensor. Must be uint32. N-D with shape [8, 8]. -*/ - -REG_OP(ScoreFiltePreSort) - .INPUT(rois, TensorType({DT_FLOAT16})) - .INPUT(cls_bg_prob, TensorType({DT_FLOAT16})) - .OUTPUT(sorted_proposal, TensorType({ DT_FLOAT16})) - .OUTPUT(proposal_num, TensorType({ DT_UINT32})) - .REQUIRED_ATTR(score_threshold, Float) - .REQUIRED_ATTR(k, Int) - .ATTR(score_filter, Bool, true) - .ATTR(core_max_num, Int, 8) - .OP_END_FACTORY_REG(ScoreFiltePreSort) /** *@brief Computes Score Filte Pre-Sort function. @@ -1500,6 +1471,26 @@ REG_OP(Sort) .ATTR(descending, Bool, false) .OP_END_FACTORY_REG(Sort) +/** +*@brief Computes iou for input bboxes and gtboxes. + +*@par Inputs: +* Two inputs, including: +*@li bboxes: boxes, a 4D Tensor of type float16 with the shape (x0, x1, y0, y1), +*@li gtboxes: boxes, a 4D Tensor of type float16 with the shape (x0, x1, y0, y1).\n + +*@par Attributes: +*@li mode: A optional attribute of type string, whether judge the mode of iou. \n + +*@par Outputs: +*@li overlap: A 2D Tensor of type float16 with shape [n, m]. \n + +*@attention Constraints: +* Only computation of float16 data is supported. + +*@par Restrictions: +*Warning:THIS FUNCTION IS DEPRECATED. Please use Iou instead. +*/ REG_OP(PtIou) .INPUT(bboxes, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(gtboxes, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -1541,6 +1532,9 @@ selected indices from the boxes tensor, where M <= max_output_size. \n *@par Third-party framework compatibility *Compatible with onnx NonMaxSuppression operator. + +*@par Restrictions: +*Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(NonMaxSuppressionV6) @@ -1729,3 +1723,4 @@ REG_OP(PSROIPoolingGradV2D) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_DETECT_OPS_H_ + diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index a0251d88..22023f46 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -1072,26 +1072,6 @@ REG_OP(INInferV2D) .OUTPUT(batch_variance, TensorType({DT_FLOAT})) .OP_END_FACTORY_REG(INInferV2D) -/** -*@brief Performs instance normalization for inference of InHost part. - -*@par Inputs:\n -* One input, including: (NC1HWC0 supported) -* variance: A [N, C1, 1, 1, C0] Tensor of type float32, for the variance. - -*@par Attributes: -* epsilon: An optional float32, specifying the small value added to -variance to avoid dividing by zero. Defaults to "0.00001" . \n - -*@par Outputs:\n -* variance_sqrt: A [N, C1, 1, 1, C0] Tensor of type float32, for the variance_sqrt. -*/ -REG_OP(InHost) - .INPUT(variance, TensorType({DT_FLOAT})) - .OUTPUT(variance_sqrt, TensorType({DT_FLOAT})) - .ATTR(epsilon, Float, 0.00001) - .OP_END_FACTORY_REG(InHost) - /** * @brief perform instance normalization to x. \n @@ -1124,6 +1104,26 @@ REG_OP(InstanceNorm) .REQUIRED_ATTR(epsilon, Float) .OP_END_FACTORY_REG(InstanceNorm) +/** +* @brief Computes Kl_div_loss_grad or Kl_div_loss_backward. \n + +* @par Inputs: +* Three inputs, including: +* @li grad: A Tensor. Must be one of the following types: float16, float32. +* Required. +* @li input: A Tensor. Has the same type as "grad". Required. +* @li target: A Tensor. Has the same type as "grad". Required. \n + +* @par Attributes: +* @li reduction: An optional attribute of type String. Defaults to "mean". \n +* @li log_target: An optional attribute of type Bool. Defaults to false. \n + +* @par Outputs: +* @li y: A Tensor. Has the same type as "grad". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator KlDivLossGrad. +*/ REG_OP(KlDivLossGrad) .INPUT(grad, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(input, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -1453,12 +1453,12 @@ REG_OP(PoissonNllLoss) * * * @par Output: - * y: A mutable Tensor of type int32, with the shape of [num_step, batch_size, hidden_size]. \n + * y: A mutable Tensor of type float16, with the shape of [num_step, batch_size, hidden_size]. \n * */ REG_OP(RnnGenMask) .INPUT(seq_length, TensorType({DT_INT32})) - .OUTPUT(seq_mask, TensorType({DT_INT32})) + .OUTPUT(seq_mask, TensorType({DT_FLOAT16})) .REQUIRED_ATTR(num_step, Int) .REQUIRED_ATTR(hidden_size, Int) .OP_END_FACTORY_REG(RnnGenMask) diff --git a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h index 743c28b7..ef9fabb8 100644 --- a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h @@ -237,18 +237,18 @@ REG_OP(AvgPool3DD) * @li ceil_mode: When true, will use ceil instead of floor in the formula to compute the output shape. * @li count_include_pad: When true, will include the zero-padding in the averaging calculation. * @li divisor_override: if specified, it will be used as divisor, otherwise size of the pooling region will be used. -* @li data_format: A string, format of input data . +* @li data_format: A string, format of input data. * @par Outputs: -* @output: A mutable tensor with the same shape and type as "orig_input". +* @output: A mutable tensor with the same shape and type as "orig_input_shape". * @par Third-party framework compatibility * @li Compatible with the TensorFlow operator AvgPoolGrad. */ REG_OP(AvgPool3DGrad) - .INPUT(orig_input_shape, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) - .INPUT(grads, TensorType({DT_INT32})) + .INPUT(orig_input_shape, TensorType({DT_INT32})) + .INPUT(grads, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) .OUTPUT(output, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) .REQUIRED_ATTR(ksize, ListInt) .REQUIRED_ATTR(strides, ListInt) @@ -888,7 +888,7 @@ REG_OP(AvgPoolV2Grad) * @brief Computes gradients of averagev2 pooling function. * @par Inputs: -* @li input_grad: An NHWC tensor of type float16, float32, or double. +*input_grad: An NHWC tensor of type float16, float32, or double. * @par Attributes: * @li orig_input_shape: A required tuple or list of type int32. @@ -906,10 +906,10 @@ REG_OP(AvgPoolV2Grad) * @li data_format: An optional string. Defaults to "NHWC". * @par Outputs: -* @out_grad: A mutable tensor with the same shape and type as "orig_input". +*out_grad: A mutable tensor with the same shape and type as "orig_input". * @par Third-party framework compatibility -* @li Compatible with the TensorFlow operator AvgPoolGrad. +*Compatible with the TensorFlow operator AvgPoolGrad. */ REG_OP(AvgPoolV2GradD) .INPUT(input_grad, TensorType({DT_FLOAT16})) @@ -1682,7 +1682,27 @@ REG_OP(MaxPoolWithArgmaxV1) .ATTR(ceil_mode, Bool, false) .OP_END_FACTORY_REG(MaxPoolWithArgmaxV1) -// SubSample +/** +*@brief Randomly sample a subset of positive and negative examples,and overwrite +the label vector to the ignore value (-1) for all elements that are not +included in the sample.\n + +* @par Inputs: +* One input: +* labels: shape of labels,(N, ) label vector with values. \n + +* @par Attributes: +* @li batch_size_per_images: A require attribute of type int. +* @li positive_fraction: A require attribute of type float. + +*@par Outputs: +*y: The result of subSample. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator SubSample. +*@par Restrictions: +*Warning: This operator can be integrated only by MaskRcnn. Please do not use it directly. +*/ REG_OP(SubSample) .INPUT(labels, TensorType({DT_INT32})) .OUTPUT(y, TensorType({DT_INT32})) @@ -1690,7 +1710,28 @@ REG_OP(SubSample) .REQUIRED_ATTR(positive_fraction, Float) .OP_END_FACTORY_REG(SubSample) -// SubSampleLabels +/** +*@brief Randomly sample a subset of positive and negative examples,and overwrite +the label vector to the ignore value (-1) for all elements that are not +included in the sample.\n + +* @par Inputs: +* two inputs, including: +* @li labels: shape of labels,(N, ) label vector with values:. +* @li shuffle_matrix: random matrix with shape (N, ). \n + +* @par Attributes: +* @li batch_size_per_images: A require attribute of type int. +* @li positive_fraction: A require attribute of type float. + +*@par Outputs: +*y: The result of subSample. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator SubSampleLabels. +*@par Restrictions: +*Warning: This operator can be integrated only by MaskRcnn. Please do not use it directly. +*/ REG_OP(SubSampleLabels) .INPUT(labels, TensorType({DT_INT32})) .INPUT(shuffle_matrix, TensorType({DT_INT32})) diff --git a/third_party/fwkacllib/inc/ops/nn_training_ops.h b/third_party/fwkacllib/inc/ops/nn_training_ops.h index 92074872..75e91aee 100644 --- a/third_party/fwkacllib/inc/ops/nn_training_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_training_ops.h @@ -2101,6 +2101,55 @@ REG_OP(FusedMulApplyMomentumExtern) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(FusedMulApplyMomentumExtern) +/** +*@brief Updates '*var' according to the momentum scheme. +* accum = accum * momentum - x1 * x2 * lr +* if use_nesterov is True: +* var += accum * momentum - x1 * x2 * lr +* else: +* var += accum +* +*@par Inputs: +*@li var: A mutable tensor. Must be one of the data types defined in +* TensorType::NumberType(). Should be from a Variable(). +*@li accum: A mutable tensor. Has the same type as "var". Should be from a +* Variable(). +*@li lr: A tensor for the learning rate. Has the same type as "var". Should be +* from a Variable(). +*@li x1: A Tensor has type TensorType::NumberType(). +*@li momentum: A scalar. Has the same type as "var". +*@li x2: A scalar has the same type as "var". +* +*@par Attributes: +*@li use_nesterov: An optional bool. Defaults to "False". +* If "True", var will be updated by using Nesterov momentum. +*@li use_locking: An optional bool. Defaults to "False". +* If "True", updating of the "var" tensor is protected by a lock; +* otherwise the behavior is undefined, but may exhibit less contention. +* +*@par Outputs: +* var: A mutable tensor. Has the same type as input "var". +* +*@attention Constraints: +* The input tensors must have the same shape. +* +*@par Third-party framework compatibility +* Compatible with the TensorFlow operator ResourceApplyKerasMomentum. +* +*/ +REG_OP(FusedMulApplyKerasMomentum) + .INPUT(var, TensorType::NumberType()) + .INPUT(accum, TensorType::NumberType()) + .INPUT(lr, TensorType::NumberType()) + .INPUT(x1, TensorType::NumberType()) + .INPUT(momentum, TensorType::NumberType()) + .INPUT(x2, TensorType::NumberType()) + .OUTPUT(var, TensorType::NumberType()) + .OUTPUT(accum, TensorType::NumberType()) + .ATTR(use_locking, Bool, false) + .ATTR(use_nesterov, Bool, false) + .OP_END_FACTORY_REG(FusedMulApplyKerasMomentum) + /** *@brief Update "g" according to the LARS algorithm . \n diff --git a/third_party/fwkacllib/inc/ops/parsing_ops.h b/third_party/fwkacllib/inc/ops/parsing_ops.h index 452961a9..b625180a 100644 --- a/third_party/fwkacllib/inc/ops/parsing_ops.h +++ b/third_party/fwkacllib/inc/ops/parsing_ops.h @@ -86,7 +86,7 @@ REG_OP(ParseSingleExample) .ATTR(sparse_keys, ListString, {}) .ATTR(dense_keys, ListString, {}) .ATTR(sparse_types, ListType, {}) - .ATTR(dense_types, ListType, {}) + .ATTR(Tdense, ListType, {}) .ATTR(dense_shapes, ListListInt, {}) .OP_END_FACTORY_REG(ParseSingleExample) @@ -173,9 +173,9 @@ REG_OP(ParseTensor) REG_OP(DecodeCSV) .INPUT(records, TensorType({DT_STRING})) .DYNAMIC_INPUT(record_defaults, TensorType({DT_FLOAT, DT_DOUBLE, DT_INT32, - DT_INT64, DT_STRING, DT_RESOURCE})) + DT_INT64, DT_STRING})) .DYNAMIC_OUTPUT(output, TensorType({DT_FLOAT, DT_DOUBLE, DT_INT32, - DT_INT64, DT_STRING, DT_RESOURCE})) + DT_INT64, DT_STRING})) .ATTR(OUT_TYPE, ListType, {}) .ATTR(field_delim, String, ",") .ATTR(use_quote_delim, Bool, true) @@ -283,12 +283,12 @@ REG_OP(ParseSingleSequenceExample) .ATTR(Ncontext_dense, Int, 0) .ATTR(Nfeature_list_sparse, Int, 0) .ATTR(Nfeature_list_dense, Int, 0) - .REQUIRED_ATTR(context_sparse_types, ListType) - .REQUIRED_ATTR(Tcontext_dense, ListType) - .REQUIRED_ATTR(feature_list_dense_types, ListType) - .REQUIRED_ATTR(context_dense_shapes, ListListInt) - .REQUIRED_ATTR(feature_list_sparse_types, ListType) - .REQUIRED_ATTR(feature_list_dense_shapes, ListListInt) + .ATTR(context_sparse_types, ListType, {}) + .ATTR(Tcontext_dense, ListType, {}) + .ATTR(feature_list_dense_types, ListType, {}) + .ATTR(context_dense_shapes, ListListInt, {}) + .ATTR(feature_list_sparse_types, ListType, {}) + .ATTR(feature_list_dense_shapes, ListListInt, {}) .OP_END_FACTORY_REG(ParseSingleSequenceExample) } // namespace ge diff --git a/third_party/fwkacllib/inc/ops/random_ops.h b/third_party/fwkacllib/inc/ops/random_ops.h index 8104cb01..b65a68f1 100644 --- a/third_party/fwkacllib/inc/ops/random_ops.h +++ b/third_party/fwkacllib/inc/ops/random_ops.h @@ -548,6 +548,8 @@ REG_OP(ShuffleChannel) * Each value along the axis zero represents the outcome of * the corresponding sample in a batch. * + * @par Restrictions: + * Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(MultinomialFuss) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_FLOAT64})) diff --git a/third_party/fwkacllib/inc/ops/rnn.h b/third_party/fwkacllib/inc/ops/rnn.h index d4b3b102..d671a531 100644 --- a/third_party/fwkacllib/inc/ops/rnn.h +++ b/third_party/fwkacllib/inc/ops/rnn.h @@ -190,7 +190,7 @@ REG_OP(DynamicRNNGrad) *@li x:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li w:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. *@li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. -*@li seq_length:A optional 1D Tensor. Must be one of the following types: int32. The format must be ND. +*@li seq_length:A optional Tensor. Only Support float16 in FRACTAL_NZ and int32 in ND. *@li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. @@ -228,7 +228,7 @@ REG_OP(DynamicRNN) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(w, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(b, TensorType({DT_FLOAT16, DT_FLOAT})) - .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32})) + .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32, DT_FLOAT16})) .OPTIONAL_INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) .OPTIONAL_INPUT(init_c, TensorType({DT_FLOAT16, DT_FLOAT})) .OPTIONAL_INPUT(wci, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -698,9 +698,6 @@ REG_OP(DynamicGRU) *@li reset:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li new:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li hidden_new:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. - -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(DynamicGRUV2) .INPUT(x, TensorType({DT_FLOAT16})) @@ -988,6 +985,27 @@ REG_OP(CommonLSTM) .ATTR(input_forget, Int, 0) .OP_END_FACTORY_REG(CommonLSTM) +/** + * @brief Calculate the mask. According to hidden_size and num_step, convert seq_length to mask. + * + * @par Inputs: + * @li seq_length: A 1D Tensor. Must be one of the following types: int32. Record the current length of each batch. [batch_size]. + * @li b: A 1D Tensor. Must be one of the following types: fp16/fp32. Record the hidden_size. [4 * hidden_size]. + * @li x: A 3D Tensor. Must be one of the following types: fp16/fp32. Record the num_step/batch_size/input_size. [num_step, batch_size, input_size]. + * + * @par Outputs: + * seq_mask: A 3D Tensor. Must be one of the following types: fp16/fp32. with the shape of [num_step, batch_size, hidden_size]. And has the same type as "b" \n + * + * @par Restrictions: + * Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. + */ +REG_OP(RnnGenMaskV2) + .INPUT(seq_length, TensorType({DT_INT32})) + .INPUT(b, TensorType({{DT_FLOAT16, DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(seq_mask, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(RnnGenMaskV2) + /** * @brief Common GRU calculation. @@ -1002,22 +1020,15 @@ REG_OP(CommonLSTM) * @par Attributes: * @li activation_alpha: Optional scaling values used by some activation functions. \n - * @li activation_beta: Optional scaling values used by some activation functions. \n - * @li activations: A list of 2 (or 4 if bidirectional) activation functions for update, reset, and hidden gates. \n - * @li clip: Cell clip threshold. \n - * @li direction: Specify if the RNN is forward, reverse, or bidirectional. \n - * @li hidden_size: Number of neurons in the hidden layer. \n - * @li linear_before_reset: When computing the output of the hidden gate, apply the linear transformation before multiplying by the output of the reset gate. \n * @par Outputs: * @li y: A Tensor that concats all the intermediate output values of the hidden(float16,float32). The format must be FRACTAL_NZ - * @li y_h: The last output value of the hidden(float16,float32). The format must be FRACTAL_NZ */ REG_OP(CommonGRU) diff --git a/third_party/fwkacllib/inc/ops/selection_ops.h b/third_party/fwkacllib/inc/ops/selection_ops.h index da5bdb6a..f99493b7 100644 --- a/third_party/fwkacllib/inc/ops/selection_ops.h +++ b/third_party/fwkacllib/inc/ops/selection_ops.h @@ -2254,6 +2254,33 @@ REG_OP(IndexFillD) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) .REQUIRED_ATTR(dim, Int) .OP_END_FACTORY_REG(IndexFillD) + +/** +* @brief For each row r of this and for each column c, do (*this)(r, c) += src(j, c), \n +* where j ranges from indexes[r].first through indexes[r].second - 1. \n +* In general indexes must be >= 0 and < src.NumRows(); \n +* but to represent an empty range you may use the pair (-1, -1) or any pair of numbers (i, j) such that i >= j. \n + +* @par Inputs: +* Three inputs, including: +* @li x: A Tensor. Must be one of the following types: +* float16, float32. +* @li indices: A Tensor of the indices, type should be int32. +* @li src: A Tensor of the same type as "x". \n + +* @par Outputs: +* @li x: A Tensor. Same as input "x". + +* @par Third-party framework compatibility +* Compatible with the kaldi operator AddRowRanges. +*/ +REG_OP(AddRowRanges) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(src, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(indices, TensorType({DT_INT32})) + .OUTPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .OP_END_FACTORY_REG(AddRowRanges) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_SELECTION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/string_ops.h b/third_party/fwkacllib/inc/ops/string_ops.h index d7233906..080b9a3f 100644 --- a/third_party/fwkacllib/inc/ops/string_ops.h +++ b/third_party/fwkacllib/inc/ops/string_ops.h @@ -114,6 +114,7 @@ REG_OP(UnicodeDecodeWithOffsets) .ATTR(errors, String, "replace") .ATTR(replacement_char, Int, 65533) .ATTR(replace_control_characters, Bool, false) + .ATTR(Tsplits, Type, DT_INT64) .OP_END_FACTORY_REG(UnicodeDecodeWithOffsets) /** @@ -161,6 +162,7 @@ REG_OP(UnicodeDecode) .ATTR(errors, String, "replace") .ATTR(replacement_char, Int, 65533) .ATTR(replace_control_characters, Bool, false) + .ATTR(Tsplits, Type, DT_INT64) .OP_END_FACTORY_REG(UnicodeDecode) /** diff --git a/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h b/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h index 71226d87..2cf6e0c4 100644 --- a/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h +++ b/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h @@ -23,8 +23,8 @@ * @attention 无 * @param option [IN] 调优参数 * @param msg [OUT] 调优异常下返回信息 - * @retval #MSTUNE_SUCCESS 执行成功 - * @retval #MSTUNE_FAILED 执行失败 + * @retval #AOE_SUCCESS 执行成功 + * @retval #AOE_FAILURE 执行失败 * @par 依赖: * @li tune_api.cpp:该接口所属的开发包。 * @li tune_api.h:该接口声明所在的头文件。 @@ -33,26 +33,6 @@ */ AoeStatus AoeOfflineTuning(const std::map &option, std::string &msg); -/** - * @ingroup aoe - * @par 描述: 梯度调优 - * - * @attention 无 - * @param tuningGraph [IN] 调优图 - * @param dependGraph [IN] 调优依赖图 - * @param session [IN] ge连接会话 - * @param option [IN] 参数集. 包含调优参数及ge参数 - * @retval #MSTUNE_SUCCESS 执行成功 - * @retval #MSTUNE_FAILED 执行失败 - * @par 依赖: - * @li tune_api.cpp:该接口所属的开发包。 - * @li tune_api.h:该接口声明所在的头文件。 - * @see 无 - * @since - */ -extern "C" MsTuneStatus MsTrainTuning(ge::Graph &tuningGraph, std::vector &dependGraph, - ge::Session *session, const std::map> &option); - /** * @ingroup aoe * @par 描述: 调优初始化 @@ -61,7 +41,7 @@ extern "C" MsTuneStatus MsTrainTuning(ge::Graph &tuningGraph, std::vector Date: Thu, 20 May 2021 17:40:34 +0800 Subject: [PATCH 27/59] run ge head --- inc/external/acl/acl_mdl.h | 13 +++ inc/external/hccl/hccl.h | 16 +++ metadef | 2 +- third_party/fwkacllib/inc/ops/array_ops.h | 23 +++++ third_party/fwkacllib/inc/ops/batch_ops.h | 4 +- third_party/fwkacllib/inc/ops/correlation.h | 52 ++++++++++ .../inc/ops/elewise_calculation_ops.h | 19 ---- third_party/fwkacllib/inc/ops/image_ops.h | 66 +++++++++++++ .../inc/ops/matrix_calculation_ops.h | 2 +- third_party/fwkacllib/inc/ops/nn_detect_ops.h | 2 - third_party/fwkacllib/inc/ops/nn_norm_ops.h | 75 +++++++++++++- .../fwkacllib/inc/ops/nonlinear_fuc_ops.h | 63 ++++++++++-- third_party/fwkacllib/inc/ops/pad_ops.h | 15 ++- third_party/fwkacllib/inc/ops/quantize_ops.h | 8 +- third_party/fwkacllib/inc/ops/rnn.h | 97 ++++++++++++++++++- .../fwkacllib/inc/ops/transformation_ops.h | 46 +++++++++ third_party/fwkacllib/inc/runtime/kernel.h | 6 +- third_party/fwkacllib/inc/toolchain/slog.h | 24 ++--- 18 files changed, 473 insertions(+), 60 deletions(-) create mode 100644 third_party/fwkacllib/inc/ops/correlation.h diff --git a/inc/external/acl/acl_mdl.h b/inc/external/acl/acl_mdl.h index 88f85cb3..2bf85e29 100644 --- a/inc/external/acl/acl_mdl.h +++ b/inc/external/acl/acl_mdl.h @@ -43,6 +43,7 @@ extern "C" { #define ACL_DYNAMIC_TENSOR_NAME "ascend_mbatch_shape_data" #define ACL_DYNAMIC_AIPP_NAME "ascend_dynamic_aipp_data" +#define ACL_ATTR_NAME_DATA_DUMP_ORIGIN_OP_NAMES "_datadump_original_op_names" typedef struct aclmdlDataset aclmdlDataset; typedef struct aclmdlDesc aclmdlDesc; @@ -636,6 +637,18 @@ ACL_FUNC_VISIBILITY aclError aclmdlGetOutputDims(const aclmdlDesc *modelDesc, si */ ACL_FUNC_VISIBILITY aclError aclmdlGetCurOutputDims(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims); +/** + * @ingroup AscendCL + * @brief get attr value by op name + * + * @param modelDesc [IN] model description + * @param opName [IN] op name + * @param attr [IN] attr name + * + * @retval the attr value + */ +ACL_FUNC_VISIBILITY const char *aclmdlGetOpAttr(aclmdlDesc *modelDesc, const char *opName, const char *attr); + /** * @ingroup AscendCL * @brief get input name by index diff --git a/inc/external/hccl/hccl.h b/inc/external/hccl/hccl.h index 9992a636..8261adc4 100644 --- a/inc/external/hccl/hccl.h +++ b/inc/external/hccl/hccl.h @@ -118,7 +118,23 @@ extern HcclResult HcclReduceScatter(void *sendBuf, void *recvBuf, uint64_t recvC */ extern HcclResult HcclAllGather(void *sendBuf, void *recvBuf, uint64_t sendCount, HcclDataType dataType, HcclComm comm, aclrtStream stream); +/** + * @brief Get the rank size of this comm. + * + * @param comm A pointer identifying the communication resource based on. + * @param rankSize A pointer identifying the rank size. + * @return HcclResult + */ +extern HcclResult HcclGetRankSize(HcclComm comm, uint32_t *rankSize); +/** + * @brief Get the rank id of this comm. + * + * @param comm A pointer identifying the communication resource based on. + * @param rankSize A pointer identifying the rank id. + * @return HcclResult + */ +extern HcclResult HcclGetRankId(HcclComm comm, uint32_t *rank); /** * @brief Barrier operator. * diff --git a/metadef b/metadef index 7cb171b9..7cbdf957 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit 7cb171b9c511fec57ccc0ad746ef2126267fe18b +Subproject commit 7cbdf95765133b5a5b979c2231013f7c76c3d529 diff --git a/third_party/fwkacllib/inc/ops/array_ops.h b/third_party/fwkacllib/inc/ops/array_ops.h index 375802fc..b5f49dad 100644 --- a/third_party/fwkacllib/inc/ops/array_ops.h +++ b/third_party/fwkacllib/inc/ops/array_ops.h @@ -1202,6 +1202,29 @@ REG_OP(Expand) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) .OP_END_FACTORY_REG(Expand) +/** +*@Returns a tensor containing the indices of all non-zero elements of input. \n + +*@par Inputs: +*@li x: A Tensor. Must be one of the following types: float16, float32, int32, int64. + +*@par Attributes: +* transpose: the output tensor will be transposed if true. \n + +*@par Outputs: +* y: A Tensor. Has the same type as "x" . \n + +*@par Third-party framework compatibility +*Compatible with the PyTorch operator NonZero. +*/ + +REG_OP(NonZero) + .INPUT(x, TensorType({DT_DOUBLE, DT_FLOAT, DT_FLOAT16, DT_INT8, DT_UINT8, DT_INT16, \ + DT_UINT16, DT_INT32, DT_UINT32, DT_INT64, DT_UINT64, DT_BOOL})) + .OUTPUT(y, TensorType({DT_INT64})) + .ATTR(transpose, Bool, false) + .OP_END_FACTORY_REG(NonZero) + /** * @brief Expand the input tensor to a compatible shape. \n diff --git a/third_party/fwkacllib/inc/ops/batch_ops.h b/third_party/fwkacllib/inc/ops/batch_ops.h index 181bf694..ca4fe1db 100644 --- a/third_party/fwkacllib/inc/ops/batch_ops.h +++ b/third_party/fwkacllib/inc/ops/batch_ops.h @@ -64,10 +64,10 @@ the same types as "x_tensors" . It's a dynamic output. \n REG_OP(Batch) .DYNAMIC_INPUT(x_tensors, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, \ DT_INT16, DT_UINT16, DT_UINT8, DT_INT32, DT_INT64, DT_BOOL, DT_DOUBLE})) - .OUTPUT(y_index, TensorType({ DT_INT64 })) - .OUTPUT(y_id, TensorType({ DT_INT64 })) .DYNAMIC_OUTPUT(y_tensors, TensorType({DT_INT8, DT_UINT8, DT_INT16, \ DT_UINT16, DT_INT32, DT_INT64, DT_FLOAT, DT_FLOAT16, DT_DOUBLE, DT_BOOL})) + .OUTPUT(y_index, TensorType({ DT_INT64 })) + .OUTPUT(y_id, TensorType({ DT_INT64 })) .REQUIRED_ATTR(num_batch_threads, Int) .REQUIRED_ATTR(max_batch_size, Int) .ATTR(max_enqueued_batches, Int, 10) diff --git a/third_party/fwkacllib/inc/ops/correlation.h b/third_party/fwkacllib/inc/ops/correlation.h new file mode 100644 index 00000000..caebba50 --- /dev/null +++ b/third_party/fwkacllib/inc/ops/correlation.h @@ -0,0 +1,52 @@ +/** + * Copyright 2020 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. + */ + +/*! + * \file correlation.h + * \brief + */ +#ifndef GE_OP_CORRELATION_OPS_H +#define GE_OP_CORRELATION_OPS_H + +#include "graph/operator_reg.h" + +namespace ge { +/** +*@brief Computes a 2D Correlation given 4D "x" and "filter" tensors. +* +*@par Inputs: +* @li filter: A 4D tensor of filters. +* @li x: A 4D tensor of input images, batch number must equal to batch +* number of "filter", and channel must equal to channel of "filter". +* +*@par Attributes: +* @li groups: set correlation mode, must be 1 or channel. +* +*@par Outputs: +*y: A Tensor. Has the same type as "x". + +*@par Third-party framework compatibility +* Compatible with caffe correlation custom operator. +*/ +REG_OP(Correlation) + .INPUT(filter, TensorType({DT_FLOAT16, DT_INT8})) + .INPUT(x, TensorType({DT_FLOAT16, DT_INT8})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_INT32})) + .ATTR(groups, Int, 1) + .OP_END_FACTORY_REG(Correlation) +} // namespace ge + +#endif // GE_OP_NN_CALCULATION_OPS_H diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index 8c87cfe8..7850536d 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -3467,25 +3467,6 @@ REG_OP(AxpyV2) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) .OP_END_FACTORY_REG(AxpyV2) -/** -* @brief Computes the result of x1 + x2. - -* @par Inputs: -* @li x1: An ND tensor of type float16, float, int32. -* @li x2: An ND tensor of type float16, float, int32. \n - -* @par Outputs: -* @li y: An ND tensor tensor with the same type as "x1". \n - -* @par Third-party framework compatibility -* Compatible with the Pytorch operator Add. -*/ -REG_OP(PtAdd) - .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) - .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) - .OP_END_FACTORY_REG(PtAdd) - /** * @brief Computes the result of x1 * x2. diff --git a/third_party/fwkacllib/inc/ops/image_ops.h b/third_party/fwkacllib/inc/ops/image_ops.h index e6802c1e..71f1b9e1 100644 --- a/third_party/fwkacllib/inc/ops/image_ops.h +++ b/third_party/fwkacllib/inc/ops/image_ops.h @@ -1483,6 +1483,55 @@ REG_OP(CombinedNonMaxSuppression) .ATTR(clip_boxes, Bool, true) .OP_END_FACTORY_REG(CombinedNonMaxSuppression) +/** +*@brief Resizes "images" with "offset" using bilinear interpolation. \n + +*@par Inputs: +*@li img: input image, A 4-D tensor of shape `[n, h, w, c]`. +*@li warp_offset: the resize offset A 4-D float tensor of shape `[n, h, w, 2]`, 2 means (x, y) for offset point. + +*@par Outputs: +*warp_img: A Tensor after resize. \n +*/ +REG_OP(IMGWarp) + .INPUT(img, TensorType({DT_UINT8, DT_FLOAT16, DT_FLOAT32})) + .INPUT(warp_offset, TensorType({DT_FLOAT32})) + .OUTPUT(warp_img, TensorType({DT_UINT8, DT_FLOAT16, DT_FLOAT32})) + .OP_END_FACTORY_REG(IMGWarp) + +/** +*@brief Resizes "images" with "offset" using bilinear interpolation. \n + +*@par Inputs: +*@li img: input image, A 4-D tensor of shape `[n, h, w, c]`. +*@li map_offset: the resize offset A 4-D float tensor of shape `[n, h, w, 2]`, 2 means (x, y) for resize point. + +*@par Outputs: +*map_img: A Tensor after resize. \n +*/ +REG_OP(Remap) + .INPUT(img, TensorType({DT_UINT8, DT_FLOAT16, DT_FLOAT32})) + .INPUT(map_offset, TensorType({DT_FLOAT32})) + .OUTPUT(map_img, TensorType({DT_UINT8, DT_FLOAT16, DT_FLOAT32})) + .OP_END_FACTORY_REG(Remap) + +/** +*@brief Resizes "images" with "offset" using bilinear interpolation. \n + +*@par Inputs: +*@li img: input image, A 5-D tensor of shape `[n, 4, c, h, w]`, +and 4 mean input[(h_top, w_left), (h_top, w_right), (h_bottom, w_left), (h_bottom, w_right)]. +*@li warp_index: the resize offset A 4-D float tensor of shape `[n, 2, h, w]`, 2 means (x, y) for resize point. + +*@par Outputs: +*remap_img: A Tensor after ResizeBilinear, A 4-D tensor of shape `[n, c, h, w]`. \n +*/ +REG_OP(IMGWarpResize) + .INPUT(img, TensorType({DT_FLOAT32})) + .INPUT(warp_index, TensorType({DT_FLOAT32})) + .OUTPUT(warp_img, TensorType({DT_FLOAT32})) + .OP_END_FACTORY_REG(IMGWarpResize) + /** *@brief Function spatial transformer . \n @@ -1802,5 +1851,22 @@ REG_OP(ImageUnfold) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(padding_mode, String, "zeros") .OP_END_FACTORY_REG(ImageUnfold) + +/** +*@brief This operation select images to warp_images according to offsets. + +*@par Inputs: +*@li images: 4-D Tensor with shape `[batch, height, width, 3]`. +*@li offsets: 4-D Tensor with shape `[batch, 4, new_height, new_width]`. + +*@par Outputs: +*warp_images: Returns 5-D Tensor with shape +`[batch, 4, new_height, new_width, 3]` and the same dtype as `images`. +*/ +REG_OP(IMGWarpOffsets) + .INPUT(images, TensorType({DT_UINT8, DT_FLOAT16, DT_FLOAT})) + .INPUT(offsets, TensorType({DT_FLOAT, DT_INT32})) + .OUTPUT(warp_images, TensorType({DT_UINT8, DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(IMGWarpOffsets) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_IMAGE_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index 083d4f9c..af02276b 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -179,7 +179,7 @@ REG_OP(GEMM) *@brief Multiplies matrix "a" by matrix "b", producing "a * b" . \n *@par Inputs: -*Three inputs, including: +*Two inputs, including: * @li x1: A matrix Tensor. Must be one of the following types: float16, * float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ]. * @li x2: A matrix Tensor. Must be one of the following types: float16, diff --git a/third_party/fwkacllib/inc/ops/nn_detect_ops.h b/third_party/fwkacllib/inc/ops/nn_detect_ops.h index cc60f483..d4141e47 100644 --- a/third_party/fwkacllib/inc/ops/nn_detect_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_detect_ops.h @@ -1460,8 +1460,6 @@ REG_OP(DecodeBboxV2) * @li y1: A Tensor. Must have the same type as x. * @li y2: A Tensor. Indices of y1 in x. Dtype must be int32. * -*@attention Constraints: -* The upper limit of data on the direction axis is 7040. */ REG_OP(Sort) .INPUT(x, TensorType({ DT_FLOAT16 })) diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index 22023f46..796e1e61 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -55,7 +55,9 @@ REG_OP(LogSoftmaxGrad) *Two inputs, including: * @li features: A Tensor. Must be one of the following types: half, float32, double. * A "batch_size * num_classes" matrix. -* @li labels: A Tensor of the same type as "features". batch_size vector with values in [0, num_classes). +* @li labels: A Tensor. Must be one of the following types: 'int32', 'int64'. +* batch_size vector with values in [0, num_classes). +* This is the label for the given minibatch entry. *@par Outputs: @@ -638,6 +640,48 @@ REG_OP(LayerNormXBackprop) .OUTPUT(pd_x, TensorType({DT_FLOAT, DT_FLOAT16})) .OP_END_FACTORY_REG(LayerNormXBackprop) +/** +*@brief LayerNormXBackpropV2 operator interface implementation +* calculating: dy, x, variance, mean, gamma +* pd_xl = data_dy*data_gamma +* pd_var = np.sum(((-0.5)*pd_xl*(data_x - data_mean) +* np.power((data_variance + EPSLON), (-1.5))), +* reduce_axis, keepdims=True) +* pd_mean = np.sum(((-1.0)*pd_xl +* np.power((data_variance + EPSLON), (-0.5))), +* reduce_axis, keepdims=True) +* + pd_var*(1.0/m) +* np.sum(((-2.0)*(data_x - data_mean)), reduce_axis, keepdims=True) +* pd_x = pd_xl*np.power((data_variance + EPSLON), (-0.5)) + +* pd_var*(2.0/m)*(data_x - data_mean) + pd_mean*(1.0/m) +* res_for_gamma = (data_x - data_mean) * np.power((data_variance + EPSLON), (-0.5)) + +*@par Inputs: +*Five inputs, including: +* @li dy: A Tensor. Must be one of the following types: float16, float32. +* @li x: A Tensor. Must be one of the following types: float16, float32. +* @li variance: A Tensor. Must be one of the following types: float16, float32. +* @li mean: A Tensor. Must be one of the following types: float16, float32. +* @li gamma: A Tensor. Must be one of the following types: float16, float32 . \n + +*@par Outputs: +*Three outputs, including: +* @li pd_x: A Tensor. Must be one of the following types: float16, float32. +* @li res_for_gamma: A Tensor. Must be one of the following types: float32. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(LayerNormXBackpropV2) + .INPUT(dy, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(variance, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(mean, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(gamma, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(pd_x, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(res_for_gamma, TensorType({DT_FLOAT})) + .OP_END_FACTORY_REG(LayerNormXBackpropV2) + /** *@brief LayerNormBetaGammaBackprop operator interface implementation * calculating: dy, x, variance, mean @@ -681,6 +725,35 @@ REG_OP(LayerNormBetaGammaBackprop) .REQUIRED_ATTR(shape_gamma, ListInt) .OP_END_FACTORY_REG(LayerNormBetaGammaBackprop) +/** +*@brief LayerNormBetaGammaBackpropV2 operator interface implementation +* calculating: dy, x, variance, mean +* pd_gamma = np.sum((data_dy*res_for_gamma), param_axis, keepdims=True) +* pd_beta = np.sum(data_dy, param_axis, keepdims=True) + +*@par Inputs: +*Three inputs, including: +* @li dy: A Tensor. Must be one of the following types: float16, float32. +* @li x: A Tensor. Must be one of the following types: float16, float32. +* @li variance: A Tensor. Must be one of the following types: float16, float32. +* @li mean: A Tensor. Must be one of the following types: float16, float32 . \n + +*@par Outputs: +*Three outputs, including: +* @li pd_gamma: A Tensor. Must be one of the following types: float16, float32. +* @li pd_beta: A Tensor. Must be one of the following types: float16, float32. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(LayerNormBetaGammaBackpropV2) + .INPUT(dy, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(res_for_gamma, TensorType({DT_FLOAT})) + .OUTPUT(pd_gamma, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(pd_beta, TensorType({DT_FLOAT, DT_FLOAT16})) + .REQUIRED_ATTR(shape_gamma, ListInt) + .OP_END_FACTORY_REG(LayerNormBetaGammaBackpropV2) + /** *@brief Return "output" according to the algorithm of dropout_do_mask: * scale_x = x *(1 / keep_prob) diff --git a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h index 4cbe4057..ca1c24eb 100644 --- a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h +++ b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h @@ -536,13 +536,19 @@ REG_OP(Elu) * max(0, x) + min(0, alpha * (exp(x/alpha) - 1)). \n *@par Inputs: -*x: A float16, float32 or double, for the input data type . \n +*x: A float16, float32, for the input data type . \n *@par Attributes: -*alpha: A float32. Defines at which negative value the ELU saturates. Defaults to "1.0" . \n +*alpha1: A float32. Defines at which negative value the ELU saturates. Defaults to "1.0" . \n + +*@par Attributes: +*alpha2: A float32. Defines at which negative value the ELU saturates. Defaults to "1.0" . \n + +*@par Attributes: +*alpha3: A float32. Defines at which positive value the ELU saturates. Defaults to "1.0" . \n *@par Outputs: -*y: A float16, float32 or double, for the normalized result . \n +*y: A float16, float32, for the normalized result . \n *@attention Constraints: *@li The input is of type float16 or float32 . \n @@ -553,9 +559,11 @@ REG_OP(Elu) *@li Compatible with ONNX's Celu operator */ REG_OP(Celu) - .INPUT(x, TensorType::FloatingDataType()) - .OUTPUT(y, TensorType::FloatingDataType()) - .ATTR(alpha, Float, 1.0) + .INPUT(x, TensorType({DT_FLOAT,DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT,DT_FLOAT16})) + .ATTR(alpha1, Float, 1.0) + .ATTR(alpha2, Float, 1.0) + .ATTR(alpha3, Float, 1.0) .OP_END_FACTORY_REG(Celu) /** @@ -690,6 +698,25 @@ REG_OP(Mish) .OUTPUT(y, TensorType({ DT_FLOAT,DT_FLOAT16 })) .OP_END_FACTORY_REG(Mish) +/** + * @brief: pytorch mish_grad operator. + * @par Inputs: + * three input, including: + * @li grad: A Tensor. shape, datatype and format is same as x + * @li x: A Tensor. Must be one of the following types: float16, float32 + * @li tanhx: A Tensor. shape, datatype and format is same as x + * @par Outputs: + * 1 output, including: + * @li x_grad: A Tensor. shape, datatype and format is same as x + */ + +REG_OP(MishGrad) + .INPUT(grad, TensorType({ DT_FLOAT,DT_FLOAT16 })) + .INPUT(x, TensorType({ DT_FLOAT,DT_FLOAT16 })) + .OPTIONAL_INPUT(tanhx, TensorType({ DT_FLOAT,DT_FLOAT16 })) + .OUTPUT(x_grad, TensorType({ DT_FLOAT,DT_FLOAT16 })) + .OP_END_FACTORY_REG(MishGrad) + /** * @brief pytorch hardtanh_backward operator. * @@ -993,6 +1020,30 @@ REG_OP(HardSigmoidGrad) .ATTR(beta, Float, 0.5) .OP_END_FACTORY_REG(HardSigmoidGrad) +/** +* @brief Calculate the shrink function. \n + +* @par Inputs: +* One inputs, including: +* @li input_x: A tensor. Must be one of the following types: +* float16, float32. \n + +* @par Attributes: +* @li lambd: An optional float. Defaults to 0.5. \n +* @li bias: An optional float. Defaults to 0.0. \n + +* @par Outputs: +* y: A Tensor with the same dtype and shape of input_x's. \n + +* @par Third-party framework compatibility +* Compatible with the ONNX operator Shrink. \n +*/ +REG_OP(Shrink) + .INPUT(input_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(lambd, Float, 0.5) + .ATTR(bias, Float, 0.0) + .OP_END_FACTORY_REG(Shrink) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NONLINEAR_FUC_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/pad_ops.h b/third_party/fwkacllib/inc/ops/pad_ops.h index 42da3828..bacbe40d 100644 --- a/third_party/fwkacllib/inc/ops/pad_ops.h +++ b/third_party/fwkacllib/inc/ops/pad_ops.h @@ -273,14 +273,11 @@ REG_OP(PadV3) *@brief Pads a tensor. *@par Inputs: -*x: A Tensor. Must be one of the following types: float16, float32, int8, uint8, int32. +* @li x: A Tensor. Must be one of the following types: float16, float32. +* @li paddings: A Tensor. Must be int32 type +* paddings is a required input tensor. *@par Attributes: -* @li paddings: An required "vector>". -* For each dimension D of input, paddings[D, 0] indicates how many -* values to add before the contents of tensor in that dimension, -* and paddings[D, 1] indicates how many values to add after the -* contents of tensor in that dimension. * @li constant_values: An optional int value for pad. * @li mode: An optional string, Defaults to "constant", indicates paddings mode, * support "constant", "reflect", "edge" @@ -298,9 +295,9 @@ REG_OP(PadV3) * Warning: THIS FUNCTION IS DEPRECATED. Please use PadV3 instead. */ REG_OP(PadV3D) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_UINT8})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_UINT8})) - .REQUIRED_ATTR(paddings, ListListInt) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(paddings, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(constant_values, Int, 0) .ATTR(mode, String, "constant") .ATTR(paddings_contiguous, Bool, true) diff --git a/third_party/fwkacllib/inc/ops/quantize_ops.h b/third_party/fwkacllib/inc/ops/quantize_ops.h index eafc8cc4..d6eda1e6 100644 --- a/third_party/fwkacllib/inc/ops/quantize_ops.h +++ b/third_party/fwkacllib/inc/ops/quantize_ops.h @@ -214,7 +214,7 @@ REG_OP(AscendRequant) *@brief Requantizes the input of int16 . \n *@par Inputs: -*@li x: An NC1HWC0 tensor of type int16, specifying the input. +*@li x0: An NC1HWC0 tensor of type int16, specifying the input. *@li req_scale: An NC1HWC0 tensor of type uint64, specifying the scaling ratio. *@li x1: An NC1HWC0 tensor of type int16 . \n @@ -223,17 +223,17 @@ REG_OP(AscendRequant) *@li relu_flag: A optional bool, specifying whether to perform ReLU, either "True" or "False". Defaults to "False" . \n *@par Outputs: -*@li y: The dequantized output tensor of type int8 and with format NC1HWC0. +*@li y0: The dequantized output tensor of type int8 and with format NC1HWC0. *@li y1: The dequantized output tensor of type int16 and with format NC1HWC0 . \n *@par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. */ REG_OP(AscendRequantS16) - .INPUT(x, TensorType({DT_INT16})) + .INPUT(x0, TensorType({DT_INT16})) .INPUT(req_scale, TensorType({DT_UINT64})) .OPTIONAL_INPUT(x1, TensorType({DT_INT16})) - .OUTPUT(y, TensorType({DT_INT8})) + .OUTPUT(y0, TensorType({DT_INT8})) .OUTPUT(y1, TensorType({DT_INT16})) .ATTR(dual_output, Bool, false) .ATTR(relu_flag, Bool, false) diff --git a/third_party/fwkacllib/inc/ops/rnn.h b/third_party/fwkacllib/inc/ops/rnn.h index d671a531..9c6a7d1b 100644 --- a/third_party/fwkacllib/inc/ops/rnn.h +++ b/third_party/fwkacllib/inc/ops/rnn.h @@ -33,6 +33,7 @@ namespace ge { *@li c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li w:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_Z. *@li b:A 1D Tensor. Must be one of the following types: float16. The format must be ND . \n +*@li mask:A 1D Tensor. Must be one of the following types: uint8. *@par Attributes: *@li keep_prob:An integer identifying the keep prob in the op. Default to 1. @@ -42,7 +43,6 @@ namespace ge { *@par Outputs: *seven outputs: -*@li mask:A 1D Tensor. Must be one of the following types: uint8. *@li ct:A 4D Tensor. Must be one of the following types: float16, float32. *@li ht:A 4D Tensor. Must be one of the following types: float16. *@li it:A 4D Tensor. Must be one of the following types: float16, float32. @@ -209,6 +209,7 @@ REG_OP(DynamicRNNGrad) *@li time_major:An bool identifying the time major in the op. Default to true. *@li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported. *@li forget_bias:An float identifying the forget bias in the op. Default to 0. +*@li gate_order:An string identifying the type of gate order in the op. Support "ijfo" and "ifjo". Default to "ijfo". *@li is_training:An bool identifying is training in the op. Default to true . \n *@par Outputs: @@ -253,9 +254,103 @@ REG_OP(DynamicRNN) .ATTR(time_major, Bool, true) .ATTR(activation, String, "tanh") .ATTR(forget_bias, Float, 0.0) + .ATTR(gate_order, String, "ijfo") .ATTR(is_training, Bool, true) .OP_END_FACTORY_REG(DynamicRNN) +/** +*@brief: DynamicRNNV2 calculation. +*@par Inputs: +*ten inputs: +*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li weight_input:A required 4D Tensor. Must be one of the following types: float16, float32. +*The format must be FRACTAL_Z. +*@li weight_hidden:A required 4D Tensor. Must be one of the following types: float16, float32. +*The format must be FRACTAL_Z. +*@li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. +*@li seq_length:A optional 1D Tensor. Must be one of the following types: int32. The format must be ND. +*@li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li wcf:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li wco:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li mask:A 1D optional Tensor. Must be one of the following types: uint8. The format must be ND . \n + +*@par Attributes: +*@li cell_type:An string identifying the cell type in the op. Default to "LSTM". Only LSTM is currently supported. +*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". +*Only UNIDIRECTIONAL is currently supported. +*@li cell_depth:An integer identifying the cell depth in the op. Default to 1. +*@li use_peephole:An bool identifying if use peephole in the op. Default to false. +*@li keep_prob:An float identifying the keep prob in the op. Default to 1. +*@li cell_clip:An float identifying the cell clip in the op. Default to -1. +*@li num_proj:An integer identifying the num projection in the op. Default to 0. +*@li time_major:An bool identifying the time major in the op. Default to true. +*@li activation:An string identifying the type of activation function in the op. Default to "tanh". +*Only tanh is currently supported. +*@li recurrent_activation:An string identifying the type of activation function in the op. Default to "sigmoid". +*Supprot "sigmoid" and "hard_sigmoid". In general, set "hard_sigmoid" for TF Keras LSTM. +*@li forget_bias:An float identifying the forget bias in the op. Default to 0. +*@li gate_order:An string identifying the type of gate order in the op. Support "ijfo" and "ifco". Default to "ijfo". +*Set "ijfo" for TF operator LSTM, Set "ifco" for TF Keras LSTM. +*@li stateful: An bool identifying the type of stateful in the op. Default to fasle.Only false is currently supported. +*@li merge_mode: An string identifying the type of merge_modein the op. Default to "concat". +*Only "concat" is currently supported +*@li is_training:An bool identifying is training in the op. Default to true . \n + +*@par Outputs: +*eight outputs: +*@li y:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li output_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*Return the last output_h. +*@li output_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*Return the last output_c. +*@li i:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li j:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li f:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li o:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@par Third-party framework compatibility: +* Compatible with the TF operator LSTM or TF keras operator LSTM. +*/ + +REG_OP(DynamicRNNV2) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(weight_input, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(weight_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(b, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32})) + .OPTIONAL_INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(init_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wci, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wcf, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wco, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(mask, TensorType({DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(i, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(j, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(f, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(o, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(tanhc, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(cell_type, String, "LSTM") + .ATTR(direction, String, "UNIDIRECTIONAL") + .ATTR(cell_depth, Int, 1) + .ATTR(use_peephole, Bool, false) + .ATTR(keep_prob, Float, 1.0) + .ATTR(cell_clip, Float, -1.0) + .ATTR(num_proj, Int, 0) + .ATTR(time_major, Bool, true) + .ATTR(activation, String, "tanh") + .ATTR(recurrent_activation, String, "sigmoid") + .ATTR(forget_bias, Float, 0.0) + .ATTR(gate_order, String, "ijfo") + .ATTR(stateful, Bool, false) + .ATTR(merge_mode, String, "concat") + .ATTR(is_training, Bool, true) + .OP_END_FACTORY_REG(DynamicRNNV2) + /** *@brief: DynamicRNNV3 calculation. *@par Inputs: diff --git a/third_party/fwkacllib/inc/ops/transformation_ops.h b/third_party/fwkacllib/inc/ops/transformation_ops.h index 48a094f7..2e8ffd9c 100644 --- a/third_party/fwkacllib/inc/ops/transformation_ops.h +++ b/third_party/fwkacllib/inc/ops/transformation_ops.h @@ -742,6 +742,52 @@ REG_OP(Col2im) .REQUIRED_ATTR(stride, ListInt) .OP_END_FACTORY_REG(Col2im) +/** +* @brief Performs Im2col for each batch entry. \n + +* @par Inputs: +* x: A 4D Tensor with shape [batch, in_rows, in_cols, depth], Must be one of the +* following types:float32, int8, float16. The inputs must have data_format with +* one of follows:NHWC, NCHW. + +* @par Attributes: +* @li ksizes: A required list or tuple. The size of the sliding window for each +* dimension of images. +* @li strides: A optional list or tuple. How far the centers of two consecutive +* patches are in the images. Defaults to "{1}". +* @li dilations: A optional list or tuple. Defaults to "{1}". +* This is the input stride, specifying how far two consecutive patch +* samples are in the input. Equivalent to extracting patches +* with patch_sizes_eff = patch_sizes + (patch_sizes - 1) * +* (dilations - 1), followed by subsampling them spatially by a factor of dilations. +* This is equivalent to rate in dilated (a.k.a. Atrous) convolutions. +* @li padding_mode: A optional String. The type of padding algorithm to use, +* support "SAME", "VALID", "CALCULATED". Among the three modes, only the "CALCULATED" +* means to use the pads below. Defaults to "CALCULATED". +* @li pads: A optional list or tuple. The pad distance. Defaults to "{0}". \n + +* @par Outputs: +* y: A 4D Tensor with shape [batch, out_rows, out_cols, ksize_rows * +* ksize_cols * depth] containing image patches with size ksize_rows x ksize_cols +* x depth vectorized in the "depth" dimension. Note "out_rows" and "out_cols" +* are the dimensions of the output patches . \n + +* @attention Constraints: +* "ksizes", "strides", "dilations" and "pads" are lists of integers . \n + +* @par Third-party framework compatibility +* Compatible with Pytorch Im2col operator. +*/ +REG_OP(Im2col) + .INPUT(x, TensorType::RealNumberType()) + .OUTPUT(y, TensorType::RealNumberType()) + .REQUIRED_ATTR(ksizes, ListInt) + .ATTR(strides, ListInt, {1}) + .ATTR(dilations, ListInt, {1}) + .ATTR(padding_mode, String, "CALCULATED") + .ATTR(pads, ListInt, {0}) + .OP_END_FACTORY_REG(Im2col) + /** *@brief Generates a 2D or 3D flow field (sampling grid), given a batch of affine matrices theta. \n diff --git a/third_party/fwkacllib/inc/runtime/kernel.h b/third_party/fwkacllib/inc/runtime/kernel.h index 338e8854..c79ee7a5 100644 --- a/third_party/fwkacllib/inc/runtime/kernel.h +++ b/third_party/fwkacllib/inc/runtime/kernel.h @@ -186,9 +186,9 @@ typedef void (*rtCallback_t)(void *fnData); #define RT_KERNEL_CUSTOM_AICPU (0x08) // STARS topic scheduler sqe : topic_type -#define RT_KERNEL_DEVICE_FIRST (0X10) -#define RT_KERNEL_HOST_ONLY (0X20) -#define RT_KERNEL_HOST_FIRST (0X30) +#define RT_KERNEL_DEVICE_FIRST (0x10) +#define RT_KERNEL_HOST_ONLY (0x20) +#define RT_KERNEL_HOST_FIRST (0x40) /** * @ingroup rt_kernel diff --git a/third_party/fwkacllib/inc/toolchain/slog.h b/third_party/fwkacllib/inc/toolchain/slog.h index c6be6b79..cc7c83ca 100644 --- a/third_party/fwkacllib/inc/toolchain/slog.h +++ b/third_party/fwkacllib/inc/toolchain/slog.h @@ -17,6 +17,8 @@ #ifndef D_SYSLOG_H_ #define D_SYSLOG_H_ +static const int TMP_LOG = 0; + #ifdef __cplusplus #ifndef LOG_CPP extern "C" { @@ -261,7 +263,7 @@ DLL_EXPORT int DlogSetAttr(LogAttr logAttr); #define dlog_error(moduleId, fmt, ...) \ do { \ DlogErrorInner(moduleId, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ - } while (0) + } while (TMP_LOG != 0) /** * @ingroup slog @@ -276,7 +278,7 @@ DLL_EXPORT int DlogSetAttr(LogAttr logAttr); if(CheckLogLevel(moduleId, DLOG_WARN) == 1) { \ DlogWarnInner(moduleId, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ } \ - } while (0) + } while (TMP_LOG != 0) /** * @ingroup slog @@ -291,7 +293,7 @@ DLL_EXPORT int DlogSetAttr(LogAttr logAttr); if(CheckLogLevel(moduleId, DLOG_INFO) == 1) { \ DlogInfoInner(moduleId, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ } \ - } while (0) + } while (TMP_LOG != 0) /** * @ingroup slog @@ -306,7 +308,7 @@ DLL_EXPORT int DlogSetAttr(LogAttr logAttr); if(CheckLogLevel(moduleId, DLOG_DEBUG) == 1) { \ DlogDebugInner(moduleId, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ } \ - } while (0) + } while (TMP_LOG != 0) /** * @ingroup slog @@ -318,7 +320,7 @@ DLL_EXPORT int DlogSetAttr(LogAttr logAttr); #define dlog_event(moduleId, fmt, ...) \ do { \ DlogEventInner(moduleId, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ - } while (0) + } while (TMP_LOG != 0) /** * @ingroup slog @@ -334,7 +336,7 @@ DLL_EXPORT int DlogSetAttr(LogAttr logAttr); if(CheckLogLevel(moduleId, level) == 1) { \ DlogInner(moduleId, level, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ } \ - } while (0) + } while (TMP_LOG != 0) /** * @ingroup slog @@ -351,7 +353,7 @@ DLL_EXPORT int DlogSetAttr(LogAttr logAttr); if(CheckLogLevel(moduleId, level) == 1) { \ DlogInner(moduleId, level, "[%s:%d][%s]" fmt, __FILE__, __LINE__, submodule, ##__VA_ARGS__); \ } \ - } while (0) + } while (TMP_LOG != 0) /** * @ingroup slog @@ -369,7 +371,7 @@ DLL_EXPORT int DlogSetAttr(LogAttr logAttr); if(CheckLogLevel(moduleId, level) == 1) { \ DlogWithKVInner(moduleId, level, pstKVArray, kvNum, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ } \ - } while (0) + } while (TMP_LOG != 0) /** * @ingroup slog @@ -453,7 +455,7 @@ DLL_EXPORT int DlogSetAttrForC(LogAttr logAttr); if(CheckLogLevelForC(moduleId, level) == 1) { \ DlogInnerForC(moduleId, level, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ } \ - } while (0) + } while (TMP_LOG != 0) /** * @ingroup slog @@ -470,7 +472,7 @@ DLL_EXPORT int DlogSetAttrForC(LogAttr logAttr); if(CheckLogLevelForC(moduleId, level) == 1) { \ DlogInnerForC(moduleId, level, "[%s:%d][%s]" fmt, __FILE__, __LINE__, submodule, ##__VA_ARGS__); \ } \ - } while (0) + } while (TMP_LOG != 0) /** * @ingroup slog @@ -488,7 +490,7 @@ DLL_EXPORT int DlogSetAttrForC(LogAttr logAttr); if(CheckLogLevelForC(moduleId, level) == 1) { \ DlogWithKVInnerForC(moduleId, level, pstKVArray, kvNum, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ } \ - } while (0) + } while (TMP_LOG != 0) /** * @ingroup slog From ba20c7d22c39028c3136692c47888f9018a00ea6 Mon Sep 17 00:00:00 2001 From: dingpeifei Date: Sat, 5 Jun 2021 10:43:16 +0800 Subject: [PATCH 28/59] code_sync_0604_inc --- inc/external/acl/acl.h | 10 +- inc/external/acl/acl_base.h | 91 ++-- inc/external/acl/acl_mdl.h | 361 ++++++++------- inc/external/acl/acl_op.h | 119 +++-- inc/external/acl/acl_op_compiler.h | 54 ++- inc/external/acl/acl_prof.h | 46 +- inc/external/acl/acl_rt.h | 142 +++--- inc/external/acl/acl_tdt.h | 31 +- inc/external/acl/error_codes/rt_error_codes.h | 144 +++--- inc/external/acl/ops/acl_cblas.h | 179 ++++++-- inc/external/acl/ops/acl_dvpp.h | 425 +++++++++++------- inc/external/acl/ops/acl_fv.h | 14 +- inc/external/hccl/hccl.h | 39 +- inc/external/hccl/hccl_types.h | 84 ++-- inc/external/runtime/rt_error_codes.h | 144 +++--- .../fwkacllib/inc/ops/control_flow_ops.h | 8 +- third_party/fwkacllib/inc/ops/ctc_ops.h | 81 ++++ .../inc/ops/elewise_calculation_ops.h | 25 +- third_party/fwkacllib/inc/ops/globalavgpool.h | 49 ++ third_party/fwkacllib/inc/ops/image_ops.h | 68 +++ third_party/fwkacllib/inc/ops/linalg_ops.h | 6 +- third_party/fwkacllib/inc/ops/math_ops.h | 12 +- .../inc/ops/matrix_calculation_ops.h | 38 +- .../fwkacllib/inc/ops/nn_calculation_ops.h | 4 +- third_party/fwkacllib/inc/ops/nn_detect_ops.h | 106 ++++- third_party/fwkacllib/inc/ops/nn_norm_ops.h | 6 +- third_party/fwkacllib/inc/ops/nn_ops.h | 55 +++ .../fwkacllib/inc/ops/nn_pooling_ops.h | 23 +- third_party/fwkacllib/inc/ops/pad_ops.h | 99 ++-- third_party/fwkacllib/inc/ops/quantize_ops.h | 1 - third_party/fwkacllib/inc/ops/rnn.h | 54 +++ third_party/fwkacllib/inc/ops/selection_ops.h | 22 +- third_party/fwkacllib/inc/runtime/rt.h | 1 + third_party/fwkacllib/inc/runtime/rt_model.h | 1 + third_party/fwkacllib/inc/tdt/tsd_client.h | 82 ---- 35 files changed, 1646 insertions(+), 978 deletions(-) create mode 100644 third_party/fwkacllib/inc/ops/globalavgpool.h diff --git a/inc/external/acl/acl.h b/inc/external/acl/acl.h index 8d261201..a53d029d 100644 --- a/inc/external/acl/acl.h +++ b/inc/external/acl/acl.h @@ -26,9 +26,9 @@ extern "C" { #endif // Current version is 1.0.0 -#define ACL_MAJOR_VERSION 1 -#define ACL_MINOR_VERSION 0 -#define ACL_PATCH_VERSION 0 +#define ACL_MAJOR_VERSION 1 +#define ACL_MINOR_VERSION 0 +#define ACL_PATCH_VERSION 0 /** * @ingroup AscendCL @@ -72,11 +72,11 @@ ACL_FUNC_VISIBILITY aclError aclrtGetVersion(int32_t *majorVersion, int32_t *min * * @retval null for failed * @retval OtherValues success - */ +*/ ACL_FUNC_VISIBILITY const char *aclGetRecentErrMsg(); #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_H_ +#endif // INC_EXTERNAL_ACL_ACL_H_ diff --git a/inc/external/acl/acl_base.h b/inc/external/acl/acl_base.h index 64d4bd81..417a80c8 100644 --- a/inc/external/acl/acl_base.h +++ b/inc/external/acl/acl_base.h @@ -136,49 +136,50 @@ static const int ACL_ERROR_PROFILING_FAILURE = 500005; #define ACL_UNKNOWN_RANK 0xFFFFFFFFFFFFFFFE typedef enum { - ACL_DT_UNDEFINED = -1, - ACL_FLOAT = 0, - ACL_FLOAT16 = 1, - ACL_INT8 = 2, - ACL_INT32 = 3, - ACL_UINT8 = 4, - ACL_INT16 = 6, - ACL_UINT16 = 7, - ACL_UINT32 = 8, - ACL_INT64 = 9, - ACL_UINT64 = 10, - ACL_DOUBLE = 11, - ACL_BOOL = 12, - ACL_STRING = 13, + ACL_DT_UNDEFINED = -1, + ACL_FLOAT = 0, + ACL_FLOAT16 = 1, + ACL_INT8 = 2, + ACL_INT32 = 3, + ACL_UINT8 = 4, + ACL_INT16 = 6, + ACL_UINT16 = 7, + ACL_UINT32 = 8, + ACL_INT64 = 9, + ACL_UINT64 = 10, + ACL_DOUBLE = 11, + ACL_BOOL = 12, + ACL_STRING = 13, } aclDataType; typedef enum { - ACL_FORMAT_UNDEFINED = -1, - ACL_FORMAT_NCHW = 0, - ACL_FORMAT_NHWC = 1, - ACL_FORMAT_ND = 2, - ACL_FORMAT_NC1HWC0 = 3, - ACL_FORMAT_FRACTAL_Z = 4, - ACL_FORMAT_NC1HWC0_C04 = 12, - ACL_FORMAT_NDHWC = 27, - ACL_FORMAT_FRACTAL_NZ = 29, - ACL_FORMAT_NCDHW = 30, - ACL_FORMAT_NDC1HWC0 = 32, - ACL_FRACTAL_Z_3D = 33 + ACL_FORMAT_UNDEFINED = -1, + ACL_FORMAT_NCHW = 0, + ACL_FORMAT_NHWC = 1, + ACL_FORMAT_ND = 2, + ACL_FORMAT_NC1HWC0 = 3, + ACL_FORMAT_FRACTAL_Z = 4, + ACL_FORMAT_NC1HWC0_C04 = 12, + ACL_FORMAT_NDHWC = 27, + ACL_FORMAT_FRACTAL_NZ = 29, + ACL_FORMAT_NCDHW = 30, + ACL_FORMAT_NDC1HWC0 = 32, + ACL_FRACTAL_Z_3D = 33 } aclFormat; typedef enum { - ACL_DEBUG = 0, - ACL_INFO = 1, - ACL_WARNING = 2, - ACL_ERROR = 3, + ACL_DEBUG = 0, + ACL_INFO = 1, + ACL_WARNING = 2, + ACL_ERROR = 3, } aclLogLevel; typedef enum { - ACL_MEMTYPE_DEVICE = 0, - ACL_MEMTYPE_HOST = 1, + ACL_MEMTYPE_DEVICE = 0, + ACL_MEMTYPE_HOST = 1, } aclMemType; + /** * @ingroup AscendCL * @brief Converts data of type aclFloat16 to data of type float @@ -311,7 +312,9 @@ ACL_FUNC_VISIBILITY size_t aclDataTypeSize(aclDataType dataType); * @retval aclTensorDesc pointer. * @retval nullptr if param is invalid or run out of memory */ -ACL_FUNC_VISIBILITY aclTensorDesc *aclCreateTensorDesc(aclDataType dataType, int numDims, const int64_t *dims, +ACL_FUNC_VISIBILITY aclTensorDesc *aclCreateTensorDesc(aclDataType dataType, + int numDims, + const int64_t *dims, aclFormat format); /** @@ -333,7 +336,8 @@ ACL_FUNC_VISIBILITY void aclDestroyTensorDesc(const aclTensorDesc *desc); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclSetTensorShapeRange(aclTensorDesc *desc, size_t dimsCount, +ACL_FUNC_VISIBILITY aclError aclSetTensorShapeRange(aclTensorDesc* desc, + size_t dimsCount, int64_t dimsRange[][ACL_TENSOR_SHAPE_RANGE_NUM]); /** @@ -430,7 +434,9 @@ ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimV2(const aclTensorDesc *desc, si * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimRange(const aclTensorDesc *desc, size_t index, size_t dimRangeNum, +ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimRange(const aclTensorDesc *desc, + size_t index, + size_t dimRangeNum, int64_t *dimRange); /** @@ -467,7 +473,7 @@ ACL_FUNC_VISIBILITY const char *aclGetTensorDescName(aclTensorDesc *desc); * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclTransTensorDescFormat(const aclTensorDesc *srcDesc, aclFormat dstFormat, - aclTensorDesc **dstDesc); + aclTensorDesc **dstDesc); /** * @ingroup AscendCL @@ -555,7 +561,7 @@ ACL_FUNC_VISIBILITY aclError aclSetTensorOriginShape(aclTensorDesc *desc, int nu * * @retval null for failed. * @retval OtherValues success. - */ +*/ ACL_FUNC_VISIBILITY aclTensorDesc *aclGetTensorDescByIndex(aclTensorDesc *desc, size_t index); /** @@ -566,7 +572,7 @@ ACL_FUNC_VISIBILITY aclTensorDesc *aclGetTensorDescByIndex(aclTensorDesc *desc, * * @retval null for failed * @retval OtherValues success - */ +*/ ACL_FUNC_VISIBILITY void *aclGetTensorDescAddress(const aclTensorDesc *desc); /** @@ -618,7 +624,7 @@ ACL_FUNC_VISIBILITY aclError aclSetTensorPlaceMent(aclTensorDesc *desc, aclMemTy * @param ... [IN] the value of current log */ ACL_FUNC_VISIBILITY void aclAppLog(aclLogLevel logLevel, const char *func, const char *file, uint32_t line, - const char *fmt, ...); + const char *fmt, ...); /** * @ingroup AscendCL @@ -626,13 +632,14 @@ ACL_FUNC_VISIBILITY void aclAppLog(aclLogLevel logLevel, const char *func, const * * @retval null for failed * @retval OtherValues success - */ +*/ ACL_FUNC_VISIBILITY const char *aclrtGetSocName(); -#define ACL_APP_LOG(level, fmt, ...) aclAppLog(level, __FUNCTION__, __FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define ACL_APP_LOG(level, fmt, ...) \ + aclAppLog(level, __FUNCTION__, __FILE__, __LINE__, fmt, ##__VA_ARGS__) #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_BASE_H_ +#endif // INC_EXTERNAL_ACL_ACL_BASE_H_ diff --git a/inc/external/acl/acl_mdl.h b/inc/external/acl/acl_mdl.h index 2bf85e29..1721929e 100644 --- a/inc/external/acl/acl_mdl.h +++ b/inc/external/acl/acl_mdl.h @@ -27,19 +27,19 @@ extern "C" { #endif -#define ACL_MAX_DIM_CNT 128 -#define ACL_MAX_TENSOR_NAME_LEN 128 -#define ACL_MAX_BATCH_NUM 128 -#define ACL_MAX_HW_NUM 128 -#define ACL_MAX_SHAPE_COUNT 128 -#define ACL_INVALID_NODE_INDEX 0xFFFFFFFF - -#define ACL_MDL_LOAD_FROM_FILE 1 -#define ACL_MDL_LOAD_FROM_FILE_WITH_MEM 2 -#define ACL_MDL_LOAD_FROM_MEM 3 -#define ACL_MDL_LOAD_FROM_MEM_WITH_MEM 4 -#define ACL_MDL_LOAD_FROM_FILE_WITH_Q 5 -#define ACL_MDL_LOAD_FROM_MEM_WITH_Q 6 +#define ACL_MAX_DIM_CNT 128 +#define ACL_MAX_TENSOR_NAME_LEN 128 +#define ACL_MAX_BATCH_NUM 128 +#define ACL_MAX_HW_NUM 128 +#define ACL_MAX_SHAPE_COUNT 128 +#define ACL_INVALID_NODE_INDEX 0xFFFFFFFF + +#define ACL_MDL_LOAD_FROM_FILE 1 +#define ACL_MDL_LOAD_FROM_FILE_WITH_MEM 2 +#define ACL_MDL_LOAD_FROM_MEM 3 +#define ACL_MDL_LOAD_FROM_MEM_WITH_MEM 4 +#define ACL_MDL_LOAD_FROM_FILE_WITH_Q 5 +#define ACL_MDL_LOAD_FROM_MEM_WITH_Q 6 #define ACL_DYNAMIC_TENSOR_NAME "ascend_mbatch_shape_data" #define ACL_DYNAMIC_AIPP_NAME "ascend_dynamic_aipp_data" @@ -52,123 +52,123 @@ typedef struct aclAippExtendInfo aclAippExtendInfo; typedef struct aclmdlConfigHandle aclmdlConfigHandle; typedef enum { - ACL_YUV420SP_U8 = 1, - ACL_XRGB8888_U8, - ACL_RGB888_U8, - ACL_YUV400_U8, - ACL_NC1HWC0DI_FP16, - ACL_NC1HWC0DI_S8, - ACL_ARGB8888_U8, - ACL_YUYV_U8, - ACL_YUV422SP_U8, - ACL_AYUV444_U8, - ACL_RAW10, - ACL_RAW12, - ACL_RAW16, - ACL_RAW24, - ACL_AIPP_RESERVED = 0xffff, + ACL_YUV420SP_U8 = 1, + ACL_XRGB8888_U8, + ACL_RGB888_U8, + ACL_YUV400_U8, + ACL_NC1HWC0DI_FP16, + ACL_NC1HWC0DI_S8, + ACL_ARGB8888_U8, + ACL_YUYV_U8, + ACL_YUV422SP_U8, + ACL_AYUV444_U8, + ACL_RAW10, + ACL_RAW12, + ACL_RAW16, + ACL_RAW24, + ACL_AIPP_RESERVED = 0xffff, } aclAippInputFormat; typedef enum { - ACL_MDL_PRIORITY_INT32 = 0, - ACL_MDL_LOAD_TYPE_SIZET, - ACL_MDL_PATH_PTR, /**< pointer to model load path with deep copy */ - ACL_MDL_MEM_ADDR_PTR, /**< pointer to model memory with shallow copy */ - ACL_MDL_MEM_SIZET, - ACL_MDL_WEIGHT_ADDR_PTR, /**< pointer to weight memory of model with shallow copy */ - ACL_MDL_WEIGHT_SIZET, - ACL_MDL_WORKSPACE_ADDR_PTR, /**< pointer to worksapce memory of model with shallow copy */ - ACL_MDL_WORKSPACE_SIZET, - ACL_MDL_INPUTQ_NUM_SIZET, - ACL_MDL_INPUTQ_ADDR_PTR, /**< pointer to inputQ with shallow copy */ - ACL_MDL_OUTPUTQ_NUM_SIZET, - ACL_MDL_OUTPUTQ_ADDR_PTR /**< pointer to outputQ with shallow copy */ + ACL_MDL_PRIORITY_INT32 = 0, + ACL_MDL_LOAD_TYPE_SIZET, + ACL_MDL_PATH_PTR, /**< pointer to model load path with deep copy */ + ACL_MDL_MEM_ADDR_PTR, /**< pointer to model memory with shallow copy */ + ACL_MDL_MEM_SIZET, + ACL_MDL_WEIGHT_ADDR_PTR, /**< pointer to weight memory of model with shallow copy */ + ACL_MDL_WEIGHT_SIZET, + ACL_MDL_WORKSPACE_ADDR_PTR, /**< pointer to worksapce memory of model with shallow copy */ + ACL_MDL_WORKSPACE_SIZET, + ACL_MDL_INPUTQ_NUM_SIZET, + ACL_MDL_INPUTQ_ADDR_PTR, /**< pointer to inputQ with shallow copy */ + ACL_MDL_OUTPUTQ_NUM_SIZET, + ACL_MDL_OUTPUTQ_ADDR_PTR /**< pointer to outputQ with shallow copy */ } aclmdlConfigAttr; typedef enum { - ACL_DATA_WITHOUT_AIPP = 0, - ACL_DATA_WITH_STATIC_AIPP, - ACL_DATA_WITH_DYNAMIC_AIPP, - ACL_DYNAMIC_AIPP_NODE + ACL_DATA_WITHOUT_AIPP = 0, + ACL_DATA_WITH_STATIC_AIPP, + ACL_DATA_WITH_DYNAMIC_AIPP, + ACL_DYNAMIC_AIPP_NODE } aclmdlInputAippType; typedef struct aclmdlIODims { - char name[ACL_MAX_TENSOR_NAME_LEN]; /**< tensor name */ - size_t dimCount; /**< dim array count */ - int64_t dims[ACL_MAX_DIM_CNT]; /**< dim data array */ + char name[ACL_MAX_TENSOR_NAME_LEN]; /**< tensor name */ + size_t dimCount; /**< dim array count */ + int64_t dims[ACL_MAX_DIM_CNT]; /**< dim data array */ } aclmdlIODims; typedef struct aclAippDims { - aclmdlIODims srcDims; /**< input dims before model transform */ - size_t srcSize; /**< input size before model transform */ - aclmdlIODims aippOutdims; /**< aipp output dims */ - size_t aippOutSize; /**< aipp output size */ + aclmdlIODims srcDims; /**< input dims before model transform */ + size_t srcSize; /**< input size before model transform */ + aclmdlIODims aippOutdims; /**< aipp output dims */ + size_t aippOutSize; /**< aipp output size */ } aclAippDims; typedef struct aclmdlBatch { - size_t batchCount; /**< batch array count */ - uint64_t batch[ACL_MAX_BATCH_NUM]; /**< batch data array */ + size_t batchCount; /**< batch array count */ + uint64_t batch[ACL_MAX_BATCH_NUM]; /**< batch data array */ } aclmdlBatch; typedef struct aclmdlHW { - size_t hwCount; /**< height&width array count */ - uint64_t hw[ACL_MAX_HW_NUM][2]; /**< height&width data array */ + size_t hwCount; /**< height&width array count */ + uint64_t hw[ACL_MAX_HW_NUM][2]; /**< height&width data array */ } aclmdlHW; typedef struct aclAippInfo { - aclAippInputFormat inputFormat; - int32_t srcImageSizeW; - int32_t srcImageSizeH; - int8_t cropSwitch; - int32_t loadStartPosW; - int32_t loadStartPosH; - int32_t cropSizeW; - int32_t cropSizeH; - int8_t resizeSwitch; - int32_t resizeOutputW; - int32_t resizeOutputH; - int8_t paddingSwitch; - int32_t leftPaddingSize; - int32_t rightPaddingSize; - int32_t topPaddingSize; - int32_t bottomPaddingSize; - int8_t cscSwitch; - int8_t rbuvSwapSwitch; - int8_t axSwapSwitch; - int8_t singleLineMode; - int32_t matrixR0C0; - int32_t matrixR0C1; - int32_t matrixR0C2; - int32_t matrixR1C0; - int32_t matrixR1C1; - int32_t matrixR1C2; - int32_t matrixR2C0; - int32_t matrixR2C1; - int32_t matrixR2C2; - int32_t outputBias0; - int32_t outputBias1; - int32_t outputBias2; - int32_t inputBias0; - int32_t inputBias1; - int32_t inputBias2; - int32_t meanChn0; - int32_t meanChn1; - int32_t meanChn2; - int32_t meanChn3; - float minChn0; - float minChn1; - float minChn2; - float minChn3; - float varReciChn0; - float varReciChn1; - float varReciChn2; - float varReciChn3; - aclFormat srcFormat; - aclDataType srcDatatype; - size_t srcDimNum; - size_t shapeCount; - aclAippDims outDims[ACL_MAX_SHAPE_COUNT]; - aclAippExtendInfo *aippExtend; /**< reserved parameters, current version needs to be null */ + aclAippInputFormat inputFormat; + int32_t srcImageSizeW; + int32_t srcImageSizeH; + int8_t cropSwitch; + int32_t loadStartPosW; + int32_t loadStartPosH; + int32_t cropSizeW; + int32_t cropSizeH; + int8_t resizeSwitch; + int32_t resizeOutputW; + int32_t resizeOutputH; + int8_t paddingSwitch; + int32_t leftPaddingSize; + int32_t rightPaddingSize; + int32_t topPaddingSize; + int32_t bottomPaddingSize; + int8_t cscSwitch; + int8_t rbuvSwapSwitch; + int8_t axSwapSwitch; + int8_t singleLineMode; + int32_t matrixR0C0; + int32_t matrixR0C1; + int32_t matrixR0C2; + int32_t matrixR1C0; + int32_t matrixR1C1; + int32_t matrixR1C2; + int32_t matrixR2C0; + int32_t matrixR2C1; + int32_t matrixR2C2; + int32_t outputBias0; + int32_t outputBias1; + int32_t outputBias2; + int32_t inputBias0; + int32_t inputBias1; + int32_t inputBias2; + int32_t meanChn0; + int32_t meanChn1; + int32_t meanChn2; + int32_t meanChn3; + float minChn0; + float minChn1; + float minChn2; + float minChn3; + float varReciChn0; + float varReciChn1; + float varReciChn2; + float varReciChn3; + aclFormat srcFormat; + aclDataType srcDatatype; + size_t srcDimNum; + size_t shapeCount; + aclAippDims outDims[ACL_MAX_SHAPE_COUNT]; + aclAippExtendInfo *aippExtend; /**< reserved parameters, current version needs to be null */ } aclAippInfo; /** @@ -292,7 +292,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlAddDatasetBuffer(aclmdlDataset *dataset, aclD * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclmdlSetDatasetTensorDesc(aclmdlDataset *dataset, aclTensorDesc *tensorDesc, +ACL_FUNC_VISIBILITY aclError aclmdlSetDatasetTensorDesc(aclmdlDataset *dataset, + aclTensorDesc *tensorDesc, size_t index); /** @@ -354,7 +355,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFile(const char *modelPath, uint32_t * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMem(const void *model, size_t modelSize, uint32_t *modelId); +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMem(const void *model, size_t modelSize, + uint32_t *modelId); /** * @ingroup AscendCL @@ -376,8 +378,9 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMem(const void *model, size_t modelSi * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithMem(const char *modelPath, uint32_t *modelId, void *workPtr, - size_t workSize, void *weightPtr, size_t weightSize); +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithMem(const char *modelPath, + uint32_t *modelId, void *workPtr, size_t workSize, + void *weightPtr, size_t weightSize); /** * @ingroup AscendCL @@ -400,9 +403,9 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithMem(const char *modelPath, ui * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithMem(const void *model, size_t modelSize, uint32_t *modelId, - void *workPtr, size_t workSize, void *weightPtr, - size_t weightSize); +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithMem(const void *model, size_t modelSize, + uint32_t *modelId, void *workPtr, size_t workSize, + void *weightPtr, size_t weightSize); /** * @ingroup AscendCL @@ -437,8 +440,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithQ(const char *modelPath, uint * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithQ(const void *model, size_t modelSize, uint32_t *modelId, - const uint32_t *inputQ, size_t inputQNum, const uint32_t *outputQ, - size_t outputQNum); + const uint32_t *inputQ, size_t inputQNum, + const uint32_t *outputQ, size_t outputQNum); /** * @ingroup AscendCL @@ -468,8 +471,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlExecute(uint32_t modelId, const aclmdlDataset * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem */ -ACL_FUNC_VISIBILITY aclError aclmdlExecuteAsync(uint32_t modelId, const aclmdlDataset *input, aclmdlDataset *output, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclmdlExecuteAsync(uint32_t modelId, const aclmdlDataset *input, + aclmdlDataset *output, aclrtStream stream); /** * @ingroup AscendCL @@ -644,7 +647,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlGetCurOutputDims(const aclmdlDesc *modelDesc, * @param modelDesc [IN] model description * @param opName [IN] op name * @param attr [IN] attr name - * + * * @retval the attr value */ ACL_FUNC_VISIBILITY const char *aclmdlGetOpAttr(aclmdlDesc *modelDesc, const char *opName, const char *attr); @@ -856,11 +859,11 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPInputFormat(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, int8_t csc_switch, int16_t cscMatrixR0C0, - int16_t cscMatrixR0C1, int16_t cscMatrixR0C2, int16_t cscMatrixR1C0, - int16_t cscMatrixR1C1, int16_t cscMatrixR1C2, int16_t cscMatrixR2C0, - int16_t cscMatrixR2C1, int16_t cscMatrixR2C2, +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, int8_t csc_switch, + int16_t cscMatrixR0C0, int16_t cscMatrixR0C1, int16_t cscMatrixR0C2, + int16_t cscMatrixR1C0, int16_t cscMatrixR1C1, int16_t cscMatrixR1C2, + int16_t cscMatrixR2C0, int16_t cscMatrixR2C1, int16_t cscMatrixR2C2, uint8_t cscOutputBiasR0, uint8_t cscOutputBiasR1, uint8_t cscOutputBiasR2, uint8_t cscInputBiasR0, uint8_t cscInputBiasR1, uint8_t cscInputBiasR2); @@ -876,7 +879,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, in * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ +*/ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPRbuvSwapSwitch(aclmdlAIPP *aippParmsSet, int8_t rbuvSwapSwitch); /** @@ -890,7 +893,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPRbuvSwapSwitch(aclmdlAIPP *aippParmsSe * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ +*/ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPAxSwapSwitch(aclmdlAIPP *aippParmsSet, int8_t axSwapSwitch); /** @@ -905,7 +908,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPAxSwapSwitch(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ +*/ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPSrcImageSize(aclmdlAIPP *aippParmsSet, int32_t srcImageSizeW, int32_t srcImageSizeH); @@ -925,10 +928,14 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPSrcImageSize(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPScfParams(aclmdlAIPP *aippParmsSet, int8_t scfSwitch, int32_t scfInputSizeW, - int32_t scfInputSizeH, int32_t scfOutputSizeW, - int32_t scfOutputSizeH, uint64_t batchIndex); +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPScfParams(aclmdlAIPP *aippParmsSet, + int8_t scfSwitch, + int32_t scfInputSizeW, + int32_t scfInputSizeH, + int32_t scfOutputSizeW, + int32_t scfOutputSizeH, + uint64_t batchIndex); /** * @ingroup AscendCL @@ -946,9 +953,13 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPScfParams(aclmdlAIPP *aippParmsSet, in * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCropParams(aclmdlAIPP *aippParmsSet, int8_t cropSwitch, int32_t cropStartPosW, - int32_t cropStartPosH, int32_t cropSizeW, int32_t cropSizeH, +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCropParams(aclmdlAIPP *aippParmsSet, + int8_t cropSwitch, + int32_t cropStartPosW, + int32_t cropStartPosH, + int32_t cropSizeW, + int32_t cropSizeH, uint64_t batchIndex); /** @@ -967,7 +978,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCropParams(aclmdlAIPP *aippParmsSet, i * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ +*/ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPaddingParams(aclmdlAIPP *aippParmsSet, int8_t paddingSwitch, int32_t paddingSizeTop, int32_t paddingSizeBottom, int32_t paddingSizeLeft, int32_t paddingSizeRight, @@ -988,10 +999,13 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPaddingParams(aclmdlAIPP *aippParmsSet * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMean(aclmdlAIPP *aippParmsSet, int16_t dtcPixelMeanChn0, - int16_t dtcPixelMeanChn1, int16_t dtcPixelMeanChn2, - int16_t dtcPixelMeanChn3, uint64_t batchIndex); +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMean(aclmdlAIPP *aippParmsSet, + int16_t dtcPixelMeanChn0, + int16_t dtcPixelMeanChn1, + int16_t dtcPixelMeanChn2, + int16_t dtcPixelMeanChn3, + uint64_t batchIndex); /** * @ingroup AscendCL @@ -1008,10 +1022,13 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMean(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMin(aclmdlAIPP *aippParmsSet, float dtcPixelMinChn0, - float dtcPixelMinChn1, float dtcPixelMinChn2, - float dtcPixelMinChn3, uint64_t batchIndex); +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMin(aclmdlAIPP *aippParmsSet, + float dtcPixelMinChn0, + float dtcPixelMinChn1, + float dtcPixelMinChn2, + float dtcPixelMinChn3, + uint64_t batchIndex); /** * @ingroup AscendCL @@ -1028,10 +1045,13 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMin(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP - */ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPixelVarReci(aclmdlAIPP *aippParmsSet, float dtcPixelVarReciChn0, - float dtcPixelVarReciChn1, float dtcPixelVarReciChn2, - float dtcPixelVarReciChn3, uint64_t batchIndex); +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPixelVarReci(aclmdlAIPP *aippParmsSet, + float dtcPixelVarReciChn0, + float dtcPixelVarReciChn1, + float dtcPixelVarReciChn2, + float dtcPixelVarReciChn3, + uint64_t batchIndex); /** * @ingroup AscendCL @@ -1047,8 +1067,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPixelVarReci(aclmdlAIPP *aippParmsSet, * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP - */ -ACL_FUNC_VISIBILITY aclError aclmdlSetInputAIPP(uint32_t modelId, aclmdlDataset *dataset, size_t index, +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetInputAIPP(uint32_t modelId, + aclmdlDataset *dataset, + size_t index, const aclmdlAIPP *aippParmsSet); /** @@ -1065,8 +1087,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetInputAIPP(uint32_t modelId, aclmdlDataset * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP - */ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPByInputIndex(uint32_t modelId, aclmdlDataset *dataset, size_t index, +*/ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPByInputIndex(uint32_t modelId, + aclmdlDataset *dataset, + size_t index, const aclmdlAIPP *aippParmsSet); /** @@ -1084,8 +1108,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPByInputIndex(uint32_t modelId, aclmdlD * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP - */ -ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, size_t index, aclmdlInputAippType *type, +*/ +ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, + size_t index, + aclmdlInputAippType *type, size_t *dynamicAttachedDataIndex); /** @@ -1102,7 +1128,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, size_t index, a * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName - */ +*/ ACL_FUNC_VISIBILITY aclError aclmdlGetFirstAippInfo(uint32_t modelId, size_t index, aclAippInfo *aippinfo); /** @@ -1121,11 +1147,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlGetFirstAippInfo(uint32_t modelId, size_t ind * * @retval ACL_SUCCESS The function is successfully executed * @retval OtherValues Failure - */ -ACL_FUNC_VISIBILITY aclError aclmdlCreateAndGetOpDesc(uint32_t deviceId, uint32_t streamId, uint32_t taskId, - char *opName, size_t opNameLen, aclTensorDesc **inputDesc, - size_t *numInputs, aclTensorDesc **outputDesc, - size_t *numOutputs); +*/ +ACL_FUNC_VISIBILITY aclError aclmdlCreateAndGetOpDesc(uint32_t deviceId, uint32_t streamId, + uint32_t taskId, char *opName, size_t opNameLen, aclTensorDesc **inputDesc, size_t *numInputs, + aclTensorDesc **outputDesc, size_t *numOutputs); /** * @ingroup AscendCL @@ -1133,7 +1158,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlCreateAndGetOpDesc(uint32_t deviceId, uint32_ * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure - */ +*/ ACL_FUNC_VISIBILITY aclError aclmdlInitDump(); /** @@ -1144,7 +1169,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlInitDump(); * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure - */ +*/ ACL_FUNC_VISIBILITY aclError aclmdlSetDump(const char *dumpCfgPath); /** @@ -1153,7 +1178,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetDump(const char *dumpCfgPath); * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure - */ +*/ ACL_FUNC_VISIBILITY aclError aclmdlFinalizeDump(); /** @@ -1165,7 +1190,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlFinalizeDump(); * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure - */ +*/ ACL_FUNC_VISIBILITY aclError aclmdlLoadWithConfig(const aclmdlConfigHandle *handle, uint32_t *modelId); /** @@ -1175,7 +1200,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadWithConfig(const aclmdlConfigHandle *hand * @retval the aclmdlConfigHandle pointer * * @see aclmdlDestroyConfigHandle - */ +*/ ACL_FUNC_VISIBILITY aclmdlConfigHandle *aclmdlCreateConfigHandle(); /** @@ -1204,7 +1229,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlDestroyConfigHandle(aclmdlConfigHandle *handl * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclmdlSetConfigOpt(aclmdlConfigHandle *handle, aclmdlConfigAttr attr, - const void *attrValue, size_t valueSize); + const void *attrValue, size_t valueSize); /** * @ingroup AscendCL @@ -1222,4 +1247,4 @@ ACL_FUNC_VISIBILITY const char *aclmdlGetTensorRealName(const aclmdlDesc *modelD } #endif -#endif // INC_EXTERNAL_ACL_ACL_MODEL_H_ +#endif // INC_EXTERNAL_ACL_ACL_MODEL_H_ diff --git a/inc/external/acl/acl_op.h b/inc/external/acl/acl_op.h index d2e59bfb..b1be0d6e 100644 --- a/inc/external/acl/acl_op.h +++ b/inc/external/acl/acl_op.h @@ -33,9 +33,9 @@ typedef void (*aclDataDeallocator)(void *data, size_t length); static const int ACL_COMPILE_FLAG_BIN_SELECTOR = 1; typedef enum aclEngineType { - ACL_ENGINE_SYS, - ACL_ENGINE_AICORE, - ACL_ENGINE_VECTOR, + ACL_ENGINE_SYS, + ACL_ENGINE_AICORE, + ACL_ENGINE_VECTOR, } aclopEngineType; /** @@ -148,7 +148,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrString(aclopAttr *attr, const char *att * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListBool(aclopAttr *attr, const char *attrName, int numValues, - const uint8_t *values); + const uint8_t *values); /** * @ingroup AscendCL @@ -163,7 +163,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListBool(aclopAttr *attr, const char *a * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListInt(aclopAttr *attr, const char *attrName, int numValues, - const int64_t *values); + const int64_t *values); /** * @ingroup AscendCL @@ -178,7 +178,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListInt(aclopAttr *attr, const char *at * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListFloat(aclopAttr *attr, const char *attrName, int numValues, - const float *values); + const float *values); /** * @ingroup AscendCL @@ -193,7 +193,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListFloat(aclopAttr *attr, const char * * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListString(aclopAttr *attr, const char *attrName, int numValues, - const char **values); + const char **values); /** * @ingroup AscendCL @@ -208,8 +208,11 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListString(aclopAttr *attr, const char * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, const char *attrName, int numLists, - const int *numValues, const int64_t *const values[]); +ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, + const char *attrName, + int numLists, + const int *numValues, + const int64_t *const values[]); /** * @ingroup AscendCL @@ -239,10 +242,15 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, const char * @retval OtherValues Failure */ ACL_DEPRECATED_MESSAGE("aclopExecute is deprecated, use aclopExecuteV2 instead") -ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], - const aclDataBuffer *const inputs[], int numOutputs, - const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], - const aclopAttr *attr, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, + int numInputs, + const aclTensorDesc *const inputDesc[], + const aclDataBuffer *const inputs[], + int numOutputs, + const aclTensorDesc *const outputDesc[], + aclDataBuffer *const outputs[], + const aclopAttr *attr, + aclrtStream stream); /** * @ingroup AscendCL @@ -272,9 +280,15 @@ ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, int numInputs, con * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, int numInputs, aclTensorDesc *inputDesc[], - aclDataBuffer *inputs[], int numOutputs, aclTensorDesc *outputDesc[], - aclDataBuffer *outputs[], aclopAttr *attr, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, + int numInputs, + aclTensorDesc *inputDesc[], + aclDataBuffer *inputs[], + int numOutputs, + aclTensorDesc *outputDesc[], + aclDataBuffer *outputs[], + aclopAttr *attr, + aclrtStream stream); /** * @ingroup AscendCL @@ -292,9 +306,12 @@ ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, int numInputs, a * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCreateHandle(const char *opType, int numInputs, - const aclTensorDesc *const inputDesc[], int numOutputs, - const aclTensorDesc *const outputDesc[], const aclopAttr *opAttr, +ACL_FUNC_VISIBILITY aclError aclopCreateHandle(const char *opType, + int numInputs, + const aclTensorDesc *const inputDesc[], + int numOutputs, + const aclTensorDesc *const outputDesc[], + const aclopAttr *opAttr, aclopHandle **handle); /** @@ -326,9 +343,12 @@ ACL_FUNC_VISIBILITY void aclopDestroyHandle(aclopHandle *handle); * * @see aclopCreateHandle | aclCreateDataBuffer */ -ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, int numInputs, - const aclDataBuffer *const inputs[], int numOutputs, - aclDataBuffer *const outputs[], aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, + int numInputs, + const aclDataBuffer *const inputs[], + int numOutputs, + aclDataBuffer *const outputs[], + aclrtStream stream); /** * @ingroup AscendCL @@ -344,8 +364,11 @@ ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, int numInp * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, const aclDataBuffer *srcBuffer, - const aclTensorDesc *dstDesc, aclDataBuffer *dstBuffer, uint8_t truncate, +ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, + const aclDataBuffer *srcBuffer, + const aclTensorDesc *dstDesc, + aclDataBuffer *dstBuffer, + uint8_t truncate, aclrtStream stream); /** @@ -360,9 +383,12 @@ ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, const aclDa * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, aclTensorDesc *dstDesc, uint8_t truncate, +ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, + aclTensorDesc *dstDesc, + uint8_t truncate, aclopHandle **handle); + /** * @ingroup AscendCL * @brief create kernel @@ -381,10 +407,15 @@ ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, ac * * @see aclopCompile */ -ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, const char *kernelId, const char *kernelName, - void *binData, int binSize, aclopEngineType enginetype, +ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, + const char *kernelId, + const char *kernelName, + void *binData, + int binSize, + aclopEngineType enginetype, aclDataDeallocator deallocator); + /** * @ingroup AscendCL * @brief create kernel @@ -399,8 +430,11 @@ ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, const char *k * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -typedef aclError (*aclopCompileFunc)(int numInputs, const aclTensorDesc *const inputDesc[], int numOutputs, - const aclTensorDesc *const outputDesc[], const aclopAttr *opAttr, +typedef aclError (*aclopCompileFunc)(int numInputs, + const aclTensorDesc *const inputDesc[], + int numOutputs, + const aclTensorDesc *const outputDesc[], + const aclopAttr *opAttr, aclopKernelDesc *aclopKernelDesc); /** @@ -441,8 +475,11 @@ ACL_FUNC_VISIBILITY aclError aclopUnregisterCompileFunc(const char *opType); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopSetKernelArgs(aclopKernelDesc *kernelDesc, const char *kernelId, uint32_t blockDim, - const void *args, uint32_t argSize); +ACL_FUNC_VISIBILITY aclError aclopSetKernelArgs(aclopKernelDesc *kernelDesc, + const char *kernelId, + uint32_t blockDim, + const void *args, + uint32_t argSize); /** * @ingroup AscendCL @@ -473,9 +510,12 @@ ACL_FUNC_VISIBILITY aclError aclopSetKernelWorkspaceSizes(aclopKernelDesc *kerne * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, int numInputs, - const aclTensorDesc *const inputDesc[], int numOutputs, - const aclTensorDesc *const outputDesc[], const aclopAttr *attr); +ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, + int numInputs, + const aclTensorDesc *const inputDesc[], + int numOutputs, + const aclTensorDesc *const outputDesc[], + const aclopAttr *attr); /** * @ingroup AscendCL @@ -493,12 +533,17 @@ ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, int numInputs * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopInferShape(const char *opType, int numInputs, aclTensorDesc *inputDesc[], - aclDataBuffer *inputs[], int numOutputs, aclTensorDesc *outputDesc[], +ACL_FUNC_VISIBILITY aclError aclopInferShape(const char *opType, + int numInputs, + aclTensorDesc *inputDesc[], + aclDataBuffer *inputs[], + int numOutputs, + aclTensorDesc *outputDesc[], aclopAttr *attr); + #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_OP_H_ +#endif // INC_EXTERNAL_ACL_ACL_OP_H_ diff --git a/inc/external/acl/acl_op_compiler.h b/inc/external/acl/acl_op_compiler.h index d9d1b3da..353d2a1a 100644 --- a/inc/external/acl/acl_op_compiler.h +++ b/inc/external/acl/acl_op_compiler.h @@ -24,22 +24,28 @@ extern "C" { #endif -typedef enum aclCompileType { ACL_COMPILE_SYS, ACL_COMPILE_UNREGISTERED } aclopCompileType; +typedef enum aclCompileType { + ACL_COMPILE_SYS, + ACL_COMPILE_UNREGISTERED +} aclopCompileType; typedef enum { - ACL_PRECISION_MODE, - ACL_AICORE_NUM, - ACL_AUTO_TUNE_MODE, - ACL_OP_SELECT_IMPL_MODE, - ACL_OPTYPELIST_FOR_IMPLMODE, - ACL_OP_DEBUG_LEVEL, - ACL_DEBUG_DIR, - ACL_OP_COMPILER_CACHE_MODE, - ACL_OP_COMPILER_CACHE_DIR, - ACL_OP_PERFORMANCE_MODE + ACL_PRECISION_MODE, + ACL_AICORE_NUM, + ACL_AUTO_TUNE_MODE, + ACL_OP_SELECT_IMPL_MODE, + ACL_OPTYPELIST_FOR_IMPLMODE, + ACL_OP_DEBUG_LEVEL, + ACL_DEBUG_DIR, + ACL_OP_COMPILER_CACHE_MODE, + ACL_OP_COMPILER_CACHE_DIR, + ACL_OP_PERFORMANCE_MODE } aclCompileOpt; -typedef enum aclCompileFlag { ACL_OP_COMPILE_DEFAULT, ACL_OP_COMPILE_FUZZ } aclOpCompileFlag; +typedef enum aclCompileFlag { + ACL_OP_COMPILE_DEFAULT, + ACL_OP_COMPILE_FUZZ +} aclOpCompileFlag; /** * @ingroup AscendCL @@ -59,10 +65,15 @@ typedef enum aclCompileFlag { ACL_OP_COMPILE_DEFAULT, ACL_OP_COMPILE_FUZZ } aclO * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], - int numOutputs, const aclTensorDesc *const outputDesc[], - const aclopAttr *attr, aclopEngineType engineType, - aclopCompileType compileFlag, const char *opPath); +ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, + int numInputs, + const aclTensorDesc *const inputDesc[], + int numOutputs, + const aclTensorDesc *const outputDesc[], + const aclopAttr *attr, + aclopEngineType engineType, + aclopCompileType compileFlag, + const char *opPath); /** * @ingroup AscendCL @@ -85,10 +96,11 @@ ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, int numInputs, con * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCompileAndExecute( - const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], const aclDataBuffer *const inputs[], - int numOutputs, const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], const aclopAttr *attr, - aclopEngineType engineType, aclopCompileType compileFlag, const char *opPath, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopCompileAndExecute(const char *opType, + int numInputs, const aclTensorDesc *const inputDesc[], const aclDataBuffer *const inputs[], + int numOutputs, const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], + const aclopAttr *attr, aclopEngineType engineType, aclopCompileType compileFlag, + const char *opPath, aclrtStream stream); /** * @ingroup AscendCL @@ -118,4 +130,4 @@ ACL_FUNC_VISIBILITY aclError aclopSetCompileFlag(aclOpCompileFlag flag); } #endif -#endif // INC_EXTERNAL_ACL_ACL_OP_COMPILER_H_ +#endif // INC_EXTERNAL_ACL_ACL_OP_COMPILER_H_ diff --git a/inc/external/acl/acl_prof.h b/inc/external/acl/acl_prof.h index 3784d8c6..93bc3a9b 100644 --- a/inc/external/acl/acl_prof.h +++ b/inc/external/acl/acl_prof.h @@ -23,24 +23,24 @@ extern "C" { #endif -#define ACL_PROF_ACL_API 0x0001 -#define ACL_PROF_TASK_TIME 0x0002 -#define ACL_PROF_AICORE_METRICS 0x0004 -#define ACL_PROF_AICPU 0x0008 +#define ACL_PROF_ACL_API 0x0001 +#define ACL_PROF_TASK_TIME 0x0002 +#define ACL_PROF_AICORE_METRICS 0x0004 +#define ACL_PROF_AICPU 0x0008 /** * @deprecated please use aclprofGetOpTypeLen and aclprofGetOpTNameLen instead */ -#define ACL_PROF_MAX_OP_NAME_LEN 257 -#define ACL_PROF_MAX_OP_TYPE_LEN 65 +#define ACL_PROF_MAX_OP_NAME_LEN 257 +#define ACL_PROF_MAX_OP_TYPE_LEN 65 typedef enum { - ACL_AICORE_ARITHMETIC_UTILIZATION = 0, - ACL_AICORE_PIPE_UTILIZATION = 1, - ACL_AICORE_MEMORY_BANDWIDTH = 2, - ACL_AICORE_L0B_AND_WIDTH = 3, - ACL_AICORE_RESOURCE_CONFLICT_RATIO = 4, - ACL_AICORE_NONE = 0xFF + ACL_AICORE_ARITHMETIC_UTILIZATION = 0, + ACL_AICORE_PIPE_UTILIZATION = 1, + ACL_AICORE_MEMORY_BANDWIDTH = 2, + ACL_AICORE_L0B_AND_WIDTH = 3, + ACL_AICORE_RESOURCE_CONFLICT_RATIO = 4, + ACL_AICORE_NONE = 0xFF } aclprofAicoreMetrics; typedef struct aclprofConfig aclprofConfig; @@ -101,8 +101,7 @@ ACL_FUNC_VISIBILITY aclError aclprofStart(const aclprofConfig *profilerConfig); * @see aclprofDestroyConfig */ ACL_FUNC_VISIBILITY aclprofConfig *aclprofCreateConfig(uint32_t *deviceIdList, uint32_t deviceNums, - aclprofAicoreMetrics aicoreMetrics, - aclprofAicoreEvents *aicoreEvents, uint64_t dataTypeConfig); + aclprofAicoreMetrics aicoreMetrics, aclprofAicoreEvents *aicoreEvents, uint64_t dataTypeConfig); /** * @ingroup AscendCL @@ -142,7 +141,8 @@ ACL_FUNC_VISIBILITY aclError aclprofStop(const aclprofConfig *profilerConfig); * * @see aclprofModelUnSubscribe */ -ACL_FUNC_VISIBILITY aclError aclprofModelSubscribe(uint32_t modelId, const aclprofSubscribeConfig *profSubscribeConfig); +ACL_FUNC_VISIBILITY aclError aclprofModelSubscribe(uint32_t modelId, + const aclprofSubscribeConfig *profSubscribeConfig); /** * @ingroup AscendCL @@ -170,7 +170,7 @@ ACL_FUNC_VISIBILITY aclError aclprofModelUnSubscribe(uint32_t modelId); * @see aclprofDestroySubscribeConfig */ ACL_FUNC_VISIBILITY aclprofSubscribeConfig *aclprofCreateSubscribeConfig(int8_t timeInfoSwitch, - aclprofAicoreMetrics aicoreMetrics, void *fd); + aclprofAicoreMetrics aicoreMetrics, void *fd); /** * @ingroup AscendCL @@ -222,7 +222,7 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpNum(const void *opInfo, size_t opInfoLe * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclprofGetOpTypeLen(const void *opInfo, size_t opInfoLen, uint32_t index, - size_t *opTypeLen); + size_t *opTypeLen); /** * @ingroup AscendCL @@ -237,8 +237,8 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpTypeLen(const void *opInfo, size_t opIn * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoLen, uint32_t index, char *opType, - size_t opTypeLen); +ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoLen, uint32_t index, + char *opType, size_t opTypeLen); /** * @ingroup AscendCL @@ -253,7 +253,7 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoL * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclprofGetOpNameLen(const void *opInfo, size_t opInfoLen, uint32_t index, - size_t *opNameLen); + size_t *opNameLen); /** * @ingroup AscendCL @@ -268,8 +268,8 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpNameLen(const void *opInfo, size_t opIn * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclprofGetOpName(const void *opInfo, size_t opInfoLen, uint32_t index, char *opName, - size_t opNameLen); +ACL_FUNC_VISIBILITY aclError aclprofGetOpName(const void *opInfo, size_t opInfoLen, uint32_t index, + char *opName, size_t opNameLen); /** * @ingroup AscendCL @@ -326,4 +326,4 @@ ACL_FUNC_VISIBILITY size_t aclprofGetModelId(const void *opInfo, size_t opInfoLe } #endif -#endif // INC_EXTERNAL_ACL_PROF_H_ +#endif // INC_EXTERNAL_ACL_PROF_H_ diff --git a/inc/external/acl/acl_rt.h b/inc/external/acl/acl_rt.h index 5ee70724..3c777ecc 100644 --- a/inc/external/acl/acl_rt.h +++ b/inc/external/acl/acl_rt.h @@ -28,63 +28,63 @@ extern "C" { #define ACL_EVENT_TIME_LINE 0x00000008u typedef enum aclrtRunMode { - ACL_DEVICE, - ACL_HOST, + ACL_DEVICE, + ACL_HOST, } aclrtRunMode; typedef enum aclrtTsId { - ACL_TS_ID_AICORE = 0, - ACL_TS_ID_AIVECTOR = 1, - ACL_TS_ID_RESERVED = 2, + ACL_TS_ID_AICORE = 0, + ACL_TS_ID_AIVECTOR = 1, + ACL_TS_ID_RESERVED = 2, } aclrtTsId; typedef enum aclrtEventStatus { - ACL_EVENT_STATUS_COMPLETE = 0, - ACL_EVENT_STATUS_NOT_READY = 1, - ACL_EVENT_STATUS_RESERVED = 2, + ACL_EVENT_STATUS_COMPLETE = 0, + ACL_EVENT_STATUS_NOT_READY = 1, + ACL_EVENT_STATUS_RESERVED = 2, } aclrtEventStatus; typedef enum aclrtCallbackBlockType { - ACL_CALLBACK_NO_BLOCK, - ACL_CALLBACK_BLOCK, + ACL_CALLBACK_NO_BLOCK, + ACL_CALLBACK_BLOCK, } aclrtCallbackBlockType; typedef enum aclrtMemcpyKind { - ACL_MEMCPY_HOST_TO_HOST, - ACL_MEMCPY_HOST_TO_DEVICE, - ACL_MEMCPY_DEVICE_TO_HOST, - ACL_MEMCPY_DEVICE_TO_DEVICE, + ACL_MEMCPY_HOST_TO_HOST, + ACL_MEMCPY_HOST_TO_DEVICE, + ACL_MEMCPY_DEVICE_TO_HOST, + ACL_MEMCPY_DEVICE_TO_DEVICE, } aclrtMemcpyKind; typedef enum aclrtMemMallocPolicy { - ACL_MEM_MALLOC_HUGE_FIRST, - ACL_MEM_MALLOC_HUGE_ONLY, - ACL_MEM_MALLOC_NORMAL_ONLY, - ACL_MEM_MALLOC_HUGE_FIRST_P2P, - ACL_MEM_MALLOC_HUGE_ONLY_P2P, - ACL_MEM_MALLOC_NORMAL_ONLY_P2P, + ACL_MEM_MALLOC_HUGE_FIRST, + ACL_MEM_MALLOC_HUGE_ONLY, + ACL_MEM_MALLOC_NORMAL_ONLY, + ACL_MEM_MALLOC_HUGE_FIRST_P2P, + ACL_MEM_MALLOC_HUGE_ONLY_P2P, + ACL_MEM_MALLOC_NORMAL_ONLY_P2P, } aclrtMemMallocPolicy; typedef enum aclrtMemAttr { - ACL_DDR_MEM, - ACL_HBM_MEM, - ACL_DDR_MEM_HUGE, - ACL_DDR_MEM_NORMAL, - ACL_HBM_MEM_HUGE, - ACL_HBM_MEM_NORMAL, - ACL_DDR_MEM_P2P_HUGE, - ACL_DDR_MEM_P2P_NORMAL, - ACL_HBM_MEM_P2P_HUGE, - ACL_HBM_MEM_P2P_NORMAL, + ACL_DDR_MEM, + ACL_HBM_MEM, + ACL_DDR_MEM_HUGE, + ACL_DDR_MEM_NORMAL, + ACL_HBM_MEM_HUGE, + ACL_HBM_MEM_NORMAL, + ACL_DDR_MEM_P2P_HUGE, + ACL_DDR_MEM_P2P_NORMAL, + ACL_HBM_MEM_P2P_HUGE, + ACL_HBM_MEM_P2P_NORMAL, } aclrtMemAttr; typedef enum aclrtGroupAttr { - ACL_GROUP_AICORE_INT, - ACL_GROUP_AIV_INT, - ACL_GROUP_AIC_INT, - ACL_GROUP_SDMANUM_INT, - ACL_GROUP_ASQNUM_INT, - ACL_GROUP_GROUPID_INT + ACL_GROUP_AICORE_INT, + ACL_GROUP_AIV_INT, + ACL_GROUP_AIC_INT, + ACL_GROUP_SDMANUM_INT, + ACL_GROUP_ASQNUM_INT, + ACL_GROUP_GROUPID_INT } aclrtGroupAttr; typedef struct tagRtGroupInfo aclrtGroupInfo; @@ -487,7 +487,7 @@ ACL_FUNC_VISIBILITY aclError aclrtRecordEvent(aclrtEvent event, aclrtStream stre */ ACL_FUNC_VISIBILITY aclError aclrtResetEvent(aclrtEvent event, aclrtStream stream); -/** + /** * @ingroup AscendCL * @brief Queries an event's status * @@ -549,7 +549,9 @@ ACL_FUNC_VISIBILITY aclError aclrtEventElapsedTime(float *ms, aclrtEvent start, * * @see aclrtFree | acldvppMalloc | aclrtMallocCached */ -ACL_FUNC_VISIBILITY aclError aclrtMalloc(void **devPtr, size_t size, aclrtMemMallocPolicy policy); +ACL_FUNC_VISIBILITY aclError aclrtMalloc(void **devPtr, + size_t size, + aclrtMemMallocPolicy policy); /** * @ingroup AscendCL @@ -572,7 +574,9 @@ ACL_FUNC_VISIBILITY aclError aclrtMalloc(void **devPtr, size_t size, aclrtMemMal * * @see aclrtFree | aclrtMalloc */ -ACL_FUNC_VISIBILITY aclError aclrtMallocCached(void **devPtr, size_t size, aclrtMemMallocPolicy policy); +ACL_FUNC_VISIBILITY aclError aclrtMallocCached(void **devPtr, + size_t size, + aclrtMemMallocPolicy policy); /** * @ingroup AscendCL @@ -663,7 +667,10 @@ ACL_FUNC_VISIBILITY aclError aclrtFreeHost(void *hostPtr); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclrtMemcpy(void *dst, size_t destMax, const void *src, size_t count, +ACL_FUNC_VISIBILITY aclError aclrtMemcpy(void *dst, + size_t destMax, + const void *src, + size_t count, aclrtMemcpyKind kind); /** @@ -710,31 +717,38 @@ ACL_FUNC_VISIBILITY aclError aclrtMemset(void *devPtr, size_t maxCount, int32_t * * @see aclrtSynchronizeStream */ -ACL_FUNC_VISIBILITY aclError aclrtMemcpyAsync(void *dst, size_t destMax, const void *src, size_t count, - aclrtMemcpyKind kind, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclrtMemcpyAsync(void *dst, + size_t destMax, + const void *src, + size_t count, + aclrtMemcpyKind kind, + aclrtStream stream); /** - * @ingroup AscendCL - * @brief Asynchronous initialize memory - * and set contents of memory to specified value async - * - * @par Function +* @ingroup AscendCL +* @brief Asynchronous initialize memory +* and set contents of memory to specified value async +* +* @par Function * The memory to be initialized is on the Host or device side, * and the system determines whether * it is host or device according to the address * - * @param devPtr [IN] destination address pointer - * @param maxCount [IN] Max length of destination address memory - * @param value [IN] set value - * @param count [IN] the number of byte to set - * @param stream [IN] asynchronized task stream - * - * @retval ACL_SUCCESS The function is successfully executed. - * @retval OtherValues Failure - * - * @see aclrtSynchronizeStream - */ -ACL_FUNC_VISIBILITY aclError aclrtMemsetAsync(void *devPtr, size_t maxCount, int32_t value, size_t count, +* @param devPtr [IN] destination address pointer +* @param maxCount [IN] Max length of destination address memory +* @param value [IN] set value +* @param count [IN] the number of byte to set +* @param stream [IN] asynchronized task stream +* +* @retval ACL_SUCCESS The function is successfully executed. +* @retval OtherValues Failure +* +* @see aclrtSynchronizeStream +*/ +ACL_FUNC_VISIBILITY aclError aclrtMemsetAsync(void *devPtr, + size_t maxCount, + int32_t value, + size_t count, aclrtStream stream); /** @@ -880,8 +894,11 @@ ACL_FUNC_VISIBILITY aclError aclrtGetAllGroupInfo(aclrtGroupInfo *groupInfo); * * @see aclrtGetGroupCount | aclrtGetAllGroupInfo */ -ACL_FUNC_VISIBILITY aclError aclrtGetGroupInfoDetail(const aclrtGroupInfo *groupInfo, int32_t groupIndex, - aclrtGroupAttr attr, void *attrValue, size_t valueLen, +ACL_FUNC_VISIBILITY aclError aclrtGetGroupInfoDetail(const aclrtGroupInfo *groupInfo, + int32_t groupIndex, + aclrtGroupAttr attr, + void *attrValue, + size_t valueLen, size_t *paramRetSize); /** @@ -955,4 +972,5 @@ ACL_FUNC_VISIBILITY aclError aclrtSetOpWaitTimeout(uint32_t timeout); } #endif -#endif // INC_EXTERNAL_ACL_ACL_RT_H_ +#endif // INC_EXTERNAL_ACL_ACL_RT_H_ + diff --git a/inc/external/acl/acl_tdt.h b/inc/external/acl/acl_tdt.h index c357518d..61995121 100644 --- a/inc/external/acl/acl_tdt.h +++ b/inc/external/acl/acl_tdt.h @@ -24,10 +24,10 @@ extern "C" { #endif enum acltdtTensorType { - ACL_TENSOR_DATA_UNDEFINED = -1, - ACL_TENSOR_DATA_TENSOR, - ACL_TENSOR_DATA_END_OF_SEQUENCE, - ACL_TENSOR_DATA_ABNORMAL + ACL_TENSOR_DATA_UNDEFINED = -1, + ACL_TENSOR_DATA_TENSOR, + ACL_TENSOR_DATA_END_OF_SEQUENCE, + ACL_TENSOR_DATA_ABNORMAL }; typedef struct acltdtDataItem acltdtDataItem; @@ -64,7 +64,7 @@ ACL_FUNC_VISIBILITY aclDataType acltdtGetDataTypeFromItem(const acltdtDataItem * * * @retval null for failed * @retval OtherValues success - */ +*/ ACL_FUNC_VISIBILITY void *acltdtGetDataAddrFromItem(const acltdtDataItem *dataItem); /** @@ -75,7 +75,7 @@ ACL_FUNC_VISIBILITY void *acltdtGetDataAddrFromItem(const acltdtDataItem *dataIt * * @retval 0 for failed * @retval OtherValues success - */ +*/ ACL_FUNC_VISIBILITY size_t acltdtGetDataSizeFromItem(const acltdtDataItem *dataItem); /** @@ -86,7 +86,7 @@ ACL_FUNC_VISIBILITY size_t acltdtGetDataSizeFromItem(const acltdtDataItem *dataI * * @retval 0 for failed * @retval OtherValues success - */ +*/ ACL_FUNC_VISIBILITY size_t acltdtGetDimNumFromItem(const acltdtDataItem *dataItem); /** @@ -118,8 +118,12 @@ ACL_FUNC_VISIBILITY aclError acltdtGetDimsFromItem(const acltdtDataItem *dataIte * * @see acltdtDestroyDataItem */ -ACL_FUNC_VISIBILITY acltdtDataItem *acltdtCreateDataItem(acltdtTensorType tdtType, const int64_t *dims, size_t dimNum, - aclDataType dataType, void *data, size_t size); +ACL_FUNC_VISIBILITY acltdtDataItem *acltdtCreateDataItem(acltdtTensorType tdtType, + const int64_t *dims, + size_t dimNum, + aclDataType dataType, + void *data, + size_t size); /** * @ingroup AscendCL @@ -250,7 +254,8 @@ ACL_FUNC_VISIBILITY aclError acltdtDestroyChannel(acltdtChannelHandle *handle); * * @see acltdtReceiveTensor */ -ACL_FUNC_VISIBILITY aclError acltdtSendTensor(const acltdtChannelHandle *handle, const acltdtDataset *dataset, +ACL_FUNC_VISIBILITY aclError acltdtSendTensor(const acltdtChannelHandle *handle, + const acltdtDataset *dataset, int32_t timeout); /** @@ -266,11 +271,13 @@ ACL_FUNC_VISIBILITY aclError acltdtSendTensor(const acltdtChannelHandle *handle, * * @see acltdtSendTensor */ -ACL_FUNC_VISIBILITY aclError acltdtReceiveTensor(const acltdtChannelHandle *handle, acltdtDataset *dataset, +ACL_FUNC_VISIBILITY aclError acltdtReceiveTensor(const acltdtChannelHandle *handle, + acltdtDataset *dataset, int32_t timeout); #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_TDT_H_ +#endif //INC_EXTERNAL_ACL_ACL_TDT_H_ + diff --git a/inc/external/acl/error_codes/rt_error_codes.h b/inc/external/acl/error_codes/rt_error_codes.h index 1c196c48..c9a40432 100644 --- a/inc/external/acl/error_codes/rt_error_codes.h +++ b/inc/external/acl/error_codes/rt_error_codes.h @@ -23,84 +23,84 @@ extern "C" { #endif -static const int32_t ACL_RT_SUCCESS = 0; // success +static const int32_t ACL_RT_SUCCESS = 0; // success -static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid -static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id -static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null -static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context -static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context -static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal -static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned -static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed -static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed -static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream -static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread -static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set -static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create -static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream -static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type -static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle -static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type +static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid +static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id +static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null +static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context +static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context +static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal +static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned +static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed +static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed +static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream +static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread +static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set +static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create +static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream +static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type +static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle +static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type -static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support -static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error -static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error -static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow -static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device -static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail -static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission -static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource -static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource -static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource -static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource +static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support +static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error +static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error +static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow +static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device +static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail +static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission +static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource +static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource +static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource +static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource -static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error -static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout -static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception -static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout +static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception -static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error -static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error -static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect +static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error +static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error +static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect #ifdef __cplusplus } #endif -#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ +#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/inc/external/acl/ops/acl_cblas.h b/inc/external/acl/ops/acl_cblas.h index 3d81eb2b..a2bd8c61 100644 --- a/inc/external/acl/ops/acl_cblas.h +++ b/inc/external/acl/ops/acl_cblas.h @@ -23,9 +23,17 @@ extern "C" { #endif -typedef enum aclTransType { ACL_TRANS_N, ACL_TRANS_T, ACL_TRANS_NZ, ACL_TRANS_NZ_T } aclTransType; +typedef enum aclTransType { + ACL_TRANS_N, + ACL_TRANS_T, + ACL_TRANS_NZ, + ACL_TRANS_NZ_T +} aclTransType; -typedef enum aclComputeType { ACL_COMPUTE_HIGH_PRECISION, ACL_COMPUTE_LOW_PRECISION } aclComputeType; +typedef enum aclComputeType { + ACL_COMPUTE_HIGH_PRECISION, + ACL_COMPUTE_LOW_PRECISION +} aclComputeType; /** * @ingroup AscendCL @@ -53,11 +61,12 @@ typedef enum aclComputeType { ACL_COMPUTE_HIGH_PRECISION, ACL_COMPUTE_LOW_PRECIS * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure - */ -ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, const void *alpha, const void *a, int lda, - aclDataType dataTypeA, const void *x, int incx, aclDataType dataTypeX, - const void *beta, void *y, int incy, aclDataType dataTypeY, - aclComputeType type, aclrtStream stream); +*/ +ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, + const void *alpha, const void *a, int lda, aclDataType dataTypeA, + const void *x, int incx, aclDataType dataTypeX, + const void *beta, void *y, int incy, aclDataType dataTypeY, + aclComputeType type, aclrtStream stream); /** * @ingroup AscendCL @@ -74,10 +83,15 @@ ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, co * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure - */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, int m, int n, aclDataType dataTypeA, - aclDataType dataTypeX, aclDataType dataTypeY, - aclComputeType type, aclopHandle **handle); +*/ +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, + int m, + int n, + aclDataType dataTypeA, + aclDataType dataTypeX, + aclDataType dataTypeY, + aclComputeType type, + aclopHandle **handle); /** * @ingroup AscendCL @@ -101,9 +115,18 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, i * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, int m, int n, const aclFloat16 *alpha, - const aclFloat16 *a, int lda, const aclFloat16 *x, int incx, - const aclFloat16 *beta, aclFloat16 *y, int incy, aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, + int m, + int n, + const aclFloat16 *alpha, + const aclFloat16 *a, + int lda, + const aclFloat16 *x, + int incx, + const aclFloat16 *beta, + aclFloat16 *y, + int incy, + aclComputeType type, aclrtStream stream); /** @@ -119,7 +142,10 @@ ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, int m, int n, con * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, int m, int n, aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, + int m, + int n, + aclComputeType type, aclopHandle **handle); /** @@ -145,9 +171,19 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, in * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, int m, int n, const int32_t *alpha, const int8_t *a, - int lda, const int8_t *x, int incx, const int32_t *beta, int32_t *y, - int incy, aclComputeType type, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, + int m, + int n, + const int32_t *alpha, + const int8_t *a, + int lda, + const int8_t *x, + int incx, + const int32_t *beta, + int32_t *y, + int incy, + aclComputeType type, + aclrtStream stream); /** * @ingroup AscendCL @@ -162,7 +198,10 @@ ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, int m, int n, co * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, int m, int n, aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, + int m, + int n, + aclComputeType type, aclopHandle **handle); /** @@ -194,11 +233,26 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, i * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, - int k, const void *alpha, const void *matrixA, int lda, - aclDataType dataTypeA, const void *matrixB, int ldb, aclDataType dataTypeB, - const void *beta, void *matrixC, int ldc, aclDataType dataTypeC, - aclComputeType type, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, + aclTransType transB, + aclTransType transC, + int m, + int n, + int k, + const void *alpha, + const void *matrixA, + int lda, + aclDataType dataTypeA, + const void *matrixB, + int ldb, + aclDataType dataTypeB, + const void *beta, + void *matrixC, + int ldc, + aclDataType dataTypeC, + aclComputeType type, + aclrtStream stream); + /** * @ingroup AscendCL @@ -220,10 +274,18 @@ ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, aclTransType tra * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, aclTransType transB, aclTransType transC, - int m, int n, int k, aclDataType dataTypeA, - aclDataType dataTypeB, aclDataType dataTypeC, - aclComputeType type, aclopHandle **handle); +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, + aclTransType transB, + aclTransType transC, + int m, + int n, + int k, + aclDataType dataTypeA, + aclDataType dataTypeB, + aclDataType dataTypeC, + aclComputeType type, + aclopHandle **handle); + /** * @ingroup AscendCL @@ -251,10 +313,22 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, a * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, - int k, const aclFloat16 *alpha, const aclFloat16 *matrixA, int lda, - const aclFloat16 *matrixB, int ldb, const aclFloat16 *beta, - aclFloat16 *matrixC, int ldc, aclComputeType type, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, + aclTransType transB, + aclTransType transC, + int m, + int n, + int k, + const aclFloat16 *alpha, + const aclFloat16 *matrixA, + int lda, + const aclFloat16 *matrixB, + int ldb, + const aclFloat16 *beta, + aclFloat16 *matrixC, + int ldc, + aclComputeType type, + aclrtStream stream); /** * @ingroup AscendCL @@ -272,8 +346,13 @@ ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, aclTransType tran * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, aclTransType transB, aclTransType transC, - int m, int n, int k, aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, + aclTransType transB, + aclTransType transC, + int m, + int n, + int k, + aclComputeType type, aclopHandle **handle); /** @@ -302,10 +381,23 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, ac * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, - int k, const int32_t *alpha, const int8_t *matrixA, int lda, - const int8_t *matrixB, int ldb, const int32_t *beta, int32_t *matrixC, - int ldc, aclComputeType type, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, + aclTransType transB, + aclTransType transC, + int m, + int n, + int k, + const int32_t *alpha, + const int8_t *matrixA, + int lda, + const int8_t *matrixB, + int ldb, + const int32_t *beta, + int32_t *matrixC, + int ldc, + aclComputeType type, + aclrtStream stream); + /** * @ingroup AscendCL @@ -323,12 +415,17 @@ ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, aclTransType tra * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemm(aclTransType transA, aclTransType transB, aclTransType transC, - int m, int n, int k, aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemm(aclTransType transA, + aclTransType transB, + aclTransType transC, + int m, + int n, + int k, + aclComputeType type, aclopHandle **handle); #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_CBLAS_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_CBLAS_H_ diff --git a/inc/external/acl/ops/acl_dvpp.h b/inc/external/acl/ops/acl_dvpp.h index dcaa3936..90dc70e8 100644 --- a/inc/external/acl/ops/acl_dvpp.h +++ b/inc/external/acl/ops/acl_dvpp.h @@ -53,109 +53,123 @@ typedef void (*aclvencCallback)(acldvppPicDesc *input, acldvppStreamDesc *output // Supported Pixel Format enum acldvppPixelFormat { - PIXEL_FORMAT_YUV_400 = 0, // 0 - PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1, // 1 - PIXEL_FORMAT_YVU_SEMIPLANAR_420 = 2, // 2 - PIXEL_FORMAT_YUV_SEMIPLANAR_422 = 3, // 3 - PIXEL_FORMAT_YVU_SEMIPLANAR_422 = 4, // 4 - PIXEL_FORMAT_YUV_SEMIPLANAR_444 = 5, // 5 - PIXEL_FORMAT_YVU_SEMIPLANAR_444 = 6, // 6 - PIXEL_FORMAT_YUYV_PACKED_422 = 7, // 7 - PIXEL_FORMAT_UYVY_PACKED_422 = 8, // 8 - PIXEL_FORMAT_YVYU_PACKED_422 = 9, // 9 - PIXEL_FORMAT_VYUY_PACKED_422 = 10, // 10 - PIXEL_FORMAT_YUV_PACKED_444 = 11, // 11 - PIXEL_FORMAT_RGB_888 = 12, // 12 - PIXEL_FORMAT_BGR_888 = 13, // 13 - PIXEL_FORMAT_ARGB_8888 = 14, // 14 - PIXEL_FORMAT_ABGR_8888 = 15, // 15 - PIXEL_FORMAT_RGBA_8888 = 16, // 16 - PIXEL_FORMAT_BGRA_8888 = 17, // 17 - PIXEL_FORMAT_YUV_SEMI_PLANNER_420_10BIT = 18, // 18 - PIXEL_FORMAT_YVU_SEMI_PLANNER_420_10BIT = 19, // 19 - PIXEL_FORMAT_YVU_PLANAR_420 = 20, // 20 - PIXEL_FORMAT_YVU_PLANAR_422, - PIXEL_FORMAT_YVU_PLANAR_444, - PIXEL_FORMAT_RGB_444 = 23, - PIXEL_FORMAT_BGR_444, - PIXEL_FORMAT_ARGB_4444, - PIXEL_FORMAT_ABGR_4444, - PIXEL_FORMAT_RGBA_4444, - PIXEL_FORMAT_BGRA_4444, - PIXEL_FORMAT_RGB_555, - PIXEL_FORMAT_BGR_555, - PIXEL_FORMAT_RGB_565, - PIXEL_FORMAT_BGR_565, - PIXEL_FORMAT_ARGB_1555, - PIXEL_FORMAT_ABGR_1555, - PIXEL_FORMAT_RGBA_1555, - PIXEL_FORMAT_BGRA_1555, - PIXEL_FORMAT_ARGB_8565, - PIXEL_FORMAT_ABGR_8565, - PIXEL_FORMAT_RGBA_8565, - PIXEL_FORMAT_BGRA_8565, - PIXEL_FORMAT_RGB_BAYER_8BPP = 50, - PIXEL_FORMAT_RGB_BAYER_10BPP, - PIXEL_FORMAT_RGB_BAYER_12BPP, - PIXEL_FORMAT_RGB_BAYER_14BPP, - PIXEL_FORMAT_RGB_BAYER_16BPP, - PIXEL_FORMAT_BGR_888_PLANAR = 70, - PIXEL_FORMAT_HSV_888_PACKAGE, - PIXEL_FORMAT_HSV_888_PLANAR, - PIXEL_FORMAT_LAB_888_PACKAGE, - PIXEL_FORMAT_LAB_888_PLANAR, - PIXEL_FORMAT_S8C1, - PIXEL_FORMAT_S8C2_PACKAGE, - PIXEL_FORMAT_S8C2_PLANAR, - PIXEL_FORMAT_S16C1, - PIXEL_FORMAT_U8C1, - PIXEL_FORMAT_U16C1, - PIXEL_FORMAT_S32C1, - PIXEL_FORMAT_U32C1, - PIXEL_FORMAT_U64C1, - PIXEL_FORMAT_S64C1, - PIXEL_FORMAT_YUV_SEMIPLANAR_440 = 1000, - PIXEL_FORMAT_YVU_SEMIPLANAR_440, - PIXEL_FORMAT_FLOAT32, - PIXEL_FORMAT_BUTT, - PIXEL_FORMAT_UNKNOWN = 10000 + PIXEL_FORMAT_YUV_400 = 0, // 0 + PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1, // 1 + PIXEL_FORMAT_YVU_SEMIPLANAR_420 = 2, // 2 + PIXEL_FORMAT_YUV_SEMIPLANAR_422 = 3, // 3 + PIXEL_FORMAT_YVU_SEMIPLANAR_422 = 4, // 4 + PIXEL_FORMAT_YUV_SEMIPLANAR_444 = 5, // 5 + PIXEL_FORMAT_YVU_SEMIPLANAR_444 = 6, // 6 + PIXEL_FORMAT_YUYV_PACKED_422 = 7, // 7 + PIXEL_FORMAT_UYVY_PACKED_422 = 8, // 8 + PIXEL_FORMAT_YVYU_PACKED_422 = 9, // 9 + PIXEL_FORMAT_VYUY_PACKED_422 = 10, // 10 + PIXEL_FORMAT_YUV_PACKED_444 = 11, // 11 + PIXEL_FORMAT_RGB_888 = 12, // 12 + PIXEL_FORMAT_BGR_888 = 13, // 13 + PIXEL_FORMAT_ARGB_8888 = 14, // 14 + PIXEL_FORMAT_ABGR_8888 = 15, // 15 + PIXEL_FORMAT_RGBA_8888 = 16, // 16 + PIXEL_FORMAT_BGRA_8888 = 17, // 17 + PIXEL_FORMAT_YUV_SEMI_PLANNER_420_10BIT = 18, // 18 + PIXEL_FORMAT_YVU_SEMI_PLANNER_420_10BIT = 19, // 19 + PIXEL_FORMAT_YVU_PLANAR_420 = 20, // 20 + PIXEL_FORMAT_YVU_PLANAR_422, + PIXEL_FORMAT_YVU_PLANAR_444, + PIXEL_FORMAT_RGB_444 = 23, + PIXEL_FORMAT_BGR_444, + PIXEL_FORMAT_ARGB_4444, + PIXEL_FORMAT_ABGR_4444, + PIXEL_FORMAT_RGBA_4444, + PIXEL_FORMAT_BGRA_4444, + PIXEL_FORMAT_RGB_555, + PIXEL_FORMAT_BGR_555, + PIXEL_FORMAT_RGB_565, + PIXEL_FORMAT_BGR_565, + PIXEL_FORMAT_ARGB_1555, + PIXEL_FORMAT_ABGR_1555, + PIXEL_FORMAT_RGBA_1555, + PIXEL_FORMAT_BGRA_1555, + PIXEL_FORMAT_ARGB_8565, + PIXEL_FORMAT_ABGR_8565, + PIXEL_FORMAT_RGBA_8565, + PIXEL_FORMAT_BGRA_8565, + PIXEL_FORMAT_RGB_BAYER_8BPP = 50, + PIXEL_FORMAT_RGB_BAYER_10BPP, + PIXEL_FORMAT_RGB_BAYER_12BPP, + PIXEL_FORMAT_RGB_BAYER_14BPP, + PIXEL_FORMAT_RGB_BAYER_16BPP, + PIXEL_FORMAT_BGR_888_PLANAR = 70, + PIXEL_FORMAT_HSV_888_PACKAGE, + PIXEL_FORMAT_HSV_888_PLANAR, + PIXEL_FORMAT_LAB_888_PACKAGE, + PIXEL_FORMAT_LAB_888_PLANAR, + PIXEL_FORMAT_S8C1, + PIXEL_FORMAT_S8C2_PACKAGE, + PIXEL_FORMAT_S8C2_PLANAR, + PIXEL_FORMAT_S16C1, + PIXEL_FORMAT_U8C1, + PIXEL_FORMAT_U16C1, + PIXEL_FORMAT_S32C1, + PIXEL_FORMAT_U32C1, + PIXEL_FORMAT_U64C1, + PIXEL_FORMAT_S64C1, + PIXEL_FORMAT_YUV_SEMIPLANAR_440 = 1000, + PIXEL_FORMAT_YVU_SEMIPLANAR_440, + PIXEL_FORMAT_FLOAT32, + PIXEL_FORMAT_BUTT, + PIXEL_FORMAT_UNKNOWN = 10000 }; // Stream Format -enum acldvppStreamFormat { H265_MAIN_LEVEL = 0, H264_BASELINE_LEVEL, H264_MAIN_LEVEL, H264_HIGH_LEVEL }; +enum acldvppStreamFormat { + H265_MAIN_LEVEL = 0, + H264_BASELINE_LEVEL, + H264_MAIN_LEVEL, + H264_HIGH_LEVEL +}; // Supported Channel Mode -enum acldvppChannelMode { DVPP_CHNMODE_VPC = 1, DVPP_CHNMODE_JPEGD = 2, DVPP_CHNMODE_JPEGE = 4 }; +enum acldvppChannelMode { + DVPP_CHNMODE_VPC = 1, + DVPP_CHNMODE_JPEGD = 2, + DVPP_CHNMODE_JPEGE = 4 +}; // Supported Border Type -enum acldvppBorderType { BORDER_CONSTANT = 0, BORDER_REPLICATE, BORDER_REFLECT, BORDER_REFLECT_101 }; +enum acldvppBorderType { + BORDER_CONSTANT = 0, + BORDER_REPLICATE, + BORDER_REFLECT, + BORDER_REFLECT_101 +}; // Venc parameter type enum aclvencChannelDescParamType { - ACL_VENC_THREAD_ID_UINT64 = 0, - ACL_VENC_CALLBACK_PTR, - ACL_VENC_PIXEL_FORMAT_UINT32, - ACL_VENC_ENCODE_TYPE_UINT32, - ACL_VENC_PIC_WIDTH_UINT32, - ACL_VENC_PIC_HEIGHT_UINT32, - ACL_VENC_KEY_FRAME_INTERVAL_UINT32, - ACL_VENC_BUF_ADDR_PTR, - ACL_VENC_BUF_SIZE_UINT32, - ACL_VENC_RC_MODE_UINT32, - ACL_VENC_SRC_RATE_UINT32, - ACL_VENC_MAX_BITRATE_UINT32, - ACL_VENC_MAX_IP_PROP_UINT32 + ACL_VENC_THREAD_ID_UINT64 = 0, + ACL_VENC_CALLBACK_PTR, + ACL_VENC_PIXEL_FORMAT_UINT32, + ACL_VENC_ENCODE_TYPE_UINT32, + ACL_VENC_PIC_WIDTH_UINT32, + ACL_VENC_PIC_HEIGHT_UINT32, + ACL_VENC_KEY_FRAME_INTERVAL_UINT32, + ACL_VENC_BUF_ADDR_PTR, + ACL_VENC_BUF_SIZE_UINT32, + ACL_VENC_RC_MODE_UINT32, + ACL_VENC_SRC_RATE_UINT32, + ACL_VENC_MAX_BITRATE_UINT32, + ACL_VENC_MAX_IP_PROP_UINT32 }; // Jpeg picture format enum acldvppJpegFormat { - ACL_JPEG_CSS_444 = 0, - ACL_JPEG_CSS_422, - ACL_JPEG_CSS_420, - ACL_JPEG_CSS_GRAY, - ACL_JPEG_CSS_440, - ACL_JPEG_CSS_411, - ACL_JPEG_CSS_UNKNOWN = 1000 + ACL_JPEG_CSS_444 = 0, + ACL_JPEG_CSS_422, + ACL_JPEG_CSS_420, + ACL_JPEG_CSS_GRAY, + ACL_JPEG_CSS_440, + ACL_JPEG_CSS_411, + ACL_JPEG_CSS_UNKNOWN = 1000 }; /** @@ -509,7 +523,9 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescRetCode(const acldvppPicDesc *picD * @retval null for failed. * @retval other success */ -ACL_FUNC_VISIBILITY acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, uint32_t right, uint32_t top, +ACL_FUNC_VISIBILITY acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, + uint32_t right, + uint32_t top, uint32_t bottom); /** @@ -588,7 +604,10 @@ ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfigBottom(acldvppRoiConfig *config, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfig(acldvppRoiConfig *config, uint32_t left, uint32_t right, uint32_t top, +ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfig(acldvppRoiConfig *config, + uint32_t left, + uint32_t right, + uint32_t top, uint32_t bottom); /** @@ -1077,8 +1096,7 @@ ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescMaxBitRate(aclvencChannelDesc * @retval ACL_SUCCESS for success, other for failure */ ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescParam(aclvencChannelDesc *channelDesc, - aclvencChannelDescParamType paramType, size_t length, - const void *param); + aclvencChannelDescParamType paramType, size_t length, const void *param); /** * @ingroup AscendCL @@ -1227,8 +1245,7 @@ ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescMaxBitRate(const aclvencChanne * @retval ACL_SUCCESS for success, other for failure */ ACL_FUNC_VISIBILITY aclError aclvencGetChannelDescParam(const aclvencChannelDesc *channelDesc, - aclvencChannelDescParamType paramType, size_t length, - size_t *paramRetSize, void *param); + aclvencChannelDescParamType paramType, size_t length, size_t *paramRetSize, void *param); /** * @ingroup AscendCL @@ -1528,7 +1545,10 @@ ACL_FUNC_VISIBILITY aclError aclvdecDestroyFrameConfig(aclvdecFrameConfig *vdecF * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, uint32_t size, uint32_t *width, uint32_t *height, +ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, + uint32_t size, + uint32_t *width, + uint32_t *height, int32_t *components); /** @@ -1545,8 +1565,11 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, uint32_t * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, uint32_t size, uint32_t *width, - uint32_t *height, int32_t *components, +ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, + uint32_t size, + uint32_t *width, + uint32_t *height, + int32_t *components, acldvppJpegFormat *format); /** @@ -1561,7 +1584,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, uint32_ * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictEncSize(const acldvppPicDesc *inputDesc, - const acldvppJpegeConfig *config, uint32_t *size); + const acldvppJpegeConfig *config, + uint32_t *size); /** * @ingroup AscendCL @@ -1575,8 +1599,10 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictEncSize(const acldvppPicDesc *inp * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, uint32_t dataSize, - acldvppPixelFormat outputPixelFormat, uint32_t *decSize); +ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, + uint32_t dataSize, + acldvppPixelFormat outputPixelFormat, + uint32_t *decSize); /** * @ingroup AscendCL @@ -1591,8 +1617,11 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, uint32_ * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, uint32_t dataSize, uint32_t *width, - uint32_t *height, int32_t *components); +ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, + uint32_t dataSize, + uint32_t *width, + uint32_t *height, + int32_t *components); /** * @ingroup AscendCL @@ -1606,8 +1635,10 @@ ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, uint32_t d * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppPngPredictDecSize(const void *data, uint32_t dataSize, - acldvppPixelFormat outputPixelFormat, uint32_t *decSize); +ACL_FUNC_VISIBILITY aclError acldvppPngPredictDecSize(const void *data, + uint32_t dataSize, + acldvppPixelFormat outputPixelFormat, + uint32_t *decSize); /** * @ingroup AscendCL @@ -1671,8 +1702,10 @@ ACL_FUNC_VISIBILITY aclError acldvppDestroyChannel(acldvppChannelDesc *channelDe * @see acldvppCreateChannel | acldvppCreatePicDesc * | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, acldvppResizeConfig *resizeConfig, +ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + acldvppResizeConfig *resizeConfig, aclrtStream stream); /** @@ -1708,8 +1741,10 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDe * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, +ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + acldvppRoiConfig *cropArea, aclrtStream stream); /** @@ -1746,9 +1781,13 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, - acldvppResizeConfig *resizeConfig, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizeAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + acldvppRoiConfig *cropArea, + acldvppResizeConfig *resizeConfig, + aclrtStream stream); + /** * @ingroup AscendCL @@ -1772,9 +1811,12 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizeAsync(acldvppChannelDesc *chann * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, - uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, - acldvppRoiConfig *cropAreas[], aclrtStream stream); + acldvppBatchPicDesc *srcBatchPicDescs, + uint32_t *roiNums, + uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + aclrtStream stream); /** * @ingroup AscendCL @@ -1799,10 +1841,13 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channe * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateDvppConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, - uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, + acldvppBatchPicDesc *srcBatchPicDescs, + uint32_t *roiNums, + uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], - acldvppResizeConfig *resizeConfig, aclrtStream stream); + acldvppResizeConfig *resizeConfig, + aclrtStream stream); /** * @ingroup AscendCL @@ -1825,9 +1870,12 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeAsync(acldvppChannelDesc * * * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateRoiConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, - acldvppRoiConfig *pasteArea, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + acldvppRoiConfig *cropArea, + acldvppRoiConfig *pasteArea, + aclrtStream stream); /** * @ingroup AscendCL @@ -1851,10 +1899,13 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *cha * * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizePasteAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, +ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizePasteAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + acldvppRoiConfig *cropArea, acldvppRoiConfig *pasteArea, - acldvppResizeConfig *resizeConfig, aclrtStream stream); + acldvppResizeConfig *resizeConfig, + aclrtStream stream); /** * @ingroup AscendCL @@ -1879,11 +1930,14 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizePasteAsync(acldvppChannelDesc * * * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, - uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, - acldvppRoiConfig *cropAreas[], - acldvppRoiConfig *pasteAreas[], aclrtStream stream); + ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *channelDesc, + acldvppBatchPicDesc *srcBatchPicDescs, + uint32_t *roiNums, + uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + acldvppRoiConfig *pasteAreas[], + aclrtStream stream); /** * @ingroup AscendCL @@ -1909,10 +1963,16 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc * * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizePasteAsync( - acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], acldvppRoiConfig *pasteAreas[], - acldvppResizeConfig *resizeConfig, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizePasteAsync(acldvppChannelDesc *channelDesc, + acldvppBatchPicDesc *srcBatchPicDescs, + uint32_t *roiNums, + uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + acldvppRoiConfig *pasteAreas[], + acldvppResizeConfig *resizeConfig, + aclrtStream stream); + /** * @ingroup AscendCL @@ -1940,8 +2000,11 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizePasteAsync( * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, - acldvppPicDesc *outputDesc, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, + const void *data, + uint32_t size, + acldvppPicDesc *outputDesc, + aclrtStream stream); /** * @ingroup AscendCL @@ -1959,8 +2022,11 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelD * * @see acldvppCreateChannel | acldvppCreateJpegeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - const void *data, uint32_t *size, acldvppJpegeConfig *config, +ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + const void *data, + uint32_t *size, + acldvppJpegeConfig *config, aclrtStream stream); /** @@ -1978,8 +2044,11 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelD * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppPngDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, - acldvppPicDesc *outputDesc, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppPngDecodeAsync(acldvppChannelDesc *channelDesc, + const void *data, + uint32_t size, + acldvppPicDesc *outputDesc, + aclrtStream stream); /** * @ingroup AscendCL @@ -2034,8 +2103,11 @@ ACL_FUNC_VISIBILITY aclError aclvdecDestroyChannel(aclvdecChannelDesc *channelDe * * @see aclvdecCreateChannel | acldvppCreateStreamDesc | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, acldvppStreamDesc *input, - acldvppPicDesc *output, aclvdecFrameConfig *config, void *userData); +ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, + acldvppStreamDesc *input, + acldvppPicDesc *output, + aclvdecFrameConfig *config, + void *userData); /** * @ingroup AscendCL @@ -2054,8 +2126,10 @@ ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, a * * @see aclvdecCreateChannel | acldvppCreateStreamDesc | acldvppCreatePicDesc | aclvdecSendFrame */ -ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channelDesc, acldvppStreamDesc *input, - aclvdecFrameConfig *config, void *userData); +ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channelDesc, + acldvppStreamDesc *input, + aclvdecFrameConfig *config, + void *userData); /** * @ingroup AscendCL @@ -2076,8 +2150,10 @@ ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channel * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + aclrtStream stream); /** * @ingroup AscendCL @@ -2099,8 +2175,11 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *cha * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, void *reserve, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + void *reserve, + aclrtStream stream); /** * @ingroup AscendCL @@ -2112,7 +2191,8 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelD * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetChannelDescMode(acldvppChannelDesc *channelDesc, uint32_t mode); +ACL_FUNC_VISIBILITY aclError acldvppSetChannelDescMode(acldvppChannelDesc *channelDesc, + uint32_t mode); /** * @ingroup AscendCL @@ -2147,7 +2227,8 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetResizeConfigInterpolation(const acldvppRe * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutMode(aclvdecChannelDesc *channelDesc, uint32_t outMode); +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutMode(aclvdecChannelDesc *channelDesc, + uint32_t outMode); /** * @ingroup AscendCL @@ -2244,7 +2325,9 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetLutMapDims(const acldvppLutMap *lutMap); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, uint32_t dim, uint8_t **data, +ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, + uint32_t dim, + uint8_t **data, uint32_t *len); /** * @ingroup AscendCL @@ -2262,8 +2345,10 @@ ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, u * @see acldvppCreateChannel|acldvppCreatePicDesc|acldvppCreateLutMap */ ACL_FUNC_VISIBILITY aclError acldvppVpcEqualizeHistAsync(const acldvppChannelDesc *channelDesc, - const acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, - const acldvppLutMap *lutMap, aclrtStream stream); + const acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + const acldvppLutMap *lutMap, + aclrtStream stream); /** * @ingroup AscendCL @@ -2284,7 +2369,8 @@ ACL_FUNC_VISIBILITY acldvppBorderConfig *acldvppCreateBorderConfig(); * * @retval ACL_SUCCESS for success, other for failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigValue(acldvppBorderConfig *borderConfig, uint32_t index, +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigValue(acldvppBorderConfig *borderConfig, + uint32_t index, double value); /** @@ -2429,8 +2515,10 @@ ACL_FUNC_VISIBILITY aclError acldvppDestroyBorderConfig(acldvppBorderConfig *bor * @see acldvppCreateChannel|acldvppCreatePicDesc|acldvppCreateBorderConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcMakeBorderAsync(const acldvppChannelDesc *channelDesc, - const acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, - const acldvppBorderConfig *borderConfig, aclrtStream stream); + const acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, + const acldvppBorderConfig *borderConfig, + aclrtStream stream); /** * @ingroup AscendCL @@ -2447,8 +2535,11 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcMakeBorderAsync(const acldvppChannelDesc * * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateHist */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *srcPicDesc, - acldvppHist *hist, void *reserve, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channelDesc, + acldvppPicDesc *srcPicDesc, + acldvppHist *hist, + void *reserve, + aclrtStream stream); /** * @ingroup AscendCL @@ -2457,7 +2548,7 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channel * @retval null for failed. * @retval OtherValues success. */ -ACL_FUNC_VISIBILITY acldvppHist *acldvppCreateHist(); +ACL_FUNC_VISIBILITY acldvppHist* acldvppCreateHist(); /** * @ingroup AscendCL @@ -2514,7 +2605,7 @@ ACL_FUNC_VISIBILITY aclError acldvppGetHistData(acldvppHist *hist, uint32_t dim, * * @see acldvppCreateHist | acldvppVpcCalcHistAsync */ -ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist *hist); +ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist* hist); /** * @ingroup AscendCL @@ -2533,6 +2624,7 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist *hist); */ ACL_FUNC_VISIBILITY aclError acldvppClearHist(acldvppHist *hist); + /** * @ingroup AscendCL * @brief dvpp vpc batch crop, resize config and make border. @@ -2556,13 +2648,18 @@ ACL_FUNC_VISIBILITY aclError acldvppClearHist(acldvppHist *hist); * * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeMakeBorderAsync( - acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], acldvppBorderConfig *borderCfgs[], - acldvppResizeConfig *resizeConfig, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeMakeBorderAsync(acldvppChannelDesc *channelDesc, + acldvppBatchPicDesc *srcBatchPicDescs, + uint32_t *roiNums, + uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + acldvppBorderConfig *borderCfgs[], + acldvppResizeConfig *resizeConfig, + aclrtStream stream); #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ diff --git a/inc/external/acl/ops/acl_fv.h b/inc/external/acl/ops/acl_fv.h index 27dc367a..40cd50cb 100644 --- a/inc/external/acl/ops/acl_fv.h +++ b/inc/external/acl/ops/acl_fv.h @@ -32,8 +32,8 @@ typedef struct aclfvSearchResult aclfvSearchResult; // search operation type enum aclfvSearchType { - SEARCH_1_N, // 1:N operation type - SEARCH_N_M // N:M operation type + SEARCH_1_N, // 1:N operation type + SEARCH_N_M // N:M operation type }; /** @@ -104,8 +104,7 @@ ACL_FUNC_VISIBILITY aclError aclfvSetNMTopNum(aclfvInitPara *initPara, uint32_t * @retval OtherValues success. */ ACL_FUNC_VISIBILITY aclfvFeatureInfo *aclfvCreateFeatureInfo(uint32_t id0, uint32_t id1, uint32_t offset, - uint32_t featureLen, uint32_t featureCount, - uint8_t *featureData, uint32_t featureDataLen); + uint32_t featureLen, uint32_t featureCount, uint8_t *featureData, uint32_t featureDataLen); /** * @ingroup AscendCL @@ -234,9 +233,8 @@ ACL_FUNC_VISIBILITY aclError aclfvDestroySearchInput(aclfvSearchInput *searchInp * @retval null for failed. OtherValues success */ ACL_FUNC_VISIBILITY aclfvSearchResult *aclfvCreateSearchResult(uint32_t queryCnt, uint32_t *resultNum, - uint32_t resultNumDataLen, uint32_t *id0, uint32_t *id1, - uint32_t *resultOffset, float *resultDistance, - uint32_t dataLen); + uint32_t resultNumDataLen, uint32_t *id0, uint32_t *id1, uint32_t *resultOffset, float *resultDistance, + uint32_t dataLen); /** * @ingroup AscendCL @@ -350,4 +348,4 @@ ACL_FUNC_VISIBILITY aclError aclfvSearch(aclfvSearchType type, aclfvSearchInput } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_RETR_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_RETR_H_ diff --git a/inc/external/hccl/hccl.h b/inc/external/hccl/hccl.h index 8261adc4..969d855a 100644 --- a/inc/external/hccl/hccl.h +++ b/inc/external/hccl/hccl.h @@ -27,7 +27,7 @@ #ifdef __cplusplus extern "C" { -#endif // __cplusplus +#endif // __cplusplus /** * @brief Initialize HCCL. @@ -66,15 +66,14 @@ extern HcclResult HcclCommInitRootInfo(uint32_t nRanks, const HcclRootInfo *root * @param sendBuf A pointer identifying the input data address of the operator. * @param recvBuf A pointer identifying the output data address of the operator. * @param count An integer(u64) identifying the number of the output data. - * @param dataType The data type of the operator, must be one of the following types: int8, int16, int32, float16, - * float32. + * @param dataType The data type of the operator, must be one of the following types: int8, int16, int32, float16, float32. * @param op The reduction type of the operator, must be one of the following types: sum, min, max, prod. * @param comm A pointer identifying the communication resource based on. * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclAllReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType, HcclReduceOp op, - HcclComm comm, aclrtStream stream); +extern HcclResult HcclAllReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType, +HcclReduceOp op, HcclComm comm, aclrtStream stream); /** * @brief Broadcast operator. @@ -85,10 +84,10 @@ extern HcclResult HcclAllReduce(void *sendBuf, void *recvBuf, uint64_t count, Hc * @param root An integer(u32) identifying the the root rank in the operator. * @param comm A pointer identifying the communication resource based on * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclBroadcast(void *buf, uint64_t count, HcclDataType dataType, uint32_t root, HcclComm comm, - aclrtStream stream); +extern HcclResult HcclBroadcast(void *buf, uint64_t count, HcclDataType dataType, uint32_t root, HcclComm comm, +aclrtStream stream); /** * @brief ReduceScatter operator. @@ -100,10 +99,10 @@ extern HcclResult HcclBroadcast(void *buf, uint64_t count, HcclDataType dataType * @param op The reduction type of the operator, must be one of the following types: sum, min, max, prod. * @param comm A pointer identifying the communication resource based on. * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclReduceScatter(void *sendBuf, void *recvBuf, uint64_t recvCount, HcclDataType dataType, - HcclReduceOp op, HcclComm comm, aclrtStream stream); +extern HcclResult HcclReduceScatter(void *sendBuf, void *recvBuf, uint64_t recvCount, HcclDataType dataType, +HcclReduceOp op, HcclComm comm, aclrtStream stream); /** * @brief AllGather operator. @@ -114,16 +113,16 @@ extern HcclResult HcclReduceScatter(void *sendBuf, void *recvBuf, uint64_t recvC * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. * @param comm A pointer identifying the communication resource based on. * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclAllGather(void *sendBuf, void *recvBuf, uint64_t sendCount, HcclDataType dataType, HcclComm comm, - aclrtStream stream); +extern HcclResult HcclAllGather(void *sendBuf, void *recvBuf, uint64_t sendCount, HcclDataType dataType, +HcclComm comm, aclrtStream stream); /** * @brief Get the rank size of this comm. * * @param comm A pointer identifying the communication resource based on. * @param rankSize A pointer identifying the rank size. - * @return HcclResult + * @return HcclResult */ extern HcclResult HcclGetRankSize(HcclComm comm, uint32_t *rankSize); @@ -132,7 +131,7 @@ extern HcclResult HcclGetRankSize(HcclComm comm, uint32_t *rankSize); * * @param comm A pointer identifying the communication resource based on. * @param rankSize A pointer identifying the rank id. - * @return HcclResult + * @return HcclResult */ extern HcclResult HcclGetRankId(HcclComm comm, uint32_t *rank); /** @@ -140,7 +139,7 @@ extern HcclResult HcclGetRankId(HcclComm comm, uint32_t *rank); * * @param comm A pointer identifying the communication resource based on. * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ extern HcclResult HcclBarrier(HcclComm comm, aclrtStream stream); @@ -155,5 +154,5 @@ extern HcclResult HcclCommDestroy(HcclComm comm); #ifdef __cplusplus } -#endif // __cplusplus -#endif // HCCL_H_ +#endif // __cplusplus +#endif // HCCL_H_ diff --git a/inc/external/hccl/hccl_types.h b/inc/external/hccl/hccl_types.h index 0e832396..50a64795 100644 --- a/inc/external/hccl/hccl_types.h +++ b/inc/external/hccl/hccl_types.h @@ -16,10 +16,10 @@ /** * @file hccl_types.h - * @brief HCCL data type definition - * + * @brief HCCL data type definition + * */ - + #ifndef HCCL_TYPES_H_ #define HCCL_TYPES_H_ @@ -27,33 +27,33 @@ #ifdef __cplusplus extern "C" { -#endif // __cplusplus +#endif // __cplusplus /** * @brief HCCL functions return value definition */ typedef enum { - HCCL_SUCCESS = 0, /**< success */ - HCCL_E_PARA = 1, /**< parameter error */ - HCCL_E_PTR = 2, /**< empty pointer */ - HCCL_E_MEMORY = 3, /**< memory error */ - HCCL_E_INTERNAL = 4, /**< internal error */ - HCCL_E_NOT_SUPPORT = 5, /**< not support feature */ - HCCL_E_NOT_FOUND = 6, /**< not found specific resource */ - HCCL_E_UNAVAIL = 7, /**< resource unavailable */ - HCCL_E_SYSCALL = 8, /**< call system interface error */ - HCCL_E_TIMEOUT = 9, /**< timeout */ - HCCL_E_OPEN_FILE_FAILURE = 10, /**< open file fail */ - HCCL_E_TCP_CONNECT = 11, /**< tcp connect fail */ - HCCL_E_ROCE_CONNECT = 12, /**< roce connect fail */ - HCCL_E_TCP_TRANSFER = 13, /**< tcp transfer fail */ - HCCL_E_ROCE_TRANSFER = 14, /**< roce transfer fail */ - HCCL_E_RUNTIME = 15, /**< call runtime api fail */ - HCCL_E_DRV = 16, /**< call driver api fail */ - HCCL_E_PROFILING = 17, /**< call profiling api fail */ - HCCL_E_CCE = 18, /**< call cce api fail */ - HCCL_E_NETWORK = 19, /**< call network api fail */ - HCCL_E_RESERVED /**< reserved */ + HCCL_SUCCESS = 0, /**< success */ + HCCL_E_PARA = 1, /**< parameter error */ + HCCL_E_PTR = 2, /**< empty pointer */ + HCCL_E_MEMORY = 3, /**< memory error */ + HCCL_E_INTERNAL = 4, /**< internal error */ + HCCL_E_NOT_SUPPORT = 5, /**< not support feature */ + HCCL_E_NOT_FOUND = 6, /**< not found specific resource */ + HCCL_E_UNAVAIL = 7, /**< resource unavailable */ + HCCL_E_SYSCALL = 8, /**< call system interface error */ + HCCL_E_TIMEOUT = 9, /**< timeout */ + HCCL_E_OPEN_FILE_FAILURE = 10, /**< open file fail */ + HCCL_E_TCP_CONNECT = 11, /**< tcp connect fail */ + HCCL_E_ROCE_CONNECT = 12, /**< roce connect fail */ + HCCL_E_TCP_TRANSFER = 13, /**< tcp transfer fail */ + HCCL_E_ROCE_TRANSFER = 14, /**< roce transfer fail */ + HCCL_E_RUNTIME = 15, /**< call runtime api fail */ + HCCL_E_DRV = 16, /**< call driver api fail */ + HCCL_E_PROFILING = 17, /**< call profiling api fail */ + HCCL_E_CCE = 18, /**< call cce api fail */ + HCCL_E_NETWORK = 19, /**< call network api fail */ + HCCL_E_RESERVED /**< reserved */ } HcclResult; /** @@ -65,37 +65,37 @@ typedef void *HcclComm; * @brief HCCL Reduction opperation */ typedef enum { - HCCL_REDUCE_SUM = 0, /**< sum */ - HCCL_REDUCE_PROD = 1, /**< prod */ - HCCL_REDUCE_MAX = 2, /**< max */ - HCCL_REDUCE_MIN = 3, /**< min */ - HCCL_REDUCE_RESERVED /**< reserved */ + HCCL_REDUCE_SUM = 0, /**< sum */ + HCCL_REDUCE_PROD = 1, /**< prod */ + HCCL_REDUCE_MAX = 2, /**< max */ + HCCL_REDUCE_MIN = 3, /**< min */ + HCCL_REDUCE_RESERVED /**< reserved */ } HcclReduceOp; /** * @brief HCCL data type */ typedef enum { - HCCL_DATA_TYPE_INT8 = 0, /**< int8 */ - HCCL_DATA_TYPE_INT16 = 1, /**< int16 */ - HCCL_DATA_TYPE_INT32 = 2, /**< int32 */ - HCCL_DATA_TYPE_FP16 = 3, /**< fp16 */ - HCCL_DATA_TYPE_FP32 = 4, /**< fp32 */ - HCCL_DATA_TYPE_INT64 = 5, /**< int64 */ - HCCL_DATA_TYPE_UINT64 = 6, /**< uint64 */ - HCCL_DATA_TYPE_RESERVED /**< reserved */ + HCCL_DATA_TYPE_INT8 = 0, /**< int8 */ + HCCL_DATA_TYPE_INT16 = 1, /**< int16 */ + HCCL_DATA_TYPE_INT32 = 2, /**< int32 */ + HCCL_DATA_TYPE_FP16 = 3, /**< fp16 */ + HCCL_DATA_TYPE_FP32 = 4, /**< fp32 */ + HCCL_DATA_TYPE_INT64 = 5, /**< int64 */ + HCCL_DATA_TYPE_UINT64 = 6, /**< uint64 */ + HCCL_DATA_TYPE_RESERVED /**< reserved */ } HcclDataType; -const uint32_t HCCL_ROOT_INFO_BYTES = 4108; // 4108: root info length +const uint32_t HCCL_ROOT_INFO_BYTES = 4108; // 4108: root info length /** * @brief HCCL root info */ typedef struct HcclRootInfoDef { - char internal[HCCL_ROOT_INFO_BYTES]; + char internal[HCCL_ROOT_INFO_BYTES]; } HcclRootInfo; #ifdef __cplusplus } -#endif // __cplusplus -#endif // HCCL_TYPES_H_ +#endif // __cplusplus +#endif // HCCL_TYPES_H_ diff --git a/inc/external/runtime/rt_error_codes.h b/inc/external/runtime/rt_error_codes.h index 1c196c48..c9a40432 100644 --- a/inc/external/runtime/rt_error_codes.h +++ b/inc/external/runtime/rt_error_codes.h @@ -23,84 +23,84 @@ extern "C" { #endif -static const int32_t ACL_RT_SUCCESS = 0; // success +static const int32_t ACL_RT_SUCCESS = 0; // success -static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid -static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id -static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null -static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context -static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context -static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal -static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned -static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed -static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed -static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream -static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread -static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set -static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create -static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream -static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type -static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle -static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type +static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid +static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id +static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null +static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context +static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context +static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal +static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned +static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed +static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed +static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream +static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread +static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set +static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create +static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream +static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type +static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle +static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type -static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support -static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error -static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error -static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow -static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device -static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail -static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission -static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource -static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource -static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource -static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource +static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support +static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error +static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error +static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow +static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device +static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail +static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission +static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource +static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource +static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource +static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource -static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error -static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout -static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception -static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout +static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception -static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error -static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error -static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect +static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error +static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error +static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect #ifdef __cplusplus } #endif -#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ +#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/third_party/fwkacllib/inc/ops/control_flow_ops.h b/third_party/fwkacllib/inc/ops/control_flow_ops.h index c0b6ad72..9a0e0cd5 100644 --- a/third_party/fwkacllib/inc/ops/control_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/control_flow_ops.h @@ -387,12 +387,12 @@ REG_OP(ControlTrigger) *@par Inputs: * Three inputs, including: -*@li x: One dimensional tensore of type int32, specifying queried shape, max size is 8. -*@li data_seq: One dimensional tensore of type int32, specifying the mapped table is queried. -*@li level_index: One dimensional tensore of type int32, specifying secondary index. \n +*@li x: One dimensional tensor of type int32, specifying queried shape, max size is 128. +*@li data_seq: One dimensional tensor of type int32, specifying the mapped table is queried. +*@li level_index: One dimensional tensor of type int32, specifying secondary index. \n *@par Outputs: -*@li y: A Tensor with shape [batch, 8], of type int32, specifying index of shape in the map. +*@li y: A Tensor with shape [8], of type int32, specifying index of shape in the map. *@par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. */ diff --git a/third_party/fwkacllib/inc/ops/ctc_ops.h b/third_party/fwkacllib/inc/ops/ctc_ops.h index c6a265cc..e907b828 100644 --- a/third_party/fwkacllib/inc/ops/ctc_ops.h +++ b/third_party/fwkacllib/inc/ops/ctc_ops.h @@ -137,6 +137,87 @@ REG_OP(CTCBeamSearchDecoder) .OUTPUT(log_probability, TensorType({DT_FLOAT, DT_DOUBLE})) .OP_END_FACTORY_REG(CTCBeamSearchDecoder) +/** +*@brief The Connectionist Temporal Classification loss. + +*@par Inputs: +*@li log_probs: Tensor of size (T, N, C), where T =input length, N =batch size, + and C = number of classes (including blank). + It represent the logarithmized probabilities of the outputs. +*@li targets: Tensor of size (N, S), where S= max target length. + It represent the target sequences. +*@li input_lengths: Tuple or tensor of size (N). It represent the lengths of the inputs. +*@li target_lengths: Tuple or tensor of size (N). It represent lengths of the targets. + +*@par Outputs: +*@li neg_log_likelihood: A loss value which is differentiable with respect to each input node. +*@li log_alpha: The probability of possible trace of input to target. + +*@par Attributes: +*@li blank : Blank label. Default 0. +*@li reduction: Specifies the reduction to apply to the output. Default: 'mean'. +*@li zero_infinity : Whether to zero infinite losses and the associated gradients. + +*@par Third-party framework compatibility +* Compatible with Pytorch CTCLoss operator. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(CTCLossV2) + .INPUT(log_probs, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(targets, TensorType({DT_INT32, DT_INT64})) + .INPUT(input_lengths, TensorType({DT_INT32, DT_INT64})) + .INPUT(target_lengths, TensorType({DT_INT32, DT_INT64})) + .OUTPUT(neg_log_likelihood, TensorType({DT_FLOAT, DT_DOUBLE})) + .OUTPUT(log_alpha, TensorType({DT_FLOAT, DT_DOUBLE})) + .ATTR(blank, Int, 0) + .ATTR(reduction, String, "mean") + .ATTR(zero_infinity, Bool, false) + .OP_END_FACTORY_REG(CTCLossV2) + +/** +*@brief The Connectionist Temporal Classification loss grad. + +*@par Inputs: +*@li grad_out: Gradient renewal coefficient. Tensor of size (N), where N = batch size. +*@li log_probs: Tensor of size (T, N, C), where T =input length, N =batch size, + and C = number of classes (including blank). + It represent the logarithmized probabilities of the outputs. +*@li targets: Tensor of size (N, S), where S= max target length. + It represent the target sequences. +*@li input_lengths: Tuple or tensor of size (N). It represent the lengths of the inputs. +*@li target_lengths: Tuple or tensor of size (N). It represent lengths of the targets. +*@li neg_log_likelihood: A loss value which is differentiable with respect to each input node. +*@li log_alpha: The probability of possible trace of input to target. + +*@par Outputs: +*@li grad: Tensor of size (T, N, C), The grad of Connectionist Temporal Classification loss. + +*@par Attributes: +*@li blank : Blank label. Default 0. +*@li reduction: Specifies the reduction to apply to the output. Default: 'mean'. +*@li zero_infinity : Whether to zero infinite losses and the associated gradients. + +*@par Third-party framework compatibility +* Compatible with Pytorch CTCLoss operator. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(CTCLossV2Grad) + .INPUT(grad_out, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(log_probs, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(targets, TensorType({DT_INT32, DT_INT64})) + .INPUT(input_lengths, TensorType({DT_INT32, DT_INT64})) + .INPUT(target_lengths, TensorType({DT_INT32, DT_INT64})) + .INPUT(neg_log_likelihood, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(log_alpha, TensorType({DT_FLOAT, DT_DOUBLE})) + .OUTPUT(grad, TensorType({DT_FLOAT, DT_DOUBLE})) + .ATTR(blank, Int, 0) + .ATTR(reduction, String, "mean") + .ATTR(zero_infinity, Bool, false) + .OP_END_FACTORY_REG(CTCLossV2Grad) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_CTC_OPS_H_ \ No newline at end of file diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index 7850536d..c8df447d 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -1039,7 +1039,7 @@ REG_OP(BesselI1e) * y = log_base(shift + scale * x), with "base" > 0. \n * @par Inputs: -* @li x: A Tensor of type complex64, complex128, float16, float32 or double. \n +* x: A Tensor of type complex64, complex128, float16, float32 or double. \n * @par Attributes: * @li base: An optional float32, specifying the base "e". Defaults to "-1.0" @@ -1084,7 +1084,7 @@ REG_OP(Log) * uint8, int8, uint16, int16, int32, int64, complex64, complex128. \n * @attention Constraints: -* @li "x1" and "x2" have incompatible shapes or types. \n +* "x1" and "x2" have incompatible shapes or types. \n * @par Third-party framework compatibility * Compatible with the TensorFlow operator Multiply. @@ -3415,7 +3415,7 @@ REG_OP(Addcdiv) .INPUT(input_data, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(value, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT32 })) + .INPUT(value, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT32})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(Addcdiv) @@ -3467,25 +3467,6 @@ REG_OP(AxpyV2) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) .OP_END_FACTORY_REG(AxpyV2) -/** -* @brief Computes the result of x1 * x2. - -* @par Inputs: -* @li x1: An ND tensor of type float16, float32, int32. -* @li x2: An ND tensor of type float16, float32, int32. \n - -* @par Outputs: -* @li y: Same shape and type as the largest ND tensor in x1 x2. \n - -* @par Third-party framework compatibility -* Compatible with the Pytorch operator muls. -*/ -REG_OP(PtMuls) - .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) - .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) - .OP_END_FACTORY_REG(PtMuls) - /** * @brief Computes the result of x1 - x2. diff --git a/third_party/fwkacllib/inc/ops/globalavgpool.h b/third_party/fwkacllib/inc/ops/globalavgpool.h new file mode 100644 index 00000000..06f03d30 --- /dev/null +++ b/third_party/fwkacllib/inc/ops/globalavgpool.h @@ -0,0 +1,49 @@ +/** + * Copyright 2019 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. + */ + +/*! + * \file globalavgpool.h + * \brief + */ +#ifndef OPS_BUILT_IN_OP_PROTO_INC_GLOBALAVERAGEPOOL_H_ +#define OPS_BUILT_IN_OP_PROTO_INC_GLOBALAVERAGEPOOL_H_ + +#include "graph/operator_reg.h" + +namespace ge { +/** +*@brief GlobalAveragePool consumes an input tensor X and applies average pooling across the values in the same channel. +This is equivalent to AveragePool with kernel size equal to the spatial dimension of input tensor \n + +*@par Inputs: +*@li x: Input data tensor from the previous operator; dimensions for image case are (N x C x H x W), +where N is the batch size, C is the number of channels, and H and W are the height and the width of the data. +For non image case, the dimensions are in the form of (N x C x D1 x D2 ... Dn), where N is the batch size. + +*@par Outputs: +*y: Output data tensor from pooling across the input tensor. The output tensor has the same rank as the input. +The first two dimensions of output shape are the same as the input (N x C), while the other dimensions are all 1 + +*@par Restrictions: +*Warning: This operator can be integrated only by configuring INSERT_OP_FILE of aclgrphBuildModel. Please do not use it directly. +*/ +REG_OP(GlobalAveragePool) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OP_END_FACTORY_REG(GlobalAveragePool) +} // namespace ge + +#endif // OPS_BUILT_IN_OP_PROTO_INC_GLOBALAVGPOOL_H_ \ No newline at end of file diff --git a/third_party/fwkacllib/inc/ops/image_ops.h b/third_party/fwkacllib/inc/ops/image_ops.h index 71f1b9e1..6909345a 100644 --- a/third_party/fwkacllib/inc/ops/image_ops.h +++ b/third_party/fwkacllib/inc/ops/image_ops.h @@ -1868,5 +1868,73 @@ REG_OP(IMGWarpOffsets) .INPUT(offsets, TensorType({DT_FLOAT, DT_INT32})) .OUTPUT(warp_images, TensorType({DT_UINT8, DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(IMGWarpOffsets) + +/** +*@brief This operation samples 3d input x by using interpolation based on flow field grid, + which is usually gennerated by affine_grid. + +*@par Inputs: +*@li x: 5-D Tensor with shape `[batch, channels, depth, height, width]`. +*@li grid: flow field grid, 5-D Tensor with shape `[batch, depth, height, width, 2]`. + +*@par Attributes: +*@li interpolation_mode: An optional string specifying the interpolation method. +*@li padding_mode: An optional string specifying the pad method. +*@li align_corners: An optional bool. If "true", the centers of the corner + pixels of the input and output tensors are aligned. Defaults to "false" . + +*@par Outputs: +*y: Returns 5-D Tensor with the same dtype as `x`. + +*@par Third-party framework compatibility +*Compatible with pytorch GridSampler3D operator. + +*@par Restrictions: +*Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(GridSampler3D) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(grid, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .ATTR(interpolation_mode, String, "bilinear") + .ATTR(padding_mode, String, "zeros") + .ATTR(align_corners, Bool, false) + .OP_END_FACTORY_REG(GridSampler3D) + +/** +*@brief Computes the gradients of GridSampler3D. + +*@par Inputs: +*@li grad: 5-D Tensor with shape `[batch, channels, depth, height, width]`. +*@li x: 5-D Tensor with shape `[batch, channels, depth, height, width]`. +*@li grid: flow field grid, 5-D Tensor with shape `[batch, depth, height, width, 2]`. + +*@par Attributes: +*@li interpolation_mode: An optional string specifying the interpolation method. +*@li padding_mode: An optional string specifying the pad method. +*@li align_corners: An optional bool. If "true", the centers of the corner + pixels of the input and output tensors are aligned. Defaults to "false" . + +*@par Outputs: +*dx: Returns 5-D Tensor with the same dtype and shape as `x`. +*dgrid: Returns 5-D Tensor with the same dtype and shape as `grid`. + +*@par Third-party framework compatibility +*Compatible with pytorch GridSampler3DGrad operator. + +*@par Restrictions: +*Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(GridSampler3DGrad) + .INPUT(grad, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(grid, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(dx, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(dgrid, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .ATTR(interpolation_mode, String, "bilinear") + .ATTR(padding_mode, String, "zeros") + .ATTR(align_corners, Bool, false) + .OP_END_FACTORY_REG(GridSampler3DGrad) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_IMAGE_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/linalg_ops.h b/third_party/fwkacllib/inc/ops/linalg_ops.h index 532a641d..69c77bf6 100644 --- a/third_party/fwkacllib/inc/ops/linalg_ops.h +++ b/third_party/fwkacllib/inc/ops/linalg_ops.h @@ -340,9 +340,9 @@ form square matrices. \n */ REG_OP(SelfAdjointEig) - .INPUT(x, TensorType({ DT_DOUBLE, DT_FLOAT })) - .OUTPUT(eigen_value, TensorType({ DT_DOUBLE, DT_FLOAT })) - .OUTPUT(eigen_vector, TensorType({ DT_DOUBLE, DT_FLOAT })) + .INPUT(x, TensorType({ DT_DOUBLE, DT_FLOAT, DT_COMPLEX64, DT_COMPLEX128 })) + .OUTPUT(eigen_value, TensorType({ DT_DOUBLE, DT_FLOAT, DT_COMPLEX64, DT_COMPLEX128 })) + .OUTPUT(eigen_vector, TensorType({ DT_DOUBLE, DT_FLOAT, DT_COMPLEX64, DT_COMPLEX128 })) .ATTR(compute_v, Bool, true) .OP_END_FACTORY_REG(SelfAdjointEig) diff --git a/third_party/fwkacllib/inc/ops/math_ops.h b/third_party/fwkacllib/inc/ops/math_ops.h index 4a44d744..8f11ab0f 100644 --- a/third_party/fwkacllib/inc/ops/math_ops.h +++ b/third_party/fwkacllib/inc/ops/math_ops.h @@ -818,8 +818,8 @@ REG_OP(ActsULQ) .INPUT(clamp_min, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(clamp_max, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) - .OUTPUT(clamp_min_mask, TensorType({DT_BOOL})) - .OUTPUT(clamp_max_mask, TensorType({DT_BOOL})) + .OUTPUT(clamp_min_mask, TensorType({DT_BOOL, DT_FLOAT16, DT_FLOAT})) + .OUTPUT(clamp_max_mask, TensorType({DT_BOOL, DT_FLOAT16, DT_FLOAT})) .OUTPUT(x_clamped_loss, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(fixed_min, Bool, false) .ATTR(num_bits, Int, 8) @@ -845,8 +845,8 @@ REG_OP(ActsULQ) REG_OP(ActsULQInputGrad) .INPUT(y_grad, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(clamp_min_mask, TensorType({DT_BOOL})) - .INPUT(clamp_max_mask, TensorType({DT_BOOL})) + .INPUT(clamp_min_mask, TensorType({DT_BOOL, DT_FLOAT16, DT_FLOAT})) + .INPUT(clamp_max_mask, TensorType({DT_BOOL, DT_FLOAT16, DT_FLOAT})) .OUTPUT(x_grad, TensorType({DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(ActsULQInputGrad) @@ -870,7 +870,7 @@ REG_OP(ActsULQInputGrad) REG_OP(ActULQClampMaxGrad) .INPUT(y_grad, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(clamp_max_mask, TensorType({DT_BOOL})) + .INPUT(clamp_max_mask, TensorType({DT_BOOL, DT_FLOAT16, DT_FLOAT})) .INPUT(x_clamped_loss, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(clamp_max_grad, TensorType({DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(ActULQClampMaxGrad) @@ -895,7 +895,7 @@ REG_OP(ActULQClampMaxGrad) REG_OP(ActULQClampMinGrad) .INPUT(y_grad, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(clamp_min_mask, TensorType({DT_BOOL})) + .INPUT(clamp_min_mask, TensorType({DT_BOOL, DT_FLOAT16, DT_FLOAT})) .INPUT(x_clamped_loss, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(clamp_min_grad, TensorType({DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(ActULQClampMinGrad) diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index af02276b..b317be37 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -455,6 +455,34 @@ REG_OP(TensorScatterUpdate) .OUTPUT(y, TensorType::BasicType()) .OP_END_FACTORY_REG(TensorScatterUpdate) +/** +*@brief Uses "updates" to update tensor "data" by "indices". \n + +*@par Inputs: +* Three inputs, including: +*@li data: An ND Tensor . \n +*Must be one of the following types: float16, float32, int32, int8, uint8 +*@li indices: An ND Tensor of type int32 or int64 +*@li updates: An Tensor. Same shape as indices. format:NCHW, NHWC . \n +*Must be one of the following types: float16, float32, int32, int8, uint8 + +*@par Attributes: +*@li axis: An optional attribute. Defaults to 0. + +*@par Outputs: +*y: A Tensor. Has the same type and format as input "data" . \n + +*@par Third-party framework compatibility +* Compatible with the ONNX operator ScatterElements. +*/ +REG_OP(ScatterElements) + .INPUT(data, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(indices, TensorType::IndexNumberType()) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .ATTR(axis, Int, 0) + .OP_END_FACTORY_REG(ScatterElements) + /** *@brief Adds sparse "updates" to a variable reference . \n @@ -1140,24 +1168,24 @@ REG_OP(Tril) *@par Attributes: *equation: The subscripts for the Einstein summation. \n -*tensor_size: tensor size of input \n +*N: tensor size of input \n *@par Outputs: *@li y: Sums the product of the elements of the input operands along dimensions specified using a notation based on the Einstein summation convention. \n *@attention Constraints: -*Input tensor_size must be Int. \n +*Input N must be Int. \n *@par Third-party framework compatibility *Compatible with Pytorch einsum operator. */ -REG_OP(EinSum) +REG_OP(Einsum) .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) .REQUIRED_ATTR(equation, String) - .REQUIRED_ATTR(tensor_size, Int) - .OP_END_FACTORY_REG(EinSum) + .REQUIRED_ATTR(N, Int) + .OP_END_FACTORY_REG(Einsum) /** *@brief Returns a 2-D tensor with ones on the diagonal and zeros elsewhere. \n diff --git a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h index 0eeeb511..98473c65 100644 --- a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h @@ -784,16 +784,14 @@ REG_OP(Conv2DBackpropFilterD) | Tensor | x | filter | bias | y ------------|---------|---------|---------|-------- | Data Type | float16 | float16 | float16 | float16 - | |---------|---------|---------|-------- | | float32 | float32 | float32 | float32 - | |---------|---------|---------|-------- | | int8 | int8 | int32 | int32 ------------|---------|---------|---------|-------- | Format | NCHW | NCHW | ND | NCHW | | NHWC | HWCN | | NHWC @endverbatim * For float32 type, the actual calculation on the chip is based on -* float16. For int8, a dequant or requant operator must be followed. +* float16. *\n * *@par Attributes: diff --git a/third_party/fwkacllib/inc/ops/nn_detect_ops.h b/third_party/fwkacllib/inc/ops/nn_detect_ops.h index d4141e47..5fa40ad6 100644 --- a/third_party/fwkacllib/inc/ops/nn_detect_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_detect_ops.h @@ -1450,7 +1450,8 @@ REG_OP(DecodeBboxV2) * *@par Inputs: *Inputs include: -* x: A Tensor. Must be float16 or float32. +* x: A Tensor. Dtype support: flaot16, flaot, int16, int8, + uint8, int32, int64. * *@par Attributes: * @li axis: optional, int. @@ -1462,9 +1463,11 @@ REG_OP(DecodeBboxV2) * */ REG_OP(Sort) - .INPUT(x, TensorType({ DT_FLOAT16 })) - .OUTPUT(y1, TensorType({ DT_FLOAT16 })) - .OUTPUT(y2, TensorType({ DT_INT32 })) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT16, DT_INT8, + DT_UINT8, DT_INT32, DT_INT64})) + .OUTPUT(y1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT16, DT_INT8, + DT_UINT8, DT_INT32, DT_INT64})) + .OUTPUT(y2, TensorType({DT_INT32})) .ATTR(axis, Int, -1) .ATTR(descending, Bool, false) .OP_END_FACTORY_REG(Sort) @@ -1718,6 +1721,101 @@ REG_OP(PSROIPoolingGradV2D) .REQUIRED_ATTR(input_size, ListInt) .OP_END_FACTORY_REG(PSROIPoolingGradV2D) +/** +*@brief Generate the responsible flags of anchor in a single feature map. + +*@par Inputs: +*@li gt_bboxes: Ground truth box, 2-D Tensor with shape `[batch, 4]`. + +*@par Attributes: +*@li featmap_size: The size of feature maps, listint. +*@li strides: Stride of current level, listint. +*@li num_base_anchors: The number of base anchors. + +*@par Outputs: +*flags: The valid flags of each anchor in a single level. +*/ +REG_OP(AnchorResponseFlags) + .INPUT(gt_bboxes, TensorType({DT_FLOAT})) + .OUTPUT(flags, TensorType({DT_UINT8})) + .REQUIRED_ATTR(featmap_size, ListInt) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(num_base_anchors, Int) + .OP_END_FACTORY_REG(AnchorResponseFlags) + +/** +*@brief Generates bounding boxes based on yolo's "anchor" and "ground-truth" boxes. +* It is a customized mmdetection operator . \n + +*@par Inputs: +* Three inputs, including: +*@li anchor_boxes: anchor boxes generated by the yolo training set. +* A 2D Tensor of type float32 or float16 with shape (N, 4). "N" indicates the number +* of ROIs, "N" indicates the number of ROIs, and the value "4" refers to (tx, ty, tw, th). +*@li gt_bboxes: target of the transformation, e.g, ground-truth boxes. +* A 2D Tensor of type float32 or float16 with shape (N, 4). +* "N" indicates the number of ROIs, and 4 indicates "dx", "dy", "dw", and "dh" . +*@li stride: Scale for each box. +* A 1D Tensor of type int32 shape (N,). +* "N" indicates the number of ROIs. \n + +*@par Attributes: +*@li performance_mode: select performance mode, "high_precision" or "high_performance". +* select "high_precision" when input type is float32, the output tensor precision +* will be smaller than 0.0001, select "high_performance" when input type is float32, +* the ops will be best performance, but precision will be only smaller than 0.005. + +*@par Outputs: +*encoded_bboxes: Bboxes generated based on "anchor_boxes" and "gt_bboxes". Have the +* same format and type as "anchor_boxes". +* +*@attention Constraints: +* input anchor boxes only support maximum N=20480. \n +*/ +REG_OP(YoloBoxesEncode) + .INPUT(anchor_boxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(gt_bboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(stride, TensorType({DT_INT32})) + .ATTR(performance_mode, String, "high_precision") + .OUTPUT(encoded_bboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(YoloBoxesEncode) + +/** +*@brief Performs Position Sensitive PS ROI Pooling Grad. + +*@par Inputs: +* Eight inputs, including: +*@li assigned_gt_inds: Tensor of type float16 or float32, shape (n, ) +*@li overlaps: A Tensor. Datatype is same as assigned_gt_inds. IOU between gt_bboxes and bboxes. shape(k, n) +*@li box_responsible_flags: A Tensor. Support uint8. Flag to indicate whether box is responsible. +*@li max_overlaps: A Tensor. Datatype is same as assigned_gt_inds. overlaps.max(axis=0). +*@li argmax_overlaps: A Tensor. Support int32. overlaps.argmax(axis=0). +*@li gt_max_overlaps: A Tensor. Datatype is same as assigned_gt_inds. overlaps.max(axis=1). +*@li gt_argmax_overlaps: A Tensor. Support int32. overlaps.argmax(axis=1). +*@li num_gts: A Tensor. Support int32. real k. shape (1, ) + +*@par Attributes: +*@li output_dim: float. IOU threshold for positive bboxes. +*@li group_size: float. minimum iou for a bbox to be considered as a positive bbox +*@li spatial_scale: bool. whether to assign all bboxes with the same highest overlap with some gt to that gt. + +*@par Outputs: +*@li assigned_gt_inds_pos: A Tensor. Support float16/float32. shape (n, ). +*/ +REG_OP(GridAssignPositive) + .INPUT(assigned_gt_inds, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(overlaps, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(box_responsible_flags, TensorType({ DT_UINT8 })) + .INPUT(max_overlaps, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(argmax_overlaps, TensorType({ DT_INT32 })) + .INPUT(gt_max_overlaps, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(gt_argmax_overlaps, TensorType({ DT_INT32 })) + .INPUT(num_gts, TensorType({ DT_INT32 })) + .OUTPUT(assigned_gt_inds_pos, TensorType({DT_FLOAT, DT_FLOAT16})) + .REQUIRED_ATTR(pos_iou_thr, Float) + .REQUIRED_ATTR(min_pos_iou, Float) + .REQUIRED_ATTR(gt_max_assign_all, Bool) + .OP_END_FACTORY_REG(GridAssignPositive) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_DETECT_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index 796e1e61..c6718c7c 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -107,6 +107,9 @@ REG_OP(SoftmaxCrossEntropyWithLogits) * @li grad_softmax: A Tensor. Has the same shape and type as "softmax". * The format is NC1HWC0 or DN . \n +*@par Attributes: +* axes: An optional list of ints. Defaults to "{-1}" . \n + *@par Outputs: *grad_x: A Tensor. Has the same shape and type as "softmax" . \n @@ -117,6 +120,7 @@ REG_OP(SoftmaxGrad) .INPUT(softmax, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .INPUT(grad_softmax, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .OUTPUT(grad_x, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .ATTR(axes, ListInt, {-1}) .OP_END_FACTORY_REG(SoftmaxGrad) /** @@ -889,7 +893,7 @@ REG_OP(Scale) *@par Inputs: *One input, including: -*@li x: A Tensor. Must be 4-D shape, and only support the following types: float16, float32 . \n +*x: A Tensor. Must be 4-D shape, and only support the following types: float16, float32 . \n *@par Attributes: *@li depth_radius: An optional int32, specifying the half-width of the normalization window. Defaults to "5". diff --git a/third_party/fwkacllib/inc/ops/nn_ops.h b/third_party/fwkacllib/inc/ops/nn_ops.h index f7dd6795..49fd02fa 100644 --- a/third_party/fwkacllib/inc/ops/nn_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_ops.h @@ -104,5 +104,60 @@ REG_OP(FusedBatchNormV2) .ATTR(data_format, String, "NHWC") .ATTR(is_training, Bool, true) .OP_END_FACTORY_REG(FusedBatchNormV2) + +/** + * @brief: Large amount of data sort.First operator of TopK. + * @par Inputs: + * two input, including: + * @li input_data: A Tensor. Data to be sorted. Support float16 + * @li input_index: A Tensor. Range(0, 2048). Datatype and format is same as input_data. + * @par Attributes: + * @li k_num: Int.Number to be sorted. + * @par Outputs: + * 1 output, including: + * @li output_proposal: A Tensor. Datatype and format is same as input_data. Proposal sorted for each channel. + */ +REG_OP(SegmentSort) + .INPUT(input_data, TensorType({DT_FLOAT16})) + .INPUT(input_index, TensorType({DT_FLOAT16})) + .OUTPUT(output_proposal, TensorType({DT_FLOAT16})) + .REQUIRED_ATTR(k_num, Int) + .OP_END_FACTORY_REG(SegmentSort) + +/** + * @brief: Large amount of data sort.Second operator of TopK. + * @par Inputs: + * two input, including: + * @li input_proposal: A Tensor. Proposal sorted for each channel. Support float16 + * @par Attributes: + * @li k_num: Int.Number to be sorted. + * @par Outputs: + * 1 output, including: + * @li output_proposal: A Tensor. Datatype and format is same as input_data. Proposal sorted for each channel. + */ +REG_OP(MultiMerge) + .INPUT(input_proposal, TensorType({DT_FLOAT16})) + .OUTPUT(output_proposal, TensorType({DT_FLOAT16})) + .REQUIRED_ATTR(k_num, Int) + .OP_END_FACTORY_REG(MultiMerge) + +/** + * @brief: Large amount of data sort.Third operator of TopK. + * @par Inputs: + * two input, including: + * @li input_proposal: A Tensor. Proposal sorted for each channel. Support float16 + * @par Attributes: + * @li k_num: Int.Number to be sorted. + * @par Outputs: + * 2 output, including: + * @li output_data: A Tensor. Datatype and format is same as input_data. Data sorted. + * @li output_index: A Tensor. int32. Data index. + */ +REG_OP(SingleMerge) + .INPUT(input_proposal, TensorType({DT_FLOAT16})) + .OUTPUT(output_data, TensorType({DT_FLOAT16})) + .OUTPUT(output_index, TensorType({DT_INT32})) + .REQUIRED_ATTR(k_num, Int) + .OP_END_FACTORY_REG(SingleMerge) }// namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h index ef9fabb8..80a21333 100644 --- a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h @@ -227,12 +227,12 @@ REG_OP(AvgPool3DD) * @brief Computes AvgPool3DGrad function. * @par Inputs: -* @li orig_input_shape: An NDHWC tensor of type float16, float32, or double. -* @li grads: An NDHWC tensor of type int32. +* @li orig_input_shape: An NDHWC tensor of type int32. +* @li grads: An NDHWC tensor of type float16, float32, or double. * @par Attributes: -* @li ksize: List of ints that has length 1, 3 or 5. The size of the window for each dimension of the input tensor. -* @li strides:List of ints that has length 1, 3 or 5. The stride of the sliding window for each dimension of the input tensor. +* @li ksize: List of ints that has length 5. The size of the window for each dimension of the input tensor. +* @li strides:List of ints that has length 5. The stride of the sliding window for each dimension of the input tensor. * @li pads: List of ints, implicit zero paddings on both sides of the input. * @li ceil_mode: When true, will use ceil instead of floor in the formula to compute the output shape. * @li count_include_pad: When true, will include the zero-padding in the averaging calculation. @@ -242,6 +242,9 @@ REG_OP(AvgPool3DD) * @par Outputs: * @output: A mutable tensor with the same shape and type as "orig_input_shape". +* @attention Constraints: +* @li "ksize" is in the range [1, 255]. "strides" is in the range [1, 63] + * @par Third-party framework compatibility * @li Compatible with the TensorFlow operator AvgPoolGrad. */ @@ -269,8 +272,8 @@ REG_OP(AvgPool3DGrad) * @par Attributes: * @li orig_input_shape: List of ints that has length 5. The size of the window for each dimension of the input tensor. -* @li ksize: List of ints that has length 3. The size of the window for each dimension of the input tensor. -* @li strides:List of ints that has length 3. The stride of the sliding window for each dimension of the input tensor. +* @li ksize: List of ints that has length 5. The size of the window for each dimension of the input tensor. +* @li strides:List of ints that has length 5. The stride of the sliding window for each dimension of the input tensor. * @li pads: List of ints, implicit zero paddings on both sides of the input. * @li ceil_mode: When true, will use ceil instead of floor in the formula to compute the output shape. * @li count_include_pad: When true, will include the zero-padding in the averaging calculation. @@ -290,7 +293,7 @@ REG_OP(AvgPool3DGradD) .INPUT(grads, TensorType({DT_FLOAT16})) .OPTIONAL_INPUT(filter, TensorType({DT_FLOAT16})) .OPTIONAL_INPUT(multiplier, TensorType({DT_FLOAT16})) - .OUTPUT(output, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .OUTPUT(output, TensorType({DT_FLOAT16})) .REQUIRED_ATTR(orig_input_shape, ListInt) .REQUIRED_ATTR(ksize, ListInt) .REQUIRED_ATTR(strides, ListInt) @@ -621,7 +624,7 @@ REG_OP(MaxPoolV2) *@par Inputs: * One input: -*x: An 4D Tensor. Supported type: float, double, int32, +* x: An 4D Tensor. Supported type: float, double, int32, * uint8, int16, int8, int64, uint16, half, uint32, uint64. * Must set the format, supported format list ["NCHW, NHWC"]. \n @@ -635,8 +638,8 @@ REG_OP(MaxPoolV2) *@li padding: A required string. No default value . \n *@par Outputs: -*y: A Tensor. Has the same type and format as input "x". -*argmax: A Tensor. Has the same type and format as input "x". +*@li y: A Tensor. Has the same type and format as input "x". +*@li argmax: A Tensor. Has the same type and format as input "x". *@attention Constraints: *@li "ksize" is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, * ksize[1] * ksize[2] <= 255. diff --git a/third_party/fwkacllib/inc/ops/pad_ops.h b/third_party/fwkacllib/inc/ops/pad_ops.h index bacbe40d..6854c866 100644 --- a/third_party/fwkacllib/inc/ops/pad_ops.h +++ b/third_party/fwkacllib/inc/ops/pad_ops.h @@ -269,39 +269,42 @@ REG_OP(PadV3) .ATTR(paddings_contiguous, Bool, true) .OP_END_FACTORY_REG(PadV3) -/** -*@brief Pads a tensor. - -*@par Inputs: -* @li x: A Tensor. Must be one of the following types: float16, float32. -* @li paddings: A Tensor. Must be int32 type -* paddings is a required input tensor. - -*@par Attributes: -* @li constant_values: An optional int value for pad. -* @li mode: An optional string, Defaults to "constant", indicates paddings mode, -* support "constant", "reflect", "edge" -* @li paddings_contiguous: An optional bool value, Defaults to true. -* If true, paddings is arranged as [[begin0, end0], [begin1, end1], ...] -* If false, paddings is arranged as [[begin0, begin1], ..., [end0, end1], ...] - -*@par Outputs: -*y: A Tensor of the same type as "x". - -*@par Third-party framework compatibility: -* Compatible with ONNX operator Pad. - -* @par Restrictions: -* Warning: THIS FUNCTION IS DEPRECATED. Please use PadV3 instead. -*/ -REG_OP(PadV3D) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(paddings, TensorType({DT_INT32})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) - .ATTR(constant_values, Int, 0) - .ATTR(mode, String, "constant") - .ATTR(paddings_contiguous, Bool, true) - .OP_END_FACTORY_REG(PadV3D) + /** + *@brief Pads a tensor. + + *@par Inputs: + *x: A Tensor. Must be one of the following types: float16, float32, int8, uint8, int32. + + *@par Attributes: + * @li paddings: An required "vector>". + * For each dimension D of input, paddings[D, 0] indicates how many + * values to add before the contents of tensor in that dimension, + * and paddings[D, 1] indicates how many values to add after the + * contents of tensor in that dimension. + * @li constant_values: An optional int value for pad. + * @li mode: An optional string, Defaults to "constant", indicates paddings mode, + * support "constant", "reflect", "edge" + * @li paddings_contiguous: An optional bool value, Defaults to true. + * If true, paddings is arranged as [[begin0, end0], [begin1, end1], ...] + * If false, paddings is arranged as [[begin0, begin1], ..., [end0, end1], ...] + + *@par Outputs: + *y: A Tensor of the same type as "x". + + *@par Third-party framework compatibility: + * Compatible with ONNX operator Pad. + + * @par Restrictions: + * Warning: THIS FUNCTION IS DEPRECATED. Please use PadV3 instead. + */ + REG_OP(PadV3D) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_UINT8})) + .REQUIRED_ATTR(paddings, ListListInt) + .ATTR(constant_values, Int, 0) + .ATTR(mode, String, "constant") + .ATTR(paddings_contiguous, Bool, true) + .OP_END_FACTORY_REG(PadV3D) /** *@brief Create a diagonal tensor @@ -397,6 +400,36 @@ REG_OP(EmbeddingRankId) .ATTR(mode, String, "mod") .OP_END_FACTORY_REG(EmbeddingRankId) +/** +*@brief EmbeddingLocalIndex, Sort statistics index according to rank_id \n + +*@par Inputs: +* @li addr_table: A 2D tensor which last dimension must be 3. +* @li index: A tensor with data type int32, int64, uint32, uint64. + +*@par Attributes: +* @li row_memory: The size of Embedding vector in a row, the default is 320. +* @li mode: String type, currently there are two options: 'mod' and 'order' + +*@par Outputs: +* @li local_idx:Index on each server. +* @li nums:The number of local_idx found on each server. +* @li recover_idx:The sorted local_idx element is at the position corresponding +* to the original input index. + +*@par Third-party framework compatibility +* Compatible with the TensorFlow operator Diag. +*/ +REG_OP(EmbeddingLocalIndex) + .INPUT(addr_table, TensorType({DT_UINT64})) + .INPUT(index, TensorType({DT_INT64,DT_INT32,DT_UINT32,DT_UINT64})) + .OUTPUT(local_idx, TensorType({DT_INT64,DT_INT32,DT_UINT32,DT_UINT64})) + .OUTPUT(nums, TensorType({DT_INT64,DT_INT32,DT_UINT32,DT_UINT64})) + .OUTPUT(recover_idx, TensorType({DT_INT64,DT_INT32,DT_UINT32,DT_UINT64})) + .ATTR(row_memory, Int, 320) + .ATTR(mode, String, "mod") + .OP_END_FACTORY_REG(EmbeddingLocalIndex) + /** * @brief Fill the value to a tensor has the specified shape. diff --git a/third_party/fwkacllib/inc/ops/quantize_ops.h b/third_party/fwkacllib/inc/ops/quantize_ops.h index d6eda1e6..69d5e67e 100644 --- a/third_party/fwkacllib/inc/ops/quantize_ops.h +++ b/third_party/fwkacllib/inc/ops/quantize_ops.h @@ -238,7 +238,6 @@ REG_OP(AscendRequantS16) .ATTR(dual_output, Bool, false) .ATTR(relu_flag, Bool, false) .OP_END_FACTORY_REG(AscendRequantS16) - } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_QUANTIZE_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/rnn.h b/third_party/fwkacllib/inc/ops/rnn.h index 9c6a7d1b..80546860 100644 --- a/third_party/fwkacllib/inc/ops/rnn.h +++ b/third_party/fwkacllib/inc/ops/rnn.h @@ -528,6 +528,60 @@ REG_OP(LSTMInputGrad) .OP_END_FACTORY_REG(LSTMInputGrad) + +/** +*@brief: Dynamic LSTM Cell grad calculation.Calculate the gradient of gates and cell state. +*@par Inputs: +*twelve inputs: +*@li init_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dc:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li i:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li j:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li f:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li o:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li mask:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li t_state:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ . \n + +*@par Attributes: +*@li forget_bias:An integer identifying the forget bias in the op. Default to 1. +*@li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported . \n +*@li direction:An string that marks the calculation sequence of the operator. Default to "Forward". +*@li gate_order:An string mark the order of output 4 gate. Default to "ijfo". + +*@par Outputs: +*two outputs: +*@li dgate:A 4D Tensor. Must be one of the following types: float16. +*@li dct_1:A 4D Tensor. Must be one of the following types: float16, float32. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(DynamicLSTMGradCell) + .INPUT(init_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(c, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(dy, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(dh, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(dc, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(i, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(j, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(f, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(o, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(tanhct, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(mask, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(t_state, TensorType({DT_INT32, DT_INT32})) + .OUTPUT(dgate, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dct_1, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(forget_bias, Float, 1) + .ATTR(activation, String, "") + .ATTR(direction, String, "Forward") + .ATTR(gate_order, String, "ijfo") + .OP_END_FACTORY_REG(DynamicLSTMGradCell) + + /** *@brief: Basic LSTM Cell backward calculation.Calculate the gradient of input and hidden state. *@par Inputs: diff --git a/third_party/fwkacllib/inc/ops/selection_ops.h b/third_party/fwkacllib/inc/ops/selection_ops.h index f99493b7..3e67a1ea 100644 --- a/third_party/fwkacllib/inc/ops/selection_ops.h +++ b/third_party/fwkacllib/inc/ops/selection_ops.h @@ -299,8 +299,6 @@ REG_OP(GatherElements) *@par Outputs: *y: A Tensor. Has the same type as "x" . \n -*@attention Constraints: - *@par Third-party framework compatibility * Compatible with the TensorFlow operator StridedSlice. */ @@ -351,8 +349,6 @@ REG_OP(StridedSlice) *@par Outputs: *y: A Tensor. Has the same type as "x" . \n -*@attention Constraints: - *@par Third-party framework compatibility * Compatible with the TensorFlow operator StridedSlice. @@ -409,8 +405,6 @@ REG_OP(StridedSliceD) *@par Outputs: *output: A Tensor. Has the same type as "dy" . \n -*@attention Constraints: - *@par Third-party framework compatibility * Compatible with the TensorFlow operator StridedSliceGradD. @@ -468,8 +462,6 @@ REG_OP(StridedSliceGradD) *@par Outputs: *output: A Tensor has the same type as "dy" . \n -*@attention Constraints: - *@par Third-party framework compatibility * Compatible with the TensorFlow operator StridedSliceGrad. */ @@ -2107,19 +2099,19 @@ REG_OP(InplaceIndexAdd) * @brief Replace the value of X with value according to mask. * @par Inputs: * three inputs, including: -* @li x: A Tensor of dtype is float16 or float32 or int32 or int8. -* @li mask: A Tensor of dtype float16 or float32 or int32 or int8. -* @li value: A Tensor or scalar of dtype float16 or float32 or int32 or int8. \n +* @li x: A Tensor of dtype is float16 or float32 or int64 or int32 or int8. +* @li mask: A Tensor of dtype bool. +* @li value: A Tensor of dtype float16 or float32 or int64 or int32 or int8. * @par Outputs: * @li y: A tensor. Must be one of the following dtypes: -* float16, float32, int32, int8. +* float16, float32, int64, int32, int8. */ REG_OP(MaskedFill) - .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32})) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32, DT_INT64})) .INPUT(mask, TensorType({DT_BOOL})) - .INPUT(value, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32})) + .INPUT(value, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32, DT_INT64})) .OP_END_FACTORY_REG(MaskedFill) /** diff --git a/third_party/fwkacllib/inc/runtime/rt.h b/third_party/fwkacllib/inc/runtime/rt.h index fb6e2e20..10f884f2 100644 --- a/third_party/fwkacllib/inc/runtime/rt.h +++ b/third_party/fwkacllib/inc/runtime/rt.h @@ -28,5 +28,6 @@ #include "rt_model.h" #include "stream.h" #include "rt_stars.h" +#include "rt_ffts.h" #endif // __CCE_RUNTIME_RT_H__ diff --git a/third_party/fwkacllib/inc/runtime/rt_model.h b/third_party/fwkacllib/inc/runtime/rt_model.h index 8c93fbd5..a7618b45 100644 --- a/third_party/fwkacllib/inc/runtime/rt_model.h +++ b/third_party/fwkacllib/inc/runtime/rt_model.h @@ -52,6 +52,7 @@ typedef enum tagModelTaskType { RT_MODEL_TASK_MODEL_EXIT, RT_MODEL_TASK_ALL_KERNEL, RT_MODEL_TASK_PROFILER_TRACE_EX, + RT_MODEL_TASK_FFTS_TASK, } rtModelTaskType_t; typedef enum tagModelStreamType { diff --git a/third_party/fwkacllib/inc/tdt/tsd_client.h b/third_party/fwkacllib/inc/tdt/tsd_client.h index 665c8b82..36fc500e 100644 --- a/third_party/fwkacllib/inc/tdt/tsd_client.h +++ b/third_party/fwkacllib/inc/tdt/tsd_client.h @@ -107,88 +107,6 @@ TDT_LIB_EXPORT TDT_StatusT UpdateProfilingMode(const uint32_t logicDeviceId, con */ TDT_LIB_EXPORT TDT_StatusT TsdSetMsprofReporterCallback(MsprofReporterCallback callback); -/** -* @ingroup CreateCmdParameterObj -* @brief creat tsdclient func parameter obj. -* -* @par Function -* creat tsdclient func parameter obj. -* -* @param type [IN] type tdt::TsdCmdType, tsd func type. -* @param cmdParameterObj [IN] type void *, func parameter obj. -* @retval TDT_OK Success -* @retval TDT_INTERFACE_NOT_SUPPORT -* -* @par Dependency -* @li libtsdclient.so: Library to which the interface belongs. -* @li data_common.h: Header file where tdt::TsdCmdType and tdt::InputItem defined. -* @li status.h: Header file where 'TDT_StatusT' defined -*/ -TDT_StatusT CreateCmdParameterObj(tdt::TsdCmdType type, void **cmdParameterObj); - -/** -* @ingroup SetCmdParameterObjAttribute -* @brief set cmdParameterObj input value. -* -* @par Function -* set cmdParameterObj input value. -* -* @param type [IN] type tdt::TsdCmdType, tsd func type. -* @param cmdParameterObj [IN] type void *, func parameter obj. -* @param itemType [IN] type tdt::InputItem, func input type. -* @param valuePtr [IN] type const void *, input value. -* @param valueLength [IN] type int, input value length. -* @retval TDT_OK Success -* @retval TDT_INTERFACE_NOT_SUPPORT -* -* @par Dependency -* @li libtsdclient.so: Library to which the interface belongs. -* @li data_common.h: Header file where tdt::TsdCmdType and tdt::InputItem defined. -* @li status.h: Header file where 'TDT_StatusT' defined -*/ -TDT_StatusT SetCmdParameterObjAttribute(tdt::TsdCmdType type, void *cmdParameterObj, tdt::InputItem itemType, const void *valuePtr, int valueLength); - -/** -* @ingroup GetCmdParameterObjAttribute -* @brief set cmdParameterObj input value. -* -* @par Function -* set cmdParameterObj input value. -* -* @param type [IN] type tdt::TsdCmdType, tsd func type. -* @param cmdParameterObj [IN] type void *, func parameter obj. -* @param itemType [IN] type tdt::InputItem, func input type. -* @param valuePtr [IN] type const void *, input value. -* @param valueLength [IN] type int, input value length. -* @retval TDT_OK Success -* @retval TDT_INTERFACE_NOT_SUPPORT -* -* @par Dependency -* @li libtsdclient.so: Library to which the interface belongs. -* @li data_common.h: Header file where tdt::TsdCmdType and tdt::InputItem defined. -* @li status.h: Header file where 'TDT_StatusT' defined -*/ -TDT_StatusT GetCmdParameterObjAttribute(tdt::TsdCmdType type, void *cmdParameterObj, tdt::InputItem itemType, void *valuePtr, int &valueLength); - -/** -* @ingroup TsdClientCmd -* @brief creat tsdclient func parameter obj. -* -* @par Function -* creat tsdclient func parameter obj. -* -* @param type [IN] type tdt::TsdCmdType, tsd func type. -* @param cmdParameterObj [IN] type void *, func parameter obj. -* @retval TDT_OK Success -* @retval TDT_INTERFACE_NOT_SUPPORT -* -* @par Dependency -* @li libtsdclient.so: Library to which the interface belongs. -* @li data_common.h: Header file where tdt::TsdCmdType and tdt::InputItem defined. -* @li status.h: Header file where 'TDT_StatusT' defined -*/ -TDT_StatusT TsdClientCmd(tdt::TsdCmdType cmd, void *cmdParameterObj); - #ifdef __cplusplus } #endif // __cplusplus From bc93b5b7421d0b4b9947c3686cc200f9c342a1bc Mon Sep 17 00:00:00 2001 From: dingpeifei Date: Mon, 7 Jun 2021 10:06:00 +0800 Subject: [PATCH 29/59] code_sync_0604 --- third_party/fwkacllib/inc/runtime/rt_ffts.h | 184 ++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 third_party/fwkacllib/inc/runtime/rt_ffts.h diff --git a/third_party/fwkacllib/inc/runtime/rt_ffts.h b/third_party/fwkacllib/inc/runtime/rt_ffts.h new file mode 100644 index 00000000..bae5a54d --- /dev/null +++ b/third_party/fwkacllib/inc/runtime/rt_ffts.h @@ -0,0 +1,184 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + * Description: ffts interface + */ + +#ifndef __CCE_RUNTIME_FFTS_H +#define __CCE_RUNTIME_FFTS_H + +#include "base.h" + +#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +extern "C" { +#endif + +#define RT_FFTS_MAX_SUB_TASK_NUM 32U +#define RT_FFTS_MAX_TICKET_CACHE_NUM 64U +#define RT_FFTS_MAX_MANUAL_THREAD_NUM 16U +#define RT_FFTS_MAX_TICKET_CACHE_PER_SUBTASK 8U +#define RT_FFTS_MANUAL_SRC_DEPEND_TBL_LEN 32U + +typedef enum tagFftsType { + RT_FFTS_TYPE_AUTO_THREAD = 2, // ffts auto thread mode, same as ffts define + RT_FFTS_TYPE_MANUAL_THREAD = 3, // ffts manual thread mode, same as ffts define +} rtFftsType_t; + +typedef enum tagFftsSubTaskType { + RT_FFTS_SUB_TASK_TYPE_AIC = 0, + RT_FFTS_SUB_TASK_TYPE_AIV = 1, + RT_FFTS_SUB_TASK_TYPE_NOP = 2, + RT_FFTS_SUB_TASK_TYPE_NOTIFY_WAIT = 3, + RT_FFTS_SUB_TASK_TYPE_NOTIFY_RECORD = 4, + RT_FFTS_SUB_TASK_TYPE_WRITE_VALUE = 5, + RT_FFTS_SUB_TASK_TYPE_MIX_AIC = 6, + RT_FFTS_SUB_TASK_TYPE_MIX_AIV = 7, + RT_FFTS_SUB_TASK_TYPE_SDMA = 8, + RT_FFTS_SUB_TASK_TYPE_RESERVED, +} rtFftsSubTaskType_t; + +typedef struct tagManualThreadDmuInfo { + uint64_t dataAddr; // device mem + uint16_t numOuter; + uint16_t numInner; + uint32_t strideOuter; + uint32_t lenInner; + uint32_t strideInner; +} rtManualThreadDmuInfo_t; + +typedef struct tagManualThreadDependency { + uint8_t dependency[RT_FFTS_MANUAL_SRC_DEPEND_TBL_LEN]; +} rtManualThreadDependency_t; + +typedef struct tagManualThreadAicAivInfo { + uint64_t taskParamAddr; // device mem + uint16_t taskParamOffset; + // when satMode=1 and FP16 computation with none INF inputs overflows/underflows, results will be +/-INF of FP16 + // when satMode=0 and FP16 computation with none INF inputs overflows/underflows, + // results will be saturated to +/-MAX of FP16 + uint8_t satMode; + uint8_t scheduleMode; // 0:normal mode, 1:batch mode, 2:sync mode 3:reserved + uint8_t iCachePrefetchCnt; // units is 2K + uint8_t prefetchEnableBitmap; // 8 bit bitmap 1 0 1 0 + uint8_t prefetchOnceBitmap; // 8 bit bitmap 1 0 1 0 + uint16_t prefetchOnceDmuNum; // prefetch_once_dmu_descriptor_index in ffts + // num: thread0_prefetch_dmu_descriptor_index – prefetch_once_dmu_descriptor_index + uint16_t threadPrefetchDmuIdx[RT_FFTS_MAX_MANUAL_THREAD_NUM]; // max valid is threadDim + uint16_t threadBlkDim[RT_FFTS_MAX_MANUAL_THREAD_NUM]; + const char *threadTaskFuncStub[RT_FFTS_MAX_MANUAL_THREAD_NUM]; + + rtManualThreadDmuInfo_t *prefetchList; // dmu desc 0-64k, length is the last threadPrefetchDmuIdx[threadDim-1] + rtManualThreadDependency_t srcDepTbl[RT_FFTS_MAX_TICKET_CACHE_PER_SUBTASK]; +} rtManualThreadAicAivInfo_t; + +typedef struct tagAutoThreadPrefetch { + uint64_t dataAddr; // device mem + uint32_t dataAddrOffset; + uint32_t nonTailDataLen; + uint32_t tailDataLen; +} rtAutoThreadPrefetch_t; + +typedef struct tagAutoThreadAicAivInfo { + uint64_t taskParamAddr; // device mem + uint16_t taskParamOffset; + // when satMode=1 and FP16 computation with none INF inputs overflows/underflows, results will be +/-INF of FP16 + // when satMode=0 and FP16 computation with none INF inputs overflows/underflows, results will be saturated to +/-MAX of FP16 + uint8_t satMode; + uint8_t scheduleMode; // 0:normal mode, 1:batch mode, 2:sync mode 3:reserved + uint8_t iCachePrefetchCnt; // units is 2K + uint8_t prefetchEnableBitmap; // 8 bit bitmap + uint8_t prefetchOnceBitmap; // 8 bit bitmap + + uint16_t tailBlkDim; + uint16_t nonTailBlkDim; + + const char *nonTailTaskFuncStub; + const char *tailTaskFuncStub; + + // for prefetch, valid num is prefetchEnableBitmap bit count. + // if prefetchEnableBitmap='00010011', need prefetch number is 3, srcPrefetch is only 0, 1, 2 is valid + rtAutoThreadPrefetch_t srcPrefetch[RT_FFTS_MAX_TICKET_CACHE_PER_SUBTASK]; +} rtAutoThreadAicAivInfo_t; + +typedef struct tagAutoThreadCacheInfo { + uint64_t dataAddr; // device mem + uint32_t dataAddrOffset; + uint32_t nonTailDataLen; + uint32_t tailDataLen; + uint16_t ticketCacheRefCnt; +} rtAutoThreadCacheInfo_t; + +typedef struct tagManualThreadCacheInfo { + rtManualThreadDmuInfo_t *dmuList; // 0-64k + uint16_t dmuNum; + uint16_t sliceDmuIdx[RT_FFTS_MAX_MANUAL_THREAD_NUM]; + uint16_t ticketCacheRefCntTbl[RT_FFTS_MAX_MANUAL_THREAD_NUM]; +} rtManualThreadCacheInfo_t; + +typedef enum tagCacheOp { + RT_CACHE_OP_NONE = 0, + RT_CACHE_OP_FLUSH = 1, + RT_CACHE_OP_INVALIDATE = 2, + RT_CACHE_OP_WRITE_BACK = 3, +} rtCacheOp_t; + +typedef struct tagTicketCache { + rtCacheOp_t cacheOption; + uint8_t ticketCacheWindow; + union { + rtAutoThreadCacheInfo_t autoThreadCache; + rtManualThreadCacheInfo_t manualThreadCache; + } custom; +} rtTicketCache_t; + +typedef struct tagManualThreadNopInfo { + // depend srcTickCacheVldBitmap in rtFftsSubTaskInfo_t + rtManualThreadDependency_t srcDepTbl[RT_FFTS_MAX_TICKET_CACHE_PER_SUBTASK]; +} rtManualThreadNopInfo_t; + +typedef struct tagFftsSubTaskInfo { + rtFftsSubTaskType_t subTaskType; + uint16_t threadDim; + uint8_t dstTickCacheVldBitmap; + uint8_t srcTickCacheVldBitmap; + uint8_t srcDataOutOfSubGraphBitmap; + uint8_t dstTickCacheID[RT_FFTS_MAX_TICKET_CACHE_PER_SUBTASK]; + uint8_t srcTickCacheID[RT_FFTS_MAX_TICKET_CACHE_PER_SUBTASK]; + union { + rtAutoThreadAicAivInfo_t autoThreadAicAiv; + rtManualThreadAicAivInfo_t manualThreadAicAiv; + rtManualThreadNopInfo_t manualThreadNop; + } custom; +} rtFftsSubTaskInfo_t; + +typedef struct tagFftsDescInfo { + uint8_t tm; // thread subtask kickstart mode, 0:order, 1:disorder + uint8_t di; // discard invalidate + uint8_t dw; // discard write back + uint8_t df; // discard flush + uint8_t dataSplitUnit; // split source or ticket cache by 2^dataSplitUnit MB + uint8_t prefetchOstNum; + uint8_t cacheMaintainOstNum; + uint8_t aicPrefetchUpper; + uint8_t aicPrefetchLower; + uint8_t aivPrefetchUpper; + uint8_t aivPrefetchLower; +} rtFftsDescInfo_t; + +typedef struct tagFftsTaskInfo { + rtFftsType_t fftsType; + uint16_t subTaskNum; + uint16_t tickCacheNum; + rtFftsDescInfo_t fftsDesc; + // sub task desc, real num is subTaskNum + rtFftsSubTaskInfo_t subTask[RT_FFTS_MAX_SUB_TASK_NUM]; + + // ticket cache, real number is tickCacheNum. + rtTicketCache_t ticketCache[RT_FFTS_MAX_TICKET_CACHE_NUM]; +} rtFftsTaskInfo_t; + +RTS_API rtError_t rtFftsTaskLaunch(rtFftsTaskInfo_t *fftsTaskInfo, rtStream_t stream); + +#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +} +#endif +#endif // __CCE_RUNTIME_FFTS_H From ac2ce17a9af7237d947d3ff9371a8247273d0fb4 Mon Sep 17 00:00:00 2001 From: dingpeifei Date: Thu, 17 Jun 2021 19:19:58 +0800 Subject: [PATCH 30/59] code_sync_0617_inc --- inc/external/acl/acl.h | 8 +- inc/external/acl/acl_base.h | 91 ++-- inc/external/acl/acl_mdl.h | 361 +++++++-------- inc/external/acl/acl_op.h | 119 ++--- inc/external/acl/acl_op_compiler.h | 54 +-- inc/external/acl/acl_prof.h | 46 +- inc/external/acl/acl_rt.h | 142 +++--- inc/external/acl/acl_tdt.h | 31 +- inc/external/acl/error_codes/rt_error_codes.h | 147 +++--- inc/external/acl/ops/acl_cblas.h | 179 ++------ inc/external/acl/ops/acl_dvpp.h | 425 +++++++----------- inc/external/acl/ops/acl_fv.h | 29 +- inc/external/hccl/hccl.h | 39 +- inc/external/hccl/hccl_types.h | 84 ++-- inc/external/runtime/rt_error_codes.h | 147 +++--- scripts/format_source_code.sh | 107 +++++ .../fwkacllib/inc/cce/taskdown_common.hpp | 19 +- third_party/fwkacllib/inc/hccl/base.h | 36 +- third_party/fwkacllib/inc/hccl/hcom.h | 14 + third_party/fwkacllib/inc/ops/array_ops.h | 6 +- third_party/fwkacllib/inc/ops/bitwise_ops.h | 29 ++ .../fwkacllib/inc/ops/control_flow_ops.h | 2 +- third_party/fwkacllib/inc/ops/data_flow_ops.h | 22 +- .../inc/ops/elewise_calculation_ops.h | 2 +- third_party/fwkacllib/inc/ops/hcom_ops.h | 72 +++ third_party/fwkacllib/inc/ops/math_ops.h | 26 ++ third_party/fwkacllib/inc/ops/nn_norm_ops.h | 160 ++++++- third_party/fwkacllib/inc/ops/reduce_ops.h | 50 ++- third_party/fwkacllib/inc/ops/selection_ops.h | 34 ++ .../fwkacllib/inc/ops/split_combination_ops.h | 6 +- third_party/fwkacllib/inc/ops/string_ops.h | 39 ++ .../fwkacllib/inc/ops/transformation_ops.h | 132 +++++- third_party/fwkacllib/inc/runtime/rt_stars.h | 56 +++ .../fwkacllib/inc/toolchain/prof_callback.h | 30 +- 34 files changed, 1568 insertions(+), 1176 deletions(-) create mode 100755 scripts/format_source_code.sh diff --git a/inc/external/acl/acl.h b/inc/external/acl/acl.h index 8b1fb78f..8d261201 100644 --- a/inc/external/acl/acl.h +++ b/inc/external/acl/acl.h @@ -26,9 +26,9 @@ extern "C" { #endif // Current version is 1.0.0 -#define ACL_MAJOR_VERSION 1 -#define ACL_MINOR_VERSION 0 -#define ACL_PATCH_VERSION 0 +#define ACL_MAJOR_VERSION 1 +#define ACL_MINOR_VERSION 0 +#define ACL_PATCH_VERSION 0 /** * @ingroup AscendCL @@ -79,4 +79,4 @@ ACL_FUNC_VISIBILITY const char *aclGetRecentErrMsg(); } #endif -#endif // INC_EXTERNAL_ACL_ACL_H_ +#endif // INC_EXTERNAL_ACL_ACL_H_ diff --git a/inc/external/acl/acl_base.h b/inc/external/acl/acl_base.h index 417a80c8..64d4bd81 100644 --- a/inc/external/acl/acl_base.h +++ b/inc/external/acl/acl_base.h @@ -136,50 +136,49 @@ static const int ACL_ERROR_PROFILING_FAILURE = 500005; #define ACL_UNKNOWN_RANK 0xFFFFFFFFFFFFFFFE typedef enum { - ACL_DT_UNDEFINED = -1, - ACL_FLOAT = 0, - ACL_FLOAT16 = 1, - ACL_INT8 = 2, - ACL_INT32 = 3, - ACL_UINT8 = 4, - ACL_INT16 = 6, - ACL_UINT16 = 7, - ACL_UINT32 = 8, - ACL_INT64 = 9, - ACL_UINT64 = 10, - ACL_DOUBLE = 11, - ACL_BOOL = 12, - ACL_STRING = 13, + ACL_DT_UNDEFINED = -1, + ACL_FLOAT = 0, + ACL_FLOAT16 = 1, + ACL_INT8 = 2, + ACL_INT32 = 3, + ACL_UINT8 = 4, + ACL_INT16 = 6, + ACL_UINT16 = 7, + ACL_UINT32 = 8, + ACL_INT64 = 9, + ACL_UINT64 = 10, + ACL_DOUBLE = 11, + ACL_BOOL = 12, + ACL_STRING = 13, } aclDataType; typedef enum { - ACL_FORMAT_UNDEFINED = -1, - ACL_FORMAT_NCHW = 0, - ACL_FORMAT_NHWC = 1, - ACL_FORMAT_ND = 2, - ACL_FORMAT_NC1HWC0 = 3, - ACL_FORMAT_FRACTAL_Z = 4, - ACL_FORMAT_NC1HWC0_C04 = 12, - ACL_FORMAT_NDHWC = 27, - ACL_FORMAT_FRACTAL_NZ = 29, - ACL_FORMAT_NCDHW = 30, - ACL_FORMAT_NDC1HWC0 = 32, - ACL_FRACTAL_Z_3D = 33 + ACL_FORMAT_UNDEFINED = -1, + ACL_FORMAT_NCHW = 0, + ACL_FORMAT_NHWC = 1, + ACL_FORMAT_ND = 2, + ACL_FORMAT_NC1HWC0 = 3, + ACL_FORMAT_FRACTAL_Z = 4, + ACL_FORMAT_NC1HWC0_C04 = 12, + ACL_FORMAT_NDHWC = 27, + ACL_FORMAT_FRACTAL_NZ = 29, + ACL_FORMAT_NCDHW = 30, + ACL_FORMAT_NDC1HWC0 = 32, + ACL_FRACTAL_Z_3D = 33 } aclFormat; typedef enum { - ACL_DEBUG = 0, - ACL_INFO = 1, - ACL_WARNING = 2, - ACL_ERROR = 3, + ACL_DEBUG = 0, + ACL_INFO = 1, + ACL_WARNING = 2, + ACL_ERROR = 3, } aclLogLevel; typedef enum { - ACL_MEMTYPE_DEVICE = 0, - ACL_MEMTYPE_HOST = 1, + ACL_MEMTYPE_DEVICE = 0, + ACL_MEMTYPE_HOST = 1, } aclMemType; - /** * @ingroup AscendCL * @brief Converts data of type aclFloat16 to data of type float @@ -312,9 +311,7 @@ ACL_FUNC_VISIBILITY size_t aclDataTypeSize(aclDataType dataType); * @retval aclTensorDesc pointer. * @retval nullptr if param is invalid or run out of memory */ -ACL_FUNC_VISIBILITY aclTensorDesc *aclCreateTensorDesc(aclDataType dataType, - int numDims, - const int64_t *dims, +ACL_FUNC_VISIBILITY aclTensorDesc *aclCreateTensorDesc(aclDataType dataType, int numDims, const int64_t *dims, aclFormat format); /** @@ -336,8 +333,7 @@ ACL_FUNC_VISIBILITY void aclDestroyTensorDesc(const aclTensorDesc *desc); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclSetTensorShapeRange(aclTensorDesc* desc, - size_t dimsCount, +ACL_FUNC_VISIBILITY aclError aclSetTensorShapeRange(aclTensorDesc *desc, size_t dimsCount, int64_t dimsRange[][ACL_TENSOR_SHAPE_RANGE_NUM]); /** @@ -434,9 +430,7 @@ ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimV2(const aclTensorDesc *desc, si * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimRange(const aclTensorDesc *desc, - size_t index, - size_t dimRangeNum, +ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimRange(const aclTensorDesc *desc, size_t index, size_t dimRangeNum, int64_t *dimRange); /** @@ -473,7 +467,7 @@ ACL_FUNC_VISIBILITY const char *aclGetTensorDescName(aclTensorDesc *desc); * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclTransTensorDescFormat(const aclTensorDesc *srcDesc, aclFormat dstFormat, - aclTensorDesc **dstDesc); + aclTensorDesc **dstDesc); /** * @ingroup AscendCL @@ -561,7 +555,7 @@ ACL_FUNC_VISIBILITY aclError aclSetTensorOriginShape(aclTensorDesc *desc, int nu * * @retval null for failed. * @retval OtherValues success. -*/ + */ ACL_FUNC_VISIBILITY aclTensorDesc *aclGetTensorDescByIndex(aclTensorDesc *desc, size_t index); /** @@ -572,7 +566,7 @@ ACL_FUNC_VISIBILITY aclTensorDesc *aclGetTensorDescByIndex(aclTensorDesc *desc, * * @retval null for failed * @retval OtherValues success -*/ + */ ACL_FUNC_VISIBILITY void *aclGetTensorDescAddress(const aclTensorDesc *desc); /** @@ -624,7 +618,7 @@ ACL_FUNC_VISIBILITY aclError aclSetTensorPlaceMent(aclTensorDesc *desc, aclMemTy * @param ... [IN] the value of current log */ ACL_FUNC_VISIBILITY void aclAppLog(aclLogLevel logLevel, const char *func, const char *file, uint32_t line, - const char *fmt, ...); + const char *fmt, ...); /** * @ingroup AscendCL @@ -632,14 +626,13 @@ ACL_FUNC_VISIBILITY void aclAppLog(aclLogLevel logLevel, const char *func, const * * @retval null for failed * @retval OtherValues success -*/ + */ ACL_FUNC_VISIBILITY const char *aclrtGetSocName(); -#define ACL_APP_LOG(level, fmt, ...) \ - aclAppLog(level, __FUNCTION__, __FILE__, __LINE__, fmt, ##__VA_ARGS__) +#define ACL_APP_LOG(level, fmt, ...) aclAppLog(level, __FUNCTION__, __FILE__, __LINE__, fmt, ##__VA_ARGS__) #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_BASE_H_ +#endif // INC_EXTERNAL_ACL_ACL_BASE_H_ diff --git a/inc/external/acl/acl_mdl.h b/inc/external/acl/acl_mdl.h index 1721929e..2bf85e29 100644 --- a/inc/external/acl/acl_mdl.h +++ b/inc/external/acl/acl_mdl.h @@ -27,19 +27,19 @@ extern "C" { #endif -#define ACL_MAX_DIM_CNT 128 -#define ACL_MAX_TENSOR_NAME_LEN 128 -#define ACL_MAX_BATCH_NUM 128 -#define ACL_MAX_HW_NUM 128 -#define ACL_MAX_SHAPE_COUNT 128 -#define ACL_INVALID_NODE_INDEX 0xFFFFFFFF - -#define ACL_MDL_LOAD_FROM_FILE 1 -#define ACL_MDL_LOAD_FROM_FILE_WITH_MEM 2 -#define ACL_MDL_LOAD_FROM_MEM 3 -#define ACL_MDL_LOAD_FROM_MEM_WITH_MEM 4 -#define ACL_MDL_LOAD_FROM_FILE_WITH_Q 5 -#define ACL_MDL_LOAD_FROM_MEM_WITH_Q 6 +#define ACL_MAX_DIM_CNT 128 +#define ACL_MAX_TENSOR_NAME_LEN 128 +#define ACL_MAX_BATCH_NUM 128 +#define ACL_MAX_HW_NUM 128 +#define ACL_MAX_SHAPE_COUNT 128 +#define ACL_INVALID_NODE_INDEX 0xFFFFFFFF + +#define ACL_MDL_LOAD_FROM_FILE 1 +#define ACL_MDL_LOAD_FROM_FILE_WITH_MEM 2 +#define ACL_MDL_LOAD_FROM_MEM 3 +#define ACL_MDL_LOAD_FROM_MEM_WITH_MEM 4 +#define ACL_MDL_LOAD_FROM_FILE_WITH_Q 5 +#define ACL_MDL_LOAD_FROM_MEM_WITH_Q 6 #define ACL_DYNAMIC_TENSOR_NAME "ascend_mbatch_shape_data" #define ACL_DYNAMIC_AIPP_NAME "ascend_dynamic_aipp_data" @@ -52,123 +52,123 @@ typedef struct aclAippExtendInfo aclAippExtendInfo; typedef struct aclmdlConfigHandle aclmdlConfigHandle; typedef enum { - ACL_YUV420SP_U8 = 1, - ACL_XRGB8888_U8, - ACL_RGB888_U8, - ACL_YUV400_U8, - ACL_NC1HWC0DI_FP16, - ACL_NC1HWC0DI_S8, - ACL_ARGB8888_U8, - ACL_YUYV_U8, - ACL_YUV422SP_U8, - ACL_AYUV444_U8, - ACL_RAW10, - ACL_RAW12, - ACL_RAW16, - ACL_RAW24, - ACL_AIPP_RESERVED = 0xffff, + ACL_YUV420SP_U8 = 1, + ACL_XRGB8888_U8, + ACL_RGB888_U8, + ACL_YUV400_U8, + ACL_NC1HWC0DI_FP16, + ACL_NC1HWC0DI_S8, + ACL_ARGB8888_U8, + ACL_YUYV_U8, + ACL_YUV422SP_U8, + ACL_AYUV444_U8, + ACL_RAW10, + ACL_RAW12, + ACL_RAW16, + ACL_RAW24, + ACL_AIPP_RESERVED = 0xffff, } aclAippInputFormat; typedef enum { - ACL_MDL_PRIORITY_INT32 = 0, - ACL_MDL_LOAD_TYPE_SIZET, - ACL_MDL_PATH_PTR, /**< pointer to model load path with deep copy */ - ACL_MDL_MEM_ADDR_PTR, /**< pointer to model memory with shallow copy */ - ACL_MDL_MEM_SIZET, - ACL_MDL_WEIGHT_ADDR_PTR, /**< pointer to weight memory of model with shallow copy */ - ACL_MDL_WEIGHT_SIZET, - ACL_MDL_WORKSPACE_ADDR_PTR, /**< pointer to worksapce memory of model with shallow copy */ - ACL_MDL_WORKSPACE_SIZET, - ACL_MDL_INPUTQ_NUM_SIZET, - ACL_MDL_INPUTQ_ADDR_PTR, /**< pointer to inputQ with shallow copy */ - ACL_MDL_OUTPUTQ_NUM_SIZET, - ACL_MDL_OUTPUTQ_ADDR_PTR /**< pointer to outputQ with shallow copy */ + ACL_MDL_PRIORITY_INT32 = 0, + ACL_MDL_LOAD_TYPE_SIZET, + ACL_MDL_PATH_PTR, /**< pointer to model load path with deep copy */ + ACL_MDL_MEM_ADDR_PTR, /**< pointer to model memory with shallow copy */ + ACL_MDL_MEM_SIZET, + ACL_MDL_WEIGHT_ADDR_PTR, /**< pointer to weight memory of model with shallow copy */ + ACL_MDL_WEIGHT_SIZET, + ACL_MDL_WORKSPACE_ADDR_PTR, /**< pointer to worksapce memory of model with shallow copy */ + ACL_MDL_WORKSPACE_SIZET, + ACL_MDL_INPUTQ_NUM_SIZET, + ACL_MDL_INPUTQ_ADDR_PTR, /**< pointer to inputQ with shallow copy */ + ACL_MDL_OUTPUTQ_NUM_SIZET, + ACL_MDL_OUTPUTQ_ADDR_PTR /**< pointer to outputQ with shallow copy */ } aclmdlConfigAttr; typedef enum { - ACL_DATA_WITHOUT_AIPP = 0, - ACL_DATA_WITH_STATIC_AIPP, - ACL_DATA_WITH_DYNAMIC_AIPP, - ACL_DYNAMIC_AIPP_NODE + ACL_DATA_WITHOUT_AIPP = 0, + ACL_DATA_WITH_STATIC_AIPP, + ACL_DATA_WITH_DYNAMIC_AIPP, + ACL_DYNAMIC_AIPP_NODE } aclmdlInputAippType; typedef struct aclmdlIODims { - char name[ACL_MAX_TENSOR_NAME_LEN]; /**< tensor name */ - size_t dimCount; /**< dim array count */ - int64_t dims[ACL_MAX_DIM_CNT]; /**< dim data array */ + char name[ACL_MAX_TENSOR_NAME_LEN]; /**< tensor name */ + size_t dimCount; /**< dim array count */ + int64_t dims[ACL_MAX_DIM_CNT]; /**< dim data array */ } aclmdlIODims; typedef struct aclAippDims { - aclmdlIODims srcDims; /**< input dims before model transform */ - size_t srcSize; /**< input size before model transform */ - aclmdlIODims aippOutdims; /**< aipp output dims */ - size_t aippOutSize; /**< aipp output size */ + aclmdlIODims srcDims; /**< input dims before model transform */ + size_t srcSize; /**< input size before model transform */ + aclmdlIODims aippOutdims; /**< aipp output dims */ + size_t aippOutSize; /**< aipp output size */ } aclAippDims; typedef struct aclmdlBatch { - size_t batchCount; /**< batch array count */ - uint64_t batch[ACL_MAX_BATCH_NUM]; /**< batch data array */ + size_t batchCount; /**< batch array count */ + uint64_t batch[ACL_MAX_BATCH_NUM]; /**< batch data array */ } aclmdlBatch; typedef struct aclmdlHW { - size_t hwCount; /**< height&width array count */ - uint64_t hw[ACL_MAX_HW_NUM][2]; /**< height&width data array */ + size_t hwCount; /**< height&width array count */ + uint64_t hw[ACL_MAX_HW_NUM][2]; /**< height&width data array */ } aclmdlHW; typedef struct aclAippInfo { - aclAippInputFormat inputFormat; - int32_t srcImageSizeW; - int32_t srcImageSizeH; - int8_t cropSwitch; - int32_t loadStartPosW; - int32_t loadStartPosH; - int32_t cropSizeW; - int32_t cropSizeH; - int8_t resizeSwitch; - int32_t resizeOutputW; - int32_t resizeOutputH; - int8_t paddingSwitch; - int32_t leftPaddingSize; - int32_t rightPaddingSize; - int32_t topPaddingSize; - int32_t bottomPaddingSize; - int8_t cscSwitch; - int8_t rbuvSwapSwitch; - int8_t axSwapSwitch; - int8_t singleLineMode; - int32_t matrixR0C0; - int32_t matrixR0C1; - int32_t matrixR0C2; - int32_t matrixR1C0; - int32_t matrixR1C1; - int32_t matrixR1C2; - int32_t matrixR2C0; - int32_t matrixR2C1; - int32_t matrixR2C2; - int32_t outputBias0; - int32_t outputBias1; - int32_t outputBias2; - int32_t inputBias0; - int32_t inputBias1; - int32_t inputBias2; - int32_t meanChn0; - int32_t meanChn1; - int32_t meanChn2; - int32_t meanChn3; - float minChn0; - float minChn1; - float minChn2; - float minChn3; - float varReciChn0; - float varReciChn1; - float varReciChn2; - float varReciChn3; - aclFormat srcFormat; - aclDataType srcDatatype; - size_t srcDimNum; - size_t shapeCount; - aclAippDims outDims[ACL_MAX_SHAPE_COUNT]; - aclAippExtendInfo *aippExtend; /**< reserved parameters, current version needs to be null */ + aclAippInputFormat inputFormat; + int32_t srcImageSizeW; + int32_t srcImageSizeH; + int8_t cropSwitch; + int32_t loadStartPosW; + int32_t loadStartPosH; + int32_t cropSizeW; + int32_t cropSizeH; + int8_t resizeSwitch; + int32_t resizeOutputW; + int32_t resizeOutputH; + int8_t paddingSwitch; + int32_t leftPaddingSize; + int32_t rightPaddingSize; + int32_t topPaddingSize; + int32_t bottomPaddingSize; + int8_t cscSwitch; + int8_t rbuvSwapSwitch; + int8_t axSwapSwitch; + int8_t singleLineMode; + int32_t matrixR0C0; + int32_t matrixR0C1; + int32_t matrixR0C2; + int32_t matrixR1C0; + int32_t matrixR1C1; + int32_t matrixR1C2; + int32_t matrixR2C0; + int32_t matrixR2C1; + int32_t matrixR2C2; + int32_t outputBias0; + int32_t outputBias1; + int32_t outputBias2; + int32_t inputBias0; + int32_t inputBias1; + int32_t inputBias2; + int32_t meanChn0; + int32_t meanChn1; + int32_t meanChn2; + int32_t meanChn3; + float minChn0; + float minChn1; + float minChn2; + float minChn3; + float varReciChn0; + float varReciChn1; + float varReciChn2; + float varReciChn3; + aclFormat srcFormat; + aclDataType srcDatatype; + size_t srcDimNum; + size_t shapeCount; + aclAippDims outDims[ACL_MAX_SHAPE_COUNT]; + aclAippExtendInfo *aippExtend; /**< reserved parameters, current version needs to be null */ } aclAippInfo; /** @@ -292,8 +292,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlAddDatasetBuffer(aclmdlDataset *dataset, aclD * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclmdlSetDatasetTensorDesc(aclmdlDataset *dataset, - aclTensorDesc *tensorDesc, +ACL_FUNC_VISIBILITY aclError aclmdlSetDatasetTensorDesc(aclmdlDataset *dataset, aclTensorDesc *tensorDesc, size_t index); /** @@ -355,8 +354,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFile(const char *modelPath, uint32_t * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMem(const void *model, size_t modelSize, - uint32_t *modelId); +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMem(const void *model, size_t modelSize, uint32_t *modelId); /** * @ingroup AscendCL @@ -378,9 +376,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMem(const void *model, size_t modelS * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithMem(const char *modelPath, - uint32_t *modelId, void *workPtr, size_t workSize, - void *weightPtr, size_t weightSize); +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithMem(const char *modelPath, uint32_t *modelId, void *workPtr, + size_t workSize, void *weightPtr, size_t weightSize); /** * @ingroup AscendCL @@ -403,9 +400,9 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithMem(const char *modelPath, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithMem(const void *model, size_t modelSize, - uint32_t *modelId, void *workPtr, size_t workSize, - void *weightPtr, size_t weightSize); +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithMem(const void *model, size_t modelSize, uint32_t *modelId, + void *workPtr, size_t workSize, void *weightPtr, + size_t weightSize); /** * @ingroup AscendCL @@ -440,8 +437,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithQ(const char *modelPath, uint * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithQ(const void *model, size_t modelSize, uint32_t *modelId, - const uint32_t *inputQ, size_t inputQNum, - const uint32_t *outputQ, size_t outputQNum); + const uint32_t *inputQ, size_t inputQNum, const uint32_t *outputQ, + size_t outputQNum); /** * @ingroup AscendCL @@ -471,8 +468,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlExecute(uint32_t modelId, const aclmdlDataset * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem */ -ACL_FUNC_VISIBILITY aclError aclmdlExecuteAsync(uint32_t modelId, const aclmdlDataset *input, - aclmdlDataset *output, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclmdlExecuteAsync(uint32_t modelId, const aclmdlDataset *input, aclmdlDataset *output, + aclrtStream stream); /** * @ingroup AscendCL @@ -647,7 +644,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlGetCurOutputDims(const aclmdlDesc *modelDesc, * @param modelDesc [IN] model description * @param opName [IN] op name * @param attr [IN] attr name - * + * * @retval the attr value */ ACL_FUNC_VISIBILITY const char *aclmdlGetOpAttr(aclmdlDesc *modelDesc, const char *opName, const char *attr); @@ -859,11 +856,11 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPInputFormat(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, int8_t csc_switch, - int16_t cscMatrixR0C0, int16_t cscMatrixR0C1, int16_t cscMatrixR0C2, - int16_t cscMatrixR1C0, int16_t cscMatrixR1C1, int16_t cscMatrixR1C2, - int16_t cscMatrixR2C0, int16_t cscMatrixR2C1, int16_t cscMatrixR2C2, + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, int8_t csc_switch, int16_t cscMatrixR0C0, + int16_t cscMatrixR0C1, int16_t cscMatrixR0C2, int16_t cscMatrixR1C0, + int16_t cscMatrixR1C1, int16_t cscMatrixR1C2, int16_t cscMatrixR2C0, + int16_t cscMatrixR2C1, int16_t cscMatrixR2C2, uint8_t cscOutputBiasR0, uint8_t cscOutputBiasR1, uint8_t cscOutputBiasR2, uint8_t cscInputBiasR0, uint8_t cscInputBiasR1, uint8_t cscInputBiasR2); @@ -879,7 +876,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, in * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPRbuvSwapSwitch(aclmdlAIPP *aippParmsSet, int8_t rbuvSwapSwitch); /** @@ -893,7 +890,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPRbuvSwapSwitch(aclmdlAIPP *aippParmsSe * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPAxSwapSwitch(aclmdlAIPP *aippParmsSet, int8_t axSwapSwitch); /** @@ -908,7 +905,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPAxSwapSwitch(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPSrcImageSize(aclmdlAIPP *aippParmsSet, int32_t srcImageSizeW, int32_t srcImageSizeH); @@ -928,14 +925,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPSrcImageSize(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPScfParams(aclmdlAIPP *aippParmsSet, - int8_t scfSwitch, - int32_t scfInputSizeW, - int32_t scfInputSizeH, - int32_t scfOutputSizeW, - int32_t scfOutputSizeH, - uint64_t batchIndex); + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPScfParams(aclmdlAIPP *aippParmsSet, int8_t scfSwitch, int32_t scfInputSizeW, + int32_t scfInputSizeH, int32_t scfOutputSizeW, + int32_t scfOutputSizeH, uint64_t batchIndex); /** * @ingroup AscendCL @@ -953,13 +946,9 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPScfParams(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCropParams(aclmdlAIPP *aippParmsSet, - int8_t cropSwitch, - int32_t cropStartPosW, - int32_t cropStartPosH, - int32_t cropSizeW, - int32_t cropSizeH, + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCropParams(aclmdlAIPP *aippParmsSet, int8_t cropSwitch, int32_t cropStartPosW, + int32_t cropStartPosH, int32_t cropSizeW, int32_t cropSizeH, uint64_t batchIndex); /** @@ -978,7 +967,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCropParams(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPaddingParams(aclmdlAIPP *aippParmsSet, int8_t paddingSwitch, int32_t paddingSizeTop, int32_t paddingSizeBottom, int32_t paddingSizeLeft, int32_t paddingSizeRight, @@ -999,13 +988,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPaddingParams(aclmdlAIPP *aippParmsSet * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMean(aclmdlAIPP *aippParmsSet, - int16_t dtcPixelMeanChn0, - int16_t dtcPixelMeanChn1, - int16_t dtcPixelMeanChn2, - int16_t dtcPixelMeanChn3, - uint64_t batchIndex); + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMean(aclmdlAIPP *aippParmsSet, int16_t dtcPixelMeanChn0, + int16_t dtcPixelMeanChn1, int16_t dtcPixelMeanChn2, + int16_t dtcPixelMeanChn3, uint64_t batchIndex); /** * @ingroup AscendCL @@ -1022,13 +1008,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMean(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMin(aclmdlAIPP *aippParmsSet, - float dtcPixelMinChn0, - float dtcPixelMinChn1, - float dtcPixelMinChn2, - float dtcPixelMinChn3, - uint64_t batchIndex); + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMin(aclmdlAIPP *aippParmsSet, float dtcPixelMinChn0, + float dtcPixelMinChn1, float dtcPixelMinChn2, + float dtcPixelMinChn3, uint64_t batchIndex); /** * @ingroup AscendCL @@ -1045,13 +1028,10 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMin(aclmdlAIPP *aippParmsSet, * @retval OtherValues Failure * * @see aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPixelVarReci(aclmdlAIPP *aippParmsSet, - float dtcPixelVarReciChn0, - float dtcPixelVarReciChn1, - float dtcPixelVarReciChn2, - float dtcPixelVarReciChn3, - uint64_t batchIndex); + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPixelVarReci(aclmdlAIPP *aippParmsSet, float dtcPixelVarReciChn0, + float dtcPixelVarReciChn1, float dtcPixelVarReciChn2, + float dtcPixelVarReciChn3, uint64_t batchIndex); /** * @ingroup AscendCL @@ -1067,10 +1047,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPixelVarReci(aclmdlAIPP *aippParmsSet, * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetInputAIPP(uint32_t modelId, - aclmdlDataset *dataset, - size_t index, + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetInputAIPP(uint32_t modelId, aclmdlDataset *dataset, size_t index, const aclmdlAIPP *aippParmsSet); /** @@ -1087,10 +1065,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetInputAIPP(uint32_t modelId, * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPByInputIndex(uint32_t modelId, - aclmdlDataset *dataset, - size_t index, + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPByInputIndex(uint32_t modelId, aclmdlDataset *dataset, size_t index, const aclmdlAIPP *aippParmsSet); /** @@ -1108,10 +1084,8 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPByInputIndex(uint32_t modelId, * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP -*/ -ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, - size_t index, - aclmdlInputAippType *type, + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, size_t index, aclmdlInputAippType *type, size_t *dynamicAttachedDataIndex); /** @@ -1128,7 +1102,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, * * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlGetFirstAippInfo(uint32_t modelId, size_t index, aclAippInfo *aippinfo); /** @@ -1147,10 +1121,11 @@ ACL_FUNC_VISIBILITY aclError aclmdlGetFirstAippInfo(uint32_t modelId, size_t ind * * @retval ACL_SUCCESS The function is successfully executed * @retval OtherValues Failure -*/ -ACL_FUNC_VISIBILITY aclError aclmdlCreateAndGetOpDesc(uint32_t deviceId, uint32_t streamId, - uint32_t taskId, char *opName, size_t opNameLen, aclTensorDesc **inputDesc, size_t *numInputs, - aclTensorDesc **outputDesc, size_t *numOutputs); + */ +ACL_FUNC_VISIBILITY aclError aclmdlCreateAndGetOpDesc(uint32_t deviceId, uint32_t streamId, uint32_t taskId, + char *opName, size_t opNameLen, aclTensorDesc **inputDesc, + size_t *numInputs, aclTensorDesc **outputDesc, + size_t *numOutputs); /** * @ingroup AscendCL @@ -1158,7 +1133,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlCreateAndGetOpDesc(uint32_t deviceId, uint32_ * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlInitDump(); /** @@ -1169,7 +1144,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlInitDump(); * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlSetDump(const char *dumpCfgPath); /** @@ -1178,7 +1153,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetDump(const char *dumpCfgPath); * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlFinalizeDump(); /** @@ -1190,7 +1165,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlFinalizeDump(); * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure -*/ + */ ACL_FUNC_VISIBILITY aclError aclmdlLoadWithConfig(const aclmdlConfigHandle *handle, uint32_t *modelId); /** @@ -1200,7 +1175,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlLoadWithConfig(const aclmdlConfigHandle *hand * @retval the aclmdlConfigHandle pointer * * @see aclmdlDestroyConfigHandle -*/ + */ ACL_FUNC_VISIBILITY aclmdlConfigHandle *aclmdlCreateConfigHandle(); /** @@ -1229,7 +1204,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlDestroyConfigHandle(aclmdlConfigHandle *handl * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclmdlSetConfigOpt(aclmdlConfigHandle *handle, aclmdlConfigAttr attr, - const void *attrValue, size_t valueSize); + const void *attrValue, size_t valueSize); /** * @ingroup AscendCL @@ -1247,4 +1222,4 @@ ACL_FUNC_VISIBILITY const char *aclmdlGetTensorRealName(const aclmdlDesc *modelD } #endif -#endif // INC_EXTERNAL_ACL_ACL_MODEL_H_ +#endif // INC_EXTERNAL_ACL_ACL_MODEL_H_ diff --git a/inc/external/acl/acl_op.h b/inc/external/acl/acl_op.h index b1be0d6e..d2e59bfb 100644 --- a/inc/external/acl/acl_op.h +++ b/inc/external/acl/acl_op.h @@ -33,9 +33,9 @@ typedef void (*aclDataDeallocator)(void *data, size_t length); static const int ACL_COMPILE_FLAG_BIN_SELECTOR = 1; typedef enum aclEngineType { - ACL_ENGINE_SYS, - ACL_ENGINE_AICORE, - ACL_ENGINE_VECTOR, + ACL_ENGINE_SYS, + ACL_ENGINE_AICORE, + ACL_ENGINE_VECTOR, } aclopEngineType; /** @@ -148,7 +148,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrString(aclopAttr *attr, const char *att * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListBool(aclopAttr *attr, const char *attrName, int numValues, - const uint8_t *values); + const uint8_t *values); /** * @ingroup AscendCL @@ -163,7 +163,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListBool(aclopAttr *attr, const char *a * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListInt(aclopAttr *attr, const char *attrName, int numValues, - const int64_t *values); + const int64_t *values); /** * @ingroup AscendCL @@ -178,7 +178,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListInt(aclopAttr *attr, const char *at * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListFloat(aclopAttr *attr, const char *attrName, int numValues, - const float *values); + const float *values); /** * @ingroup AscendCL @@ -193,7 +193,7 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListFloat(aclopAttr *attr, const char * * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopSetAttrListString(aclopAttr *attr, const char *attrName, int numValues, - const char **values); + const char **values); /** * @ingroup AscendCL @@ -208,11 +208,8 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListString(aclopAttr *attr, const char * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, - const char *attrName, - int numLists, - const int *numValues, - const int64_t *const values[]); +ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, const char *attrName, int numLists, + const int *numValues, const int64_t *const values[]); /** * @ingroup AscendCL @@ -242,15 +239,10 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, * @retval OtherValues Failure */ ACL_DEPRECATED_MESSAGE("aclopExecute is deprecated, use aclopExecuteV2 instead") -ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, - int numInputs, - const aclTensorDesc *const inputDesc[], - const aclDataBuffer *const inputs[], - int numOutputs, - const aclTensorDesc *const outputDesc[], - aclDataBuffer *const outputs[], - const aclopAttr *attr, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], + const aclDataBuffer *const inputs[], int numOutputs, + const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], + const aclopAttr *attr, aclrtStream stream); /** * @ingroup AscendCL @@ -280,15 +272,9 @@ ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, - int numInputs, - aclTensorDesc *inputDesc[], - aclDataBuffer *inputs[], - int numOutputs, - aclTensorDesc *outputDesc[], - aclDataBuffer *outputs[], - aclopAttr *attr, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, int numInputs, aclTensorDesc *inputDesc[], + aclDataBuffer *inputs[], int numOutputs, aclTensorDesc *outputDesc[], + aclDataBuffer *outputs[], aclopAttr *attr, aclrtStream stream); /** * @ingroup AscendCL @@ -306,12 +292,9 @@ ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCreateHandle(const char *opType, - int numInputs, - const aclTensorDesc *const inputDesc[], - int numOutputs, - const aclTensorDesc *const outputDesc[], - const aclopAttr *opAttr, +ACL_FUNC_VISIBILITY aclError aclopCreateHandle(const char *opType, int numInputs, + const aclTensorDesc *const inputDesc[], int numOutputs, + const aclTensorDesc *const outputDesc[], const aclopAttr *opAttr, aclopHandle **handle); /** @@ -343,12 +326,9 @@ ACL_FUNC_VISIBILITY void aclopDestroyHandle(aclopHandle *handle); * * @see aclopCreateHandle | aclCreateDataBuffer */ -ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, - int numInputs, - const aclDataBuffer *const inputs[], - int numOutputs, - aclDataBuffer *const outputs[], - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, int numInputs, + const aclDataBuffer *const inputs[], int numOutputs, + aclDataBuffer *const outputs[], aclrtStream stream); /** * @ingroup AscendCL @@ -364,11 +344,8 @@ ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, - const aclDataBuffer *srcBuffer, - const aclTensorDesc *dstDesc, - aclDataBuffer *dstBuffer, - uint8_t truncate, +ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, const aclDataBuffer *srcBuffer, + const aclTensorDesc *dstDesc, aclDataBuffer *dstBuffer, uint8_t truncate, aclrtStream stream); /** @@ -383,12 +360,9 @@ ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, - aclTensorDesc *dstDesc, - uint8_t truncate, +ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, aclTensorDesc *dstDesc, uint8_t truncate, aclopHandle **handle); - /** * @ingroup AscendCL * @brief create kernel @@ -407,15 +381,10 @@ ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, * * @see aclopCompile */ -ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, - const char *kernelId, - const char *kernelName, - void *binData, - int binSize, - aclopEngineType enginetype, +ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, const char *kernelId, const char *kernelName, + void *binData, int binSize, aclopEngineType enginetype, aclDataDeallocator deallocator); - /** * @ingroup AscendCL * @brief create kernel @@ -430,11 +399,8 @@ ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -typedef aclError (*aclopCompileFunc)(int numInputs, - const aclTensorDesc *const inputDesc[], - int numOutputs, - const aclTensorDesc *const outputDesc[], - const aclopAttr *opAttr, +typedef aclError (*aclopCompileFunc)(int numInputs, const aclTensorDesc *const inputDesc[], int numOutputs, + const aclTensorDesc *const outputDesc[], const aclopAttr *opAttr, aclopKernelDesc *aclopKernelDesc); /** @@ -475,11 +441,8 @@ ACL_FUNC_VISIBILITY aclError aclopUnregisterCompileFunc(const char *opType); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopSetKernelArgs(aclopKernelDesc *kernelDesc, - const char *kernelId, - uint32_t blockDim, - const void *args, - uint32_t argSize); +ACL_FUNC_VISIBILITY aclError aclopSetKernelArgs(aclopKernelDesc *kernelDesc, const char *kernelId, uint32_t blockDim, + const void *args, uint32_t argSize); /** * @ingroup AscendCL @@ -510,12 +473,9 @@ ACL_FUNC_VISIBILITY aclError aclopSetKernelWorkspaceSizes(aclopKernelDesc *kerne * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, - int numInputs, - const aclTensorDesc *const inputDesc[], - int numOutputs, - const aclTensorDesc *const outputDesc[], - const aclopAttr *attr); +ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, int numInputs, + const aclTensorDesc *const inputDesc[], int numOutputs, + const aclTensorDesc *const outputDesc[], const aclopAttr *attr); /** * @ingroup AscendCL @@ -533,17 +493,12 @@ ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopInferShape(const char *opType, - int numInputs, - aclTensorDesc *inputDesc[], - aclDataBuffer *inputs[], - int numOutputs, - aclTensorDesc *outputDesc[], +ACL_FUNC_VISIBILITY aclError aclopInferShape(const char *opType, int numInputs, aclTensorDesc *inputDesc[], + aclDataBuffer *inputs[], int numOutputs, aclTensorDesc *outputDesc[], aclopAttr *attr); - #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_ACL_OP_H_ +#endif // INC_EXTERNAL_ACL_ACL_OP_H_ diff --git a/inc/external/acl/acl_op_compiler.h b/inc/external/acl/acl_op_compiler.h index 353d2a1a..d9d1b3da 100644 --- a/inc/external/acl/acl_op_compiler.h +++ b/inc/external/acl/acl_op_compiler.h @@ -24,28 +24,22 @@ extern "C" { #endif -typedef enum aclCompileType { - ACL_COMPILE_SYS, - ACL_COMPILE_UNREGISTERED -} aclopCompileType; +typedef enum aclCompileType { ACL_COMPILE_SYS, ACL_COMPILE_UNREGISTERED } aclopCompileType; typedef enum { - ACL_PRECISION_MODE, - ACL_AICORE_NUM, - ACL_AUTO_TUNE_MODE, - ACL_OP_SELECT_IMPL_MODE, - ACL_OPTYPELIST_FOR_IMPLMODE, - ACL_OP_DEBUG_LEVEL, - ACL_DEBUG_DIR, - ACL_OP_COMPILER_CACHE_MODE, - ACL_OP_COMPILER_CACHE_DIR, - ACL_OP_PERFORMANCE_MODE + ACL_PRECISION_MODE, + ACL_AICORE_NUM, + ACL_AUTO_TUNE_MODE, + ACL_OP_SELECT_IMPL_MODE, + ACL_OPTYPELIST_FOR_IMPLMODE, + ACL_OP_DEBUG_LEVEL, + ACL_DEBUG_DIR, + ACL_OP_COMPILER_CACHE_MODE, + ACL_OP_COMPILER_CACHE_DIR, + ACL_OP_PERFORMANCE_MODE } aclCompileOpt; -typedef enum aclCompileFlag { - ACL_OP_COMPILE_DEFAULT, - ACL_OP_COMPILE_FUZZ -} aclOpCompileFlag; +typedef enum aclCompileFlag { ACL_OP_COMPILE_DEFAULT, ACL_OP_COMPILE_FUZZ } aclOpCompileFlag; /** * @ingroup AscendCL @@ -65,15 +59,10 @@ typedef enum aclCompileFlag { * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, - int numInputs, - const aclTensorDesc *const inputDesc[], - int numOutputs, - const aclTensorDesc *const outputDesc[], - const aclopAttr *attr, - aclopEngineType engineType, - aclopCompileType compileFlag, - const char *opPath); +ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], + int numOutputs, const aclTensorDesc *const outputDesc[], + const aclopAttr *attr, aclopEngineType engineType, + aclopCompileType compileFlag, const char *opPath); /** * @ingroup AscendCL @@ -96,11 +85,10 @@ ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclopCompileAndExecute(const char *opType, - int numInputs, const aclTensorDesc *const inputDesc[], const aclDataBuffer *const inputs[], - int numOutputs, const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], - const aclopAttr *attr, aclopEngineType engineType, aclopCompileType compileFlag, - const char *opPath, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclopCompileAndExecute( + const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], const aclDataBuffer *const inputs[], + int numOutputs, const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], const aclopAttr *attr, + aclopEngineType engineType, aclopCompileType compileFlag, const char *opPath, aclrtStream stream); /** * @ingroup AscendCL @@ -130,4 +118,4 @@ ACL_FUNC_VISIBILITY aclError aclopSetCompileFlag(aclOpCompileFlag flag); } #endif -#endif // INC_EXTERNAL_ACL_ACL_OP_COMPILER_H_ +#endif // INC_EXTERNAL_ACL_ACL_OP_COMPILER_H_ diff --git a/inc/external/acl/acl_prof.h b/inc/external/acl/acl_prof.h index 93bc3a9b..3784d8c6 100644 --- a/inc/external/acl/acl_prof.h +++ b/inc/external/acl/acl_prof.h @@ -23,24 +23,24 @@ extern "C" { #endif -#define ACL_PROF_ACL_API 0x0001 -#define ACL_PROF_TASK_TIME 0x0002 -#define ACL_PROF_AICORE_METRICS 0x0004 -#define ACL_PROF_AICPU 0x0008 +#define ACL_PROF_ACL_API 0x0001 +#define ACL_PROF_TASK_TIME 0x0002 +#define ACL_PROF_AICORE_METRICS 0x0004 +#define ACL_PROF_AICPU 0x0008 /** * @deprecated please use aclprofGetOpTypeLen and aclprofGetOpTNameLen instead */ -#define ACL_PROF_MAX_OP_NAME_LEN 257 -#define ACL_PROF_MAX_OP_TYPE_LEN 65 +#define ACL_PROF_MAX_OP_NAME_LEN 257 +#define ACL_PROF_MAX_OP_TYPE_LEN 65 typedef enum { - ACL_AICORE_ARITHMETIC_UTILIZATION = 0, - ACL_AICORE_PIPE_UTILIZATION = 1, - ACL_AICORE_MEMORY_BANDWIDTH = 2, - ACL_AICORE_L0B_AND_WIDTH = 3, - ACL_AICORE_RESOURCE_CONFLICT_RATIO = 4, - ACL_AICORE_NONE = 0xFF + ACL_AICORE_ARITHMETIC_UTILIZATION = 0, + ACL_AICORE_PIPE_UTILIZATION = 1, + ACL_AICORE_MEMORY_BANDWIDTH = 2, + ACL_AICORE_L0B_AND_WIDTH = 3, + ACL_AICORE_RESOURCE_CONFLICT_RATIO = 4, + ACL_AICORE_NONE = 0xFF } aclprofAicoreMetrics; typedef struct aclprofConfig aclprofConfig; @@ -101,7 +101,8 @@ ACL_FUNC_VISIBILITY aclError aclprofStart(const aclprofConfig *profilerConfig); * @see aclprofDestroyConfig */ ACL_FUNC_VISIBILITY aclprofConfig *aclprofCreateConfig(uint32_t *deviceIdList, uint32_t deviceNums, - aclprofAicoreMetrics aicoreMetrics, aclprofAicoreEvents *aicoreEvents, uint64_t dataTypeConfig); + aclprofAicoreMetrics aicoreMetrics, + aclprofAicoreEvents *aicoreEvents, uint64_t dataTypeConfig); /** * @ingroup AscendCL @@ -141,8 +142,7 @@ ACL_FUNC_VISIBILITY aclError aclprofStop(const aclprofConfig *profilerConfig); * * @see aclprofModelUnSubscribe */ -ACL_FUNC_VISIBILITY aclError aclprofModelSubscribe(uint32_t modelId, - const aclprofSubscribeConfig *profSubscribeConfig); +ACL_FUNC_VISIBILITY aclError aclprofModelSubscribe(uint32_t modelId, const aclprofSubscribeConfig *profSubscribeConfig); /** * @ingroup AscendCL @@ -170,7 +170,7 @@ ACL_FUNC_VISIBILITY aclError aclprofModelUnSubscribe(uint32_t modelId); * @see aclprofDestroySubscribeConfig */ ACL_FUNC_VISIBILITY aclprofSubscribeConfig *aclprofCreateSubscribeConfig(int8_t timeInfoSwitch, - aclprofAicoreMetrics aicoreMetrics, void *fd); + aclprofAicoreMetrics aicoreMetrics, void *fd); /** * @ingroup AscendCL @@ -222,7 +222,7 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpNum(const void *opInfo, size_t opInfoLe * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclprofGetOpTypeLen(const void *opInfo, size_t opInfoLen, uint32_t index, - size_t *opTypeLen); + size_t *opTypeLen); /** * @ingroup AscendCL @@ -237,8 +237,8 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpTypeLen(const void *opInfo, size_t opIn * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoLen, uint32_t index, - char *opType, size_t opTypeLen); +ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoLen, uint32_t index, char *opType, + size_t opTypeLen); /** * @ingroup AscendCL @@ -253,7 +253,7 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoL * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclprofGetOpNameLen(const void *opInfo, size_t opInfoLen, uint32_t index, - size_t *opNameLen); + size_t *opNameLen); /** * @ingroup AscendCL @@ -268,8 +268,8 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpNameLen(const void *opInfo, size_t opIn * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclprofGetOpName(const void *opInfo, size_t opInfoLen, uint32_t index, - char *opName, size_t opNameLen); +ACL_FUNC_VISIBILITY aclError aclprofGetOpName(const void *opInfo, size_t opInfoLen, uint32_t index, char *opName, + size_t opNameLen); /** * @ingroup AscendCL @@ -326,4 +326,4 @@ ACL_FUNC_VISIBILITY size_t aclprofGetModelId(const void *opInfo, size_t opInfoLe } #endif -#endif // INC_EXTERNAL_ACL_PROF_H_ +#endif // INC_EXTERNAL_ACL_PROF_H_ diff --git a/inc/external/acl/acl_rt.h b/inc/external/acl/acl_rt.h index 3c777ecc..5ee70724 100644 --- a/inc/external/acl/acl_rt.h +++ b/inc/external/acl/acl_rt.h @@ -28,63 +28,63 @@ extern "C" { #define ACL_EVENT_TIME_LINE 0x00000008u typedef enum aclrtRunMode { - ACL_DEVICE, - ACL_HOST, + ACL_DEVICE, + ACL_HOST, } aclrtRunMode; typedef enum aclrtTsId { - ACL_TS_ID_AICORE = 0, - ACL_TS_ID_AIVECTOR = 1, - ACL_TS_ID_RESERVED = 2, + ACL_TS_ID_AICORE = 0, + ACL_TS_ID_AIVECTOR = 1, + ACL_TS_ID_RESERVED = 2, } aclrtTsId; typedef enum aclrtEventStatus { - ACL_EVENT_STATUS_COMPLETE = 0, - ACL_EVENT_STATUS_NOT_READY = 1, - ACL_EVENT_STATUS_RESERVED = 2, + ACL_EVENT_STATUS_COMPLETE = 0, + ACL_EVENT_STATUS_NOT_READY = 1, + ACL_EVENT_STATUS_RESERVED = 2, } aclrtEventStatus; typedef enum aclrtCallbackBlockType { - ACL_CALLBACK_NO_BLOCK, - ACL_CALLBACK_BLOCK, + ACL_CALLBACK_NO_BLOCK, + ACL_CALLBACK_BLOCK, } aclrtCallbackBlockType; typedef enum aclrtMemcpyKind { - ACL_MEMCPY_HOST_TO_HOST, - ACL_MEMCPY_HOST_TO_DEVICE, - ACL_MEMCPY_DEVICE_TO_HOST, - ACL_MEMCPY_DEVICE_TO_DEVICE, + ACL_MEMCPY_HOST_TO_HOST, + ACL_MEMCPY_HOST_TO_DEVICE, + ACL_MEMCPY_DEVICE_TO_HOST, + ACL_MEMCPY_DEVICE_TO_DEVICE, } aclrtMemcpyKind; typedef enum aclrtMemMallocPolicy { - ACL_MEM_MALLOC_HUGE_FIRST, - ACL_MEM_MALLOC_HUGE_ONLY, - ACL_MEM_MALLOC_NORMAL_ONLY, - ACL_MEM_MALLOC_HUGE_FIRST_P2P, - ACL_MEM_MALLOC_HUGE_ONLY_P2P, - ACL_MEM_MALLOC_NORMAL_ONLY_P2P, + ACL_MEM_MALLOC_HUGE_FIRST, + ACL_MEM_MALLOC_HUGE_ONLY, + ACL_MEM_MALLOC_NORMAL_ONLY, + ACL_MEM_MALLOC_HUGE_FIRST_P2P, + ACL_MEM_MALLOC_HUGE_ONLY_P2P, + ACL_MEM_MALLOC_NORMAL_ONLY_P2P, } aclrtMemMallocPolicy; typedef enum aclrtMemAttr { - ACL_DDR_MEM, - ACL_HBM_MEM, - ACL_DDR_MEM_HUGE, - ACL_DDR_MEM_NORMAL, - ACL_HBM_MEM_HUGE, - ACL_HBM_MEM_NORMAL, - ACL_DDR_MEM_P2P_HUGE, - ACL_DDR_MEM_P2P_NORMAL, - ACL_HBM_MEM_P2P_HUGE, - ACL_HBM_MEM_P2P_NORMAL, + ACL_DDR_MEM, + ACL_HBM_MEM, + ACL_DDR_MEM_HUGE, + ACL_DDR_MEM_NORMAL, + ACL_HBM_MEM_HUGE, + ACL_HBM_MEM_NORMAL, + ACL_DDR_MEM_P2P_HUGE, + ACL_DDR_MEM_P2P_NORMAL, + ACL_HBM_MEM_P2P_HUGE, + ACL_HBM_MEM_P2P_NORMAL, } aclrtMemAttr; typedef enum aclrtGroupAttr { - ACL_GROUP_AICORE_INT, - ACL_GROUP_AIV_INT, - ACL_GROUP_AIC_INT, - ACL_GROUP_SDMANUM_INT, - ACL_GROUP_ASQNUM_INT, - ACL_GROUP_GROUPID_INT + ACL_GROUP_AICORE_INT, + ACL_GROUP_AIV_INT, + ACL_GROUP_AIC_INT, + ACL_GROUP_SDMANUM_INT, + ACL_GROUP_ASQNUM_INT, + ACL_GROUP_GROUPID_INT } aclrtGroupAttr; typedef struct tagRtGroupInfo aclrtGroupInfo; @@ -487,7 +487,7 @@ ACL_FUNC_VISIBILITY aclError aclrtRecordEvent(aclrtEvent event, aclrtStream stre */ ACL_FUNC_VISIBILITY aclError aclrtResetEvent(aclrtEvent event, aclrtStream stream); - /** +/** * @ingroup AscendCL * @brief Queries an event's status * @@ -549,9 +549,7 @@ ACL_FUNC_VISIBILITY aclError aclrtEventElapsedTime(float *ms, aclrtEvent start, * * @see aclrtFree | acldvppMalloc | aclrtMallocCached */ -ACL_FUNC_VISIBILITY aclError aclrtMalloc(void **devPtr, - size_t size, - aclrtMemMallocPolicy policy); +ACL_FUNC_VISIBILITY aclError aclrtMalloc(void **devPtr, size_t size, aclrtMemMallocPolicy policy); /** * @ingroup AscendCL @@ -574,9 +572,7 @@ ACL_FUNC_VISIBILITY aclError aclrtMalloc(void **devPtr, * * @see aclrtFree | aclrtMalloc */ -ACL_FUNC_VISIBILITY aclError aclrtMallocCached(void **devPtr, - size_t size, - aclrtMemMallocPolicy policy); +ACL_FUNC_VISIBILITY aclError aclrtMallocCached(void **devPtr, size_t size, aclrtMemMallocPolicy policy); /** * @ingroup AscendCL @@ -667,10 +663,7 @@ ACL_FUNC_VISIBILITY aclError aclrtFreeHost(void *hostPtr); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclrtMemcpy(void *dst, - size_t destMax, - const void *src, - size_t count, +ACL_FUNC_VISIBILITY aclError aclrtMemcpy(void *dst, size_t destMax, const void *src, size_t count, aclrtMemcpyKind kind); /** @@ -717,38 +710,31 @@ ACL_FUNC_VISIBILITY aclError aclrtMemset(void *devPtr, size_t maxCount, int32_t * * @see aclrtSynchronizeStream */ -ACL_FUNC_VISIBILITY aclError aclrtMemcpyAsync(void *dst, - size_t destMax, - const void *src, - size_t count, - aclrtMemcpyKind kind, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclrtMemcpyAsync(void *dst, size_t destMax, const void *src, size_t count, + aclrtMemcpyKind kind, aclrtStream stream); /** -* @ingroup AscendCL -* @brief Asynchronous initialize memory -* and set contents of memory to specified value async -* -* @par Function + * @ingroup AscendCL + * @brief Asynchronous initialize memory + * and set contents of memory to specified value async + * + * @par Function * The memory to be initialized is on the Host or device side, * and the system determines whether * it is host or device according to the address * -* @param devPtr [IN] destination address pointer -* @param maxCount [IN] Max length of destination address memory -* @param value [IN] set value -* @param count [IN] the number of byte to set -* @param stream [IN] asynchronized task stream -* -* @retval ACL_SUCCESS The function is successfully executed. -* @retval OtherValues Failure -* -* @see aclrtSynchronizeStream -*/ -ACL_FUNC_VISIBILITY aclError aclrtMemsetAsync(void *devPtr, - size_t maxCount, - int32_t value, - size_t count, + * @param devPtr [IN] destination address pointer + * @param maxCount [IN] Max length of destination address memory + * @param value [IN] set value + * @param count [IN] the number of byte to set + * @param stream [IN] asynchronized task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtSynchronizeStream + */ +ACL_FUNC_VISIBILITY aclError aclrtMemsetAsync(void *devPtr, size_t maxCount, int32_t value, size_t count, aclrtStream stream); /** @@ -894,11 +880,8 @@ ACL_FUNC_VISIBILITY aclError aclrtGetAllGroupInfo(aclrtGroupInfo *groupInfo); * * @see aclrtGetGroupCount | aclrtGetAllGroupInfo */ -ACL_FUNC_VISIBILITY aclError aclrtGetGroupInfoDetail(const aclrtGroupInfo *groupInfo, - int32_t groupIndex, - aclrtGroupAttr attr, - void *attrValue, - size_t valueLen, +ACL_FUNC_VISIBILITY aclError aclrtGetGroupInfoDetail(const aclrtGroupInfo *groupInfo, int32_t groupIndex, + aclrtGroupAttr attr, void *attrValue, size_t valueLen, size_t *paramRetSize); /** @@ -972,5 +955,4 @@ ACL_FUNC_VISIBILITY aclError aclrtSetOpWaitTimeout(uint32_t timeout); } #endif -#endif // INC_EXTERNAL_ACL_ACL_RT_H_ - +#endif // INC_EXTERNAL_ACL_ACL_RT_H_ diff --git a/inc/external/acl/acl_tdt.h b/inc/external/acl/acl_tdt.h index 61995121..c357518d 100644 --- a/inc/external/acl/acl_tdt.h +++ b/inc/external/acl/acl_tdt.h @@ -24,10 +24,10 @@ extern "C" { #endif enum acltdtTensorType { - ACL_TENSOR_DATA_UNDEFINED = -1, - ACL_TENSOR_DATA_TENSOR, - ACL_TENSOR_DATA_END_OF_SEQUENCE, - ACL_TENSOR_DATA_ABNORMAL + ACL_TENSOR_DATA_UNDEFINED = -1, + ACL_TENSOR_DATA_TENSOR, + ACL_TENSOR_DATA_END_OF_SEQUENCE, + ACL_TENSOR_DATA_ABNORMAL }; typedef struct acltdtDataItem acltdtDataItem; @@ -64,7 +64,7 @@ ACL_FUNC_VISIBILITY aclDataType acltdtGetDataTypeFromItem(const acltdtDataItem * * * @retval null for failed * @retval OtherValues success -*/ + */ ACL_FUNC_VISIBILITY void *acltdtGetDataAddrFromItem(const acltdtDataItem *dataItem); /** @@ -75,7 +75,7 @@ ACL_FUNC_VISIBILITY void *acltdtGetDataAddrFromItem(const acltdtDataItem *dataIt * * @retval 0 for failed * @retval OtherValues success -*/ + */ ACL_FUNC_VISIBILITY size_t acltdtGetDataSizeFromItem(const acltdtDataItem *dataItem); /** @@ -86,7 +86,7 @@ ACL_FUNC_VISIBILITY size_t acltdtGetDataSizeFromItem(const acltdtDataItem *dataI * * @retval 0 for failed * @retval OtherValues success -*/ + */ ACL_FUNC_VISIBILITY size_t acltdtGetDimNumFromItem(const acltdtDataItem *dataItem); /** @@ -118,12 +118,8 @@ ACL_FUNC_VISIBILITY aclError acltdtGetDimsFromItem(const acltdtDataItem *dataIte * * @see acltdtDestroyDataItem */ -ACL_FUNC_VISIBILITY acltdtDataItem *acltdtCreateDataItem(acltdtTensorType tdtType, - const int64_t *dims, - size_t dimNum, - aclDataType dataType, - void *data, - size_t size); +ACL_FUNC_VISIBILITY acltdtDataItem *acltdtCreateDataItem(acltdtTensorType tdtType, const int64_t *dims, size_t dimNum, + aclDataType dataType, void *data, size_t size); /** * @ingroup AscendCL @@ -254,8 +250,7 @@ ACL_FUNC_VISIBILITY aclError acltdtDestroyChannel(acltdtChannelHandle *handle); * * @see acltdtReceiveTensor */ -ACL_FUNC_VISIBILITY aclError acltdtSendTensor(const acltdtChannelHandle *handle, - const acltdtDataset *dataset, +ACL_FUNC_VISIBILITY aclError acltdtSendTensor(const acltdtChannelHandle *handle, const acltdtDataset *dataset, int32_t timeout); /** @@ -271,13 +266,11 @@ ACL_FUNC_VISIBILITY aclError acltdtSendTensor(const acltdtChannelHandle *handle, * * @see acltdtSendTensor */ -ACL_FUNC_VISIBILITY aclError acltdtReceiveTensor(const acltdtChannelHandle *handle, - acltdtDataset *dataset, +ACL_FUNC_VISIBILITY aclError acltdtReceiveTensor(const acltdtChannelHandle *handle, acltdtDataset *dataset, int32_t timeout); #ifdef __cplusplus } #endif -#endif //INC_EXTERNAL_ACL_ACL_TDT_H_ - +#endif // INC_EXTERNAL_ACL_ACL_TDT_H_ diff --git a/inc/external/acl/error_codes/rt_error_codes.h b/inc/external/acl/error_codes/rt_error_codes.h index c9a40432..a1392cc6 100644 --- a/inc/external/acl/error_codes/rt_error_codes.h +++ b/inc/external/acl/error_codes/rt_error_codes.h @@ -23,84 +23,87 @@ extern "C" { #endif -static const int32_t ACL_RT_SUCCESS = 0; // success +static const int32_t ACL_RT_SUCCESS = 0; // success -static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid -static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id -static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null -static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context -static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context -static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal -static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned -static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed -static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed -static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream -static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread -static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set -static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create -static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream -static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type -static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle -static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type +static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid +static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id +static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null +static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context +static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context +static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal +static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned +static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed +static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed +static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream +static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread +static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set +static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create +static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream +static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type +static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle +static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type +static const int32_t ACL_ERROR_RT_WAIT_TIMEOUT = 107019; // wait timeout -static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support -static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error -static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error -static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow -static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device -static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail -static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission -static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource -static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource -static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource -static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource +static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support +static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error +static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error +static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow +static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device +static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail +static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission +static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource +static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource +static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource +static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource +static const int32_t ACL_ERROR_RT_NO_CDQ_RESOURCE = 207011; // no cdq resource -static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error -static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout -static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception -static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout +static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception +static const int32_t ACL_ERROR_RT_CDQ_BATCH_ABNORMAL = 507037; // cdq alloc batch abnormal -static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error -static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error -static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect +static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error +static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error +static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect #ifdef __cplusplus } #endif -#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ +#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/inc/external/acl/ops/acl_cblas.h b/inc/external/acl/ops/acl_cblas.h index a2bd8c61..3d81eb2b 100644 --- a/inc/external/acl/ops/acl_cblas.h +++ b/inc/external/acl/ops/acl_cblas.h @@ -23,17 +23,9 @@ extern "C" { #endif -typedef enum aclTransType { - ACL_TRANS_N, - ACL_TRANS_T, - ACL_TRANS_NZ, - ACL_TRANS_NZ_T -} aclTransType; +typedef enum aclTransType { ACL_TRANS_N, ACL_TRANS_T, ACL_TRANS_NZ, ACL_TRANS_NZ_T } aclTransType; -typedef enum aclComputeType { - ACL_COMPUTE_HIGH_PRECISION, - ACL_COMPUTE_LOW_PRECISION -} aclComputeType; +typedef enum aclComputeType { ACL_COMPUTE_HIGH_PRECISION, ACL_COMPUTE_LOW_PRECISION } aclComputeType; /** * @ingroup AscendCL @@ -61,12 +53,11 @@ typedef enum aclComputeType { * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure -*/ -ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, - const void *alpha, const void *a, int lda, aclDataType dataTypeA, - const void *x, int incx, aclDataType dataTypeX, - const void *beta, void *y, int incy, aclDataType dataTypeY, - aclComputeType type, aclrtStream stream); + */ +ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, const void *alpha, const void *a, int lda, + aclDataType dataTypeA, const void *x, int incx, aclDataType dataTypeX, + const void *beta, void *y, int incy, aclDataType dataTypeY, + aclComputeType type, aclrtStream stream); /** * @ingroup AscendCL @@ -83,15 +74,10 @@ ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure -*/ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, - int m, - int n, - aclDataType dataTypeA, - aclDataType dataTypeX, - aclDataType dataTypeY, - aclComputeType type, - aclopHandle **handle); + */ +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, int m, int n, aclDataType dataTypeA, + aclDataType dataTypeX, aclDataType dataTypeY, + aclComputeType type, aclopHandle **handle); /** * @ingroup AscendCL @@ -115,18 +101,9 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, - int m, - int n, - const aclFloat16 *alpha, - const aclFloat16 *a, - int lda, - const aclFloat16 *x, - int incx, - const aclFloat16 *beta, - aclFloat16 *y, - int incy, - aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, int m, int n, const aclFloat16 *alpha, + const aclFloat16 *a, int lda, const aclFloat16 *x, int incx, + const aclFloat16 *beta, aclFloat16 *y, int incy, aclComputeType type, aclrtStream stream); /** @@ -142,10 +119,7 @@ ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, - int m, - int n, - aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, int m, int n, aclComputeType type, aclopHandle **handle); /** @@ -171,19 +145,9 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, - int m, - int n, - const int32_t *alpha, - const int8_t *a, - int lda, - const int8_t *x, - int incx, - const int32_t *beta, - int32_t *y, - int incy, - aclComputeType type, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, int m, int n, const int32_t *alpha, const int8_t *a, + int lda, const int8_t *x, int incx, const int32_t *beta, int32_t *y, + int incy, aclComputeType type, aclrtStream stream); /** * @ingroup AscendCL @@ -198,10 +162,7 @@ ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, - int m, - int n, - aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, int m, int n, aclComputeType type, aclopHandle **handle); /** @@ -233,26 +194,11 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, - aclTransType transB, - aclTransType transC, - int m, - int n, - int k, - const void *alpha, - const void *matrixA, - int lda, - aclDataType dataTypeA, - const void *matrixB, - int ldb, - aclDataType dataTypeB, - const void *beta, - void *matrixC, - int ldc, - aclDataType dataTypeC, - aclComputeType type, - aclrtStream stream); - +ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, + int k, const void *alpha, const void *matrixA, int lda, + aclDataType dataTypeA, const void *matrixB, int ldb, aclDataType dataTypeB, + const void *beta, void *matrixC, int ldc, aclDataType dataTypeC, + aclComputeType type, aclrtStream stream); /** * @ingroup AscendCL @@ -274,18 +220,10 @@ ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, - aclTransType transB, - aclTransType transC, - int m, - int n, - int k, - aclDataType dataTypeA, - aclDataType dataTypeB, - aclDataType dataTypeC, - aclComputeType type, - aclopHandle **handle); - +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, aclTransType transB, aclTransType transC, + int m, int n, int k, aclDataType dataTypeA, + aclDataType dataTypeB, aclDataType dataTypeC, + aclComputeType type, aclopHandle **handle); /** * @ingroup AscendCL @@ -313,22 +251,10 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, - aclTransType transB, - aclTransType transC, - int m, - int n, - int k, - const aclFloat16 *alpha, - const aclFloat16 *matrixA, - int lda, - const aclFloat16 *matrixB, - int ldb, - const aclFloat16 *beta, - aclFloat16 *matrixC, - int ldc, - aclComputeType type, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, + int k, const aclFloat16 *alpha, const aclFloat16 *matrixA, int lda, + const aclFloat16 *matrixB, int ldb, const aclFloat16 *beta, + aclFloat16 *matrixC, int ldc, aclComputeType type, aclrtStream stream); /** * @ingroup AscendCL @@ -346,13 +272,8 @@ ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, - aclTransType transB, - aclTransType transC, - int m, - int n, - int k, - aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, aclTransType transB, aclTransType transC, + int m, int n, int k, aclComputeType type, aclopHandle **handle); /** @@ -381,23 +302,10 @@ ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, - aclTransType transB, - aclTransType transC, - int m, - int n, - int k, - const int32_t *alpha, - const int8_t *matrixA, - int lda, - const int8_t *matrixB, - int ldb, - const int32_t *beta, - int32_t *matrixC, - int ldc, - aclComputeType type, - aclrtStream stream); - +ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, + int k, const int32_t *alpha, const int8_t *matrixA, int lda, + const int8_t *matrixB, int ldb, const int32_t *beta, int32_t *matrixC, + int ldc, aclComputeType type, aclrtStream stream); /** * @ingroup AscendCL @@ -415,17 +323,12 @@ ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemm(aclTransType transA, - aclTransType transB, - aclTransType transC, - int m, - int n, - int k, - aclComputeType type, +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemm(aclTransType transA, aclTransType transB, aclTransType transC, + int m, int n, int k, aclComputeType type, aclopHandle **handle); #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_CBLAS_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_CBLAS_H_ diff --git a/inc/external/acl/ops/acl_dvpp.h b/inc/external/acl/ops/acl_dvpp.h index 90dc70e8..dcaa3936 100644 --- a/inc/external/acl/ops/acl_dvpp.h +++ b/inc/external/acl/ops/acl_dvpp.h @@ -53,123 +53,109 @@ typedef void (*aclvencCallback)(acldvppPicDesc *input, acldvppStreamDesc *output // Supported Pixel Format enum acldvppPixelFormat { - PIXEL_FORMAT_YUV_400 = 0, // 0 - PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1, // 1 - PIXEL_FORMAT_YVU_SEMIPLANAR_420 = 2, // 2 - PIXEL_FORMAT_YUV_SEMIPLANAR_422 = 3, // 3 - PIXEL_FORMAT_YVU_SEMIPLANAR_422 = 4, // 4 - PIXEL_FORMAT_YUV_SEMIPLANAR_444 = 5, // 5 - PIXEL_FORMAT_YVU_SEMIPLANAR_444 = 6, // 6 - PIXEL_FORMAT_YUYV_PACKED_422 = 7, // 7 - PIXEL_FORMAT_UYVY_PACKED_422 = 8, // 8 - PIXEL_FORMAT_YVYU_PACKED_422 = 9, // 9 - PIXEL_FORMAT_VYUY_PACKED_422 = 10, // 10 - PIXEL_FORMAT_YUV_PACKED_444 = 11, // 11 - PIXEL_FORMAT_RGB_888 = 12, // 12 - PIXEL_FORMAT_BGR_888 = 13, // 13 - PIXEL_FORMAT_ARGB_8888 = 14, // 14 - PIXEL_FORMAT_ABGR_8888 = 15, // 15 - PIXEL_FORMAT_RGBA_8888 = 16, // 16 - PIXEL_FORMAT_BGRA_8888 = 17, // 17 - PIXEL_FORMAT_YUV_SEMI_PLANNER_420_10BIT = 18, // 18 - PIXEL_FORMAT_YVU_SEMI_PLANNER_420_10BIT = 19, // 19 - PIXEL_FORMAT_YVU_PLANAR_420 = 20, // 20 - PIXEL_FORMAT_YVU_PLANAR_422, - PIXEL_FORMAT_YVU_PLANAR_444, - PIXEL_FORMAT_RGB_444 = 23, - PIXEL_FORMAT_BGR_444, - PIXEL_FORMAT_ARGB_4444, - PIXEL_FORMAT_ABGR_4444, - PIXEL_FORMAT_RGBA_4444, - PIXEL_FORMAT_BGRA_4444, - PIXEL_FORMAT_RGB_555, - PIXEL_FORMAT_BGR_555, - PIXEL_FORMAT_RGB_565, - PIXEL_FORMAT_BGR_565, - PIXEL_FORMAT_ARGB_1555, - PIXEL_FORMAT_ABGR_1555, - PIXEL_FORMAT_RGBA_1555, - PIXEL_FORMAT_BGRA_1555, - PIXEL_FORMAT_ARGB_8565, - PIXEL_FORMAT_ABGR_8565, - PIXEL_FORMAT_RGBA_8565, - PIXEL_FORMAT_BGRA_8565, - PIXEL_FORMAT_RGB_BAYER_8BPP = 50, - PIXEL_FORMAT_RGB_BAYER_10BPP, - PIXEL_FORMAT_RGB_BAYER_12BPP, - PIXEL_FORMAT_RGB_BAYER_14BPP, - PIXEL_FORMAT_RGB_BAYER_16BPP, - PIXEL_FORMAT_BGR_888_PLANAR = 70, - PIXEL_FORMAT_HSV_888_PACKAGE, - PIXEL_FORMAT_HSV_888_PLANAR, - PIXEL_FORMAT_LAB_888_PACKAGE, - PIXEL_FORMAT_LAB_888_PLANAR, - PIXEL_FORMAT_S8C1, - PIXEL_FORMAT_S8C2_PACKAGE, - PIXEL_FORMAT_S8C2_PLANAR, - PIXEL_FORMAT_S16C1, - PIXEL_FORMAT_U8C1, - PIXEL_FORMAT_U16C1, - PIXEL_FORMAT_S32C1, - PIXEL_FORMAT_U32C1, - PIXEL_FORMAT_U64C1, - PIXEL_FORMAT_S64C1, - PIXEL_FORMAT_YUV_SEMIPLANAR_440 = 1000, - PIXEL_FORMAT_YVU_SEMIPLANAR_440, - PIXEL_FORMAT_FLOAT32, - PIXEL_FORMAT_BUTT, - PIXEL_FORMAT_UNKNOWN = 10000 + PIXEL_FORMAT_YUV_400 = 0, // 0 + PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1, // 1 + PIXEL_FORMAT_YVU_SEMIPLANAR_420 = 2, // 2 + PIXEL_FORMAT_YUV_SEMIPLANAR_422 = 3, // 3 + PIXEL_FORMAT_YVU_SEMIPLANAR_422 = 4, // 4 + PIXEL_FORMAT_YUV_SEMIPLANAR_444 = 5, // 5 + PIXEL_FORMAT_YVU_SEMIPLANAR_444 = 6, // 6 + PIXEL_FORMAT_YUYV_PACKED_422 = 7, // 7 + PIXEL_FORMAT_UYVY_PACKED_422 = 8, // 8 + PIXEL_FORMAT_YVYU_PACKED_422 = 9, // 9 + PIXEL_FORMAT_VYUY_PACKED_422 = 10, // 10 + PIXEL_FORMAT_YUV_PACKED_444 = 11, // 11 + PIXEL_FORMAT_RGB_888 = 12, // 12 + PIXEL_FORMAT_BGR_888 = 13, // 13 + PIXEL_FORMAT_ARGB_8888 = 14, // 14 + PIXEL_FORMAT_ABGR_8888 = 15, // 15 + PIXEL_FORMAT_RGBA_8888 = 16, // 16 + PIXEL_FORMAT_BGRA_8888 = 17, // 17 + PIXEL_FORMAT_YUV_SEMI_PLANNER_420_10BIT = 18, // 18 + PIXEL_FORMAT_YVU_SEMI_PLANNER_420_10BIT = 19, // 19 + PIXEL_FORMAT_YVU_PLANAR_420 = 20, // 20 + PIXEL_FORMAT_YVU_PLANAR_422, + PIXEL_FORMAT_YVU_PLANAR_444, + PIXEL_FORMAT_RGB_444 = 23, + PIXEL_FORMAT_BGR_444, + PIXEL_FORMAT_ARGB_4444, + PIXEL_FORMAT_ABGR_4444, + PIXEL_FORMAT_RGBA_4444, + PIXEL_FORMAT_BGRA_4444, + PIXEL_FORMAT_RGB_555, + PIXEL_FORMAT_BGR_555, + PIXEL_FORMAT_RGB_565, + PIXEL_FORMAT_BGR_565, + PIXEL_FORMAT_ARGB_1555, + PIXEL_FORMAT_ABGR_1555, + PIXEL_FORMAT_RGBA_1555, + PIXEL_FORMAT_BGRA_1555, + PIXEL_FORMAT_ARGB_8565, + PIXEL_FORMAT_ABGR_8565, + PIXEL_FORMAT_RGBA_8565, + PIXEL_FORMAT_BGRA_8565, + PIXEL_FORMAT_RGB_BAYER_8BPP = 50, + PIXEL_FORMAT_RGB_BAYER_10BPP, + PIXEL_FORMAT_RGB_BAYER_12BPP, + PIXEL_FORMAT_RGB_BAYER_14BPP, + PIXEL_FORMAT_RGB_BAYER_16BPP, + PIXEL_FORMAT_BGR_888_PLANAR = 70, + PIXEL_FORMAT_HSV_888_PACKAGE, + PIXEL_FORMAT_HSV_888_PLANAR, + PIXEL_FORMAT_LAB_888_PACKAGE, + PIXEL_FORMAT_LAB_888_PLANAR, + PIXEL_FORMAT_S8C1, + PIXEL_FORMAT_S8C2_PACKAGE, + PIXEL_FORMAT_S8C2_PLANAR, + PIXEL_FORMAT_S16C1, + PIXEL_FORMAT_U8C1, + PIXEL_FORMAT_U16C1, + PIXEL_FORMAT_S32C1, + PIXEL_FORMAT_U32C1, + PIXEL_FORMAT_U64C1, + PIXEL_FORMAT_S64C1, + PIXEL_FORMAT_YUV_SEMIPLANAR_440 = 1000, + PIXEL_FORMAT_YVU_SEMIPLANAR_440, + PIXEL_FORMAT_FLOAT32, + PIXEL_FORMAT_BUTT, + PIXEL_FORMAT_UNKNOWN = 10000 }; // Stream Format -enum acldvppStreamFormat { - H265_MAIN_LEVEL = 0, - H264_BASELINE_LEVEL, - H264_MAIN_LEVEL, - H264_HIGH_LEVEL -}; +enum acldvppStreamFormat { H265_MAIN_LEVEL = 0, H264_BASELINE_LEVEL, H264_MAIN_LEVEL, H264_HIGH_LEVEL }; // Supported Channel Mode -enum acldvppChannelMode { - DVPP_CHNMODE_VPC = 1, - DVPP_CHNMODE_JPEGD = 2, - DVPP_CHNMODE_JPEGE = 4 -}; +enum acldvppChannelMode { DVPP_CHNMODE_VPC = 1, DVPP_CHNMODE_JPEGD = 2, DVPP_CHNMODE_JPEGE = 4 }; // Supported Border Type -enum acldvppBorderType { - BORDER_CONSTANT = 0, - BORDER_REPLICATE, - BORDER_REFLECT, - BORDER_REFLECT_101 -}; +enum acldvppBorderType { BORDER_CONSTANT = 0, BORDER_REPLICATE, BORDER_REFLECT, BORDER_REFLECT_101 }; // Venc parameter type enum aclvencChannelDescParamType { - ACL_VENC_THREAD_ID_UINT64 = 0, - ACL_VENC_CALLBACK_PTR, - ACL_VENC_PIXEL_FORMAT_UINT32, - ACL_VENC_ENCODE_TYPE_UINT32, - ACL_VENC_PIC_WIDTH_UINT32, - ACL_VENC_PIC_HEIGHT_UINT32, - ACL_VENC_KEY_FRAME_INTERVAL_UINT32, - ACL_VENC_BUF_ADDR_PTR, - ACL_VENC_BUF_SIZE_UINT32, - ACL_VENC_RC_MODE_UINT32, - ACL_VENC_SRC_RATE_UINT32, - ACL_VENC_MAX_BITRATE_UINT32, - ACL_VENC_MAX_IP_PROP_UINT32 + ACL_VENC_THREAD_ID_UINT64 = 0, + ACL_VENC_CALLBACK_PTR, + ACL_VENC_PIXEL_FORMAT_UINT32, + ACL_VENC_ENCODE_TYPE_UINT32, + ACL_VENC_PIC_WIDTH_UINT32, + ACL_VENC_PIC_HEIGHT_UINT32, + ACL_VENC_KEY_FRAME_INTERVAL_UINT32, + ACL_VENC_BUF_ADDR_PTR, + ACL_VENC_BUF_SIZE_UINT32, + ACL_VENC_RC_MODE_UINT32, + ACL_VENC_SRC_RATE_UINT32, + ACL_VENC_MAX_BITRATE_UINT32, + ACL_VENC_MAX_IP_PROP_UINT32 }; // Jpeg picture format enum acldvppJpegFormat { - ACL_JPEG_CSS_444 = 0, - ACL_JPEG_CSS_422, - ACL_JPEG_CSS_420, - ACL_JPEG_CSS_GRAY, - ACL_JPEG_CSS_440, - ACL_JPEG_CSS_411, - ACL_JPEG_CSS_UNKNOWN = 1000 + ACL_JPEG_CSS_444 = 0, + ACL_JPEG_CSS_422, + ACL_JPEG_CSS_420, + ACL_JPEG_CSS_GRAY, + ACL_JPEG_CSS_440, + ACL_JPEG_CSS_411, + ACL_JPEG_CSS_UNKNOWN = 1000 }; /** @@ -523,9 +509,7 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescRetCode(const acldvppPicDesc *picD * @retval null for failed. * @retval other success */ -ACL_FUNC_VISIBILITY acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, - uint32_t right, - uint32_t top, +ACL_FUNC_VISIBILITY acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, uint32_t right, uint32_t top, uint32_t bottom); /** @@ -604,10 +588,7 @@ ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfigBottom(acldvppRoiConfig *config, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfig(acldvppRoiConfig *config, - uint32_t left, - uint32_t right, - uint32_t top, +ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfig(acldvppRoiConfig *config, uint32_t left, uint32_t right, uint32_t top, uint32_t bottom); /** @@ -1096,7 +1077,8 @@ ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescMaxBitRate(aclvencChannelDesc * @retval ACL_SUCCESS for success, other for failure */ ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescParam(aclvencChannelDesc *channelDesc, - aclvencChannelDescParamType paramType, size_t length, const void *param); + aclvencChannelDescParamType paramType, size_t length, + const void *param); /** * @ingroup AscendCL @@ -1245,7 +1227,8 @@ ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescMaxBitRate(const aclvencChanne * @retval ACL_SUCCESS for success, other for failure */ ACL_FUNC_VISIBILITY aclError aclvencGetChannelDescParam(const aclvencChannelDesc *channelDesc, - aclvencChannelDescParamType paramType, size_t length, size_t *paramRetSize, void *param); + aclvencChannelDescParamType paramType, size_t length, + size_t *paramRetSize, void *param); /** * @ingroup AscendCL @@ -1545,10 +1528,7 @@ ACL_FUNC_VISIBILITY aclError aclvdecDestroyFrameConfig(aclvdecFrameConfig *vdecF * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, - uint32_t size, - uint32_t *width, - uint32_t *height, +ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, uint32_t size, uint32_t *width, uint32_t *height, int32_t *components); /** @@ -1565,11 +1545,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, - uint32_t size, - uint32_t *width, - uint32_t *height, - int32_t *components, +ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, uint32_t size, uint32_t *width, + uint32_t *height, int32_t *components, acldvppJpegFormat *format); /** @@ -1584,8 +1561,7 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictEncSize(const acldvppPicDesc *inputDesc, - const acldvppJpegeConfig *config, - uint32_t *size); + const acldvppJpegeConfig *config, uint32_t *size); /** * @ingroup AscendCL @@ -1599,10 +1575,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictEncSize(const acldvppPicDesc *inp * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, - uint32_t dataSize, - acldvppPixelFormat outputPixelFormat, - uint32_t *decSize); +ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, uint32_t dataSize, + acldvppPixelFormat outputPixelFormat, uint32_t *decSize); /** * @ingroup AscendCL @@ -1617,11 +1591,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, - uint32_t dataSize, - uint32_t *width, - uint32_t *height, - int32_t *components); +ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, uint32_t dataSize, uint32_t *width, + uint32_t *height, int32_t *components); /** * @ingroup AscendCL @@ -1635,10 +1606,8 @@ ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppPngPredictDecSize(const void *data, - uint32_t dataSize, - acldvppPixelFormat outputPixelFormat, - uint32_t *decSize); +ACL_FUNC_VISIBILITY aclError acldvppPngPredictDecSize(const void *data, uint32_t dataSize, + acldvppPixelFormat outputPixelFormat, uint32_t *decSize); /** * @ingroup AscendCL @@ -1702,10 +1671,8 @@ ACL_FUNC_VISIBILITY aclError acldvppDestroyChannel(acldvppChannelDesc *channelDe * @see acldvppCreateChannel | acldvppCreatePicDesc * | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - acldvppResizeConfig *resizeConfig, +ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppResizeConfig *resizeConfig, aclrtStream stream); /** @@ -1741,10 +1708,8 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDe * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - acldvppRoiConfig *cropArea, +ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, aclrtStream stream); /** @@ -1781,13 +1746,9 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizeAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - acldvppRoiConfig *cropArea, - acldvppResizeConfig *resizeConfig, - aclrtStream stream); - +ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, + acldvppResizeConfig *resizeConfig, aclrtStream stream); /** * @ingroup AscendCL @@ -1811,12 +1772,9 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizeAsync(acldvppChannelDesc *chann * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, - uint32_t *roiNums, - uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, - acldvppRoiConfig *cropAreas[], - aclrtStream stream); + acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, + uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], aclrtStream stream); /** * @ingroup AscendCL @@ -1841,13 +1799,10 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channe * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateDvppConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, - uint32_t *roiNums, - uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, + acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, + uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], - acldvppResizeConfig *resizeConfig, - aclrtStream stream); + acldvppResizeConfig *resizeConfig, aclrtStream stream); /** * @ingroup AscendCL @@ -1870,12 +1825,9 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeAsync(acldvppChannelDesc * * * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateRoiConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - acldvppRoiConfig *cropArea, - acldvppRoiConfig *pasteArea, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, + acldvppRoiConfig *pasteArea, aclrtStream stream); /** * @ingroup AscendCL @@ -1899,13 +1851,10 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *cha * * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizePasteAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - acldvppRoiConfig *cropArea, +ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizePasteAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, acldvppRoiConfig *pasteArea, - acldvppResizeConfig *resizeConfig, - aclrtStream stream); + acldvppResizeConfig *resizeConfig, aclrtStream stream); /** * @ingroup AscendCL @@ -1930,14 +1879,11 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizePasteAsync(acldvppChannelDesc * * * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig */ - ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, - uint32_t *roiNums, - uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, - acldvppRoiConfig *cropAreas[], - acldvppRoiConfig *pasteAreas[], - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *channelDesc, + acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, + uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + acldvppRoiConfig *pasteAreas[], aclrtStream stream); /** * @ingroup AscendCL @@ -1963,16 +1909,10 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizePasteAsync(acldvppChannelDesc * * * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizePasteAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, - uint32_t *roiNums, - uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, - acldvppRoiConfig *cropAreas[], - acldvppRoiConfig *pasteAreas[], - acldvppResizeConfig *resizeConfig, - aclrtStream stream); - +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizePasteAsync( + acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], acldvppRoiConfig *pasteAreas[], + acldvppResizeConfig *resizeConfig, aclrtStream stream); /** * @ingroup AscendCL @@ -2000,11 +1940,8 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizePasteAsync(acldvppChannelD * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, - const void *data, - uint32_t size, - acldvppPicDesc *outputDesc, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, + acldvppPicDesc *outputDesc, aclrtStream stream); /** * @ingroup AscendCL @@ -2022,11 +1959,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelD * * @see acldvppCreateChannel | acldvppCreateJpegeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - const void *data, - uint32_t *size, - acldvppJpegeConfig *config, +ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + const void *data, uint32_t *size, acldvppJpegeConfig *config, aclrtStream stream); /** @@ -2044,11 +1978,8 @@ ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelD * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppPngDecodeAsync(acldvppChannelDesc *channelDesc, - const void *data, - uint32_t size, - acldvppPicDesc *outputDesc, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppPngDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, + acldvppPicDesc *outputDesc, aclrtStream stream); /** * @ingroup AscendCL @@ -2103,11 +2034,8 @@ ACL_FUNC_VISIBILITY aclError aclvdecDestroyChannel(aclvdecChannelDesc *channelDe * * @see aclvdecCreateChannel | acldvppCreateStreamDesc | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, - acldvppStreamDesc *input, - acldvppPicDesc *output, - aclvdecFrameConfig *config, - void *userData); +ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, acldvppStreamDesc *input, + acldvppPicDesc *output, aclvdecFrameConfig *config, void *userData); /** * @ingroup AscendCL @@ -2126,10 +2054,8 @@ ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, * * @see aclvdecCreateChannel | acldvppCreateStreamDesc | acldvppCreatePicDesc | aclvdecSendFrame */ -ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channelDesc, - acldvppStreamDesc *input, - aclvdecFrameConfig *config, - void *userData); +ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channelDesc, acldvppStreamDesc *input, + aclvdecFrameConfig *config, void *userData); /** * @ingroup AscendCL @@ -2150,10 +2076,8 @@ ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channel * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, aclrtStream stream); /** * @ingroup AscendCL @@ -2175,11 +2099,8 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *cha * * @see acldvppCreateChannel | acldvppCreatePicDesc */ -ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - void *reserve, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, void *reserve, aclrtStream stream); /** * @ingroup AscendCL @@ -2191,8 +2112,7 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelD * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetChannelDescMode(acldvppChannelDesc *channelDesc, - uint32_t mode); +ACL_FUNC_VISIBILITY aclError acldvppSetChannelDescMode(acldvppChannelDesc *channelDesc, uint32_t mode); /** * @ingroup AscendCL @@ -2227,8 +2147,7 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetResizeConfigInterpolation(const acldvppRe * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutMode(aclvdecChannelDesc *channelDesc, - uint32_t outMode); +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutMode(aclvdecChannelDesc *channelDesc, uint32_t outMode); /** * @ingroup AscendCL @@ -2325,9 +2244,7 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetLutMapDims(const acldvppLutMap *lutMap); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, - uint32_t dim, - uint8_t **data, +ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, uint32_t dim, uint8_t **data, uint32_t *len); /** * @ingroup AscendCL @@ -2345,10 +2262,8 @@ ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, * @see acldvppCreateChannel|acldvppCreatePicDesc|acldvppCreateLutMap */ ACL_FUNC_VISIBILITY aclError acldvppVpcEqualizeHistAsync(const acldvppChannelDesc *channelDesc, - const acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - const acldvppLutMap *lutMap, - aclrtStream stream); + const acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, + const acldvppLutMap *lutMap, aclrtStream stream); /** * @ingroup AscendCL @@ -2369,8 +2284,7 @@ ACL_FUNC_VISIBILITY acldvppBorderConfig *acldvppCreateBorderConfig(); * * @retval ACL_SUCCESS for success, other for failure */ -ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigValue(acldvppBorderConfig *borderConfig, - uint32_t index, +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigValue(acldvppBorderConfig *borderConfig, uint32_t index, double value); /** @@ -2515,10 +2429,8 @@ ACL_FUNC_VISIBILITY aclError acldvppDestroyBorderConfig(acldvppBorderConfig *bor * @see acldvppCreateChannel|acldvppCreatePicDesc|acldvppCreateBorderConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcMakeBorderAsync(const acldvppChannelDesc *channelDesc, - const acldvppPicDesc *inputDesc, - acldvppPicDesc *outputDesc, - const acldvppBorderConfig *borderConfig, - aclrtStream stream); + const acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, + const acldvppBorderConfig *borderConfig, aclrtStream stream); /** * @ingroup AscendCL @@ -2535,11 +2447,8 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcMakeBorderAsync(const acldvppChannelDesc * * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateHist */ -ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channelDesc, - acldvppPicDesc *srcPicDesc, - acldvppHist *hist, - void *reserve, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *srcPicDesc, + acldvppHist *hist, void *reserve, aclrtStream stream); /** * @ingroup AscendCL @@ -2548,7 +2457,7 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channel * @retval null for failed. * @retval OtherValues success. */ -ACL_FUNC_VISIBILITY acldvppHist* acldvppCreateHist(); +ACL_FUNC_VISIBILITY acldvppHist *acldvppCreateHist(); /** * @ingroup AscendCL @@ -2605,7 +2514,7 @@ ACL_FUNC_VISIBILITY aclError acldvppGetHistData(acldvppHist *hist, uint32_t dim, * * @see acldvppCreateHist | acldvppVpcCalcHistAsync */ -ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist* hist); +ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist *hist); /** * @ingroup AscendCL @@ -2624,7 +2533,6 @@ ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist* hist); */ ACL_FUNC_VISIBILITY aclError acldvppClearHist(acldvppHist *hist); - /** * @ingroup AscendCL * @brief dvpp vpc batch crop, resize config and make border. @@ -2648,18 +2556,13 @@ ACL_FUNC_VISIBILITY aclError acldvppClearHist(acldvppHist *hist); * * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig */ -ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeMakeBorderAsync(acldvppChannelDesc *channelDesc, - acldvppBatchPicDesc *srcBatchPicDescs, - uint32_t *roiNums, - uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, - acldvppRoiConfig *cropAreas[], - acldvppBorderConfig *borderCfgs[], - acldvppResizeConfig *resizeConfig, - aclrtStream stream); +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeMakeBorderAsync( + acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], acldvppBorderConfig *borderCfgs[], + acldvppResizeConfig *resizeConfig, aclrtStream stream); #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ diff --git a/inc/external/acl/ops/acl_fv.h b/inc/external/acl/ops/acl_fv.h index 40cd50cb..4bd392c9 100644 --- a/inc/external/acl/ops/acl_fv.h +++ b/inc/external/acl/ops/acl_fv.h @@ -32,8 +32,8 @@ typedef struct aclfvSearchResult aclfvSearchResult; // search operation type enum aclfvSearchType { - SEARCH_1_N, // 1:N operation type - SEARCH_N_M // N:M operation type + SEARCH_1_N, // 1:N operation type + SEARCH_N_M // N:M operation type }; /** @@ -104,7 +104,8 @@ ACL_FUNC_VISIBILITY aclError aclfvSetNMTopNum(aclfvInitPara *initPara, uint32_t * @retval OtherValues success. */ ACL_FUNC_VISIBILITY aclfvFeatureInfo *aclfvCreateFeatureInfo(uint32_t id0, uint32_t id1, uint32_t offset, - uint32_t featureLen, uint32_t featureCount, uint8_t *featureData, uint32_t featureDataLen); + uint32_t featureLen, uint32_t featureCount, + uint8_t *featureData, uint32_t featureDataLen); /** * @ingroup AscendCL @@ -233,8 +234,9 @@ ACL_FUNC_VISIBILITY aclError aclfvDestroySearchInput(aclfvSearchInput *searchInp * @retval null for failed. OtherValues success */ ACL_FUNC_VISIBILITY aclfvSearchResult *aclfvCreateSearchResult(uint32_t queryCnt, uint32_t *resultNum, - uint32_t resultNumDataLen, uint32_t *id0, uint32_t *id1, uint32_t *resultOffset, float *resultDistance, - uint32_t dataLen); + uint32_t resultNumDataLen, uint32_t *id0, uint32_t *id1, + uint32_t *resultOffset, float *resultDistance, + uint32_t dataLen); /** * @ingroup AscendCL @@ -285,12 +287,11 @@ ACL_FUNC_VISIBILITY aclError aclfvRelease(); * * @param type [IN] repo add type * @param featureInfo [IN] add feature information - * @param stream [IN] stream of task execute * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure. */ -ACL_FUNC_VISIBILITY aclError aclfvRepoAdd(aclfvSearchType type, aclfvFeatureInfo *featureInfo, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclfvRepoAdd(aclfvSearchType type, aclfvFeatureInfo *featureInfo); /** * @ingroup AscendCL @@ -298,36 +299,33 @@ ACL_FUNC_VISIBILITY aclError aclfvRepoAdd(aclfvSearchType type, aclfvFeatureInfo * * @param type [IN] repo delete type * @param repoRange [IN] repo range information - * @param stream [IN] stream of task execute * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure. */ -ACL_FUNC_VISIBILITY aclError aclfvRepoDel(aclfvSearchType type, aclfvRepoRange *repoRange, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclfvRepoDel(aclfvSearchType type, aclfvRepoRange *repoRange); /** * @ingroup AscendCL * @brief fv accurate del. * * @param featureInfo [IN] accurate delete feature information - * @param stream [IN] stream of task execute * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure. */ -ACL_FUNC_VISIBILITY aclError aclfvDel(aclfvFeatureInfo *featureInfo, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclfvDel(aclfvFeatureInfo *featureInfo); /** * @ingroup AscendCL * @brief fv accurate modify. * * @param featureInfo [IN] accurate modify feature information - * @param stream [IN] stream of task execute * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure. */ -ACL_FUNC_VISIBILITY aclError aclfvModify(aclfvFeatureInfo *featureInfo, aclrtStream stream); +ACL_FUNC_VISIBILITY aclError aclfvModify(aclfvFeatureInfo *featureInfo); /** * @ingroup AscendCL @@ -336,16 +334,15 @@ ACL_FUNC_VISIBILITY aclError aclfvModify(aclfvFeatureInfo *featureInfo, aclrtStr * @param type [IN] search type * @param searchInput [IN] search input * @param searchRst [OUT] search result - * @param stream [IN] stream of task execute * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure. */ ACL_FUNC_VISIBILITY aclError aclfvSearch(aclfvSearchType type, aclfvSearchInput *searchInput, - aclfvSearchResult *searchRst, aclrtStream stream); + aclfvSearchResult *searchRst); #ifdef __cplusplus } #endif -#endif // INC_EXTERNAL_ACL_OPS_ACL_RETR_H_ +#endif // INC_EXTERNAL_ACL_OPS_ACL_RETR_H_ diff --git a/inc/external/hccl/hccl.h b/inc/external/hccl/hccl.h index 969d855a..8261adc4 100644 --- a/inc/external/hccl/hccl.h +++ b/inc/external/hccl/hccl.h @@ -27,7 +27,7 @@ #ifdef __cplusplus extern "C" { -#endif // __cplusplus +#endif // __cplusplus /** * @brief Initialize HCCL. @@ -66,14 +66,15 @@ extern HcclResult HcclCommInitRootInfo(uint32_t nRanks, const HcclRootInfo *root * @param sendBuf A pointer identifying the input data address of the operator. * @param recvBuf A pointer identifying the output data address of the operator. * @param count An integer(u64) identifying the number of the output data. - * @param dataType The data type of the operator, must be one of the following types: int8, int16, int32, float16, float32. + * @param dataType The data type of the operator, must be one of the following types: int8, int16, int32, float16, + * float32. * @param op The reduction type of the operator, must be one of the following types: sum, min, max, prod. * @param comm A pointer identifying the communication resource based on. * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclAllReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType, -HcclReduceOp op, HcclComm comm, aclrtStream stream); +extern HcclResult HcclAllReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType, HcclReduceOp op, + HcclComm comm, aclrtStream stream); /** * @brief Broadcast operator. @@ -84,10 +85,10 @@ HcclReduceOp op, HcclComm comm, aclrtStream stream); * @param root An integer(u32) identifying the the root rank in the operator. * @param comm A pointer identifying the communication resource based on * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclBroadcast(void *buf, uint64_t count, HcclDataType dataType, uint32_t root, HcclComm comm, -aclrtStream stream); +extern HcclResult HcclBroadcast(void *buf, uint64_t count, HcclDataType dataType, uint32_t root, HcclComm comm, + aclrtStream stream); /** * @brief ReduceScatter operator. @@ -99,10 +100,10 @@ aclrtStream stream); * @param op The reduction type of the operator, must be one of the following types: sum, min, max, prod. * @param comm A pointer identifying the communication resource based on. * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclReduceScatter(void *sendBuf, void *recvBuf, uint64_t recvCount, HcclDataType dataType, -HcclReduceOp op, HcclComm comm, aclrtStream stream); +extern HcclResult HcclReduceScatter(void *sendBuf, void *recvBuf, uint64_t recvCount, HcclDataType dataType, + HcclReduceOp op, HcclComm comm, aclrtStream stream); /** * @brief AllGather operator. @@ -113,16 +114,16 @@ HcclReduceOp op, HcclComm comm, aclrtStream stream); * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. * @param comm A pointer identifying the communication resource based on. * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ -extern HcclResult HcclAllGather(void *sendBuf, void *recvBuf, uint64_t sendCount, HcclDataType dataType, -HcclComm comm, aclrtStream stream); +extern HcclResult HcclAllGather(void *sendBuf, void *recvBuf, uint64_t sendCount, HcclDataType dataType, HcclComm comm, + aclrtStream stream); /** * @brief Get the rank size of this comm. * * @param comm A pointer identifying the communication resource based on. * @param rankSize A pointer identifying the rank size. - * @return HcclResult + * @return HcclResult */ extern HcclResult HcclGetRankSize(HcclComm comm, uint32_t *rankSize); @@ -131,7 +132,7 @@ extern HcclResult HcclGetRankSize(HcclComm comm, uint32_t *rankSize); * * @param comm A pointer identifying the communication resource based on. * @param rankSize A pointer identifying the rank id. - * @return HcclResult + * @return HcclResult */ extern HcclResult HcclGetRankId(HcclComm comm, uint32_t *rank); /** @@ -139,7 +140,7 @@ extern HcclResult HcclGetRankId(HcclComm comm, uint32_t *rank); * * @param comm A pointer identifying the communication resource based on. * @param stream A pointer identifying the stream information. - * @return HcclResult + * @return HcclResult */ extern HcclResult HcclBarrier(HcclComm comm, aclrtStream stream); @@ -154,5 +155,5 @@ extern HcclResult HcclCommDestroy(HcclComm comm); #ifdef __cplusplus } -#endif // __cplusplus -#endif // HCCL_H_ +#endif // __cplusplus +#endif // HCCL_H_ diff --git a/inc/external/hccl/hccl_types.h b/inc/external/hccl/hccl_types.h index 50a64795..0e832396 100644 --- a/inc/external/hccl/hccl_types.h +++ b/inc/external/hccl/hccl_types.h @@ -16,10 +16,10 @@ /** * @file hccl_types.h - * @brief HCCL data type definition - * + * @brief HCCL data type definition + * */ - + #ifndef HCCL_TYPES_H_ #define HCCL_TYPES_H_ @@ -27,33 +27,33 @@ #ifdef __cplusplus extern "C" { -#endif // __cplusplus +#endif // __cplusplus /** * @brief HCCL functions return value definition */ typedef enum { - HCCL_SUCCESS = 0, /**< success */ - HCCL_E_PARA = 1, /**< parameter error */ - HCCL_E_PTR = 2, /**< empty pointer */ - HCCL_E_MEMORY = 3, /**< memory error */ - HCCL_E_INTERNAL = 4, /**< internal error */ - HCCL_E_NOT_SUPPORT = 5, /**< not support feature */ - HCCL_E_NOT_FOUND = 6, /**< not found specific resource */ - HCCL_E_UNAVAIL = 7, /**< resource unavailable */ - HCCL_E_SYSCALL = 8, /**< call system interface error */ - HCCL_E_TIMEOUT = 9, /**< timeout */ - HCCL_E_OPEN_FILE_FAILURE = 10, /**< open file fail */ - HCCL_E_TCP_CONNECT = 11, /**< tcp connect fail */ - HCCL_E_ROCE_CONNECT = 12, /**< roce connect fail */ - HCCL_E_TCP_TRANSFER = 13, /**< tcp transfer fail */ - HCCL_E_ROCE_TRANSFER = 14, /**< roce transfer fail */ - HCCL_E_RUNTIME = 15, /**< call runtime api fail */ - HCCL_E_DRV = 16, /**< call driver api fail */ - HCCL_E_PROFILING = 17, /**< call profiling api fail */ - HCCL_E_CCE = 18, /**< call cce api fail */ - HCCL_E_NETWORK = 19, /**< call network api fail */ - HCCL_E_RESERVED /**< reserved */ + HCCL_SUCCESS = 0, /**< success */ + HCCL_E_PARA = 1, /**< parameter error */ + HCCL_E_PTR = 2, /**< empty pointer */ + HCCL_E_MEMORY = 3, /**< memory error */ + HCCL_E_INTERNAL = 4, /**< internal error */ + HCCL_E_NOT_SUPPORT = 5, /**< not support feature */ + HCCL_E_NOT_FOUND = 6, /**< not found specific resource */ + HCCL_E_UNAVAIL = 7, /**< resource unavailable */ + HCCL_E_SYSCALL = 8, /**< call system interface error */ + HCCL_E_TIMEOUT = 9, /**< timeout */ + HCCL_E_OPEN_FILE_FAILURE = 10, /**< open file fail */ + HCCL_E_TCP_CONNECT = 11, /**< tcp connect fail */ + HCCL_E_ROCE_CONNECT = 12, /**< roce connect fail */ + HCCL_E_TCP_TRANSFER = 13, /**< tcp transfer fail */ + HCCL_E_ROCE_TRANSFER = 14, /**< roce transfer fail */ + HCCL_E_RUNTIME = 15, /**< call runtime api fail */ + HCCL_E_DRV = 16, /**< call driver api fail */ + HCCL_E_PROFILING = 17, /**< call profiling api fail */ + HCCL_E_CCE = 18, /**< call cce api fail */ + HCCL_E_NETWORK = 19, /**< call network api fail */ + HCCL_E_RESERVED /**< reserved */ } HcclResult; /** @@ -65,37 +65,37 @@ typedef void *HcclComm; * @brief HCCL Reduction opperation */ typedef enum { - HCCL_REDUCE_SUM = 0, /**< sum */ - HCCL_REDUCE_PROD = 1, /**< prod */ - HCCL_REDUCE_MAX = 2, /**< max */ - HCCL_REDUCE_MIN = 3, /**< min */ - HCCL_REDUCE_RESERVED /**< reserved */ + HCCL_REDUCE_SUM = 0, /**< sum */ + HCCL_REDUCE_PROD = 1, /**< prod */ + HCCL_REDUCE_MAX = 2, /**< max */ + HCCL_REDUCE_MIN = 3, /**< min */ + HCCL_REDUCE_RESERVED /**< reserved */ } HcclReduceOp; /** * @brief HCCL data type */ typedef enum { - HCCL_DATA_TYPE_INT8 = 0, /**< int8 */ - HCCL_DATA_TYPE_INT16 = 1, /**< int16 */ - HCCL_DATA_TYPE_INT32 = 2, /**< int32 */ - HCCL_DATA_TYPE_FP16 = 3, /**< fp16 */ - HCCL_DATA_TYPE_FP32 = 4, /**< fp32 */ - HCCL_DATA_TYPE_INT64 = 5, /**< int64 */ - HCCL_DATA_TYPE_UINT64 = 6, /**< uint64 */ - HCCL_DATA_TYPE_RESERVED /**< reserved */ + HCCL_DATA_TYPE_INT8 = 0, /**< int8 */ + HCCL_DATA_TYPE_INT16 = 1, /**< int16 */ + HCCL_DATA_TYPE_INT32 = 2, /**< int32 */ + HCCL_DATA_TYPE_FP16 = 3, /**< fp16 */ + HCCL_DATA_TYPE_FP32 = 4, /**< fp32 */ + HCCL_DATA_TYPE_INT64 = 5, /**< int64 */ + HCCL_DATA_TYPE_UINT64 = 6, /**< uint64 */ + HCCL_DATA_TYPE_RESERVED /**< reserved */ } HcclDataType; -const uint32_t HCCL_ROOT_INFO_BYTES = 4108; // 4108: root info length +const uint32_t HCCL_ROOT_INFO_BYTES = 4108; // 4108: root info length /** * @brief HCCL root info */ typedef struct HcclRootInfoDef { - char internal[HCCL_ROOT_INFO_BYTES]; + char internal[HCCL_ROOT_INFO_BYTES]; } HcclRootInfo; #ifdef __cplusplus } -#endif // __cplusplus -#endif // HCCL_TYPES_H_ +#endif // __cplusplus +#endif // HCCL_TYPES_H_ diff --git a/inc/external/runtime/rt_error_codes.h b/inc/external/runtime/rt_error_codes.h index c9a40432..a1392cc6 100644 --- a/inc/external/runtime/rt_error_codes.h +++ b/inc/external/runtime/rt_error_codes.h @@ -23,84 +23,87 @@ extern "C" { #endif -static const int32_t ACL_RT_SUCCESS = 0; // success +static const int32_t ACL_RT_SUCCESS = 0; // success -static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid -static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id -static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null -static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context -static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context -static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal -static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned -static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed -static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed -static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream -static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread -static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set -static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create -static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream -static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type -static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle -static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type +static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid +static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id +static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null +static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context +static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context +static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal +static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned +static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed +static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed +static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream +static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread +static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set +static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create +static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream +static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type +static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle +static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type +static const int32_t ACL_ERROR_RT_WAIT_TIMEOUT = 107019; // wait timeout -static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support -static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error -static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error -static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow -static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device -static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail -static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission -static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource -static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource -static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource -static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource +static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support +static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error +static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error +static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow +static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device +static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail +static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission +static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource +static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource +static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource +static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource +static const int32_t ACL_ERROR_RT_NO_CDQ_RESOURCE = 207011; // no cdq resource -static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error -static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout -static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception -static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout +static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception +static const int32_t ACL_ERROR_RT_CDQ_BATCH_ABNORMAL = 507037; // cdq alloc batch abnormal -static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error -static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error -static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect +static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error +static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error +static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect #ifdef __cplusplus } #endif -#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ +#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/scripts/format_source_code.sh b/scripts/format_source_code.sh new file mode 100755 index 00000000..1fd0b4f6 --- /dev/null +++ b/scripts/format_source_code.sh @@ -0,0 +1,107 @@ +#!/bin/bash +# Copyright 2019-2020 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. +# ============================================================================ + +set -e + +CLANG_FORMAT=$(which clang-format) || (echo "Please install 'clang-format' tool first"; exit 1) + +version=$("${CLANG_FORMAT}" --version | sed -n "s/.*\ \([0-9]*\)\.[0-9]*\.[0-9]*.*/\1/p") +if [[ "${version}" -lt "8" ]]; then + echo "clang-format's version must be at least 8.0.0" + exit 1 +fi + +CURRENT_PATH=$(pwd) +SCRIPTS_PATH=$(dirname "$0") + +echo "CURRENT_PATH=${CURRENT_PATH}" +echo "SCRIPTS_PATH=${SCRIPTS_PATH}" + +# print usage message +function usage() +{ + echo "Format the specified source files to conform the code style." + echo "Usage:" + echo "bash $0 [-a] [-c] [-l] [-h]" + echo "e.g. $0 -c" + echo "" + echo "Options:" + echo " -a format of all files" + echo " -c format of the files changed compared to last commit, default case" + echo " -l format of the files changed in last commit" + echo " -h Print usage" +} + +# check and set options +function checkopts() +{ + # init variable + mode="changed" # default format changed files + + # Process the options + while getopts 'aclh' opt + do + case "${opt}" in + a) + mode="all" + ;; + c) + mode="changed" + ;; + l) + mode="lastcommit" + ;; + h) + usage + exit 0 + ;; + *) + echo "Unknown option ${opt}!" + usage + exit 1 + esac + done +} + +# init variable +# check options +checkopts "$@" + +# switch to project root path, which contains clang-format config file '.clang-format' +cd "${SCRIPTS_PATH}/.." || exit 1 + +FMT_FILE_LIST='__format_files_list__' + +if [[ "X${mode}" == "Xall" ]]; then + find src -type f -name "*" | grep "\.h$\|\.cc$" > "${FMT_FILE_LIST}" || true + find inc -type f -name "*" | grep "\.h$\|\.cc$" >> "${FMT_FILE_LIST}" || true +elif [[ "X${mode}" == "Xchanged" ]]; then + # --diff-filter=ACMRTUXB will ignore deleted files in commit + git diff --diff-filter=ACMRTUXB --name-only | grep "^inc\|^src" | grep "\.h$\|\.cc$" >> "${FMT_FILE_LIST}" || true +else # "X${mode}" == "Xlastcommit" + git diff --diff-filter=ACMRTUXB --name-only HEAD~ HEAD | grep "^inc\|^src" | grep "\.h$\|\.cc$" > "${FMT_FILE_LIST}" || true +fi + +while read line; do + if [ -f "${line}" ]; then + ${CLANG_FORMAT} -i "${line}" + fi +done < "${FMT_FILE_LIST}" + +rm "${FMT_FILE_LIST}" +cd "${CURRENT_PATH}" || exit 1 + +echo "Specified cpp source files have been format successfully." diff --git a/third_party/fwkacllib/inc/cce/taskdown_common.hpp b/third_party/fwkacllib/inc/cce/taskdown_common.hpp index 3ecea523..7954162e 100644 --- a/third_party/fwkacllib/inc/cce/taskdown_common.hpp +++ b/third_party/fwkacllib/inc/cce/taskdown_common.hpp @@ -27,15 +27,16 @@ namespace cce { #define CC_FUSION_OP_MAX 32 typedef enum tagccKernelType { - CCE_AI_CORE = 0, /* cce aicore */ - CCE_AI_CPU = 1, /* cce aicpu */ - TE = 2, /* te operator*/ - CUSTOMIZED = 3, /* customized operator */ - TE_AI_CORE = 4, /* te aicore operator*/ - TE_AI_CPU = 5, /* te aicpu operator */ - AI_CPU = 6, /* aicpu */ - CUST_AI_CPU = 7, /* custom aicpu*/ - INVALID = 8, /* unknown kernel type */ + CCE_AI_CORE = 0, /* cce aicore */ + CCE_AI_CPU = 1, /* cce aicpu */ + TE = 2, /* te operator*/ + CUSTOMIZED = 3, /* customized operator */ + TE_AI_CORE = 4, /* te aicore operator*/ + TE_AI_CPU = 5, /* te aicpu operator */ + AI_CPU = 6, /* aicpu */ + CUST_AI_CPU = 7, /* custom aicpu*/ + HOST_CPU = 8, /* host cpu */ + INVALID = 10000 /* unknown kernel type */ } ccKernelType; typedef struct tagOpContext { diff --git a/third_party/fwkacllib/inc/hccl/base.h b/third_party/fwkacllib/inc/hccl/base.h index e57563b3..ffbf552b 100644 --- a/third_party/fwkacllib/inc/hccl/base.h +++ b/third_party/fwkacllib/inc/hccl/base.h @@ -124,27 +124,27 @@ struct HcomRemoteAccessAddrInfo { }; struct HcomAllToAllVParams { - void *sendbuf; - void *sendcounts; - void *sdispls; - HcclDataType sendtype; - void *recvbuf; - void *recvcounts; - void *rdispls; - HcclDataType recvtype; - const char *group; + void *sendbuf; // device mem + void *sendcounts; // device mem; Type: uint_64 + void *sdispls; // device mem; Type: uint_64 + HcclDataType sendtype; + void *recvbuf; // device mem + void *recvcounts; // device mem; Type: uint_64 + void *rdispls; // device mem; Type: uint_64 + HcclDataType recvtype; + const char *group; // not used now }; struct HcomGatherAllToAllVParams { - void *addrInfo; - void *addrInfoCountPerRank; - void *recvbuf; - void *recvcounts; - void *rdispls; - void *gatheredbuf; - s32 addrLength; - HcclDataType recvtype; - const char *group; + void *addrInfo; // device mem; contains host VA[uint_64]: [addr, length, addr, length, addr, length, ...] + void *addrInfoCountPerRank; // device mem; length: ranksize; contains addrInfoCounts for every rank + void *recvbuf; // device mem + void *recvcounts; // device mem; Type: uint_64 + void *rdispls; // device mem; Type: uint_64 + void *gatheredbuf; // device mem + s32 addrLength; + HcclDataType recvtype; + const char *group; // not used now }; #ifdef __cplusplus diff --git a/third_party/fwkacllib/inc/hccl/hcom.h b/third_party/fwkacllib/inc/hccl/hcom.h index 955764d6..bf1f395b 100644 --- a/third_party/fwkacllib/inc/hccl/hcom.h +++ b/third_party/fwkacllib/inc/hccl/hcom.h @@ -164,8 +164,22 @@ HcclResult HcomExecEnqueueRemoteAccess(const std::string& remoteAccessType, const std::vector& addrInfos, std::function callback); +/** + * @brief Put alltoallv communication operation into hcom executor. + * + * @param params information about alltoallv communication operation. + * @param callback callback after collective communication operation. + * @return HcclResult + */ HcclResult HcomExecEnqueueAllToAllV(HcomAllToAllVParams params, std::function callback); +/** + * @brief Put agther alltoallv communication operation into hcom executor. + * + * @param params information about agther alltoallv communication operation. + * @param callback callback after collective communication operation. + * @return HcclResult + */ HcclResult HcomExecEnqueueGatherAllToAllV(HcomGatherAllToAllVParams params, std::function callback); diff --git a/third_party/fwkacllib/inc/ops/array_ops.h b/third_party/fwkacllib/inc/ops/array_ops.h index b5f49dad..fd35b546 100644 --- a/third_party/fwkacllib/inc/ops/array_ops.h +++ b/third_party/fwkacllib/inc/ops/array_ops.h @@ -626,7 +626,7 @@ REG_OP(StopGradient) *x: A tensor. \n *@par Outputs: -*y: A tensor. \n +*y: A tensor with the same shape and contents as input. \n *@par Third-party framework compatibility *Compatible with the TensorFlow operator Identity. @@ -666,7 +666,7 @@ REG_OP(IdentityN) *@li axis: The dimension index at which to expand. \n *@par Outputs: -*y: A tensor. \n +*y: A tensor with the same data as input, with an additional dimension inserted at the index specified by axis. \n *@par Third-party framework compatibility *Compatible with the TensorFlow operator ExpandDims. @@ -713,7 +713,7 @@ REG_OP(Unsqueeze) *@par Outputs: *y: A tensor. \n -*@par Attention: +*@attention Constraints: *This operator cannot be directly called by the acllopExecute API. \n *@par Third-party framework compatibility diff --git a/third_party/fwkacllib/inc/ops/bitwise_ops.h b/third_party/fwkacllib/inc/ops/bitwise_ops.h index 39a28cf3..dac78118 100644 --- a/third_party/fwkacllib/inc/ops/bitwise_ops.h +++ b/third_party/fwkacllib/inc/ops/bitwise_ops.h @@ -25,6 +25,35 @@ namespace ge { +/** +*@brief Element-wise computes the bitwise left-shift of x and y . \n + +*@par Inputs: +*Input "x" is a k-dimensional tensor. Inputs "num_lower" and "num_upper" +are 0D scalars. +* @li x: A Tensor. Must be one of the following types: int8, int16, int32, +int64, uint8, uint16, uint32, uint64. +* @li y: A Tensor. Has the same type as "x". \n + +*@par Outputs: +* z: A Tensor. Has the same type as "x". \n + +*@attention Constraints: +*Unique runs on the Ascend AI CPU, which delivers poor performance. \n + +*@par Third-party framework compatibility +*Compatible with the TensorFlow operator LeftShift. +*/ + +REG_OP(LeftShift) + .INPUT(x, TensorType({DT_INT8, DT_INT16, DT_INT32, DT_INT64, \ + DT_UINT8, DT_UINT16, DT_UINT32, DT_UINT64})) + .INPUT(y, TensorType({DT_INT8, DT_INT16, DT_INT32, DT_INT64, \ + DT_UINT8, DT_UINT16, DT_UINT32, DT_UINT64})) + .OUTPUT(z, TensorType({DT_INT8, DT_INT16, DT_INT32, DT_INT64, \ + DT_UINT8, DT_UINT16, DT_UINT32, DT_UINT64})) + .OP_END_FACTORY_REG(LeftShift) + /** *@brief Element-wise computes the bitwise right-shift of x and y . \n diff --git a/third_party/fwkacllib/inc/ops/control_flow_ops.h b/third_party/fwkacllib/inc/ops/control_flow_ops.h index 9a0e0cd5..e5bd3534 100644 --- a/third_party/fwkacllib/inc/ops/control_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/control_flow_ops.h @@ -96,7 +96,7 @@ REG_OP(RefMerge) * Otherwise, the data is forwarded to "output_false" . \n *@par Inputs: - *@li data: The tensor to be forwarded. \ n + *@li data: The tensor to be forwarded. \n * Must be one of the following types: float16, float32, float64, * int8, int16, int32, int64, uint8, uint16, uint32, uint64, bool. *@li pred: A boolean scalar. The output port that will receive data . \n diff --git a/third_party/fwkacllib/inc/ops/data_flow_ops.h b/third_party/fwkacllib/inc/ops/data_flow_ops.h index 05de1b0a..6021f4e3 100644 --- a/third_party/fwkacllib/inc/ops/data_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/data_flow_ops.h @@ -2340,9 +2340,9 @@ REG_OP(CacheAllIndexToLocal) *@par Attributes: *output_types: types of all outputs *output_shapes: shapes of all outputs -*_dynamic_graph_execute_mode: dynamic graph execution mode, +*_dynamic_graph_execute_mode: dynamic graph execution mode, value is one of lazy_recompile and dynamic_execute -*_getnext_inputs_shape_range: shape ranges of outputs, +*_getnext_inputs_shape_range: shape ranges of outputs, it works where _dynamic_graph_execute_mode is dynamic_execute *@par Restrictions: *Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. @@ -2355,6 +2355,24 @@ REG_OP(DynamicGetNext) .ATTR(_dynamic_graph_execute_mode, String, "lazy_recompile") .ATTR(_getnext_inputs_shape_range, String, "") .OP_END_FACTORY_REG(DynamicGetNext) + +/** +*@brief AdpGetNext +*@par Outputs: +*y: the data in iterator, all types are available +*@par Attributes: +*output_types: types of all outputs +*output_shapes: shapes of all outputs +*queue_name: cdqm queue name +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(AdpGetNext) + .DYNAMIC_OUTPUT(y, TensorType::ALL()) + .ATTR(output_types, ListType, {}) + .ATTR(output_shapes, ListListInt, {{}, {}}) + .ATTR(queue_name, String, "") + .OP_END_FACTORY_REG(AdpGetNext) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_DATA_FLOW_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index c8df447d..f61e2939 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -3250,7 +3250,7 @@ REG_OP(Fills) *value: A scale. Must be float. \n *@par Outputs: -*@li y: A Tensor. Has the same type and shape as "x1". \n +*y: A Tensor. Has the same type and shape as "x1". \n *@par Third-party framework compatibility: * Compatible with the Pytorch operator adds. diff --git a/third_party/fwkacllib/inc/ops/hcom_ops.h b/third_party/fwkacllib/inc/ops/hcom_ops.h index f4ded0cd..497f6a68 100644 --- a/third_party/fwkacllib/inc/ops/hcom_ops.h +++ b/third_party/fwkacllib/inc/ops/hcom_ops.h @@ -280,5 +280,77 @@ REG_OP(HcomRemoteScatterWrite) .OPTIONAL_INPUT(local_offset, TensorType({DT_UINT64})) .OP_END_FACTORY_REG(HcomRemoteScatterWrite) +/** + * @brief All ranks send different amount of data to, and receive different + amount of data from, all ranks. + * @par Inputs: + * Five inputs, including: + * @li send_data: A tensor. the memory to send. + * @li send_counts: A list, where entry i specifies the number of elements in + send_data to send to rank i. + * @li send_displacements: A list, where entry i specifies the displacement + (offset from sendbuf) from which to send data to rank i. + * @li recv_counts: A list, where entry i specifies the number of + elements to receive from rank i. + * @li recv_displacements: A list, , where entry i specifies the displacement + (offset from recv_data) to which data from rank i should be written. + * @par Outputs: + * recv_data: A Tensor has same element type as send_data. + * @par Attributes: + * @li group: A string identifying the group name of ranks participating in + the op. +* @attention all ranks participating in the op should be full-mesh networking + using the RDMA. + */ +REG_OP(HcomAllToAllV) + .INPUT(send_data, TensorType({DT_FLOAT, DT_INT32, DT_INT8, DT_INT16, DT_FLOAT16, DT_INT64, DT_UINT64})) + .INPUT(send_counts, TensorType({DT_INT64})) + .INPUT(send_displacements, TensorType({DT_INT64})) + .INPUT(recv_counts, TensorType({DT_INT64})) + .INPUT(recv_displacements, TensorType({DT_INT64})) + .OUTPUT(recv_data, TensorType({DT_FLOAT, DT_INT32, DT_INT8, DT_INT16, DT_FLOAT16, DT_INT64, DT_UINT64})) + .REQUIRED_ATTR(group, String) + .OP_END_FACTORY_REG(HcomAllToAllV) + +/** + * @brief All ranks send different amount of data to, and receive different + amount of data from, all ranks. And concat all data descripting by addrinfo + togather into output gathered. + * @par Inputs: + * Four inputs, including: + * @li addrinfo: A tensor, descripting the memory info(address, length) to send. + * @li addrinfo_count_per_rank: A list, where entry i specifies the number of + elements in send_data to send to rank i. + * @li recv_counts: A list, where entry i specifies the number of + elements to receive from rank i. + * @li recv_displacements: A list, , where entry i specifies the displacement + (offset from recv_data) to which data from rank i should be written. + * @par Outputs: + * Two outputs, including: + * @li recv_data: A Tensor has same element type as dtype. + * @li gathered: A Tensor has same element type as dtype. + * @par Attributes: + * @li group: A string identifying the group name of ranks participating in + the op. + * @li dtype: Datatype of send buffer elements. + * @li addr_length: descripting the element memory length in the addrinfo. + -2: all element memory length in the addrinfo is the same, but it is unknown. + -1: all element memory length is unknown. + >0: all element memory length in the addrinfo is the same. the attr value is the memory length. + * @attention all ranks participating in the op should be full-mesh networking + using the RDMA. + */ +REG_OP(HcomGatherAllToAllV) + .INPUT(addrinfo, TensorType({DT_UINT64})) + .INPUT(addrinfo_count_per_rank, TensorType({DT_INT64})) + .INPUT(recv_counts, TensorType({DT_INT64})) + .INPUT(recv_displacements, TensorType({DT_INT64})) + .OUTPUT(recv_data, TensorType({DT_FLOAT, DT_INT32, DT_INT8, DT_INT16, DT_FLOAT16, DT_INT64, DT_UINT64})) + .OUTPUT(gathered, TensorType({DT_FLOAT, DT_INT32, DT_INT8, DT_INT16, DT_FLOAT16, DT_INT64, DT_UINT64})) + .REQUIRED_ATTR(group, String) + .REQUIRED_ATTR(dtype, Type) + .REQUIRED_ATTR(addr_length, Int) + .OP_END_FACTORY_REG(HcomGatherAllToAllV) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_HCOM_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/math_ops.h b/third_party/fwkacllib/inc/ops/math_ops.h index 8f11ab0f..319bcf70 100644 --- a/third_party/fwkacllib/inc/ops/math_ops.h +++ b/third_party/fwkacllib/inc/ops/math_ops.h @@ -1005,6 +1005,32 @@ REG_OP(SoftMarginLossGrad) .ATTR(reduction, String, "mean") .OP_END_FACTORY_REG(SoftMarginLossGrad) +/** +*@brief Calculate the cross product of two tensors. \n + +*@par Inputs: +*One inputs, including: +* @li x1: A tensor. Must be one of the following types: +* float16, float32, int32, int8, uint8, int16. \n +* @li x2: A tensor. Must be one of the following types: +* float16, float32, int32, int8, uint8, int16. \n + +*@par Attributes: +*@li dim: the dimination of compute.Defaults to -65530. \n + +*@par Outputs: +*y: A Tensor with the same type and shape of x1's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator cross. \n +*/ +REG_OP(Cross) + .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8, DT_INT16})) + .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8, DT_INT16})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8, DT_INT16})) + .ATTR(dim, Int, -65530) + .OP_END_FACTORY_REG(Cross) + /** *@brief Computes batched the p-norm distance between each pair of *the two collections of row vectors. \n diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index c6718c7c..b44c0780 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -336,6 +336,41 @@ REG_OP(SoftmaxV2) .ATTR(axes, ListInt, {-1}) .OP_END_FACTORY_REG(SoftmaxV2) +/** +*@brief Function softmax with dropoutDoMaskV3D + +*@par Inputs: +*Two inputs, including: +* @li x: A mutable Tensor. The type only support float16. +* @li mask: A mutable Tensor. Must met all of the following rules: +* shape of mask should be 1D. +* dtype of mask should be uint8. +* value of shape should met the following algorithm: +* value = (size(x) + 128 - 1) // 128 * 128 + +*@par Attributes: +* @li keep_prob: A mutable Tensor. Must met all of the following rules: +* shape of "keep_prob" should be (1,) or [1,]. +* Has the same type as "x" . \n +* @li axes: A list of int. The dimension softmax would be performed on. Defaults +* to "[-1]" . \n + +*@par Outputs: +*y1: A mutable Tensor. Has the same type as "x". +*y2: A mutable Tensor. Has the same type as "x". \n + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(SoftmaxV2WithDropOutDoMaskV3D) + .INPUT(x, TensorType({DT_FLOAT16})) + .INPUT(mask, TensorType({DT_UINT8})) + .OUTPUT(y1, TensorType({DT_FLOAT16})) + .OUTPUT(y2, TensorType({DT_FLOAT16})) + .REQUIRED_ATTR(keep_prob, Float) + .ATTR(axes, ListInt, {-1}) + .OP_END_FACTORY_REG(SoftmaxV2WithDropOutDoMaskV3D) + /** *@brief Computes log softmax activations . \n @@ -1150,22 +1185,23 @@ REG_OP(INInferV2D) .OP_END_FACTORY_REG(INInferV2D) /** -* @brief perform instance normalization to x. \n +* @brief InstanceNorm operator interface implementation. * @par Inputs: * Three inputs, including: -* @li x: A Tensor. Must be one of the following types: float16, float32, format is NC1HWC0. -* @li gamma: A Tensor. Must be one of the following types: float16, float32, format is ND. -* @li beta: A Tensor. Must be one of the following types: float16, float32, format is ND. +* @li x: A Tensor. Must be one of the following types: float16, float32. +* @li gamma: A Tensor. Must be one of the following types: float16, float32. +* @li beta: A Tensor. Must be one of the following types: float16, float32. * @par Attributes: * @li data_format: An attribute of type String \n -* @li epsilon: An attribute of type Float, . \n +* @li epsilon: An attribute of type Float. \n * @par Outputs: -* @li y: A Tensor. Has the same type as "x", format is NC1HWC0. \n -* @li mean: A Tensor. Has the same type as "x", format is NC1HWC0 and the shape is [N, C1, 1, 1, C0]. \n -* @li variance: A Tensor. Has the same type as "x", format is NC1HWC0 and the shape is [N, C1, 1, 1, C0]. \n +*Three outputs, including: +* @li y: A Tensor. Has the same type as "x". \n +* @li mean: A Tensor. Has the same type as "x". \n +* @li variance: A Tensor. Has the same type as "x". \n * @par Third-party framework compatibility * Can be used by onnx InstanceNormalization @@ -1177,10 +1213,93 @@ REG_OP(InstanceNorm) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(mean, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(variance, TensorType({DT_FLOAT16, DT_FLOAT})) - .REQUIRED_ATTR(data_format, String) - .REQUIRED_ATTR(epsilon, Float) + .ATTR(data_format, String, "NDHWC") + .ATTR(epsilon, Float, 1e-6) .OP_END_FACTORY_REG(InstanceNorm) +/** +*@brief InstanceNormGrad operator interface implementation. + +*@par Inputs: +*Five inputs, including: +* @li dy: A Tensor. Must be one of the following types: float16, float32. +* @li x: A Tensor. Must be one of the following types: float16, float32. +* @li variance: A Tensor. Must be one of the following types: float16, float32. +* @li mean: A Tensor. Must be one of the following types: float16, float32. +* @li gamma: A Tensor. Must be one of the following types: float16, float32 . \n + +*@par Outputs: +*Three outputs, including: +* @li pd_x: A Tensor. Must be one of the following types: float16, float32. +* @li pd_gamma: A Tensor. Must be one of the following types: float16, float32. +* @li pd_beta: A Tensor. Must be one of the following types: float16, float32. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(InstanceNormGrad) + .INPUT(dy, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(variance, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(mean, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(gamma, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(pd_x, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(pd_gamma, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(pd_beta, TensorType({DT_FLOAT, DT_FLOAT16})) + .OP_END_FACTORY_REG(InstanceNormGrad) + +/** +*@brief InstanceNormXBackprop operator interface implementation. + +*@par Inputs: +*Five inputs, including: +* @li dy: A Tensor. Must be one of the following types: float16, float32. +* @li x: A Tensor. Must be one of the following types: float16, float32. +* @li variance: A Tensor. Must be one of the following types: float16, float32. +* @li mean: A Tensor. Must be one of the following types: float16, float32. +* @li gamma: A Tensor. Must be one of the following types: float16, float32 . \n + +*@par Outputs: +*Two outputs, including: +* @li pd_x: A Tensor. Must be one of the following types: float16, float32. +* @li res_for_gamma: A Tensor. Must be one of the following types: float32. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(InstanceNormXBackprop) + .INPUT(dy, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(variance, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(mean, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(gamma, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(pd_x, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(res_for_gamma, TensorType({DT_FLOAT})) + .OP_END_FACTORY_REG(InstanceNormXBackprop) + +/** +*@brief InstanceNormBetaGammaBackprop operator interface implementation. + +*@par Inputs: +*Two inputs, including: +* @li dy: A Tensor. Must be one of the following types: float16, float32. +* @li res_for_gamma: A Tensor. Must be one of the following types: float32.\n + +*@par Outputs: +*Two outputs, including: +* @li pd_gamma: A Tensor. Must be one of the following types: float16, float32. +* @li pd_beta: A Tensor. Must be one of the following types: float16, float32. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(InstanceNormBetaGammaBackprop) + .INPUT(dy, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(res_for_gamma, TensorType({DT_FLOAT})) + .OUTPUT(pd_gamma, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(pd_beta, TensorType({DT_FLOAT, DT_FLOAT16})) + .OP_END_FACTORY_REG(InstanceNormBetaGammaBackprop) + /** * @brief Computes Kl_div_loss_grad or Kl_div_loss_backward. \n @@ -1571,6 +1690,27 @@ REG_OP(MultilabelMarginLoss) .ATTR(reduction, String, "mean") .OP_END_FACTORY_REG(MultilabelMarginLoss) +/** +*@brief Performs batch normalization . \n +*@par Inputs: +* Two inputs +*@li input_x: A Tensor. Support float32. shape (n, c, d). +*@li seq_len: A Tensor. Each batch normalize data num. Support Int32. Shape (n, ). \n +*@par Attributes: +*@li normalize_type: Str. Support "per_feature" or "all_features". +*@li epsilon: An optional float32, specifying the small value added to +variance to avoid dividing by zero. Defaults to "0.00001" . \n +*@par Outputs: +* One outputs +*@li output_y: A Tensor for the normalized "x".Support float32. shape (n, c, d).\n +*/ +REG_OP(NormalizeBatch) + .INPUT(input_x, TensorType({ DT_FLOAT })) + .INPUT(seq_len, TensorType({ DT_INT32 })) + .OUTPUT(output_y, TensorType({ DT_FLOAT })) + .REQUIRED_ATTR(normalize_type, String) + .ATTR(epsilon, Float, 0.00001) + .OP_END_FACTORY_REG(NormalizeBatch) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_NORM_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/reduce_ops.h b/third_party/fwkacllib/inc/ops/reduce_ops.h index 7d9e6df1..97c7b8e1 100644 --- a/third_party/fwkacllib/inc/ops/reduce_ops.h +++ b/third_party/fwkacllib/inc/ops/reduce_ops.h @@ -990,7 +990,7 @@ REG_OP(INInferV2) *@brief Performs reduced instance normalization . \n *@par Inputs: -*x: A Tensor of type float16 or float32, with format NC1HWC0 . \n +*x: A Tensor of type float16 or float32. \n *@par Outputs: *@li sum: A Tensor of type float32 for SUM reduced "x". @@ -1013,19 +1013,19 @@ REG_OP(INTrainingReduceV2) *@par Inputs: * Seven inputs, including: (NC1HWC0supported) *@li x: A Tensor of type float16 or float32. -*@li sum: A T [N, C1, 1, 1, C0] ensor of type float32 for the output of operator INTrainingReduceV2. -*@li square_sum: A [N, C1, 1, 1, C0] Tensor of type float32 for the output of operator INTrainingReduceV2. -*@li gamma: A [N, C1, 1, 1, C0] Tensor of type float32, for the scaling gamma. -*@li beta: A [N, C1, 1, 1, C0] Tensor of type float32, for the scaling beta. -*@li mean: A [N, C1, 1, 1, C0] Tensor of type float32, for the updated mean. -*@li variance: A [N, C1, 1, 1, C0] Tensor of type float32, for the updated variance . \n +*@li sum: A Tensor of type float32 for the output of operator INTrainingReduceV2. +*@li square_sum: A Tensor of type float32 for the output of operator INTrainingReduceV2. +*@li gamma: A Tensor of type float32, for the scaling gamma. +*@li beta: A Tensor of type float32, for the scaling beta. +*@li mean: A Tensor of type float32, for the updated mean. +*@li variance: A Tensor of type float32, for the updated variance . \n *@par Attributes: *@li momentum: A required float32, specifying the momentum to update mean and var. *@li epsilon: A required float32, specifying the small value added to variance to avoid dividing by zero . \n *@par Outputs: -* Three outputs, including: (NC1HWC0 supported) +* Three outputs *@li y: A Tensor of type float16 or float32, for normalized "x". *@li batch_mean: A Tensor of type float32, for the updated mean. *@li batch_variance: A Tensor of type float32, for the updated variance . \n @@ -1191,6 +1191,40 @@ REG_OP(ReduceStd) .ATTR(unbiased, Bool, true) .ATTR(keepdim, Bool, false) .OP_END_FACTORY_REG(ReduceStd) + +/** +* @brief Calculates the standard deviation of Tensors. + +* @par Inputs: +* include: +* @li x: A Tensor. Must be one of the following types: float16, float32. \n +* @li mean: A Tensor. It's the mean of X. Must be one of the following types: float16, float32. \n + + +* @par Attributes: +* Three Attributes, including: +* @li dim: An optional listint, Defaults to "None". \n +* @li unbiased: An optional bool. Defaults to "True". +* If "True", Use Bessel Correction. +* If "False", Do not use Bessel Correction. \n +* @li keepdim: An optional bool. Defaults to "False". +* If "True", Keep the original tensor dimension. +* If "False", Do not keep the original tensor dimension. \n + +* @par Outputs: +* @li y: A Tensor. It's the std of X. Has the same type as "x". + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator ReduceStdWithMean. +*/ +REG_OP(ReduceStdWithMean) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(mean, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .ATTR(dim, ListInt, {}) + .ATTR(unbiased, Bool, true) + .ATTR(keepdim, Bool, false) + .OP_END_FACTORY_REG(ReduceStdWithMean) } //namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_REDUCE_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/selection_ops.h b/third_party/fwkacllib/inc/ops/selection_ops.h index 3e67a1ea..1c26e033 100644 --- a/third_party/fwkacllib/inc/ops/selection_ops.h +++ b/third_party/fwkacllib/inc/ops/selection_ops.h @@ -2273,6 +2273,40 @@ REG_OP(AddRowRanges) .OUTPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) .OP_END_FACTORY_REG(AddRowRanges) +/** +*@brief masked fill tensor along with one axis by range. +* boxes. It is a customized masked fill range operator . \n + +*@par Inputs: +* Four inputs, including: +*@li x: input tensor. A ND Tensor of float32/float16/int32/int8 with shapes +* 1-D (D,), 2-D(N, D), 3-D(N, C, D) +*@li start: masked fill start pos. A 3D Tensor of int32 with +* shape (num, N). "num" indicates the number of loop masked fill, and the value N +* indicates the batch of ND Tensor, if input x shape is 1-D, N = 1. \n +*@li end: masked fill end pos. A 3D Tensor of int32 with +* shape (num, N). "num" indicates the number of loop masked fill, and the value N +* indicates the batch of ND Tensor. \n +*@li value: masked fill value. A 2D Tensor of float32/float16/int32/int8 with +* shape (num,). "num" indicates the number of loop masked fill + +*@par Attributes: +*@li axis: axis with masked fill of int32. Defaults to -1. + +*@par Outputs: +*y: A ND Tensor of float32/float16/int32/int8 with shapes 1-D (D,), 2-D(N, D), 3-D(N, C, D) + +* @par Restrictions: +* Warning: input shape's length must not be bigger than 1024 * 1024 * 1024. +*/ +REG_OP(MaskedFillRange) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32})) + .INPUT(start, TensorType({DT_INT32})) + .INPUT(end, TensorType({DT_INT32})) + .INPUT(value, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32})) + .REQUIRED_ATTR(axis, Int) + .OP_END_FACTORY_REG(MaskedFillRange) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_SELECTION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/split_combination_ops.h b/third_party/fwkacllib/inc/ops/split_combination_ops.h index af2c37bc..fe25a46f 100644 --- a/third_party/fwkacllib/inc/ops/split_combination_ops.h +++ b/third_party/fwkacllib/inc/ops/split_combination_ops.h @@ -317,15 +317,15 @@ REG_OP(Concat) * int64, uint8, uint16, uint32, uint64, float16, float32, bool . It's a dynamic input. \n *@par Attributes: -*@li axis: A optional int, defaultvalue is 0. +*@li axis: A optional int, default value is 0. * Dimension along which to pack. The range is [-(R+1), R+1). *@li N: A required int. Number of tensors . \n *@par Outputs: *y: A Tensor. Has the same type as "x". + *@par Third-party framework compatibility -*Compatible with the TensorFlow operator Pack. -It's a dynamic output. +* Compatible with the TensorFlow operator Pack. */ REG_OP(Pack) .DYNAMIC_INPUT(x, TensorType::BasicType()) diff --git a/third_party/fwkacllib/inc/ops/string_ops.h b/third_party/fwkacllib/inc/ops/string_ops.h index 080b9a3f..f9cc2549 100644 --- a/third_party/fwkacllib/inc/ops/string_ops.h +++ b/third_party/fwkacllib/inc/ops/string_ops.h @@ -896,6 +896,45 @@ REG_OP(DecodeBase64) .INPUT(x, TensorType({DT_STRING})) .OUTPUT(y, TensorType({DT_STRING})) .OP_END_FACTORY_REG(DecodeBase64) + +/** +*@brief StringNormalization performs string operations for basic cleaning . \n + +*@par Inputs: +*@li input: only accepts [C] or [1, C] UTF-8 strings tensor . \n + +*@par Outputs: +*@li output: UTF-8 strings tensor after cleaning . \n + +*@par Attributes: +*@li stopwords : list of strings (default is empty). +*List of stop words. If not set, no word would be removed from input strings +tensor. + +*@li is_case_sensitive : bool (default is false). +*Boolean. Whether the identification of stop words in input strings tensor is +case-sensitive. Default is false. + +*@li case_change_action : string (default is "NONE"). +*string enum that cases output to be lowercased/uppercases/unchanged. Valid +values are "LOWER", "UPPER", "NONE". Default is "NONE". + +*@li local : string (default is "en_US"). +*Environment dependent string that denotes the locale according to which output +strings needs to be upper/lowercased.Default en_US or platform specific equivalent +as decided by the implementation . \n + +*@attention Constraints: +*@li input can be either a 1-D or 2-D tensor, the shape of 2-D tensor must be [1, C]. +*/ +REG_OP(StringNormalizer) + .INPUT(input, TensorType({DT_STRING})) + .OUTPUT(output, TensorType({DT_STRING})) + .ATTR(stopwords, ListString, {}) + .ATTR(is_case_sensitive, Bool, false) + .ATTR(case_change_action, String, "NONE") + .ATTR(local, String, "en_US") + .OP_END_FACTORY_REG(StringNormalizer) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_STRING_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/transformation_ops.h b/third_party/fwkacllib/inc/ops/transformation_ops.h index 2e8ffd9c..4a46e35f 100644 --- a/third_party/fwkacllib/inc/ops/transformation_ops.h +++ b/third_party/fwkacllib/inc/ops/transformation_ops.h @@ -130,21 +130,20 @@ REG_OP(Transpose) .OP_END_FACTORY_REG(Transpose) /** -*@brief Doing format_transfer for various data format only -support "NHWC/NCHW" to "NC1HWC0" and "NC1HWC0" to "NHWC/NCHW" -"NCHW" to "FRACTAL_Zn" or "FRACTAL_Zn" to "NCHW". -"HWCN" to "FRACTAL_Zn" or "FRACTAL_Zn" to "HWCN" . \n +*@brief Do format transfer for various data format. +* In general, the framework will insert it atomatically . \n *@par Inputs: -*src: A Tensor dtype of all types . \n +*src: A Tensor. For all branches can be types: float16, float32, int32, int8, bool. +* For branches without padding also can be types: int16, int64, uint8, uint16, uint32, uint64 . \n *@par Attributes: -*@li src_format: A string source data format, can be "NHWC", "NCHW", "FRACTAL_Zn" etc. -*@li dst_format: A string target data format, can be "NC1HWC0", "NCHW", "FRACTAL_Zn" etc. +*@li src_format: A string source data format, can be "NHWC", "NCHW", "FRACTAL_Z" etc. +*@li dst_format: A string target data format, can be "NC1HWC0", "NCHW", "FRACTAL_Z" etc. *@li group: A optional int32, default value is 1. \n *@par Outputs: -*dst: A Tensor dtype of all types. +*dst: A Tensor. Has the same type as "src". */ REG_OP(TransData) .INPUT(src, TensorType::BasicType()) @@ -174,21 +173,27 @@ REG_OP(Permute) .OP_END_FACTORY_REG(Permute) /** -*@brief Flattens the inputs. Reserves axis 0 and flattens the input tensors -* along axis 1 . \n +*@brief Flattens the inputs tensor into a 2D matrix. If input tensor has shape (d_0, d_1,..., d_n), +* then the output will have shape (d_0 X d_1 ... d_(axis-1), d_axis X d_(axis + 1)...X d_n)\n *@par Inputs: -*One input: -*x: A multi-dimensional Tensor. Must be one of the following types: -* int8, uint8, int16, uint16, int32, uint32, int64,uint64, float16, float32 . \n +* One input: +* x: A multi-dimensional Tensor. Must be one of the following types: +* int8, uint8, int16, uint16, int32, uint32, int64,uint64, float16, float32. *@par Outputs: -*y: A 2D flattened Tensor (Reserves axis 0 and flattens the input tensors -* along axis 1). Must be one of the following data types: int8, uint8, int16, -* uint16, int32, uint32, int64,uint64, float16, float32 . \n +* y: A 2D flattened Tensor with the contents of the input tensor, with input dimensions up to axis flattened +* to the outer dimension of the output and remaining input dimensions flattened into the inner dimension of the output. +* Must be one of the following data types: int8, uint8, int16, uint16, int32, uint32, int64,uint64, float16, float32 . + +*@par Attributes: +* axis: A optional int32, default value is 1. Indicate up to which input dimensions (exclusive) should be flattened +* to the outer dimension of the output. The value for axis must be in the range [-r, r], where r is the rank of +* the input tensor. Negative value means counting dimensions from the back. When axis = 0, the shape of +* the output tensor is (1, (d_0 X d_1 ... d_n), where the shape of the input tensor is (d_0, d_1, ... d_n). *@par Third-party framework compatibility -* Compatible with TensorFlow operator Flatten. +* Compatible with TensorFlow / ONNX operator Flatten. */ REG_OP(Flatten) .INPUT(x, TensorType({DT_INT8, DT_INT16, DT_INT32, DT_INT64, @@ -197,6 +202,7 @@ REG_OP(Flatten) .OUTPUT(y, TensorType({DT_INT8, DT_INT16, DT_INT32, DT_INT64, DT_UINT8, DT_UINT16, DT_UINT32, DT_UINT64, DT_FLOAT, DT_FLOAT16})) + .ATTR(axis, Int, 1) .OP_END_FACTORY_REG(Flatten) /** @@ -824,6 +830,98 @@ REG_OP(AffineGrid) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(align_corners, Bool, false) .OP_END_FACTORY_REG(AffineGrid) + +/** +*@brief Make memory of a view be contiguous. \n + +*@par Inputs: +*Four inputs, including: +*@li x: The input tensor. +*@li size: The shape of output tensor. +*@li stride: The stride of output tensor. +*@li storage_offset: The offset in the underlying storage of the output tensor. \n + +*@par Outputs: +*y: A Tensor. Has the same type as "x" . \n + +*@par Third-party framework compatibility +*Compatible with the pytorch operator as_strided. +*/ +REG_OP(AsStrided) + .INPUT(x, TensorType::BasicType()) + .INPUT(size, TensorType::IndexNumberType()) + .INPUT(stride, TensorType::IndexNumberType()) + .INPUT(storage_offset, TensorType::IndexNumberType()) + .OUTPUT(y, TensorType::BasicType()) + .OP_END_FACTORY_REG(AsStrided) + +/** +*@brief This transform extracts n-grams from the input sequence and save them as a +vector. \n + +*@par Inputs: +*@li input: can be either a 1-D or 2-D tensor for n-gram extraction, It is ether string UTF-8 or int32/int64 . \n + +*@par Attributes: +*@li max_gram_length : int (required) +*Maximum n-gram length. If this value is 3, 3-grams will be used to generate the output . +*@li max_skip_count : int (required) +*Maximum number of items (integers/strings) to be skipped when constructing an n-gram from X. +If max_skip_count=1, min_gram_length=2, max_gram_length=3, this operator may generate 2-grams +with skip_count=0 and skip_count=1, and 3-grams with skip_count=0 and skip_count=1. +*@li min_gram_length : int (required) +*Minimum n-gram length. If this value is 2 and max_gram_length is 3, output may contain counts of +2-grams and 3-grams. +*@li mode : string (required) +*The weighting criteria. It can be one of "TF" (term frequency), "IDF" (inverse document frequency), +and "TFIDF" (the combination of TF and IDF). +*@li ngram_counts : list of ints (required) +*The starting indexes of 1-grams, 2-grams, and so on in pool. It is useful when determining the boundary +between two consecutive collections of n-grams. For example, if ngram_counts is [0, 17, 36], +the first index (zero-based) of 1-gram/2-gram/3-gram in pool are 0/17/36. This format is essentially identical +to CSR (or CSC) sparse matrix format, and we choose to use this due to its popularity. +*@li ngram_indexes : list of ints (required) +*list of int64s (type: AttributeProto::INTS). This list is parallel to the specified 'pool_*' attribute. The i-th element +in ngram_indexes indicate the coordinate of the i-th n-gram in the output tensor. +*@li pool_int64s : list of ints +*List of int64 n-grams learned from the training set. Either this or pool_strings attributes must be present but not both. +It's an 1-D tensor starting with the collections of all 1-grams and ending with the collections of n-grams. The i-th element +in pool stores the n-gram that should be mapped to coordinate ngram_indexes[i] in the output vector. +*@li pool_strings : list of strings +*List of strings n-grams learned from the training set. Either this or pool_int64s attributes must be present but not both. +It's an 1-D tensor starting with the collections of all 1-grams and ending with the collections of n-grams. The i-th element +in pool stores the n-gram that should be mapped to coordinate ngram_indexes[i] in the output vector. +*@li weights : list of floats +*list of floats. This attribute stores the weight of each n-gram in pool. The i-th element in weights is the weight of +the i-th n-gram in pool. Its length equals to the size of ngram_indexes. By default, weights is an all-one tensor.This attribute +is used when mode is "IDF" or "TFIDF" to scale the associated word counts. \n + +*@par Outputs: +*@li output: tensor(float) +*For 1-D input, output is the n-gram representation of that input. For 2-D input, the output is also a 2-D tensor +whose i-th row is the n-gram representation of the i-th input row. More specifically, if input shape is [C], the corresponding +output shape would be [max(ngram_indexes) + 1]. If input shape is [N, C], this operator produces a [N, max(ngram_indexes) + 1]-tensor. \n + +*@attention Constraints: +*@li input can be either a 1-D or 2-D tensor, shape is [C] or [N, C]. +*@li max(ngram_indexes) + 1 == len(weights), len(y) == len(weights). +*@li ngram_counts and pool(pool_int64s or pool_strings) must match. +*@li either pool_strings or pool_int64s attributes must be present but not both. +*/ + +REG_OP(TfidVectorizer) + .INPUT(input, TensorType({DT_INT32, DT_INT64, DT_STRING})) + .OUTPUT(output, TensorType({DT_FLOAT})) + .REQUIRED_ATTR(max_gram_length, Int) + .REQUIRED_ATTR(max_skip_count, Int) + .REQUIRED_ATTR(min_gram_length, Int) + .REQUIRED_ATTR(mode, String) + .REQUIRED_ATTR(ngram_counts, ListInt) + .REQUIRED_ATTR(ngram_indexes, ListInt) + .ATTR(pool_int64s, ListInt, {}) + .ATTR(pool_strings, ListString, {}) + .ATTR(weights, ListFloat, {}) + .OP_END_FACTORY_REG(TfidVectorizer) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_TRANSFORMATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/runtime/rt_stars.h b/third_party/fwkacllib/inc/runtime/rt_stars.h index 3b944065..188656b1 100644 --- a/third_party/fwkacllib/inc/runtime/rt_stars.h +++ b/third_party/fwkacllib/inc/runtime/rt_stars.h @@ -23,6 +23,62 @@ extern "C" { */ RTS_API rtError_t rtStarsTaskLaunch(const void *taskSqe, uint32_t sqeLen, rtStream_t stream); +/** + * @ingroup rt_stars + * @brief create cdq instance. + * @param [in] batchNum batch number + * @param [in] batchSize batch size + * @param [in] queName cdq name + * @return RT_ERROR_NONE for ok, ACL_ERROR_RT_NO_CDQ_RESOURCE for no cdq resources + */ +RTS_API rtError_t rtCdqCreate(uint32_t batchNum, uint32_t batchSize, const char *queName); + +/** + * @ingroup rt_stars + * @brief destroy cdq instance. + * @param [in] queName cdq name + * @return RT_ERROR_NONE for ok, others failed + */ +RTS_API rtError_t rtCdqDestroy(const char *queName); + +/** + * @ingroup rt_stars + * @brief get free batch in the queue. + * @param [in] queName cdq name + * @param [in] timeout batch size + * @param [out] batchId batch index + * @return RT_ERROR_NONE for ok, ACL_ERROR_RT_WAIT_TIMEOUT for timeout + */ +RTS_API rtError_t rtCdqAllocBatch(const char *queName, int32_t timeout, uint32_t *batchId); + +/** + * @ingroup rt_stars + * @brief launch a write_cdqm task on the stream. + * When the task is executed, the data information will be inserted into the cdqe index position of the queue. + * @param [in] queName cdq name + * @param [in] cdqeIndex cdqe index + * @param [in] data cdqe infomation + * @param [in] dataSize data size + * @param [in] stream launch task on the stream + * @return RT_ERROR_NONE for ok, others failed + */ +RTS_API rtError_t rtCdqEnQueue(const char *queName, uint32_t cdqeIndex, void *data, uint32_t dataSize, + rtStream_t stream); + +/** + * @ingroup rt_stars + * @brief launch a write_cdqm task on the stream. + * When the task is executed, the data information will be inserted into the cdqe index position of the queue. + * @param [in] queName cdq name + * @param [in] cdqeIndex cdqe index + * @param [in] data cdqe infomation + * @param [in] dataSize data size + * @param [in] stream launch task on the stream + * @return RT_ERROR_NONE for ok, others failed + */ +RTS_API rtError_t rtCdqEnQueuePtrMode(const char *queName, uint32_t cdqeIndex, const void *prtAddr, + rtStream_t stream); + #if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) } #endif diff --git a/third_party/fwkacllib/inc/toolchain/prof_callback.h b/third_party/fwkacllib/inc/toolchain/prof_callback.h index 18550157..3666c36c 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_callback.h +++ b/third_party/fwkacllib/inc/toolchain/prof_callback.h @@ -108,7 +108,18 @@ enum MsprofCtrlCallbackType { MSPROF_CTRL_INIT_ACL_ENV = 0, // start profiling with acl env MSPROF_CTRL_INIT_ACL_JSON, // start profiling with acl.json MSPROF_CTRL_INIT_GE_OPTIONS, // start profiling with ge env and options - MSPROF_CTRL_FINALIZE // stop profiling + MSPROF_CTRL_FINALIZE, // stop profiling + MSPROF_CTRL_REPORT_FUN_P, // for report callback + MSPROF_CTRL_PROF_SWITCH // for prof switch +}; + +#define MSPROF_MAX_DEV_NUM (64) + +struct MsprofCommandHandle { + uint64_t profSwitch; + uint32_t devNums; // length of device id list + uint32_t devIdList[MSPROF_MAX_DEV_NUM]; + uint32_t modelId; }; /** @@ -129,6 +140,23 @@ typedef int32_t (*MsprofCtrlCallback)(uint32_t type, void *data, uint32_t len); */ typedef void (*MsprofSetDeviceCallback)(uint32_t devId, bool isOpenDevice); +/* + * @name MsprofInit + * @brief Profiling module init + * @param [in] dataType: profiling type: ACL Env/ACL Json/GE Option + * @param [in] data: profiling switch data + * @param [in] dataLen: Length of data + * @return 0:SUCCESS, >0:FAILED + */ +int32_t MsprofInit(uint32_t dataType, void *data, uint32_t dataLen); + +/* + * @name AscendCL + * @brief Finishing Profiling + * @param NULL + * @return 0:SUCCESS, >0:FAILED + */ +int32_t MsprofFinalize(); #ifdef __cplusplus } #endif From ec89f88f1f55c37e6d5d6bb06caff5a1c83629b5 Mon Sep 17 00:00:00 2001 From: dingpeifei Date: Fri, 18 Jun 2021 11:23:12 +0800 Subject: [PATCH 31/59] code_sync_0617_update --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 34ef19ac..6e1786f4 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -160,6 +160,7 @@ else () elseif(ENABLE_MS_TESTCASES) include(cmake/external_libs/protobuf_static.cmake) include(cmake/external_libs/protoc.cmake) + include(cmake/external_libs/json.cmake) include(cmake/external_libs/securec.cmake) include(cmake/FindModule.cmake) include(cmake/intf_pub_linux.cmake) @@ -177,5 +178,4 @@ else () endif() add_subdirectory(ge) - -endif () \ No newline at end of file +endif () From 3dfd2119c1317dcd08483d9b91310092c306b5fb Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Wed, 28 Jul 2021 16:04:35 +0800 Subject: [PATCH 32/59] sync code 0728 --- CMakeLists.txt | 3 +- cmake/external_libs/json.cmake | 4 - ge/ge_runtime/CMakeLists.txt | 1 + ge/ge_runtime/task/hccl_task.cc | 16 +- ge/ge_runtime/task/label_goto_task.cc | 56 +- ge/ge_runtime/task/label_goto_task.h | 16 +- ge/ge_runtime/task/label_manager.cc | 119 + ge/ge_runtime/task/label_manager.h | 54 + ge/ge_runtime/task/label_switch_task.cc | 25 +- ge/ge_runtime/task/label_switch_task.h | 6 +- inc/external/acl/acl.h | 82 + inc/external/acl/acl_base.h | 638 ++++ inc/external/acl/acl_mdl.h | 1225 ++++++++ inc/external/acl/acl_op.h | 504 ++++ inc/external/acl/acl_op_compiler.h | 121 + inc/external/acl/acl_prof.h | 329 +++ inc/external/acl/acl_rt.h | 958 ++++++ inc/external/acl/acl_tdt.h | 276 ++ inc/external/acl/error_codes/ge_error_codes.h | 75 + inc/external/acl/error_codes/rt_error_codes.h | 109 + inc/external/acl/ops/acl_cblas.h | 334 +++ inc/external/acl/ops/acl_dvpp.h | 2568 +++++++++++++++++ inc/external/acl/ops/acl_fv.h | 348 +++ inc/external/hccl/hccl.h | 159 + inc/external/hccl/hccl_types.h | 101 + inc/external/runtime/rt_error_codes.h | 109 + inc/framework/ge_runtime/task_info.h | 5 +- metadef | 2 +- scripts/format_source_code.sh | 107 + .../fwkacllib/inc/cce/taskdown_common.hpp | 19 +- .../inc/external/runtime/rt_error_codes.h | 0 third_party/fwkacllib/inc/hccl/base.h | 36 +- third_party/fwkacllib/inc/hccl/hccl_types.h | 101 - third_party/fwkacllib/inc/hccl/hcom.h | 14 + third_party/fwkacllib/inc/mmpa/mmpa_api.h | 1 + .../fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h | 4 + .../fwkacllib/inc/mmpa/sub_inc/mmpa_win.h | 4 + third_party/fwkacllib/inc/ops/aipp.h | 4 +- third_party/fwkacllib/inc/ops/all_ops.h | 3 +- third_party/fwkacllib/inc/ops/array_ops.h | 104 +- third_party/fwkacllib/inc/ops/audio_ops.h | 2 +- .../fwkacllib/inc/ops/avg_pool_1d_ops.h | 58 + third_party/fwkacllib/inc/ops/batch_ops.h | 21 +- third_party/fwkacllib/inc/ops/bitwise_ops.h | 31 +- .../fwkacllib/inc/ops/boosted_trees_ops.h | 2 +- .../inc/ops/candidate_sampling_ops.h | 2 +- third_party/fwkacllib/inc/ops/condtake_ops.h | 2 +- .../fwkacllib/inc/ops/control_flow_ops.h | 12 +- third_party/fwkacllib/inc/ops/correlation.h | 52 + third_party/fwkacllib/inc/ops/ctc_ops.h | 83 +- third_party/fwkacllib/inc/ops/data_flow_ops.h | 89 +- .../inc/ops/elewise_calculation_ops.h | 527 +++- .../fwkacllib/inc/ops/functional_ops.h | 2 +- third_party/fwkacllib/inc/ops/get_data_ops.h | 2 +- third_party/fwkacllib/inc/ops/globalavgpool.h | 49 + third_party/fwkacllib/inc/ops/hcom_ops.h | 135 +- third_party/fwkacllib/inc/ops/hvd_ops.h | 2 +- third_party/fwkacllib/inc/ops/image_ops.h | 653 ++++- third_party/fwkacllib/inc/ops/internal_ops.h | 2 +- third_party/fwkacllib/inc/ops/linalg_ops.h | 138 +- third_party/fwkacllib/inc/ops/list_ops.h | 504 ++++ third_party/fwkacllib/inc/ops/logging_ops.h | 2 +- third_party/fwkacllib/inc/ops/lookup_ops.h | 2 +- third_party/fwkacllib/inc/ops/math_ops.h | 283 +- .../inc/ops/matrix_calculation_ops.h | 336 ++- .../fwkacllib/inc/ops/nn_batch_norm_ops.h | 134 +- .../fwkacllib/inc/ops/nn_calculation_ops.h | 448 ++- third_party/fwkacllib/inc/ops/nn_detect_ops.h | 602 +++- third_party/fwkacllib/inc/ops/nn_norm_ops.h | 777 ++++- third_party/fwkacllib/inc/ops/nn_ops.h | 141 +- .../fwkacllib/inc/ops/nn_pooling_ops.h | 488 +++- .../fwkacllib/inc/ops/nn_training_ops.h | 51 +- third_party/fwkacllib/inc/ops/no_op.h | 2 +- .../fwkacllib/inc/ops/nonlinear_fuc_ops.h | 408 ++- .../fwkacllib/inc/ops/npu_loss_scale_ops.h | 2 +- third_party/fwkacllib/inc/ops/outfeed_ops.h | 2 +- third_party/fwkacllib/inc/ops/pad_ops.h | 160 +- third_party/fwkacllib/inc/ops/parsing_ops.h | 242 +- third_party/fwkacllib/inc/ops/quantize_ops.h | 31 +- .../fwkacllib/inc/ops/ragged_array_ops.h | 2 +- .../fwkacllib/inc/ops/ragged_conversion_ops.h | 2 +- .../fwkacllib/inc/ops/ragged_math_ops.h | 2 +- third_party/fwkacllib/inc/ops/random_ops.h | 91 +- third_party/fwkacllib/inc/ops/reduce_ops.h | 279 +- .../fwkacllib/inc/ops/resource_variable_ops.h | 2 +- third_party/fwkacllib/inc/ops/rnn.h | 595 +++- third_party/fwkacllib/inc/ops/rpn_ops.h | 2 +- third_party/fwkacllib/inc/ops/save_ops.h | 2 +- third_party/fwkacllib/inc/ops/sdca_ops.h | 2 +- third_party/fwkacllib/inc/ops/selection_ops.h | 426 ++- third_party/fwkacllib/inc/ops/set_ops.h | 2 +- third_party/fwkacllib/inc/ops/sparse_ops.h | 8 +- third_party/fwkacllib/inc/ops/spectral_ops.h | 98 +- .../fwkacllib/inc/ops/split_combination_ops.h | 26 +- third_party/fwkacllib/inc/ops/state_ops.h | 2 +- .../fwkacllib/inc/ops/stateful_random_ops.h | 2 +- .../fwkacllib/inc/ops/stateless_random_ops.h | 2 +- third_party/fwkacllib/inc/ops/string_ops.h | 382 ++- third_party/fwkacllib/inc/ops/swap_co_ops.h | 2 +- .../inc/ops/target_crop_and_resize.h | 2 +- .../fwkacllib/inc/ops/transformation_ops.h | 271 +- .../fwkacllib/inc/ops/warp_perspective_ops.h | 2 +- third_party/fwkacllib/inc/runtime/event.h | 5 + third_party/fwkacllib/inc/runtime/rt.h | 1 + third_party/fwkacllib/inc/runtime/rt_stars.h | 85 + third_party/fwkacllib/inc/tdt/tsd_client.h | 82 - .../inc/toolchain/adx_datadump_server.h | 22 +- .../fwkacllib/inc/toolchain/prof_acl_api.h | 208 +- .../fwkacllib/inc/toolchain/prof_mgr_core.h | 9 + .../fwkacllib/inc/toolchain/prof_reporter.h | 70 +- third_party/prebuild/aarch64/libalog.so | Bin 223920 -> 225280 bytes .../prebuild/aarch64/liberror_manager.so | Bin 888880 -> 1159216 bytes third_party/prebuild/aarch64/libmmpa.a | Bin 63182 -> 62550 bytes third_party/prebuild/x86_64/libalog.so | Bin 164208 -> 173984 bytes .../prebuild/x86_64/liberror_manager.so | Bin 852544 -> 1168920 bytes third_party/prebuild/x86_64/libmmpa.a | Bin 57270 -> 56998 bytes 116 files changed, 16672 insertions(+), 1133 deletions(-) create mode 100644 ge/ge_runtime/task/label_manager.cc create mode 100644 ge/ge_runtime/task/label_manager.h create mode 100644 inc/external/acl/acl.h create mode 100644 inc/external/acl/acl_base.h create mode 100644 inc/external/acl/acl_mdl.h create mode 100644 inc/external/acl/acl_op.h create mode 100644 inc/external/acl/acl_op_compiler.h create mode 100644 inc/external/acl/acl_prof.h create mode 100644 inc/external/acl/acl_rt.h create mode 100644 inc/external/acl/acl_tdt.h create mode 100644 inc/external/acl/error_codes/ge_error_codes.h create mode 100644 inc/external/acl/error_codes/rt_error_codes.h create mode 100644 inc/external/acl/ops/acl_cblas.h create mode 100644 inc/external/acl/ops/acl_dvpp.h create mode 100644 inc/external/acl/ops/acl_fv.h create mode 100644 inc/external/hccl/hccl.h create mode 100644 inc/external/hccl/hccl_types.h create mode 100644 inc/external/runtime/rt_error_codes.h create mode 100755 scripts/format_source_code.sh mode change 100755 => 100644 third_party/fwkacllib/inc/external/runtime/rt_error_codes.h delete mode 100644 third_party/fwkacllib/inc/hccl/hccl_types.h create mode 100644 third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h create mode 100644 third_party/fwkacllib/inc/ops/correlation.h create mode 100644 third_party/fwkacllib/inc/ops/globalavgpool.h create mode 100644 third_party/fwkacllib/inc/ops/list_ops.h create mode 100644 third_party/fwkacllib/inc/runtime/rt_stars.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 60509838..5e58eeba 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -125,7 +125,6 @@ else () message(STATUS "PLATFORM param is invalid, should be train or inference, you choose nothing!") endif() endif() - set(METADEF_DIR ${CMAKE_CURRENT_LIST_DIR}/metadef) set(PARSER_DIR ${CMAKE_CURRENT_LIST_DIR}/parser) set(GE_DEPEND_DIR ${CMAKE_CURRENT_LIST_DIR}/..) @@ -158,6 +157,7 @@ else () elseif(ENABLE_MS_TESTCASES) include(cmake/external_libs/protobuf_static.cmake) include(cmake/external_libs/protoc.cmake) + include(cmake/external_libs/json.cmake) include(cmake/external_libs/securec.cmake) include(cmake/FindModule.cmake) include(cmake/intf_pub_linux.cmake) @@ -175,5 +175,4 @@ else () endif() add_subdirectory(ge) - endif () diff --git a/cmake/external_libs/json.cmake b/cmake/external_libs/json.cmake index 3c1cd012..04659ebc 100755 --- a/cmake/external_libs/json.cmake +++ b/cmake/external_libs/json.cmake @@ -9,10 +9,6 @@ if (GE_PB_PKG) set(REQ_URL "${GE_PB_PKG}/libs/ge_nlohmann_json/include.zip") set(MD5 "0dc903888211db3a0f170304cd9f3a89") set(JSON_INCLUDE_DIR ${JSON_SRC_DIR}) -#elseif (ENABLE_GITEE) -# set(REQ_URL "https://gitee.com/mirrors/JSON-for-Modern-CPP/repository/archive/v3.6.1.zip") -# set(MD5 "5bda78ce308e6cfcf614dcf1d5ff27a7") -#set(JSON_INCLUDE_DIR "${JSON_SRC_DIR}/include") else() set(REQ_URL "https://github.com/nlohmann/json/releases/download/v3.6.1/include.zip") set(MD5 "0dc903888211db3a0f170304cd9f3a89") diff --git a/ge/ge_runtime/CMakeLists.txt b/ge/ge_runtime/CMakeLists.txt index 3243766f..ffea784b 100644 --- a/ge/ge_runtime/CMakeLists.txt +++ b/ge/ge_runtime/CMakeLists.txt @@ -16,6 +16,7 @@ set(GE_SRC_LIST "task/label_goto_task.cc" "task/label_set_task.cc" "task/label_switch_task.cc" + "task/label_manager.cc" ) add_library(ge_runtime SHARED ${GE_SRC_LIST}) diff --git a/ge/ge_runtime/task/hccl_task.cc b/ge/ge_runtime/task/hccl_task.cc index b1c7158c..bfe0d0f3 100644 --- a/ge/ge_runtime/task/hccl_task.cc +++ b/ge/ge_runtime/task/hccl_task.cc @@ -53,15 +53,7 @@ HcclTask::HcclTask(const ModelContext &model_context, const std::shared_ptrworkspace_size() > 0) { - rtError_t rt_ret = rtMalloc(&workspace_mem_, task_info_->workspace_size(), RT_MEMORYINFO_HBM); - if (rt_ret != RT_ERROR_NONE) { - GELOGE(RT_FAILED, "Call rt api failed, ret: 0x%X", rt_ret); - return false; - } + workspace_mem_ = task_info_->workspace_addr(); } GELOGI("HcclTaskInfo Distribute Start. begin to call function LoadTask in hccl."); diff --git a/ge/ge_runtime/task/label_goto_task.cc b/ge/ge_runtime/task/label_goto_task.cc index 7cb6d556..a3b70971 100644 --- a/ge/ge_runtime/task/label_goto_task.cc +++ b/ge/ge_runtime/task/label_goto_task.cc @@ -16,33 +16,46 @@ #include "ge_runtime/task/label_goto_task.h" #include "ge_runtime/task/task_factory.h" -#include "framework/common/util.h" namespace ge { namespace model_runner { LabelGotoTask::LabelGotoTask(const ModelContext &model_context, const std::shared_ptr &task_info) - : TaskRepeater(model_context, task_info), task_info_(task_info) { + : TaskRepeater(model_context, task_info), + task_info_(task_info), + stream_(nullptr), + index_value_(nullptr) { if (task_info_ == nullptr) { GELOGW("task_info_ is null!"); return; } auto stream_list = model_context.stream_list(); auto label_list = model_context.label_list(); + rt_model_handle_ = model_context.rt_model_handle(); uint32_t stream_id = task_info->stream_id(); - uint32_t label_id = task_info->label_id(); + label_id_ = task_info->label_id(); GELOGI("Stream list size:%zu, stream id:%u.", stream_list.size(), stream_id); - GELOGI("Label list size:%zu, label id:%u.", label_list.size(), label_id); - if (stream_id >= stream_list.size() || label_id >= label_list.size()) { + GELOGI("Label list size:%zu, label id:%u.", label_list.size(), label_id_); + if (stream_id >= stream_list.size() || label_id_ >= label_list.size()) { GELOGW("Stream/Label id invalid."); return; } stream_ = stream_list[stream_id]; - label_ = label_list[label_id]; + label_manager_ = LabelManager::GetInstance(); + if (label_manager_ == nullptr) { + GELOGW("Get label manager instance failed."); + return; + } + label_info_ = label_manager_->GetLabelInfo(rt_model_handle_, {label_id_}, label_list); } LabelGotoTask::~LabelGotoTask() { - GE_FREE_RT_LOG(label_info_); - GE_FREE_RT_LOG(index_value_); + if (index_value_ != nullptr) { + rtError_t rt_ret = rtFree(index_value_); + if (rt_ret != RT_ERROR_NONE) { + GELOGE(RT_FAILED, "rtFree index_value_ failed! ret: 0x%X.", rt_ret); + } + index_value_ = nullptr; + } } bool LabelGotoTask::Distribute() { @@ -94,21 +107,34 @@ bool LabelGotoTask::CheckParamValid() { return false; } - if (label_ == nullptr) { - GELOGE(PARAM_INVALID, "label is null!"); + if (label_info_ == nullptr) { + GELOGE(PARAM_INVALID, "label info is null!"); return false; } - if (label_info_ != nullptr) { - GELOGE(PARAM_INVALID, "label_info_ has dirty data."); - return false; + if (index_value_ == nullptr) { + rtError_t rt_ret = rtMalloc(&index_value_, sizeof(uint64_t), RT_MEMORY_HBM); + if (rt_ret != RT_ERROR_NONE) { + GELOGE(RT_FAILED, "Call rt api failed, ret: 0x%X", rt_ret); + return false; + } + + uint64_t index = 0; + rt_ret = rtMemcpy(index_value_, sizeof(uint64_t), &index, sizeof(index), RT_MEMCPY_HOST_TO_DEVICE); + if (rt_ret != RT_ERROR_NONE) { + GELOGE(RT_FAILED, "Call rt api failed, ret: 0x%X", rt_ret); + return false; + } } - if (index_value_ != nullptr) { - GELOGE(PARAM_INVALID, "index_value_ has dirty data."); + void *label_info = label_info_->GetLabelInfo(); + rtError_t rt_ret = rtLabelSwitchByIndex(index_value_, 1, label_info, stream_); + if (rt_ret != RT_ERROR_NONE) { + GELOGE(RT_FAILED, "Call rt api failed, ret: 0x%X", rt_ret); return false; } + GELOGI("DistributeTask end."); return true; } diff --git a/ge/ge_runtime/task/label_goto_task.h b/ge/ge_runtime/task/label_goto_task.h index addbb700..e579c683 100644 --- a/ge/ge_runtime/task/label_goto_task.h +++ b/ge/ge_runtime/task/label_goto_task.h @@ -18,7 +18,11 @@ #define GE_GE_RUNTIME_TASK_LABEL_GOTO_TASK_H_ #include +#include +#include +#include #include "ge_runtime/task/task.h" +#include "ge_runtime/task/label_manager.h" namespace ge { namespace model_runner { @@ -31,13 +35,13 @@ class LabelGotoTask : public TaskRepeater { bool Distribute() override; private: - bool CheckParamValid(); - std::shared_ptr task_info_; - void *stream_{nullptr}; - void *label_{nullptr}; - void *label_info_{nullptr}; - void *index_value_{nullptr}; + void *stream_; + std::shared_ptr label_info_; + void *index_value_; + uint32_t label_id_; + rtModel_t rt_model_handle_; + std::shared_ptr label_manager_; }; } // namespace model_runner } // namespace ge diff --git a/ge/ge_runtime/task/label_manager.cc b/ge/ge_runtime/task/label_manager.cc new file mode 100644 index 00000000..a2b0c3aa --- /dev/null +++ b/ge/ge_runtime/task/label_manager.cc @@ -0,0 +1,119 @@ +/** + * Copyright 2021 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 "ge_runtime/task/label_manager.h" +#include +#include +#include "runtime/mem.h" +#include "runtime/rt_model.h" +#include "common/ge_inner_error_codes.h" +#include "framework/common/debug/ge_log.h" + +namespace ge { +namespace model_runner { +std::weak_ptr LabelManager::instance_; +std::mutex LabelManager::instance_mutex_; + +template +static std::string GetVectorString(const std::vector &vec) { + std::string ret; + for (size_t i = 0; i < vec.size(); ++i) { + if (i != 0) { + ret.push_back(','); + } + ret += std::to_string(vec[i]); + } + return ret; +} + +LabelGuard::~LabelGuard() { + void *label_info = GetLabelInfo(); + if (label_info != nullptr) { + rtError_t rt_ret = rtFree(label_info); + if (rt_ret != RT_ERROR_NONE) { + GELOGE(RT_FAILED, "rtFree label_info failed! ret: 0x%X.", rt_ret); + } + } +} + +std::shared_ptr LabelManager::GetInstance() { + std::lock_guard lock(instance_mutex_); + auto instance = instance_.lock(); + if (instance != nullptr) { + return instance; + } + + instance = std::make_shared(); + instance_ = instance; + return instance; +} + +std::shared_ptr LabelManager::GetLabelInfo(rtModel_t model, const std::vector &label_ids, + const std::vector &all_label) { + std::lock_guard lock(model_info_mapping_mutex_); + rtError_t rt_ret; + auto model_iter = model_info_mapping_.find(model); + if (model_iter == model_info_mapping_.end()) { + model_info_mapping_.emplace(model, std::map>()); + model_iter = model_info_mapping_.find(model); + } + + std::string label_id_str = GetVectorString(label_ids); + auto &label_map = model_iter->second; + auto label_iter = label_map.find(label_id_str); + if (label_iter != label_map.end()) { + auto label_guard = label_iter->second.lock(); + if (label_guard != nullptr) { + GELOGI("model %p find same label id %s.", model, label_id_str.c_str()); + return label_guard; + } + } + + GELOGI("Alloc label id %s for model %p.", label_id_str.c_str(), model); + void *label_info; + std::vector label_list; + bool status = true; + std::transform(label_ids.begin(), label_ids.end(), std::back_inserter(label_list), + [&all_label, &status](uint32_t idx) -> void * { + if (idx >= all_label.size()) { + GELOGE(PARAM_INVALID, "Invalid label id %u, all label list size %zu.", idx, all_label.size()); + status = false; + return nullptr; + } + return all_label[idx]; + }); + if (!status) { + GELOGE(PARAM_INVALID, "Get label info failed."); + return nullptr; + } + uint32_t label_info_size = sizeof(rtLabelDevInfo) * label_list.size(); + rt_ret = rtMalloc(&label_info, label_info_size, RT_MEMORY_HBM); + if (rt_ret != RT_ERROR_NONE) { + GELOGE(RT_FAILED, "Call rt api failed, ret: 0x%X", rt_ret); + return nullptr; + } + + rt_ret = rtLabelListCpy(label_list.data(), label_list.size(), label_info, label_info_size); + if (rt_ret != RT_ERROR_NONE) { + GELOGE(RT_FAILED, "Call rt api failed, ret: 0x%X", rt_ret); + return nullptr; + } + + auto label_guard = std::make_shared(label_info); + label_map.emplace(label_id_str, label_guard); + return label_guard; +} +} // namespace model_runner +} // namespace ge diff --git a/ge/ge_runtime/task/label_manager.h b/ge/ge_runtime/task/label_manager.h new file mode 100644 index 00000000..f2c42c29 --- /dev/null +++ b/ge/ge_runtime/task/label_manager.h @@ -0,0 +1,54 @@ +/** + * Copyright 2021 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. + */ +#ifndef GE_GE_RUNTIME_TASK_LABEL_MANAGER_H_ +#define GE_GE_RUNTIME_TASK_LABEL_MANAGER_H_ + +#include +#include +#include +#include +#include + +namespace ge { +namespace model_runner { +class LabelGuard { + public: + explicit LabelGuard(void *label_info) : label_info_(reinterpret_cast(label_info)) {} + ~LabelGuard(); + void *GetLabelInfo() { return reinterpret_cast(label_info_); } + + private: + uintptr_t label_info_; +}; + +class LabelManager { + public: + static std::shared_ptr GetInstance(); + std::shared_ptr GetLabelInfo(rtModel_t model, const std::vector &label_ids, + const std::vector &all_label); + + private: + std::mutex model_info_mapping_mutex_; + std::map>> model_info_mapping_; + + static std::weak_ptr instance_; + static std::mutex instance_mutex_; +}; + + +} // namespace model_runner +} // namespace ge +#endif // GE_GE_RUNTIME_TASK_LABEL_MANAGER_H_ \ No newline at end of file diff --git a/ge/ge_runtime/task/label_switch_task.cc b/ge/ge_runtime/task/label_switch_task.cc index 8c795da9..cde278d9 100644 --- a/ge/ge_runtime/task/label_switch_task.cc +++ b/ge/ge_runtime/task/label_switch_task.cc @@ -24,14 +24,14 @@ LabelSwitchTask::LabelSwitchTask(const ModelContext &model_context, : TaskRepeater(model_context, task_info), task_info_(task_info), stream_(nullptr), - all_label_resource_(), label_info_(nullptr) { if (task_info_ == nullptr) { GELOGW("task_info_ is null!"); return; } - all_label_resource_ = model_context.label_list(); + rt_model_handle_ = model_context.rt_model_handle(); + auto all_label_resource = model_context.label_list(); auto stream_list = model_context.stream_list(); uint32_t stream_id = task_info->stream_id(); GELOGI("Stream list size:%zu, stream id:%u.", stream_list.size(), stream_id); @@ -40,18 +40,16 @@ LabelSwitchTask::LabelSwitchTask(const ModelContext &model_context, return; } stream_ = stream_list[stream_id]; -} - -LabelSwitchTask::~LabelSwitchTask() { - if (label_info_ != nullptr) { - rtError_t rt_ret = rtFree(label_info_); - if (rt_ret != RT_ERROR_NONE) { - GELOGE(RT_FAILED, "rtFree fwkOpBuf failed! ret: 0x%X.", rt_ret); - } - label_info_ = nullptr; + label_manager_ = LabelManager::GetInstance(); + if (label_manager_ == nullptr) { + GELOGW("Get label manager instance failed."); + return; } + label_info_ = label_manager_->GetLabelInfo(rt_model_handle_, task_info_->label_list(), all_label_resource); } +LabelSwitchTask::~LabelSwitchTask() {} + bool LabelSwitchTask::Distribute() { GELOGI("LabelSwitchTask Distribute start."); if (!CheckParamValid()) { @@ -117,8 +115,8 @@ bool LabelSwitchTask::CheckParamValid() { return false; } - if (label_info_ != nullptr) { - GELOGE(PARAM_INVALID, "label_info_ has dirty data."); + if (label_info_ == nullptr) { + GELOGE(PARAM_INVALID, "CopyLabelList failed, label info is null."); return false; } @@ -126,6 +124,5 @@ bool LabelSwitchTask::CheckParamValid() { } REGISTER_TASK(TaskInfoType::LABEL_SWITCH, LabelSwitchTask, LabelSwitchTaskInfo); - } // namespace model_runner } // namespace ge diff --git a/ge/ge_runtime/task/label_switch_task.h b/ge/ge_runtime/task/label_switch_task.h index 463faa31..cfa6877c 100644 --- a/ge/ge_runtime/task/label_switch_task.h +++ b/ge/ge_runtime/task/label_switch_task.h @@ -19,6 +19,7 @@ #include #include "ge_runtime/task/task.h" +#include "ge_runtime/task/label_manager.h" namespace ge { namespace model_runner { @@ -35,8 +36,9 @@ class LabelSwitchTask : public TaskRepeater { std::shared_ptr task_info_; void *stream_; - std::vector all_label_resource_; - void *label_info_; + rtModel_t rt_model_handle_; + std::shared_ptr label_info_; + std::shared_ptr label_manager_; }; } // namespace model_runner } // namespace ge diff --git a/inc/external/acl/acl.h b/inc/external/acl/acl.h new file mode 100644 index 00000000..8d261201 --- /dev/null +++ b/inc/external/acl/acl.h @@ -0,0 +1,82 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef INC_EXTERNAL_ACL_ACL_H_ +#define INC_EXTERNAL_ACL_ACL_H_ + +#include "acl_rt.h" +#include "acl_op.h" +#include "acl_mdl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +// Current version is 1.0.0 +#define ACL_MAJOR_VERSION 1 +#define ACL_MINOR_VERSION 0 +#define ACL_PATCH_VERSION 0 + +/** + * @ingroup AscendCL + * @brief acl initialize + * + * @par Restriction + * The aclInit interface can be called only once in a process + * @param configPath [IN] the config path,it can be NULL + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclInit(const char *configPath); + +/** + * @ingroup AscendCL + * @brief acl finalize + * + * @par Restriction + * Need to call aclFinalize before the process exits. + * After calling aclFinalize,the services cannot continue to be used normally. + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclFinalize(); + +/** + * @ingroup AscendCL + * @brief query ACL interface version + * + * @param majorVersion[OUT] ACL interface major version + * @param minorVersion[OUT] ACL interface minor version + * @param patchVersion[OUT] ACL interface patch version + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtGetVersion(int32_t *majorVersion, int32_t *minorVersion, int32_t *patchVersion); + +/** + * @ingroup AscendCL + * @brief get recent error message + * + * @retval null for failed + * @retval OtherValues success + */ +ACL_FUNC_VISIBILITY const char *aclGetRecentErrMsg(); + +#ifdef __cplusplus +} +#endif + +#endif // INC_EXTERNAL_ACL_ACL_H_ diff --git a/inc/external/acl/acl_base.h b/inc/external/acl/acl_base.h new file mode 100644 index 00000000..64d4bd81 --- /dev/null +++ b/inc/external/acl/acl_base.h @@ -0,0 +1,638 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef INC_EXTERNAL_ACL_ACL_BASE_H_ +#define INC_EXTERNAL_ACL_ACL_BASE_H_ + +#include +#include +#include "error_codes/rt_error_codes.h" +#include "error_codes/ge_error_codes.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_MSC_VER) +#ifdef FUNC_VISIBILITY +#define ACL_FUNC_VISIBILITY _declspec(dllexport) +#else +#define ACL_FUNC_VISIBILITY +#endif +#else +#ifdef FUNC_VISIBILITY +#define ACL_FUNC_VISIBILITY __attribute__((visibility("default"))) +#else +#define ACL_FUNC_VISIBILITY +#endif +#endif + +#ifdef __GNUC__ +#define ACL_DEPRECATED __attribute__((deprecated)) +#define ACL_DEPRECATED_MESSAGE(message) __attribute__((deprecated(message))) +#elif defined(_MSC_VER) +#define ACL_DEPRECATED __declspec(deprecated) +#define ACL_DEPRECATED_MESSAGE(message) __declspec(deprecated(message)) +#else +#define ACL_DEPRECATED +#define ACL_DEPRECATED_MESSAGE(message) +#endif + +typedef void *aclrtStream; +typedef void *aclrtEvent; +typedef void *aclrtContext; +typedef int aclError; +typedef uint16_t aclFloat16; +typedef struct aclDataBuffer aclDataBuffer; +typedef struct aclTensorDesc aclTensorDesc; + +static const int ACL_ERROR_NONE = 0; +static const int ACL_SUCCESS = 0; + +static const int ACL_ERROR_INVALID_PARAM = 100000; +static const int ACL_ERROR_UNINITIALIZE = 100001; +static const int ACL_ERROR_REPEAT_INITIALIZE = 100002; +static const int ACL_ERROR_INVALID_FILE = 100003; +static const int ACL_ERROR_WRITE_FILE = 100004; +static const int ACL_ERROR_INVALID_FILE_SIZE = 100005; +static const int ACL_ERROR_PARSE_FILE = 100006; +static const int ACL_ERROR_FILE_MISSING_ATTR = 100007; +static const int ACL_ERROR_FILE_ATTR_INVALID = 100008; +static const int ACL_ERROR_INVALID_DUMP_CONFIG = 100009; +static const int ACL_ERROR_INVALID_PROFILING_CONFIG = 100010; +static const int ACL_ERROR_INVALID_MODEL_ID = 100011; +static const int ACL_ERROR_DESERIALIZE_MODEL = 100012; +static const int ACL_ERROR_PARSE_MODEL = 100013; +static const int ACL_ERROR_READ_MODEL_FAILURE = 100014; +static const int ACL_ERROR_MODEL_SIZE_INVALID = 100015; +static const int ACL_ERROR_MODEL_MISSING_ATTR = 100016; +static const int ACL_ERROR_MODEL_INPUT_NOT_MATCH = 100017; +static const int ACL_ERROR_MODEL_OUTPUT_NOT_MATCH = 100018; +static const int ACL_ERROR_MODEL_NOT_DYNAMIC = 100019; +static const int ACL_ERROR_OP_TYPE_NOT_MATCH = 100020; +static const int ACL_ERROR_OP_INPUT_NOT_MATCH = 100021; +static const int ACL_ERROR_OP_OUTPUT_NOT_MATCH = 100022; +static const int ACL_ERROR_OP_ATTR_NOT_MATCH = 100023; +static const int ACL_ERROR_OP_NOT_FOUND = 100024; +static const int ACL_ERROR_OP_LOAD_FAILED = 100025; +static const int ACL_ERROR_UNSUPPORTED_DATA_TYPE = 100026; +static const int ACL_ERROR_FORMAT_NOT_MATCH = 100027; +static const int ACL_ERROR_BIN_SELECTOR_NOT_REGISTERED = 100028; +static const int ACL_ERROR_KERNEL_NOT_FOUND = 100029; +static const int ACL_ERROR_BIN_SELECTOR_ALREADY_REGISTERED = 100030; +static const int ACL_ERROR_KERNEL_ALREADY_REGISTERED = 100031; +static const int ACL_ERROR_INVALID_QUEUE_ID = 100032; +static const int ACL_ERROR_REPEAT_SUBSCRIBE = 100033; +static const int ACL_ERROR_STREAM_NOT_SUBSCRIBE = 100034; +static const int ACL_ERROR_THREAD_NOT_SUBSCRIBE = 100035; +static const int ACL_ERROR_WAIT_CALLBACK_TIMEOUT = 100036; +static const int ACL_ERROR_REPEAT_FINALIZE = 100037; +static const int ACL_ERROR_NOT_STATIC_AIPP = 100038; +static const int ACL_ERROR_COMPILING_STUB_MODE = 100039; +static const int ACL_ERROR_GROUP_NOT_SET = 100040; +static const int ACL_ERROR_GROUP_NOT_CREATE = 100041; +static const int ACL_ERROR_PROF_ALREADY_RUN = 100042; +static const int ACL_ERROR_PROF_NOT_RUN = 100043; +static const int ACL_ERROR_DUMP_ALREADY_RUN = 100044; +static const int ACL_ERROR_DUMP_NOT_RUN = 100045; +static const int ACL_ERROR_PROF_REPEAT_SUBSCRIBE = 148046; +static const int ACL_ERROR_PROF_API_CONFLICT = 148047; +static const int ACL_ERROR_INVALID_MAX_OPQUEUE_NUM_CONFIG = 148048; +static const int ACL_ERROR_INVALID_OPP_PATH = 148049; +static const int ACL_ERROR_OP_UNSUPPORTED_DYNAMIC = 148050; + +static const int ACL_ERROR_BAD_ALLOC = 200000; +static const int ACL_ERROR_API_NOT_SUPPORT = 200001; +static const int ACL_ERROR_INVALID_DEVICE = 200002; +static const int ACL_ERROR_MEMORY_ADDRESS_UNALIGNED = 200003; +static const int ACL_ERROR_RESOURCE_NOT_MATCH = 200004; +static const int ACL_ERROR_INVALID_RESOURCE_HANDLE = 200005; +static const int ACL_ERROR_FEATURE_UNSUPPORTED = 200006; +static const int ACL_ERROR_PROF_MODULES_UNSUPPORTED = 200007; + +static const int ACL_ERROR_STORAGE_OVER_LIMIT = 300000; + +static const int ACL_ERROR_INTERNAL_ERROR = 500000; +static const int ACL_ERROR_FAILURE = 500001; +static const int ACL_ERROR_GE_FAILURE = 500002; +static const int ACL_ERROR_RT_FAILURE = 500003; +static const int ACL_ERROR_DRV_FAILURE = 500004; +static const int ACL_ERROR_PROFILING_FAILURE = 500005; + +#define ACL_TENSOR_SHAPE_RANGE_NUM 2 +#define ACL_UNKNOWN_RANK 0xFFFFFFFFFFFFFFFE + +typedef enum { + ACL_DT_UNDEFINED = -1, + ACL_FLOAT = 0, + ACL_FLOAT16 = 1, + ACL_INT8 = 2, + ACL_INT32 = 3, + ACL_UINT8 = 4, + ACL_INT16 = 6, + ACL_UINT16 = 7, + ACL_UINT32 = 8, + ACL_INT64 = 9, + ACL_UINT64 = 10, + ACL_DOUBLE = 11, + ACL_BOOL = 12, + ACL_STRING = 13, +} aclDataType; + +typedef enum { + ACL_FORMAT_UNDEFINED = -1, + ACL_FORMAT_NCHW = 0, + ACL_FORMAT_NHWC = 1, + ACL_FORMAT_ND = 2, + ACL_FORMAT_NC1HWC0 = 3, + ACL_FORMAT_FRACTAL_Z = 4, + ACL_FORMAT_NC1HWC0_C04 = 12, + ACL_FORMAT_NDHWC = 27, + ACL_FORMAT_FRACTAL_NZ = 29, + ACL_FORMAT_NCDHW = 30, + ACL_FORMAT_NDC1HWC0 = 32, + ACL_FRACTAL_Z_3D = 33 +} aclFormat; + +typedef enum { + ACL_DEBUG = 0, + ACL_INFO = 1, + ACL_WARNING = 2, + ACL_ERROR = 3, +} aclLogLevel; + +typedef enum { + ACL_MEMTYPE_DEVICE = 0, + ACL_MEMTYPE_HOST = 1, +} aclMemType; + +/** + * @ingroup AscendCL + * @brief Converts data of type aclFloat16 to data of type float + * + * @param value [IN] Data to be converted + * + * @retval Transformed data + */ +ACL_FUNC_VISIBILITY float aclFloat16ToFloat(aclFloat16 value); + +/** + * @ingroup AscendCL + * @brief Converts data of type float to data of type aclFloat16 + * + * @param value [IN] Data to be converted + * + * @retval Transformed data + */ +ACL_FUNC_VISIBILITY aclFloat16 aclFloatToFloat16(float value); + +/** + * @ingroup AscendCL + * @brief create data of aclDataBuffer + * + * @param data [IN] pointer to data + * @li Need to be managed by the user, + * call aclrtMalloc interface to apply for memory, + * call aclrtFree interface to release memory + * + * @param size [IN] size of data in bytes + * + * @retval pointer to created instance. nullptr if run out of memory + * + * @see aclrtMalloc | aclrtFree + */ +ACL_FUNC_VISIBILITY aclDataBuffer *aclCreateDataBuffer(void *data, size_t size); + +/** + * @ingroup AscendCL + * @brief destroy data of aclDataBuffer + * + * @par Function + * Only the aclDataBuffer type data is destroyed here. + * The memory of the data passed in when the aclDataDataBuffer interface + * is called to create aclDataBuffer type data must be released by the user + * + * @param dataBuffer [IN] pointer to the aclDataBuffer + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclCreateDataBuffer + */ +ACL_FUNC_VISIBILITY aclError aclDestroyDataBuffer(const aclDataBuffer *dataBuffer); + +/** + * @ingroup AscendCL + * @brief update new data of aclDataBuffer + * + * @param dataBuffer [OUT] pointer to aclDataBuffer + * @li The old data need to be released by the user, otherwise it may occur memory leak leakage + * call aclGetDataBufferAddr interface to get old data address + * call aclrtFree interface to release memory + * + * @param data [IN] pointer to new data + * @li Need to be managed by the user, + * call aclrtMalloc interface to apply for memory, + * call aclrtFree interface to release memory + * + * @param size [IN] size of data in bytes + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtMalloc | aclrtFree | aclGetDataBufferAddr + */ +ACL_FUNC_VISIBILITY aclError aclUpdateDataBuffer(aclDataBuffer *dataBuffer, void *data, size_t size); + +/** + * @ingroup AscendCL + * @brief get data address from aclDataBuffer + * + * @param dataBuffer [IN] pointer to the data of aclDataBuffer + * + * @retval data address + */ +ACL_FUNC_VISIBILITY void *aclGetDataBufferAddr(const aclDataBuffer *dataBuffer); + +/** + * @ingroup AscendCL + * @brief get data size of aclDataBuffer + * + * @param dataBuffer [IN] pointer to the data of aclDataBuffer + * + * @retval data size + */ +ACL_DEPRECATED_MESSAGE("aclGetDataBufferSize is deprecated, use aclGetDataBufferSizeV2 instead") +ACL_FUNC_VISIBILITY uint32_t aclGetDataBufferSize(const aclDataBuffer *dataBuffer); + +/** + * @ingroup AscendCL + * @brief get data size of aclDataBuffer to replace aclGetDataBufferSize + * + * @param dataBuffer [IN] pointer to the data of aclDataBuffer + * + * @retval data size + */ +ACL_FUNC_VISIBILITY size_t aclGetDataBufferSizeV2(const aclDataBuffer *dataBuffer); + +/** + * @ingroup AscendCL + * @brief get size of aclDataType + * + * @param dataType [IN] aclDataType data the size to get + * + * @retval size of the aclDataType + */ +ACL_FUNC_VISIBILITY size_t aclDataTypeSize(aclDataType dataType); + +// interfaces of tensor desc +/** + * @ingroup AscendCL + * @brief create data aclTensorDesc + * + * @param dataType [IN] Data types described by tensor + * @param numDims [IN] the number of dimensions of the shape + * @param dims [IN] the size of the specified dimension + * @param format [IN] tensor format + * + * @retval aclTensorDesc pointer. + * @retval nullptr if param is invalid or run out of memory + */ +ACL_FUNC_VISIBILITY aclTensorDesc *aclCreateTensorDesc(aclDataType dataType, int numDims, const int64_t *dims, + aclFormat format); + +/** + * @ingroup AscendCL + * @brief destroy data aclTensorDesc + * + * @param desc [IN] pointer to the data of aclTensorDesc to destroy + */ +ACL_FUNC_VISIBILITY void aclDestroyTensorDesc(const aclTensorDesc *desc); + +/** + * @ingroup AscendCL + * @brief set tensor shape range for aclTensorDesc + * + * @param desc [OUT] pointer to the data of aclTensorDesc + * @param dimsCount [IN] the number of dimensions of the shape + * @param dimsRange [IN] the range of dimensions of the shape + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclSetTensorShapeRange(aclTensorDesc *desc, size_t dimsCount, + int64_t dimsRange[][ACL_TENSOR_SHAPE_RANGE_NUM]); + +/** + * @ingroup AscendCL + * @brief get data type specified by the tensor description + * + * @param desc [IN] pointer to the instance of aclTensorDesc + * + * @retval data type specified by the tensor description. + * @retval ACL_DT_UNDEFINED if description is null + */ +ACL_FUNC_VISIBILITY aclDataType aclGetTensorDescType(const aclTensorDesc *desc); + +/** + * @ingroup AscendCL + * @brief get data format specified by the tensor description + * + * @param desc [IN] pointer to the instance of aclTensorDesc + * + * @retval data format specified by the tensor description. + * @retval ACL_FORMAT_UNDEFINED if description is null + */ +ACL_FUNC_VISIBILITY aclFormat aclGetTensorDescFormat(const aclTensorDesc *desc); + +/** + * @ingroup AscendCL + * @brief get tensor size specified by the tensor description + * + * @param desc [IN] pointer to the instance of aclTensorDesc + * + * @retval data size specified by the tensor description. + * @retval 0 if description is null + */ +ACL_FUNC_VISIBILITY size_t aclGetTensorDescSize(const aclTensorDesc *desc); + +/** + * @ingroup AscendCL + * @brief get element count specified by the tensor description + * + * @param desc [IN] pointer to the instance of aclTensorDesc + * + * @retval element count specified by the tensor description. + * @retval 0 if description is null + */ +ACL_FUNC_VISIBILITY size_t aclGetTensorDescElementCount(const aclTensorDesc *desc); + +/** + * @ingroup AscendCL + * @brief get number of dims specified by the tensor description + * + * @param desc [IN] pointer to the instance of aclTensorDesc + * + * @retval number of dims specified by the tensor description. + * @retval 0 if description is null + * @retval ACL_UNKNOWN_RANK if the tensor dim is -2 + */ +ACL_FUNC_VISIBILITY size_t aclGetTensorDescNumDims(const aclTensorDesc *desc); + +/** + * @ingroup AscendCL + * @brief Get the size of the specified dim in the tensor description + * + * @param desc [IN] pointer to the instance of aclTensorDesc + * @param index [IN] index of dims, start from 0. + * + * @retval dim specified by the tensor description and index. + * @retval -1 if description or index is invalid + */ +ACL_DEPRECATED_MESSAGE("aclGetTensorDescDim is deprecated, use aclGetTensorDescDimV2 instead") +ACL_FUNC_VISIBILITY int64_t aclGetTensorDescDim(const aclTensorDesc *desc, size_t index); + +/** + * @ingroup AscendCL + * @brief Get the size of the specified dim in the tensor description + * + * @param desc [IN] pointer to the instance of aclTensorDesc + * @param index [IN] index of dims, start from 0. + * @param dimSize [OUT] size of the specified dim. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimV2(const aclTensorDesc *desc, size_t index, int64_t *dimSize); + +/** + * @ingroup AscendCL + * @brief Get the range of the specified dim in the tensor description + * + * @param desc [IN] pointer to the instance of aclTensorDesc + * @param index [IN] index of dims, start from 0. + * @param dimRangeNum [IN] number of dimRange. + * @param dimRange [OUT] range of the specified dim. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclGetTensorDescDimRange(const aclTensorDesc *desc, size_t index, size_t dimRangeNum, + int64_t *dimRange); + +/** + * @ingroup AscendCL + * @brief set tensor description name + * + * @param desc [OUT] pointer to the instance of aclTensorDesc + * @param name [IN] tensor description name + */ +ACL_FUNC_VISIBILITY void aclSetTensorDescName(aclTensorDesc *desc, const char *name); + +/** + * @ingroup AscendCL + * @brief get tensor description name + * + * @param desc [IN] pointer to the instance of aclTensorDesc + * + * @retval tensor description name. + * @retval empty string if description is null + */ +ACL_FUNC_VISIBILITY const char *aclGetTensorDescName(aclTensorDesc *desc); + +/** + * @ingroup AscendCL + * @brief Convert the format in the source aclTensorDesc according to + * the specified dstFormat to generate a new target aclTensorDesc. + * The format in the source aclTensorDesc remains unchanged. + * + * @param srcDesc [IN] pointer to the source tensor desc + * @param dstFormat [IN] destination format + * @param dstDesc [OUT] pointer to the pointer to the destination tensor desc + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclTransTensorDescFormat(const aclTensorDesc *srcDesc, aclFormat dstFormat, + aclTensorDesc **dstDesc); + +/** + * @ingroup AscendCL + * @brief Set the storage format specified by the tensor description + * + * @param desc [OUT] pointer to the instance of aclTensorDesc + * @param format [IN] the storage format + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_DEPRECATED_MESSAGE("aclSetTensorStorageFormat is deprecated, use aclSetTensorFormat instead") +ACL_FUNC_VISIBILITY aclError aclSetTensorStorageFormat(aclTensorDesc *desc, aclFormat format); + +/** + * @ingroup AscendCL + * @brief Set the storage shape specified by the tensor description + * + * @param desc [OUT] pointer to the instance of aclTensorDesc + * @param numDims [IN] the number of dimensions of the shape + * @param dims [IN] the size of the specified dimension + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_DEPRECATED_MESSAGE("aclSetTensorStorageShape is deprecated, use aclSetTensorShape instead") +ACL_FUNC_VISIBILITY aclError aclSetTensorStorageShape(aclTensorDesc *desc, int numDims, const int64_t *dims); + +/** + * @ingroup AscendCL + * @brief Set the format specified by the tensor description + * + * @param desc [OUT] pointer to the instance of aclTensorDesc + * @param format [IN] the storage format + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclSetTensorFormat(aclTensorDesc *desc, aclFormat format); + +/** + * @ingroup AscendCL + * @brief Set the shape specified by the tensor description + * + * @param desc [OUT] pointer to the instance of aclTensorDesc + * @param numDims [IN] the number of dimensions of the shape + * @param dims [IN] the size of the specified dimension + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclSetTensorShape(aclTensorDesc *desc, int numDims, const int64_t *dims); + +/** + * @ingroup AscendCL + * @brief Set the original format specified by the tensor description + * + * @param desc [OUT] pointer to the instance of aclTensorDesc + * @param format [IN] the storage format + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclSetTensorOriginFormat(aclTensorDesc *desc, aclFormat format); + +/** + * @ingroup AscendCL + * @brief Set the original shape specified by the tensor description + * + * @param desc [OUT] pointer to the instance of aclTensorDesc + * @param numDims [IN] the number of dimensions of the shape + * @param dims [IN] the size of the specified dimension + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclSetTensorOriginShape(aclTensorDesc *desc, int numDims, const int64_t *dims); + +/** + * @ingroup AscendCL + * @brief get op description info + * + * @param desc [IN] pointer to tensor description + * @param index [IN] index of tensor + * + * @retval null for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY aclTensorDesc *aclGetTensorDescByIndex(aclTensorDesc *desc, size_t index); + +/** + * @ingroup AscendCL + * @brief get address of tensor + * + * @param desc [IN] pointer to tensor description + * + * @retval null for failed + * @retval OtherValues success + */ +ACL_FUNC_VISIBILITY void *aclGetTensorDescAddress(const aclTensorDesc *desc); + +/** + * @ingroup AscendCL + * @brief Set the dynamic input name specified by the tensor description + * + * @param desc [OUT] pointer to the instance of aclTensorDesc + * @param dynamicInputName [IN] pointer to the dynamic input name + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclSetTensorDynamicInput(aclTensorDesc *desc, const char *dynamicInputName); + +/** + * @ingroup AscendCL + * @brief Set const data specified by the tensor description + * + * @param desc [OUT] pointer to the instance of aclTensorDesc + * @param dataBuffer [IN] pointer to the const databuffer + * @param length [IN] the length of const databuffer + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclSetTensorConst(aclTensorDesc *desc, void *dataBuffer, size_t length); + +/** + * @ingroup AscendCL + * @brief Set tensor memory type specified by the tensor description + * + * @param desc [OUT] pointer to the instance of aclTensorDesc + * @param memType [IN] ACL_MEMTYPE_DEVICE means device, ACL_MEMTYPE_HOST means host + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclSetTensorPlaceMent(aclTensorDesc *desc, aclMemType memType); + +/** + * @ingroup AscendCL + * @brief an interface for users to output APP logs + * + * @param logLevel [IN] the level of current log + * @param func [IN] the function where the log is located + * @param file [IN] the file where the log is located + * @param line [IN] Number of source lines where the log is located + * @param fmt [IN] the format of current log + * @param ... [IN] the value of current log + */ +ACL_FUNC_VISIBILITY void aclAppLog(aclLogLevel logLevel, const char *func, const char *file, uint32_t line, + const char *fmt, ...); + +/** + * @ingroup AscendCL + * @brief get soc name + * + * @retval null for failed + * @retval OtherValues success + */ +ACL_FUNC_VISIBILITY const char *aclrtGetSocName(); + +#define ACL_APP_LOG(level, fmt, ...) aclAppLog(level, __FUNCTION__, __FILE__, __LINE__, fmt, ##__VA_ARGS__) + +#ifdef __cplusplus +} +#endif + +#endif // INC_EXTERNAL_ACL_ACL_BASE_H_ diff --git a/inc/external/acl/acl_mdl.h b/inc/external/acl/acl_mdl.h new file mode 100644 index 00000000..2bf85e29 --- /dev/null +++ b/inc/external/acl/acl_mdl.h @@ -0,0 +1,1225 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef INC_EXTERNAL_ACL_ACL_MODEL_H_ +#define INC_EXTERNAL_ACL_ACL_MODEL_H_ + +#include +#include + +#include "acl_base.h" +#include "acl_rt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ACL_MAX_DIM_CNT 128 +#define ACL_MAX_TENSOR_NAME_LEN 128 +#define ACL_MAX_BATCH_NUM 128 +#define ACL_MAX_HW_NUM 128 +#define ACL_MAX_SHAPE_COUNT 128 +#define ACL_INVALID_NODE_INDEX 0xFFFFFFFF + +#define ACL_MDL_LOAD_FROM_FILE 1 +#define ACL_MDL_LOAD_FROM_FILE_WITH_MEM 2 +#define ACL_MDL_LOAD_FROM_MEM 3 +#define ACL_MDL_LOAD_FROM_MEM_WITH_MEM 4 +#define ACL_MDL_LOAD_FROM_FILE_WITH_Q 5 +#define ACL_MDL_LOAD_FROM_MEM_WITH_Q 6 + +#define ACL_DYNAMIC_TENSOR_NAME "ascend_mbatch_shape_data" +#define ACL_DYNAMIC_AIPP_NAME "ascend_dynamic_aipp_data" +#define ACL_ATTR_NAME_DATA_DUMP_ORIGIN_OP_NAMES "_datadump_original_op_names" + +typedef struct aclmdlDataset aclmdlDataset; +typedef struct aclmdlDesc aclmdlDesc; +typedef struct aclmdlAIPP aclmdlAIPP; +typedef struct aclAippExtendInfo aclAippExtendInfo; +typedef struct aclmdlConfigHandle aclmdlConfigHandle; + +typedef enum { + ACL_YUV420SP_U8 = 1, + ACL_XRGB8888_U8, + ACL_RGB888_U8, + ACL_YUV400_U8, + ACL_NC1HWC0DI_FP16, + ACL_NC1HWC0DI_S8, + ACL_ARGB8888_U8, + ACL_YUYV_U8, + ACL_YUV422SP_U8, + ACL_AYUV444_U8, + ACL_RAW10, + ACL_RAW12, + ACL_RAW16, + ACL_RAW24, + ACL_AIPP_RESERVED = 0xffff, +} aclAippInputFormat; + +typedef enum { + ACL_MDL_PRIORITY_INT32 = 0, + ACL_MDL_LOAD_TYPE_SIZET, + ACL_MDL_PATH_PTR, /**< pointer to model load path with deep copy */ + ACL_MDL_MEM_ADDR_PTR, /**< pointer to model memory with shallow copy */ + ACL_MDL_MEM_SIZET, + ACL_MDL_WEIGHT_ADDR_PTR, /**< pointer to weight memory of model with shallow copy */ + ACL_MDL_WEIGHT_SIZET, + ACL_MDL_WORKSPACE_ADDR_PTR, /**< pointer to worksapce memory of model with shallow copy */ + ACL_MDL_WORKSPACE_SIZET, + ACL_MDL_INPUTQ_NUM_SIZET, + ACL_MDL_INPUTQ_ADDR_PTR, /**< pointer to inputQ with shallow copy */ + ACL_MDL_OUTPUTQ_NUM_SIZET, + ACL_MDL_OUTPUTQ_ADDR_PTR /**< pointer to outputQ with shallow copy */ +} aclmdlConfigAttr; + +typedef enum { + ACL_DATA_WITHOUT_AIPP = 0, + ACL_DATA_WITH_STATIC_AIPP, + ACL_DATA_WITH_DYNAMIC_AIPP, + ACL_DYNAMIC_AIPP_NODE +} aclmdlInputAippType; + +typedef struct aclmdlIODims { + char name[ACL_MAX_TENSOR_NAME_LEN]; /**< tensor name */ + size_t dimCount; /**< dim array count */ + int64_t dims[ACL_MAX_DIM_CNT]; /**< dim data array */ +} aclmdlIODims; + +typedef struct aclAippDims { + aclmdlIODims srcDims; /**< input dims before model transform */ + size_t srcSize; /**< input size before model transform */ + aclmdlIODims aippOutdims; /**< aipp output dims */ + size_t aippOutSize; /**< aipp output size */ +} aclAippDims; + +typedef struct aclmdlBatch { + size_t batchCount; /**< batch array count */ + uint64_t batch[ACL_MAX_BATCH_NUM]; /**< batch data array */ +} aclmdlBatch; + +typedef struct aclmdlHW { + size_t hwCount; /**< height&width array count */ + uint64_t hw[ACL_MAX_HW_NUM][2]; /**< height&width data array */ +} aclmdlHW; + +typedef struct aclAippInfo { + aclAippInputFormat inputFormat; + int32_t srcImageSizeW; + int32_t srcImageSizeH; + int8_t cropSwitch; + int32_t loadStartPosW; + int32_t loadStartPosH; + int32_t cropSizeW; + int32_t cropSizeH; + int8_t resizeSwitch; + int32_t resizeOutputW; + int32_t resizeOutputH; + int8_t paddingSwitch; + int32_t leftPaddingSize; + int32_t rightPaddingSize; + int32_t topPaddingSize; + int32_t bottomPaddingSize; + int8_t cscSwitch; + int8_t rbuvSwapSwitch; + int8_t axSwapSwitch; + int8_t singleLineMode; + int32_t matrixR0C0; + int32_t matrixR0C1; + int32_t matrixR0C2; + int32_t matrixR1C0; + int32_t matrixR1C1; + int32_t matrixR1C2; + int32_t matrixR2C0; + int32_t matrixR2C1; + int32_t matrixR2C2; + int32_t outputBias0; + int32_t outputBias1; + int32_t outputBias2; + int32_t inputBias0; + int32_t inputBias1; + int32_t inputBias2; + int32_t meanChn0; + int32_t meanChn1; + int32_t meanChn2; + int32_t meanChn3; + float minChn0; + float minChn1; + float minChn2; + float minChn3; + float varReciChn0; + float varReciChn1; + float varReciChn2; + float varReciChn3; + aclFormat srcFormat; + aclDataType srcDatatype; + size_t srcDimNum; + size_t shapeCount; + aclAippDims outDims[ACL_MAX_SHAPE_COUNT]; + aclAippExtendInfo *aippExtend; /**< reserved parameters, current version needs to be null */ +} aclAippInfo; + +/** + * @ingroup AscendCL + * @brief Create data of type aclmdlDesc + * + * @retval the aclmdlDesc pointer + */ +ACL_FUNC_VISIBILITY aclmdlDesc *aclmdlCreateDesc(); + +/** + * @ingroup AscendCL + * @brief destroy data of type aclmdlDesc + * + * @param modelDesc [IN] Pointer to almdldlDesc to be destroyed + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlDestroyDesc(aclmdlDesc *modelDesc); + +/** + * @ingroup AscendCL + * @brief Get aclmdlDesc data of the model according to the model ID + * + * @param modelDesc [OUT] aclmdlDesc pointer + * @param modelId [IN] model id + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetDesc(aclmdlDesc *modelDesc, uint32_t modelId); + +/** + * @ingroup AscendCL + * @brief Get the number of the inputs of + * the model according to data of aclmdlDesc + * + * @param modelDesc [IN] aclmdlDesc pointer + * + * @retval input size with aclmdlDesc + */ +ACL_FUNC_VISIBILITY size_t aclmdlGetNumInputs(aclmdlDesc *modelDesc); + +/** + * @ingroup AscendCL + * @brief Get the number of the output of + * the model according to data of aclmdlDesc + * + * @param modelDesc [IN] aclmdlDesc pointer + * + * @retval output size with aclmdlDesc + */ +ACL_FUNC_VISIBILITY size_t aclmdlGetNumOutputs(aclmdlDesc *modelDesc); + +/** + * @ingroup AscendCL + * @brief Get the size of the specified input according to + * the data of type aclmdlDesc + * + * @param modelDesc [IN] aclmdlDesc pointer + * @param index [IN] the size of the number of inputs to be obtained, + * the index value starts from 0 + * + * @retval Specify the size of the input + */ +ACL_FUNC_VISIBILITY size_t aclmdlGetInputSizeByIndex(aclmdlDesc *modelDesc, size_t index); + +/** + * @ingroup AscendCL + * @brief Get the size of the specified output according to + * the data of type aclmdlDesc + * + * @param modelDesc [IN] aclmdlDesc pointer + * @param index [IN] the size of the number of outputs to be obtained, + * the index value starts from 0 + * + * @retval Specify the size of the output + */ +ACL_FUNC_VISIBILITY size_t aclmdlGetOutputSizeByIndex(aclmdlDesc *modelDesc, size_t index); + +/** + * @ingroup AscendCL + * @brief Create data of type aclmdlDataset + * + * @retval the aclmdlDataset pointer + */ +ACL_FUNC_VISIBILITY aclmdlDataset *aclmdlCreateDataset(); + +/** + * @ingroup AscendCL + * @brief destroy data of type aclmdlDataset + * + * @param dataset [IN] Pointer to aclmdlDataset to be destroyed + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlDestroyDataset(const aclmdlDataset *dataset); + +/** + * @ingroup AscendCL + * @brief Add aclDataBuffer to aclmdlDataset + * + * @param dataset [OUT] aclmdlDataset address of aclDataBuffer to be added + * @param dataBuffer [IN] aclDataBuffer address to be added + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlAddDatasetBuffer(aclmdlDataset *dataset, aclDataBuffer *dataBuffer); + +/** + * @ingroup AscendCL + * @brief Set aclTensorDesc to aclmdlDataset + * + * @param dataset [OUT] aclmdlDataset address of aclDataBuffer to be added + * @param tensorDesc [IN] aclTensorDesc address to be added + * @param index [IN] index of tensorDesc which to be added + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetDatasetTensorDesc(aclmdlDataset *dataset, aclTensorDesc *tensorDesc, + size_t index); + +/** + * @ingroup AscendCL + * @brief Get the number of aclDataBuffer in aclmdlDataset + * + * @param dataset [IN] aclmdlDataset poiter + * + * @retval the number of aclDataBuffer + */ +ACL_FUNC_VISIBILITY size_t aclmdlGetDatasetNumBuffers(const aclmdlDataset *dataset); + +/** + * @ingroup AscendCL + * @brief Get the aclDataBuffer in aclmdlDataset by index + * + * @param dataset [IN] aclmdlDataset poiter + * @param index [IN] the index of aclDataBuffer + * + * @retval Get successfully, return the address of aclDataBuffer + * @retval Failure return NULL + */ +ACL_FUNC_VISIBILITY aclDataBuffer *aclmdlGetDatasetBuffer(const aclmdlDataset *dataset, size_t index); + +/** + * @ingroup AscendCL + * @brief Load offline model data from files + * and manage memory internally by the system + * + * @par Function + * After the system finishes loading the model, + * the model ID returned is used as a mark to identify the model + * during subsequent operations + * + * @param modelPath [IN] Storage path for offline model files + * @param modelId [OUT] Model ID generated after + * the system finishes loading the model + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFile(const char *modelPath, uint32_t *modelId); + +/** + * @ingroup AscendCL + * @brief Load offline model data from memory and manage the memory of + * model running internally by the system + * + * @par Function + * After the system finishes loading the model, + * the model ID returned is used as a mark to identify the model + * during subsequent operations + * + * @param model [IN] Model data stored in memory + * @param modelSize [IN] model data size + * @param modelId [OUT] Model ID generated after + * the system finishes loading the model + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMem(const void *model, size_t modelSize, uint32_t *modelId); + +/** + * @ingroup AscendCL + * @brief Load offline model data from a file, + * and the user manages the memory of the model run by itself + * + * @par Function + * After the system finishes loading the model, + * the model ID returned is used as a mark to identify the model + * during subsequent operations. + * @param modelPath [IN] Storage path for offline model files + * @param modelId [OUT] Model ID generated after finishes loading the model + * @param workPtr [IN] A pointer to the working memory + * required by the model on the Device,can be null + * @param workSize [IN] The amount of working memory required by the model + * @param weightPtr [IN] Pointer to model weight memory on Device + * @param weightSize [IN] The amount of weight memory required by the model + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithMem(const char *modelPath, uint32_t *modelId, void *workPtr, + size_t workSize, void *weightPtr, size_t weightSize); + +/** + * @ingroup AscendCL + * @brief Load offline model data from memory, + * and the user can manage the memory of model running + * + * @par Function + * After the system finishes loading the model, + * the model ID returned is used as a mark to identify the model + * during subsequent operations + * @param model [IN] Model data stored in memory + * @param modelSize [IN] model data size + * @param modelId [OUT] Model ID generated after finishes loading the model + * @param workPtr [IN] A pointer to the working memory + * required by the model on the Device,can be null + * @param workSize [IN] work memory size + * @param weightPtr [IN] Pointer to model weight memory on Device,can be null + * @param weightSize [IN] The amount of weight memory required by the model + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithMem(const void *model, size_t modelSize, uint32_t *modelId, + void *workPtr, size_t workSize, void *weightPtr, + size_t weightSize); + +/** + * @ingroup AscendCL + * @brief load model from file with async queue + * + * @param modelPath [IN] model path + * @param modelId [OUT] return model id if load success + * @param inputQ [IN] input queue pointer + * @param inputQNum [IN] input queue num + * @param outputQ [IN] output queue pointer + * @param outputQNum [IN] output queue num + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromFileWithQ(const char *modelPath, uint32_t *modelId, const uint32_t *inputQ, + size_t inputQNum, const uint32_t *outputQ, size_t outputQNum); + +/** + * @ingroup AscendCL + * @brief load model from memory with async queue + * + * @param model [IN] model memory which user manages + * @param modelSize [IN] model size + * @param modelId [OUT] return model id if load success + * @param inputQ [IN] input queue pointer + * @param inputQNum [IN] input queue num + * @param outputQ [IN] output queue pointer + * @param outputQNum [IN] output queue num + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlLoadFromMemWithQ(const void *model, size_t modelSize, uint32_t *modelId, + const uint32_t *inputQ, size_t inputQNum, const uint32_t *outputQ, + size_t outputQNum); + +/** + * @ingroup AscendCL + * @brief Execute model synchronous inference until the inference result is returned + * + * @param modelId [IN] ID of the model to perform inference + * @param input [IN] Input data for model inference + * @param output [OUT] Output data for model inference + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlExecute(uint32_t modelId, const aclmdlDataset *input, aclmdlDataset *output); + +/** + * @ingroup AscendCL + * @brief Execute model asynchronous inference until the inference result is returned + * + * @param modelId [IN] ID of the model to perform inference + * @param input [IN] Input data for model inference + * @param output [OUT] Output data for model inference + * @param stream [IN] stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | + * aclmdlLoadFromMemWithMem + */ +ACL_FUNC_VISIBILITY aclError aclmdlExecuteAsync(uint32_t modelId, const aclmdlDataset *input, aclmdlDataset *output, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief unload model with model id + * + * @param modelId [IN] model id to be unloaded + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlUnload(uint32_t modelId); + +/** + * @ingroup AscendCL + * @brief Get the weight memory size and working memory size + * required for model execution according to the model file + * + * @param fileName [IN] Model path to get memory information + * @param workSize [OUT] The amount of working memory for model executed + * @param weightSize [OUT] The amount of weight memory for model executed + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlQuerySize(const char *fileName, size_t *workSize, size_t *weightSize); + +/** + * @ingroup AscendCL + * @brief Obtain the weights required for + * model execution according to the model data in memory + * + * @par Restriction + * The execution and weight memory is Device memory, + * and requires user application and release. + * @param model [IN] model memory which user manages + * @param modelSize [IN] model data size + * @param workSize [OUT] The amount of working memory for model executed + * @param weightSize [OUT] The amount of weight memory for model executed + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlQuerySizeFromMem(const void *model, size_t modelSize, size_t *workSize, + size_t *weightSize); + +/** + * @ingroup AscendCL + * @brief In dynamic batch scenarios, + * it is used to set the number of images processed + * at one time during model inference + * + * @param modelId [IN] model id + * @param dataset [IN|OUT] data for model inference + * @param index [IN] index of dynamic tensor + * @param batchSize [IN] Number of images processed at a time during model + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | + * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetDynamicBatchSize(uint32_t modelId, aclmdlDataset *dataset, size_t index, + uint64_t batchSize); + +/** + * @ingroup AscendCL + * @brief Sets the H and W of the specified input of the model + * + * @param modelId [IN] model id + * @param dataset [IN|OUT] data for model inference + * @param index [IN] index of dynamic tensor + * @param height [IN] model height + * @param width [IN] model width + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | + * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetDynamicHWSize(uint32_t modelId, aclmdlDataset *dataset, size_t index, + uint64_t height, uint64_t width); + +/** + * @ingroup AscendCL + * @brief Sets the dynamic dims of the specified input of the model + * + * @param modelId [IN] model id + * @param dataset [IN|OUT] data for model inference + * @param index [IN] index of dynamic dims + * @param dims [IN] value of dynamic dims + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | + * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetInputDynamicDims(uint32_t modelId, aclmdlDataset *dataset, size_t index, + const aclmdlIODims *dims); + +/** + * @ingroup AscendCL + * @brief get input dims info + * + * @param modelDesc [IN] model description + * @param index [IN] input tensor index + * @param dims [OUT] dims info + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlGetInputDimsV2 + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetInputDims(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims); + +/** + * @ingroup AscendCL + * @brief get input dims info(version 2), especially for static aipp + * it is the same with aclmdlGetInputDims while model without static aipp + * + * @param modelDesc [IN] model description + * @param index [IN] input tensor index + * @param dims [OUT] dims info + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlGetInputDims + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetInputDimsV2(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims); + +/** + * @ingroup AscendCL + * @brief get output dims info + * + * @param modelDesc [IN] model description + * @param index [IN] output tensor index + * @param dims [OUT] dims info + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetOutputDims(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims); + +/** + * @ingroup AscendCL + * @brief get current output dims info + * + * @par Function + * The following use cases are supported: + * @li Get current output shape when model is dynamic and + * dynamic shape info is set + * @li Get max output shape when model is dynamic and + * dynamic shape info is not set + * @li Get actual output shape when model is static + * + * @param modelDesc [IN] model description + * @param index [IN] output tensor index + * @param dims [OUT] dims info + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetCurOutputDims(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims); + +/** + * @ingroup AscendCL + * @brief get attr value by op name + * + * @param modelDesc [IN] model description + * @param opName [IN] op name + * @param attr [IN] attr name + * + * @retval the attr value + */ +ACL_FUNC_VISIBILITY const char *aclmdlGetOpAttr(aclmdlDesc *modelDesc, const char *opName, const char *attr); + +/** + * @ingroup AscendCL + * @brief get input name by index + * + * @param modelDesc [IN] model description + * @param index [IN] intput tensor index + * + * @retval input tensor name,the same life cycle with modelDesc + */ +ACL_FUNC_VISIBILITY const char *aclmdlGetInputNameByIndex(const aclmdlDesc *modelDesc, size_t index); + +/** + * @ingroup AscendCL + * @brief get output name by index + * + * @param modelDesc [IN] model description + * @param index [IN] output tensor index + * + * @retval output tensor name,the same life cycle with modelDesc + */ +ACL_FUNC_VISIBILITY const char *aclmdlGetOutputNameByIndex(const aclmdlDesc *modelDesc, size_t index); + +/** + * @ingroup AscendCL + * @brief get input format by index + * + * @param modelDesc [IN] model description + * @param index [IN] intput tensor index + * + * @retval input tensor format + */ +ACL_FUNC_VISIBILITY aclFormat aclmdlGetInputFormat(const aclmdlDesc *modelDesc, size_t index); + +/** + * @ingroup AscendCL + * @brief get output format by index + * + * @param modelDesc [IN] model description + * @param index [IN] output tensor index + * + * @retval output tensor format + */ +ACL_FUNC_VISIBILITY aclFormat aclmdlGetOutputFormat(const aclmdlDesc *modelDesc, size_t index); + +/** + * @ingroup AscendCL + * @brief get input data type by index + * + * @param modelDesc [IN] model description + * @param index [IN] intput tensor index + * + * @retval input tensor data type + */ +ACL_FUNC_VISIBILITY aclDataType aclmdlGetInputDataType(const aclmdlDesc *modelDesc, size_t index); + +/** + * @ingroup AscendCL + * @brief get output data type by index + * + * @param modelDesc [IN] model description + * @param index [IN] output tensor index + * + * @retval output tensor data type + */ +ACL_FUNC_VISIBILITY aclDataType aclmdlGetOutputDataType(const aclmdlDesc *modelDesc, size_t index); + +/** + * @ingroup AscendCL + * @brief get input tensor index by name + * + * @param modelDesc [IN] model description + * @param name [IN] intput tensor name + * @param index [OUT] intput tensor index + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetInputIndexByName(const aclmdlDesc *modelDesc, const char *name, size_t *index); + +/** + * @ingroup AscendCL + * @brief get output tensor index by name + * + * @param modelDesc [IN] model description + * @param name [IN] output tensor name + * @param index [OUT] output tensor index + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetOutputIndexByName(const aclmdlDesc *modelDesc, const char *name, size_t *index); + +/** + * @ingroup AscendCL + * @brief get dynamic batch info + * + * @param modelDesc [IN] model description + * @param batch [OUT] dynamic batch info + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetDynamicBatch(const aclmdlDesc *modelDesc, aclmdlBatch *batch); + +/** + * @ingroup AscendCL + * @brief get dynamic height&width info + * + * @param modelDesc [IN] model description + * @param index [IN] input tensor index + * @param hw [OUT] dynamic height&width info + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetDynamicHW(const aclmdlDesc *modelDesc, size_t index, aclmdlHW *hw); + +/** + * @ingroup AscendCL + * @brief get dynamic gear count + * + * @param modelDesc [IN] model description + * @param index [IN] unused, must be -1 + * @param gearCount [OUT] dynamic gear count + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetInputDynamicGearCount(const aclmdlDesc *modelDesc, size_t index, + size_t *gearCount); + +/** + * @ingroup AscendCL + * @brief get dynamic dims info + * + * @param modelDesc [IN] model description + * @param index [IN] unused, must be -1 + * @param dims [OUT] value of dynamic dims + * @param gearCount [IN] dynamic gear count + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetInputDynamicDims(const aclmdlDesc *modelDesc, size_t index, aclmdlIODims *dims, + size_t gearCount); + +/** + * @ingroup AscendCL + * @brief Create data of type aclmdlAIPP + * + * @param batchSize [IN] batchsizes of model + * + * @retval the aclmdlAIPP pointer + */ +ACL_FUNC_VISIBILITY aclmdlAIPP *aclmdlCreateAIPP(uint64_t batchSize); + +/** + * @ingroup AscendCL + * @brief destroy data of type aclmdlAIPP + * + * @param aippParmsSet [IN] Pointer for aclmdlAIPP to be destroyed + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlDestroyAIPP(const aclmdlAIPP *aippParmsSet); + +/** + * @ingroup AscendCL + * @brief set InputFormat of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param inputFormat [IN] The inputFormat of aipp + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPInputFormat(aclmdlAIPP *aippParmsSet, aclAippInputFormat inputFormat); + +/** + * @ingroup AscendCL + * @brief set cscParms of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param csc_switch [IN] Csc switch + * @param cscMatrixR0C0 [IN] Csc_matrix_r0_c0 + * @param cscMatrixR0C1 [IN] Csc_matrix_r0_c1 + * @param cscMatrixR0C2 [IN] Csc_matrix_r0_c2 + * @param cscMatrixR1C0 [IN] Csc_matrix_r1_c0 + * @param cscMatrixR1C1 [IN] Csc_matrix_r1_c1 + * @param cscMatrixR1C2 [IN] Csc_matrix_r1_c2 + * @param cscMatrixR2C0 [IN] Csc_matrix_r2_c0 + * @param cscMatrixR2C1 [IN] Csc_matrix_r2_c1 + * @param cscMatrixR2C2 [IN] Csc_matrix_r2_c2 + * @param cscOutputBiasR0 [IN] Output Bias for RGB to YUV, element of row 0, unsigned number + * @param cscOutputBiasR1 [IN] Output Bias for RGB to YUV, element of row 1, unsigned number + * @param cscOutputBiasR2 [IN] Output Bias for RGB to YUV, element of row 2, unsigned number + * @param cscInputBiasR0 [IN] Input Bias for YUV to RGB, element of row 0, unsigned number + * @param cscInputBiasR1 [IN] Input Bias for YUV to RGB, element of row 1, unsigned number + * @param cscInputBiasR2 [IN] Input Bias for YUV to RGB, element of row 2, unsigned number + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, int8_t csc_switch, int16_t cscMatrixR0C0, + int16_t cscMatrixR0C1, int16_t cscMatrixR0C2, int16_t cscMatrixR1C0, + int16_t cscMatrixR1C1, int16_t cscMatrixR1C2, int16_t cscMatrixR2C0, + int16_t cscMatrixR2C1, int16_t cscMatrixR2C2, + uint8_t cscOutputBiasR0, uint8_t cscOutputBiasR1, + uint8_t cscOutputBiasR2, uint8_t cscInputBiasR0, + uint8_t cscInputBiasR1, uint8_t cscInputBiasR2); + +/** + * @ingroup AscendCL + * @brief set rb/ub swap switch of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param rbuvSwapSwitch [IN] rb/ub swap switch + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPRbuvSwapSwitch(aclmdlAIPP *aippParmsSet, int8_t rbuvSwapSwitch); + +/** + * @ingroup AscendCL + * @brief set RGBA->ARGB, YUVA->AYUV swap switch of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param axSwapSwitch [IN] RGBA->ARGB, YUVA->AYUV swap switch + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPAxSwapSwitch(aclmdlAIPP *aippParmsSet, int8_t axSwapSwitch); + +/** + * @ingroup AscendCL + * @brief set source image of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param srcImageSizeW [IN] Source image width + * @param srcImageSizeH [IN] Source image height + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPSrcImageSize(aclmdlAIPP *aippParmsSet, int32_t srcImageSizeW, + int32_t srcImageSizeH); + +/** + * @ingroup AscendCL + * @brief set resize switch of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param scfSwitch [IN] Resize switch + * @param scfInputSizeW [IN] Input width of scf + * @param scfInputSizeH [IN] Input height of scf + * @param scfOutputSizeW [IN] Output width of scf + * @param scfOutputSizeH [IN] Output height of scf + * @param batchIndex [IN] Batch parameter index + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPScfParams(aclmdlAIPP *aippParmsSet, int8_t scfSwitch, int32_t scfInputSizeW, + int32_t scfInputSizeH, int32_t scfOutputSizeW, + int32_t scfOutputSizeH, uint64_t batchIndex); + +/** + * @ingroup AscendCL + * @brief set cropParams of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param cropSwitch [IN] Crop switch + * @param cropStartPosW [IN] The start horizontal position of cropping + * @param cropStartPosH [IN] The start vertical position of cropping + * @param cropSizeW [IN] Crop width + * @param cropSizeH [IN] Crop height + * @param batchIndex [IN] Batch parameter index + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCropParams(aclmdlAIPP *aippParmsSet, int8_t cropSwitch, int32_t cropStartPosW, + int32_t cropStartPosH, int32_t cropSizeW, int32_t cropSizeH, + uint64_t batchIndex); + +/** + * @ingroup AscendCL + * @brief set paddingParams of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param paddingSwitch [IN] Padding switch + * @param paddingSizeTop [IN] Top padding size + * @param paddingSizeBottom [IN] Bottom padding size + * @param paddingSizeLeft [IN] Left padding size + * @param paddingSizeRight [IN] Right padding size + * @param batchIndex [IN] Batch parameter index + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPaddingParams(aclmdlAIPP *aippParmsSet, int8_t paddingSwitch, + int32_t paddingSizeTop, int32_t paddingSizeBottom, + int32_t paddingSizeLeft, int32_t paddingSizeRight, + uint64_t batchIndex); + +/** + * @ingroup AscendCL + * @brief set DtcPixelMean of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param dtcPixelMeanChn0 [IN] Mean value of channel 0 + * @param dtcPixelMeanChn1 [IN] Mean value of channel 1 + * @param dtcPixelMeanChn2 [IN] Mean value of channel 2 + * @param dtcPixelMeanChn3 [IN] Mean value of channel 3 + * @param batchIndex [IN] Batch parameter index + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMean(aclmdlAIPP *aippParmsSet, int16_t dtcPixelMeanChn0, + int16_t dtcPixelMeanChn1, int16_t dtcPixelMeanChn2, + int16_t dtcPixelMeanChn3, uint64_t batchIndex); + +/** + * @ingroup AscendCL + * @brief set DtcPixelMin of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param dtcPixelMinChn0 [IN] Min value of channel 0 + * @param dtcPixelMinChn1 [IN] Min value of channel 1 + * @param dtcPixelMinChn2 [IN] Min value of channel 2 + * @param dtcPixelMinChn3 [IN] Min value of channel 3 + * @param batchIndex [IN] Batch parameter index + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPDtcPixelMin(aclmdlAIPP *aippParmsSet, float dtcPixelMinChn0, + float dtcPixelMinChn1, float dtcPixelMinChn2, + float dtcPixelMinChn3, uint64_t batchIndex); + +/** + * @ingroup AscendCL + * @brief set PixelVarReci of type aclmdlAIPP + * + * @param aippParmsSet [OUT] Pointer for aclmdlAIPP + * @param dtcPixelVarReciChn0 [IN] sfr_dtc_pixel_variance_reci_ch0 + * @param dtcPixelVarReciChn1 [IN] sfr_dtc_pixel_variance_reci_ch1 + * @param dtcPixelVarReciChn2 [IN] sfr_dtc_pixel_variance_reci_ch2 + * @param dtcPixelVarReciChn3 [IN] sfr_dtc_pixel_variance_reci_ch3 + * @param batchIndex [IN] Batch parameter index + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateAIPP + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPPixelVarReci(aclmdlAIPP *aippParmsSet, float dtcPixelVarReciChn0, + float dtcPixelVarReciChn1, float dtcPixelVarReciChn2, + float dtcPixelVarReciChn3, uint64_t batchIndex); + +/** + * @ingroup AscendCL + * @brief set aipp parameters to model + * + * @param modelId [IN] model id + * @param dataset [IN] Pointer of dataset + * @param index [IN] index of input for aipp data(ACL_DYNAMIC_AIPP_NODE) + * @param aippParmsSet [IN] Pointer for aclmdlAIPP + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | + * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetInputAIPP(uint32_t modelId, aclmdlDataset *dataset, size_t index, + const aclmdlAIPP *aippParmsSet); + +/** + * @ingroup AscendCL + * @brief set aipp parameters to model + * + * @param modelId [IN] model id + * @param dataset [IN] Pointer of dataset + * @param index [IN] index of input for data which linked dynamic aipp(ACL_DATA_WITH_DYNAMIC_AIPP) + * @param aippParmsSet [IN] Pointer for aclmdlAIPP + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | + * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPByInputIndex(uint32_t modelId, aclmdlDataset *dataset, size_t index, + const aclmdlAIPP *aippParmsSet); + +/** + * @ingroup AscendCL + * @brief get input aipp type + * + * @param modelId [IN] model id + * @param index [IN] index of input + * @param type [OUT] aipp type for input.refrer to aclmdlInputAippType(enum) + * @param dynamicAttachedDataIndex [OUT] index for dynamic attached data(ACL_DYNAMIC_AIPP_NODE) + * valid when type is ACL_DATA_WITH_DYNAMIC_AIPP, invalid value is ACL_INVALID_NODE_INDEX + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | + * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName | aclmdlCreateAIPP + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, size_t index, aclmdlInputAippType *type, + size_t *dynamicAttachedDataIndex); + +/** + * @ingroup AscendCL + * @brief get static aipp parameters from model + * + * @param modelId [IN] model id + * @param index [IN] index of tensor + * @param aippinfo [OUT] Pointer for static aipp info + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval ACL_ERROR_MODEL_AIPP_NOT_EXIST The tensor of index is not configured with aipp + * @retval OtherValues Failure + * + * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | + * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName + */ +ACL_FUNC_VISIBILITY aclError aclmdlGetFirstAippInfo(uint32_t modelId, size_t index, aclAippInfo *aippinfo); + +/** + * @ingroup AscendCL + * @brief get op description info + * + * @param deviceId [IN] device id + * @param streamId [IN] stream id + * @param taskId [IN] task id + * @param opName [OUT] pointer to op name + * @param opNameLen [IN] the length of op name + * @param inputDesc [OUT] pointer to input description + * @param numInputs [OUT] the number of input tensor + * @param outputDesc [OUT] pointer to output description + * @param numOutputs [OUT] the number of output tensor + * + * @retval ACL_SUCCESS The function is successfully executed + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlCreateAndGetOpDesc(uint32_t deviceId, uint32_t streamId, uint32_t taskId, + char *opName, size_t opNameLen, aclTensorDesc **inputDesc, + size_t *numInputs, aclTensorDesc **outputDesc, + size_t *numOutputs); + +/** + * @ingroup AscendCL + * @brief init dump + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlInitDump(); + +/** + * @ingroup AscendCL + * @brief set param of dump + * + * @param dumpCfgPath [IN] the path of dump config + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetDump(const char *dumpCfgPath); + +/** + * @ingroup AscendCL + * @brief finalize dump. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlFinalizeDump(); + +/** + * @ingroup AscendCL + * @brief load model with config + * + * @param handle [IN] pointer to model config handle + * @param modelId [OUT] pointer to model id + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlLoadWithConfig(const aclmdlConfigHandle *handle, uint32_t *modelId); + +/** + * @ingroup AscendCL + * @brief create model config handle of type aclmdlConfigHandle + * + * @retval the aclmdlConfigHandle pointer + * + * @see aclmdlDestroyConfigHandle + */ +ACL_FUNC_VISIBILITY aclmdlConfigHandle *aclmdlCreateConfigHandle(); + +/** + * @ingroup AscendCL + * @brief destroy data of type aclmdlConfigHandle + * + * @param handle [IN] pointer to model config handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclmdlCreateConfigHandle + */ +ACL_FUNC_VISIBILITY aclError aclmdlDestroyConfigHandle(aclmdlConfigHandle *handle); + +/** + * @ingroup AscendCL + * @brief set config for model load + * + * @param handle [OUT] pointer to model config handle + * @param attr [IN] config attr in model config handle to be set + * @param attrValue [IN] pointer to model config value + * @param valueSize [IN] memory size of attrValue + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclmdlSetConfigOpt(aclmdlConfigHandle *handle, aclmdlConfigAttr attr, + const void *attrValue, size_t valueSize); + +/** + * @ingroup AscendCL + * @brief get real tensor name from modelDesc + * + * @param modelDesc [IN] pointer to modelDesc + * @param name [IN] tensor name + * + * @retval the pointer of real tensor name + * @retval Failure return NULL + */ +ACL_FUNC_VISIBILITY const char *aclmdlGetTensorRealName(const aclmdlDesc *modelDesc, const char *name); + +#ifdef __cplusplus +} +#endif + +#endif // INC_EXTERNAL_ACL_ACL_MODEL_H_ diff --git a/inc/external/acl/acl_op.h b/inc/external/acl/acl_op.h new file mode 100644 index 00000000..d2e59bfb --- /dev/null +++ b/inc/external/acl/acl_op.h @@ -0,0 +1,504 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef INC_EXTERNAL_ACL_ACL_OP_H_ +#define INC_EXTERNAL_ACL_ACL_OP_H_ + +#include "acl_base.h" +#include "acl_rt.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct aclopHandle aclopHandle; +typedef struct aclopAttr aclopAttr; +typedef struct aclopKernelDesc aclopKernelDesc; + +typedef void (*aclDataDeallocator)(void *data, size_t length); + +static const int ACL_COMPILE_FLAG_BIN_SELECTOR = 1; + +typedef enum aclEngineType { + ACL_ENGINE_SYS, + ACL_ENGINE_AICORE, + ACL_ENGINE_VECTOR, +} aclopEngineType; + +/** + * @ingroup AscendCL + * @brief Set base directory that contains single op models + * + * @par Restriction + * The aclopSetModelDir interface can be called only once in a process. + * @param modelDir [IN] path of the directory + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopSetModelDir(const char *modelDir); + +/** + * @ingroup AscendCL + * @brief load single op models from memory + * + * @par Restriction + * The aclopLoad interface can be called more than one times in a process. + * @param model [IN] address of single op models + * @param modelSize [IN] size of single op models + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopLoad(const void *model, size_t modelSize); + +/** + * @ingroup AscendCL + * @brief create data of type aclopAttr + * + * @retval pointer to created instance. + * @retval nullptr if run out of memory + */ +ACL_FUNC_VISIBILITY aclopAttr *aclopCreateAttr(); + +/** + * @ingroup AscendCL + * @brief destroy data of typ aclopAttr + * + * @param attr [IN] pointer to the instance of aclopAttr + */ +ACL_FUNC_VISIBILITY void aclopDestroyAttr(const aclopAttr *attr); + +/** + * @ingroup AscendCL + * @brief set an attribute. the type of the attribute is bool + * + * @param attr [OUT] pointer to the instance of aclopAttr + * @param attrName [IN] attribute name + * @param attrValue [IN] attribute value + * false if attrValue is 0, true otherwise. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopSetAttrBool(aclopAttr *attr, const char *attrName, uint8_t attrValue); + +/** + * @ingroup AscendCL + * @brief set an attribute. the type of the attribute is int64_t + * + * @param attr [OUT] pointer to the instance of aclopAttr + * @param attrName [IN] attribute name + * @param attrValue [IN] attribute value + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopSetAttrInt(aclopAttr *attr, const char *attrName, int64_t attrValue); + +/** + * @ingroup AscendCL + * @brief set an attribute. the type of the attribute is float + * + * @param attr [OUT] pointer to the instance of aclopAttr + * @param attrName [IN] attribute name + * @param attrValue [IN] attribute value + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopSetAttrFloat(aclopAttr *attr, const char *attrName, float attrValue); + +/** + * @ingroup AscendCL + * @brief set an attribute. the type of the attribute is string + * + * @param attr [OUT] pointer to the instance of aclopAttr + * @param attrName [IN] attribute name + * @param attrValue [IN] attribute value + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopSetAttrString(aclopAttr *attr, const char *attrName, const char *attrValue); + +/** + * @ingroup AscendCL + * @brief set an attribute. the type of the attribute is list of bools + * + * @param attr [OUT] pointer to the instance of aclopAttr + * @param attrName [IN] attribute name + * @param numValues [IN] number of values. false if attrValue is 0, true otherwise. + * @param values [IN] pointer to values + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopSetAttrListBool(aclopAttr *attr, const char *attrName, int numValues, + const uint8_t *values); + +/** + * @ingroup AscendCL + * @brief set an attribute. the type of the attribute is list of ints + * + * @param attr [OUT] pointer to the instance of aclopAttr + * @param attrName [IN] attribute name + * @param numValues [IN] number of values + * @param values [IN] pointer to values + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopSetAttrListInt(aclopAttr *attr, const char *attrName, int numValues, + const int64_t *values); + +/** + * @ingroup AscendCL + * @brief set an attribute. the type of the attribute is list of floats + * + * @param attr [OUT] pointer to the instance of aclopAttr + * @param attrName [IN] attribute name + * @param numValues [IN] number of values + * @param values [IN] pointer to values + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopSetAttrListFloat(aclopAttr *attr, const char *attrName, int numValues, + const float *values); + +/** + * @ingroup AscendCL + * @brief set an attribute. the type of the attribute is list of strings + * + * @param attr [OUT] pointer to the instance of aclopAttr + * @param attrName [IN] attribute name + * @param numValues [IN] number of values + * @param values [IN] pointer to values + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopSetAttrListString(aclopAttr *attr, const char *attrName, int numValues, + const char **values); + +/** + * @ingroup AscendCL + * @brief set an attribute. the type of the attribute is list of list of ints + * + * @param attr [OUT] pointer to the instance of aclopAttr + * @param attrName [IN] attribute name + * @param numLists [IN] number of lists + * @param numValues [IN] pointer to number of values of each list + * @param values [IN] pointer to values + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopSetAttrListListInt(aclopAttr *attr, const char *attrName, int numLists, + const int *numValues, const int64_t *const values[]); + +/** + * @ingroup AscendCL + * @brief Load and execute the specified operator asynchronously + * + * @par Restriction + * @li The input and output organization of each operator is different, + * and the application needs to organize the operator strictly + * according to the operator input and output parameters when calling. + * @li When the user calls aclopExecute, + * the ACL finds the corresponding task according to the optype, + * the description of the input tesnsor, + * the description of the output tesnsor, and attr, and issues the execution. + * + * @param opType [IN] type of op + * @param numInputs [IN] number of inputs + * @param inputDesc [IN] pointer to array of input tensor descriptions + * @param inputs [IN] pointer to array of input buffers + * @param numOutputs [IN] number of outputs + * @param outputDesc [IN] pointer to array of output tensor descriptions + * @param outputs [OUT] pointer to array of output buffers + * @param attr [IN] pointer to instance of aclopAttr. + * may pass nullptr if the op has no attribute + * @param stream [IN] stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_DEPRECATED_MESSAGE("aclopExecute is deprecated, use aclopExecuteV2 instead") +ACL_FUNC_VISIBILITY aclError aclopExecute(const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], + const aclDataBuffer *const inputs[], int numOutputs, + const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], + const aclopAttr *attr, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Load and execute the specified operator + * The difference with aclopExecute is that aclopExecuteV2 will refresh outputDesc + * + * @par Restriction + * @li The input and output organization of each operator is different, + * and the application needs to organize the operator strictly + * according to the operator input and output parameters when calling. + * @li When the user calls aclopExecuteV2, + * the ACL finds the corresponding task according to the optype, + * the description of the input tesnsor, + * the description of the output tesnsor, and attr, and issues the execution. + * + * @param opType [IN] type of op + * @param numInputs [IN] number of inputs + * @param inputDesc [IN] pointer to array of input tensor descriptions + * @param inputs [IN] pointer to array of input buffers + * @param numOutputs [IN] number of outputs + * @param outputDesc [IN|OUT] pointer to array of output tensor descriptions + * @param outputs [OUT] pointer to array of output buffers + * @param attr [IN] pointer to instance of aclopAttr. + * may pass nullptr if the op has no attribute + * @param stream [IN] stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopExecuteV2(const char *opType, int numInputs, aclTensorDesc *inputDesc[], + aclDataBuffer *inputs[], int numOutputs, aclTensorDesc *outputDesc[], + aclDataBuffer *outputs[], aclopAttr *attr, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief create a instance of aclopHandle. + * + * @param opType [IN] type of op + * @param numInputs [IN] number of inputs + * @param inputDesc [IN] pointer to array of input tensor descriptions + * @param numOutputs [IN] number of outputs + * @param outputDesc [IN] pointer to array of output tensor descriptions + * @param opAttr [IN] pointer to instance of aclopAttr. + * may pass nullptr if the op has no attribute + * @param handle [OUT] pointer to the pointer to the handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopCreateHandle(const char *opType, int numInputs, + const aclTensorDesc *const inputDesc[], int numOutputs, + const aclTensorDesc *const outputDesc[], const aclopAttr *opAttr, + aclopHandle **handle); + +/** + * @ingroup AscendCL + * @brief destroy aclopHandle instance + * + * @param handle [IN] pointer to the instance of aclopHandle + */ +ACL_FUNC_VISIBILITY void aclopDestroyHandle(aclopHandle *handle); + +/** + * @ingroup AscendCL + * @brief execute an op with the handle. + * can save op model matching cost compared with aclopExecute + * + * @param handle [IN] pointer to the instance of aclopHandle. + * The aclopCreateHandle interface has been called + * in advance to create aclopHandle type data. + * @param numInputs [IN] number of inputs + * @param inputs [IN] pointer to array of input buffers. + * The aclCreateDataBuffer interface has been called + * in advance to create aclDataBuffer type data. + * @param numOutputs [IN] number of outputs + * @param outputs [OUT] pointer to array of output buffers + * @param stream [IN] stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclopCreateHandle | aclCreateDataBuffer + */ +ACL_FUNC_VISIBILITY aclError aclopExecWithHandle(aclopHandle *handle, int numInputs, + const aclDataBuffer *const inputs[], int numOutputs, + aclDataBuffer *const outputs[], aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief cast data type + * + * @param srcDesc [IN] source tensor desc + * @param srcBuffer [IN] source tensor buffer + * @param dstDesc [IN] destination tensor desc + * @param dstBuffer [OUT] destination tensor buffer + * @param truncate [IN] do not truncate if value is 0, truncate otherwise + * @param stream [IN] stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopCast(const aclTensorDesc *srcDesc, const aclDataBuffer *srcBuffer, + const aclTensorDesc *dstDesc, aclDataBuffer *dstBuffer, uint8_t truncate, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief create a handle for casting datatype + * + * @param srcDesc [IN] source tensor desc + * @param dstDesc [IN] destination tensor desc + * @param truncate [IN] do not truncate if value is 0, truncate otherwise + * @param handle [OUT] pointer to the pointer to the handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopCreateHandleForCast(aclTensorDesc *srcDesc, aclTensorDesc *dstDesc, uint8_t truncate, + aclopHandle **handle); + +/** + * @ingroup AscendCL + * @brief create kernel + * + * @param opType [IN] op type + * @param kernelId [IN] kernel id + * @param kernelName [IN] kernel name + * @param binData [IN] kernel bin data + * @param binSize [IN] kernel bin size + * @param enginetype [IN] enigne type + * @param deallocator [IN] callback function for deallocating bin data, + * null if bin data to be deallocated by caller + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclopCompile + */ +ACL_FUNC_VISIBILITY aclError aclopCreateKernel(const char *opType, const char *kernelId, const char *kernelName, + void *binData, int binSize, aclopEngineType enginetype, + aclDataDeallocator deallocator); + +/** + * @ingroup AscendCL + * @brief create kernel + * + * @param numInputs [IN] number of inputs + * @param inputDesc [IN] pointer to array of input tensor descriptions + * @param numOutputs [IN] number of outputs + * @param outputDesc [IN] pointer to array of output tensor descriptions + * @param opAttr [IN] pointer to instance of aclopAttr + * @param aclopKernelDesc [IN] pointer to instance of aclopKernelDesc + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +typedef aclError (*aclopCompileFunc)(int numInputs, const aclTensorDesc *const inputDesc[], int numOutputs, + const aclTensorDesc *const outputDesc[], const aclopAttr *opAttr, + aclopKernelDesc *aclopKernelDesc); + +/** + * @ingroup AscendCL + * @brief register compile function + * + * @param opType [IN] op type + * @param func [IN] compile function + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclopUnregisterCompileFunc + */ +ACL_FUNC_VISIBILITY aclError aclopRegisterCompileFunc(const char *opType, aclopCompileFunc func); + +/** + * @ingroup AscendCL + * @brief unregister compile function + * + * @param opType [IN] op type + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopUnregisterCompileFunc(const char *opType); + +/** + * @ingroup AscendCL + * @brief set kernel args + * + * @param kernelDesc [IN] pointer to instance of aclopKernelDesc + * @param kernelId [IN] kernel id + * @param blockDim [IN] block dim + * @param args [IN] args + * @param argSize [IN] size in bytes of args + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopSetKernelArgs(aclopKernelDesc *kernelDesc, const char *kernelId, uint32_t blockDim, + const void *args, uint32_t argSize); + +/** + * @ingroup AscendCL + * @brief set workspace sizes + * + * @param kernelDesc [IN] pointer to instance of aclopKernelDesc + * @param numWorkspaces [IN] number of workspaces + * @param workspaceSizes [IN] pointer to array of sizes of workspaces + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopSetKernelWorkspaceSizes(aclopKernelDesc *kernelDesc, int numWorkspaces, + size_t *workspaceSizes); + +/** + * @ingroup AscendCL + * @brief compile op with dynamic shape + * + * @param opType [IN] op type + * @param numInputs [IN] number of inputs + * @param inputDesc [IN] pointer to array of input tensor descriptions + * @param numOutputs [IN] number of outputs + * @param outputDesc [IN] pointer to array of output tensor descriptions + * @param attr [IN] pointer to instance of aclopAttr. + * may pass nullptr if the op has no attribute + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopUpdateParams(const char *opType, int numInputs, + const aclTensorDesc *const inputDesc[], int numOutputs, + const aclTensorDesc *const outputDesc[], const aclopAttr *attr); + +/** + * @ingroup AscendCL + * @brief inferShape the specified operator synchronously + * + * @param opType [IN] type of op + * @param numInputs [IN] number of inputs + * @param inputDesc [IN] pointer to array of input tensor descriptions + * @param inputs [IN] pointer to array of input buffers + * @param numOutputs [IN] number of outputs + * @param outputDesc [OUT] pointer to array of output tensor descriptions + * @param attr [IN] pointer to instance of aclopAttr. + * may pass nullptr if the op has no attribute + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopInferShape(const char *opType, int numInputs, aclTensorDesc *inputDesc[], + aclDataBuffer *inputs[], int numOutputs, aclTensorDesc *outputDesc[], + aclopAttr *attr); + +#ifdef __cplusplus +} +#endif + +#endif // INC_EXTERNAL_ACL_ACL_OP_H_ diff --git a/inc/external/acl/acl_op_compiler.h b/inc/external/acl/acl_op_compiler.h new file mode 100644 index 00000000..d9d1b3da --- /dev/null +++ b/inc/external/acl/acl_op_compiler.h @@ -0,0 +1,121 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef INC_EXTERNAL_ACL_ACL_OP_COMPILER_H_ +#define INC_EXTERNAL_ACL_ACL_OP_COMPILER_H_ + +#include "acl_base.h" +#include "acl_op.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum aclCompileType { ACL_COMPILE_SYS, ACL_COMPILE_UNREGISTERED } aclopCompileType; + +typedef enum { + ACL_PRECISION_MODE, + ACL_AICORE_NUM, + ACL_AUTO_TUNE_MODE, + ACL_OP_SELECT_IMPL_MODE, + ACL_OPTYPELIST_FOR_IMPLMODE, + ACL_OP_DEBUG_LEVEL, + ACL_DEBUG_DIR, + ACL_OP_COMPILER_CACHE_MODE, + ACL_OP_COMPILER_CACHE_DIR, + ACL_OP_PERFORMANCE_MODE +} aclCompileOpt; + +typedef enum aclCompileFlag { ACL_OP_COMPILE_DEFAULT, ACL_OP_COMPILE_FUZZ } aclOpCompileFlag; + +/** + * @ingroup AscendCL + * @brief compile op + * + * @param opType [IN] op type + * @param numInputs [IN] number of inputs + * @param inputDesc [IN] pointer to array of input tensor descriptions + * @param numOutputs [IN] number of outputs + * @param outputDesc [IN] pointer to array of output tensor descriptions + * @param attr [IN] pointer to instance of aclopAttr. + * may pass nullptr if the op has no attribute + * @param engineType [IN] engine type + * @param compileFlag [IN] compile flag + * @param opPath [IN] path of op + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], + int numOutputs, const aclTensorDesc *const outputDesc[], + const aclopAttr *attr, aclopEngineType engineType, + aclopCompileType compileFlag, const char *opPath); + +/** + * @ingroup AscendCL + * @brief compile and execute op + * + * @param opType [IN] op type + * @param numInputs [IN] number of inputs + * @param inputDesc [IN] pointer to array of input tensor descriptions + * @param inputs [IN] pointer to array of input buffers + * @param numOutputs [IN] number of outputs + * @param outputDesc [IN] pointer to array of output tensor descriptions + * @param outputs [IN] pointer to array of outputs buffers + * @param attr [IN] pointer to instance of aclopAttr. + * may pass nullptr if the op has no attribute + * @param engineType [IN] engine type + * @param compileFlag [IN] compile flag + * @param opPath [IN] path of op + * @param stream [IN] stream handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopCompileAndExecute( + const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], const aclDataBuffer *const inputs[], + int numOutputs, const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], const aclopAttr *attr, + aclopEngineType engineType, aclopCompileType compileFlag, const char *opPath, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief set compile option + * + * @param aclCompileOpt [IN] compile option + * @param value [IN] pointer for the option value + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclSetCompileopt(aclCompileOpt opt, const char *value); + +/** + * @ingroup AscendCL + * @brief set compile flag + * + * @param flag [IN] compile flag, ACL_OP_COMPILE_DEFAULT means compile with default mode + * ACL_OP_COMPILE_FUZZ means compile with fuzz mode + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopSetCompileFlag(aclOpCompileFlag flag); + +#ifdef __cplusplus +} +#endif + +#endif // INC_EXTERNAL_ACL_ACL_OP_COMPILER_H_ diff --git a/inc/external/acl/acl_prof.h b/inc/external/acl/acl_prof.h new file mode 100644 index 00000000..3784d8c6 --- /dev/null +++ b/inc/external/acl/acl_prof.h @@ -0,0 +1,329 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef INC_EXTERNAL_ACL_PROF_H_ +#define INC_EXTERNAL_ACL_PROF_H_ + +#include "acl_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ACL_PROF_ACL_API 0x0001 +#define ACL_PROF_TASK_TIME 0x0002 +#define ACL_PROF_AICORE_METRICS 0x0004 +#define ACL_PROF_AICPU 0x0008 + +/** + * @deprecated please use aclprofGetOpTypeLen and aclprofGetOpTNameLen instead + */ +#define ACL_PROF_MAX_OP_NAME_LEN 257 +#define ACL_PROF_MAX_OP_TYPE_LEN 65 + +typedef enum { + ACL_AICORE_ARITHMETIC_UTILIZATION = 0, + ACL_AICORE_PIPE_UTILIZATION = 1, + ACL_AICORE_MEMORY_BANDWIDTH = 2, + ACL_AICORE_L0B_AND_WIDTH = 3, + ACL_AICORE_RESOURCE_CONFLICT_RATIO = 4, + ACL_AICORE_NONE = 0xFF +} aclprofAicoreMetrics; + +typedef struct aclprofConfig aclprofConfig; +typedef struct aclprofStopConfig aclprofStopConfig; +typedef struct aclprofAicoreEvents aclprofAicoreEvents; +typedef struct aclprofSubscribeConfig aclprofSubscribeConfig; + +/** + * @ingroup AscendCL + * @brief profiling initialize + * + * @param profilerResultPath [IN] path of profiling result + * @param length [IN] length of profilerResultPath + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclprofFinalize + */ +ACL_FUNC_VISIBILITY aclError aclprofInit(const char *profilerResultPath, size_t length); + +/** + * @ingroup AscendCL + * @brief profiling finalize + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclprofInit + */ +ACL_FUNC_VISIBILITY aclError aclprofFinalize(); + +/** + * @ingroup AscendCL + * @brief Start profiling modules by profilerConfig + * + * @param profilerConfig [IN] config of profiling + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclprofStop + */ +ACL_FUNC_VISIBILITY aclError aclprofStart(const aclprofConfig *profilerConfig); + +/** + * @ingroup AscendCL + * @brief Create data of type aclprofConfig + * + * @param deviceIdList [IN] list of device id + * @param deviceNums [IN] number of devices + * @param aicoreMetrics [IN] type of aicore metrics + * @param aicoreEvents [IN] pointer to aicore events, only support NULL now + * @param dataTypeConfig [IN] config modules need profiling + * + * @retval the aclprofConfig pointer + * + * @see aclprofDestroyConfig + */ +ACL_FUNC_VISIBILITY aclprofConfig *aclprofCreateConfig(uint32_t *deviceIdList, uint32_t deviceNums, + aclprofAicoreMetrics aicoreMetrics, + aclprofAicoreEvents *aicoreEvents, uint64_t dataTypeConfig); + +/** + * @ingroup AscendCL + * @brief Destroy data of type aclprofConfig + * + * @param profilerConfig [IN] config of profiling + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclprofCreateConfig + */ +ACL_FUNC_VISIBILITY aclError aclprofDestroyConfig(const aclprofConfig *profilerConfig); + +/** + * @ingroup AscendCL + * @brief stop profiling modules by stopProfilingConfig + * + * @param profilerConfig [IN] pointer to stop config of profiling + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclprofStart + */ +ACL_FUNC_VISIBILITY aclError aclprofStop(const aclprofConfig *profilerConfig); + +/** + * @ingroup AscendCL + * @brief subscribe profiling data of model + * + * @param modelId [IN] the model id subscribed + * @param profSubscribeConfig [IN] pointer to config of model subscribe + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclprofModelUnSubscribe + */ +ACL_FUNC_VISIBILITY aclError aclprofModelSubscribe(uint32_t modelId, const aclprofSubscribeConfig *profSubscribeConfig); + +/** + * @ingroup AscendCL + * @brief unsubscribe profiling data of model + * + * @param modelId [IN] the model id unsubscribed + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclprofModelSubscribe + */ +ACL_FUNC_VISIBILITY aclError aclprofModelUnSubscribe(uint32_t modelId); + +/** + * @ingroup AscendCL + * @brief create subscribe config + * + * @param timeInfoSwitch [IN] switch whether get time info from model + * @param aicoreMetrics [IN] aicore metrics + * @param fd [IN] pointer to write pipe + * + * @retval the aclprofSubscribeConfig pointer + * + * @see aclprofDestroySubscribeConfig + */ +ACL_FUNC_VISIBILITY aclprofSubscribeConfig *aclprofCreateSubscribeConfig(int8_t timeInfoSwitch, + aclprofAicoreMetrics aicoreMetrics, void *fd); + +/** + * @ingroup AscendCL + * @brief destroy subscribe config + * + * @param profSubscribeConfig [IN] subscribe config + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclprofCreateSubscribeConfig + */ +ACL_FUNC_VISIBILITY aclError aclprofDestroySubscribeConfig(const aclprofSubscribeConfig *profSubscribeConfig); + +/** + * @ingroup AscendCL + * @brief create subscribe config + * + * @param opDescSize [OUT] size of op desc + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclprofGetOpDescSize(size_t *opDescSize); + +/** + * @ingroup AscendCL + * @brief get op number from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * @param opNumber [OUT] op number of subscription data + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclprofGetOpNum(const void *opInfo, size_t opInfoLen, uint32_t *opNumber); + +/** + * @ingroup AscendCL + * @brief get length op type from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * @param index [IN] index of op array in opInfo + * @param opTypeLen [OUT] actual length of op type string + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclprofGetOpTypeLen(const void *opInfo, size_t opInfoLen, uint32_t index, + size_t *opTypeLen); + +/** + * @ingroup AscendCL + * @brief get op type from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * @param index [IN] index of op array in opInfo + * @param opType [OUT] obtained op type string + * @param opTypeLen [IN] obtained length of op type string + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoLen, uint32_t index, char *opType, + size_t opTypeLen); + +/** + * @ingroup AscendCL + * @brief get length op name from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * @param index [IN] index of op array in opInfo + * @param opNameLen [OUT] actual length of op name string + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclprofGetOpNameLen(const void *opInfo, size_t opInfoLen, uint32_t index, + size_t *opNameLen); + +/** + * @ingroup AscendCL + * @brief get op type from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * @param index [IN] index of op array in opInfo + * @param opName [OUT] obtained op name string + * @param opNameLen [IN] obtained length of op name string + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclprofGetOpName(const void *opInfo, size_t opInfoLen, uint32_t index, char *opName, + size_t opNameLen); + +/** + * @ingroup AscendCL + * @brief get start time of specified op from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * @param index [IN] index of op array in opInfo + * + * @retval start time(us) of specified op with timestamp + * @retval 0 for failed + */ +ACL_FUNC_VISIBILITY uint64_t aclprofGetOpStart(const void *opInfo, size_t opInfoLen, uint32_t index); + +/** + * @ingroup AscendCL + * @brief get end time of specified op from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * @param index [IN] index of op array in opInfo + * + * @retval end time(us) of specified op with timestamp + * @retval 0 for failed + */ +ACL_FUNC_VISIBILITY uint64_t aclprofGetOpEnd(const void *opInfo, size_t opInfoLen, uint32_t index); + +/** + * @ingroup AscendCL + * @brief get excution time of specified op from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * @param index [IN] index of op array in opInfo + * + * @retval execution time(us) of specified op with timestamp + * @retval 0 for failed + */ +ACL_FUNC_VISIBILITY uint64_t aclprofGetOpDuration(const void *opInfo, size_t opInfoLen, uint32_t index); + +/** + * @ingroup AscendCL + * @brief get model id from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * + * @retval model id of subscription data + * @retval 0 for failed + */ +ACL_FUNC_VISIBILITY size_t aclprofGetModelId(const void *opInfo, size_t opInfoLen, uint32_t index); + +#ifdef __cplusplus +} +#endif + +#endif // INC_EXTERNAL_ACL_PROF_H_ diff --git a/inc/external/acl/acl_rt.h b/inc/external/acl/acl_rt.h new file mode 100644 index 00000000..5ee70724 --- /dev/null +++ b/inc/external/acl/acl_rt.h @@ -0,0 +1,958 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef INC_EXTERNAL_ACL_ACL_RT_H_ +#define INC_EXTERNAL_ACL_ACL_RT_H_ + +#include +#include +#include "acl_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ACL_EVENT_TIME_LINE 0x00000008u + +typedef enum aclrtRunMode { + ACL_DEVICE, + ACL_HOST, +} aclrtRunMode; + +typedef enum aclrtTsId { + ACL_TS_ID_AICORE = 0, + ACL_TS_ID_AIVECTOR = 1, + ACL_TS_ID_RESERVED = 2, +} aclrtTsId; + +typedef enum aclrtEventStatus { + ACL_EVENT_STATUS_COMPLETE = 0, + ACL_EVENT_STATUS_NOT_READY = 1, + ACL_EVENT_STATUS_RESERVED = 2, +} aclrtEventStatus; + +typedef enum aclrtCallbackBlockType { + ACL_CALLBACK_NO_BLOCK, + ACL_CALLBACK_BLOCK, +} aclrtCallbackBlockType; + +typedef enum aclrtMemcpyKind { + ACL_MEMCPY_HOST_TO_HOST, + ACL_MEMCPY_HOST_TO_DEVICE, + ACL_MEMCPY_DEVICE_TO_HOST, + ACL_MEMCPY_DEVICE_TO_DEVICE, +} aclrtMemcpyKind; + +typedef enum aclrtMemMallocPolicy { + ACL_MEM_MALLOC_HUGE_FIRST, + ACL_MEM_MALLOC_HUGE_ONLY, + ACL_MEM_MALLOC_NORMAL_ONLY, + ACL_MEM_MALLOC_HUGE_FIRST_P2P, + ACL_MEM_MALLOC_HUGE_ONLY_P2P, + ACL_MEM_MALLOC_NORMAL_ONLY_P2P, +} aclrtMemMallocPolicy; + +typedef enum aclrtMemAttr { + ACL_DDR_MEM, + ACL_HBM_MEM, + ACL_DDR_MEM_HUGE, + ACL_DDR_MEM_NORMAL, + ACL_HBM_MEM_HUGE, + ACL_HBM_MEM_NORMAL, + ACL_DDR_MEM_P2P_HUGE, + ACL_DDR_MEM_P2P_NORMAL, + ACL_HBM_MEM_P2P_HUGE, + ACL_HBM_MEM_P2P_NORMAL, +} aclrtMemAttr; + +typedef enum aclrtGroupAttr { + ACL_GROUP_AICORE_INT, + ACL_GROUP_AIV_INT, + ACL_GROUP_AIC_INT, + ACL_GROUP_SDMANUM_INT, + ACL_GROUP_ASQNUM_INT, + ACL_GROUP_GROUPID_INT +} aclrtGroupAttr; + +typedef struct tagRtGroupInfo aclrtGroupInfo; + +typedef struct rtExceptionInfo aclrtExceptionInfo; + +typedef void (*aclrtCallback)(void *userData); + +typedef void (*aclrtExceptionInfoCallback)(aclrtExceptionInfo *exceptionInfo); + +/** + * @ingroup AscendCL + * @brief Set a callback function to handle exception information + * + * @param callback [IN] callback function to handle exception information + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtSetExceptionInfoCallback(aclrtExceptionInfoCallback callback); + +/** + * @ingroup AscendCL + * @brief Get task id from exception information + * + * @param info [IN] pointer of exception information + * + * @retval The task id from exception information + * @retval 0xFFFFFFFF if info is null + */ +ACL_FUNC_VISIBILITY uint32_t aclrtGetTaskIdFromExceptionInfo(const aclrtExceptionInfo *info); + +/** + * @ingroup AscendCL + * @brief Get stream id from exception information + * + * @param info [IN] pointer of exception information + * + * @retval The stream id from exception information + * @retval 0xFFFFFFFF if info is null + */ +ACL_FUNC_VISIBILITY uint32_t aclrtGetStreamIdFromExceptionInfo(const aclrtExceptionInfo *info); + +/** + * @ingroup AscendCL + * @brief Get thread id from exception information + * + * @param info [IN] pointer of exception information + * + * @retval The thread id of fail task + * @retval 0xFFFFFFFF if info is null + */ +ACL_FUNC_VISIBILITY uint32_t aclrtGetThreadIdFromExceptionInfo(const aclrtExceptionInfo *info); + +/** + * @ingroup AscendCL + * @brief Get device id from exception information + * + * @param info [IN] pointer of exception information + * + * @retval The thread id of fail task + * @retval 0xFFFFFFFF if info is null + */ +ACL_FUNC_VISIBILITY uint32_t aclrtGetDeviceIdFromExceptionInfo(const aclrtExceptionInfo *info); + +/** + * @ingroup AscendCL + * @brief The thread that handles the callback function on the Stream + * + * @param threadId [IN] thread ID + * @param stream [IN] stream handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtSubscribeReport(uint64_t threadId, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Add a callback function to be executed on the host + * to the task queue of the Stream + * + * @param fn [IN] Specify the callback function to be added + * The function prototype of the callback function is: + * typedef void (*aclrtCallback)(void *userData); + * @param userData [IN] User data to be passed to the callback function + * @param blockType [IN] callback block type + * @param stream [IN] stream handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtLaunchCallback(aclrtCallback fn, void *userData, aclrtCallbackBlockType blockType, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief After waiting for a specified time, trigger callback processing + * + * @par Function + * The thread processing callback specified by + * the aclrtSubscribeReport interface + * + * @param timeout [IN] timeout value + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtSubscribeReport + */ +ACL_FUNC_VISIBILITY aclError aclrtProcessReport(int32_t timeout); + +/** + * @ingroup AscendCL + * @brief Cancel thread registration, + * the callback function on the specified Stream + * is no longer processed by the specified thread + * + * @param threadId [IN] thread ID + * @param stream [IN] stream handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtUnSubscribeReport(uint64_t threadId, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief create context and associates it with the calling thread + * + * @par Function + * The following use cases are supported: + * @li If you don't call the aclrtCreateContext interface + * to explicitly create the context, + * the system will use the default context, which is implicitly created + * when the aclrtSetDevice interface is called. + * @li If multiple contexts are created in a process + * (there is no limit on the number of contexts), + * the current thread can only use one of them at the same time. + * It is recommended to explicitly specify the context of the current thread + * through the aclrtSetCurrentContext interface to increase. + * the maintainability of the program. + * + * @param context [OUT] point to the created context + * @param deviceId [IN] device to create context on + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtSetDevice | aclrtSetCurrentContext + */ +ACL_FUNC_VISIBILITY aclError aclrtCreateContext(aclrtContext *context, int32_t deviceId); + +/** + * @ingroup AscendCL + * @brief destroy context instance + * + * @par Function + * Can only destroy context created through aclrtCreateContext interface + * + * @param context [IN] the context to destroy + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtCreateContext + */ +ACL_FUNC_VISIBILITY aclError aclrtDestroyContext(aclrtContext context); + +/** + * @ingroup AscendCL + * @brief set the context of the thread + * + * @par Function + * The following scenarios are supported: + * @li If the aclrtCreateContext interface is called in a thread to explicitly + * create a Context (for example: ctx1), the thread's Context can be specified + * without calling the aclrtSetCurrentContext interface. + * The system uses ctx1 as the context of thread1 by default. + * @li If the aclrtCreateContext interface is not explicitly created, + * the system uses the default context as the context of the thread. + * At this time, the aclrtDestroyContext interface cannot be used to release + * the default context. + * @li If the aclrtSetCurrentContext interface is called multiple times to + * set the thread's Context, the last one prevails. + * + * @par Restriction + * @li If the cevice corresponding to the context set for the thread + * has been reset, you cannot set the context as the context of the thread, + * otherwise a business exception will result. + * @li It is recommended to use the context created in a thread. + * If the aclrtCreateContext interface is called in thread A to create a context, + * and the context is used in thread B, + * the user must guarantee the execution order of tasks in the same stream + * under the same context in two threads. + * + * @param context [IN] the current context of the thread + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtCreateContext | aclrtDestroyContext + */ +ACL_FUNC_VISIBILITY aclError aclrtSetCurrentContext(aclrtContext context); + +/** + * @ingroup AscendCL + * @brief get the context of the thread + * + * @par Function + * If the user calls the aclrtSetCurrentContext interface + * multiple times to set the context of the current thread, + * then the last set context is obtained + * + * @param context [OUT] the current context of the thread + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtSetCurrentContext + */ +ACL_FUNC_VISIBILITY aclError aclrtGetCurrentContext(aclrtContext *context); + +/** + * @ingroup AscendCL + * @brief Specify the device to use for the operation + * implicitly create the default context and the default stream + * + * @par Function + * The following use cases are supported: + * @li Device can be specified in the process or thread. + * If you call the aclrtSetDevice interface multiple + * times to specify the same device, + * you only need to call the aclrtResetDevice interface to reset the device. + * @li The same device can be specified for operation + * in different processes or threads. + * @li Device is specified in a process, + * and multiple threads in the process can share this device to explicitly + * create a Context (aclrtCreateContext interface). + * @li In multi-device scenarios, you can switch to other devices + * through the aclrtSetDevice interface in the process. + * + * @param deviceId [IN] the device id + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtResetDevice |aclrtCreateContext + */ +ACL_FUNC_VISIBILITY aclError aclrtSetDevice(int32_t deviceId); + +/** + * @ingroup AscendCL + * @brief Reset the current operating Device and free resources on the device, + * including the default context, the default stream, + * and all streams created under the default context, + * and synchronizes the interface. + * If the task under the default context or stream has not been completed, + * the system will wait for the task to complete before releasing it. + * + * @par Restriction + * @li The Context, Stream, and Event that are explicitly created + * on the device to be reset. Before resetting, + * it is recommended to follow the following interface calling sequence, + * otherwise business abnormalities may be caused. + * @li Interface calling sequence: + * call aclrtDestroyEvent interface to release Event or + * call aclrtDestroyStream interface to release explicitly created Stream-> + * call aclrtDestroyContext to release explicitly created Context-> + * call aclrtResetDevice interface + * + * @param deviceId [IN] the device id + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtResetDevice(int32_t deviceId); + +/** + * @ingroup AscendCL + * @brief get target device of current thread + * + * @param deviceId [OUT] the device id + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtGetDevice(int32_t *deviceId); + +/** + * @ingroup AscendCL + * @brief get target side + * + * @param runMode [OUT] the run mode + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtGetRunMode(aclrtRunMode *runMode); + +/** + * @ingroup AscendCL + * @brief Wait for compute device to finish + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtSynchronizeDevice(void); + +/** + * @ingroup AscendCL + * @brief Set Scheduling TS + * + * @param tsId [IN] the ts id + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtSetTsDevice(aclrtTsId tsId); + +/** + * @ingroup AscendCL + * @brief get total device number. + * + * @param count [OUT] the device number + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtGetDeviceCount(uint32_t *count); + +/** + * @ingroup AscendCL + * @brief create event instance + * + * @param event [OUT] created event + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtCreateEvent(aclrtEvent *event); + +/** + * @ingroup AscendCL + * @brief create event instance with flag + * + * @param event [OUT] created event + * @param flag [IN] event flag + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtCreateEventWithFlag(aclrtEvent *event, uint32_t flag); + +/** + * @ingroup AscendCL + * @brief destroy event instance + * + * @par Function + * Only events created through the aclrtCreateEvent interface can be + * destroyed, synchronous interfaces. When destroying an event, + * the user must ensure that the tasks involved in the aclrtSynchronizeEvent + * interface or the aclrtStreamWaitEvent interface are completed before + * they are destroyed. + * + * @param event [IN] event to destroy + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtCreateEvent | aclrtSynchronizeEvent | aclrtStreamWaitEvent + */ +ACL_FUNC_VISIBILITY aclError aclrtDestroyEvent(aclrtEvent event); + +/** + * @ingroup AscendCL + * @brief Record an Event in the Stream + * + * @param event [IN] event to record + * @param stream [IN] stream handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtRecordEvent(aclrtEvent event, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Reset an event + * + * @par Function + * Users need to make sure to wait for the tasks in the Stream + * to complete before resetting the Event + * + * @param event [IN] event to reset + * @param stream [IN] stream handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtResetEvent(aclrtEvent event, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Queries an event's status + * + * @param event [IN] event to query + * @param status [OUT] event status + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtQueryEvent(aclrtEvent event, aclrtEventStatus *status); + +/** + * @ingroup AscendCL + * @brief Block Host Running, wait event to be complete + * + * @param event [IN] event to wait + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtSynchronizeEvent(aclrtEvent event); + +/** + * @ingroup AscendCL + * @brief computes the elapsed time between events. + * + * @param ms [OUT] time between start and end in ms + * @param start [IN] starting event + * @param end [IN] ending event + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtCreateEvent | aclrtRecordEvent | aclrtSynchronizeStream + */ +ACL_FUNC_VISIBILITY aclError aclrtEventElapsedTime(float *ms, aclrtEvent start, aclrtEvent end); + +/** + * @ingroup AscendCL + * @brief alloc memory on device + * + * @par Function + * alloc for size linear memory on device + * and return a pointer to allocated memory by *devPtr + * + * @par Restriction + * @li The memory requested by the aclrtMalloc interface needs to be released + * through the aclrtFree interface. + * @li Before calling the media data processing interface, + * if you need to apply memory on the device to store input or output data, + * you need to call acldvppMalloc to apply for memory. + * + * @param devPtr [OUT] pointer to pointer to allocated memory on device + * @param size [IN] alloc memory size + * @param policy [IN] memory alloc policy + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtFree | acldvppMalloc | aclrtMallocCached + */ +ACL_FUNC_VISIBILITY aclError aclrtMalloc(void **devPtr, size_t size, aclrtMemMallocPolicy policy); + +/** + * @ingroup AscendCL + * @brief allocate memory on device with cache + * + * @par Function + * alloc for size linear memory on device + * and return a pointer to allocated memory by *devPtr + * + * @par Restriction + * @li The memory requested by the aclrtMallocCached interface needs to be released + * through the aclrtFree interface. + * + * @param devPtr [OUT] pointer to pointer to allocated memory on device + * @param size [IN] alloc memory size + * @param policy [IN] memory alloc policy + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtFree | aclrtMalloc + */ +ACL_FUNC_VISIBILITY aclError aclrtMallocCached(void **devPtr, size_t size, aclrtMemMallocPolicy policy); + +/** + * @ingroup AscendCL + * @brief flush cache data to ddr + * + * @param devPtr [IN] the pointer that flush data to ddr + * @param size [IN] flush size + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtMemFlush(void *devPtr, size_t size); + +/** + * @ingroup AscendCL + * @brief invalidate cache data + * + * @param devPtr [IN] pointer to invalidate cache data + * @param size [IN] invalidate size + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtMemInvalidate(void *devPtr, size_t size); + +/** + * @ingroup AscendCL + * @brief free device memory + * + * @par Function + * can only free memory allocated through the aclrtMalloc interface + * + * @param devPtr [IN] Pointer to memory to be freed + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtMalloc + */ +ACL_FUNC_VISIBILITY aclError aclrtFree(void *devPtr); + +/** + * @ingroup AscendCL + * @brief alloc memory on host + * + * @par Restriction + * @li The requested memory cannot be used in the Device + * and needs to be explicitly copied to the Device. + * @li The memory requested by the aclrtMallocHost interface + * needs to be released through the aclrtFreeHost interface. + * + * @param hostPtr [OUT] pointer to pointer to allocated memory on the host + * @param size [IN] alloc memory size + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtFreeHost + */ +ACL_FUNC_VISIBILITY aclError aclrtMallocHost(void **hostPtr, size_t size); + +/** + * @ingroup AscendCL + * @brief free host memory + * + * @par Function + * can only free memory allocated through the aclrtMallocHost interface + * + * @param hostPtr [IN] free memory pointer + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtMallocHost + */ +ACL_FUNC_VISIBILITY aclError aclrtFreeHost(void *hostPtr); + +/** + * @ingroup AscendCL + * @brief synchronous memory replication between host and device + * + * @param dst [IN] destination address pointer + * @param destMax [IN] Max length of the destination address memory + * @param src [IN] source address pointer + * @param count [IN] the length of byte to copy + * @param kind [IN] memcpy type + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtMemcpy(void *dst, size_t destMax, const void *src, size_t count, + aclrtMemcpyKind kind); + +/** + * @ingroup AscendCL + * @brief Initialize memory and set contents of memory to specified value + * + * @par Function + * The memory to be initialized is on the Host or device side, + * and the system determines whether + * it is host or device according to the address + * + * @param devPtr [IN] Starting address of memory + * @param maxCount [IN] Max length of destination address memory + * @param value [IN] Set value + * @param count [IN] The length of memory + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtMemset(void *devPtr, size_t maxCount, int32_t value, size_t count); + +/** + * @ingroup AscendCL + * @brief Asynchronous memory replication between Host and Device + * + * @par Function + * After calling this interface, + * be sure to call the aclrtSynchronizeStream interface to ensure that + * the task of memory replication has been completed + * + * @par Restriction + * @li For on-chip Device-to-Device memory copy, + * both the source and destination addresses must be 64-byte aligned + * + * @param dst [IN] destination address pointer + * @param destMax [IN] Max length of destination address memory + * @param src [IN] source address pointer + * @param count [IN] the number of byte to copy + * @param kind [IN] memcpy type + * @param stream [IN] asynchronized task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtSynchronizeStream + */ +ACL_FUNC_VISIBILITY aclError aclrtMemcpyAsync(void *dst, size_t destMax, const void *src, size_t count, + aclrtMemcpyKind kind, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Asynchronous initialize memory + * and set contents of memory to specified value async + * + * @par Function + * The memory to be initialized is on the Host or device side, + * and the system determines whether + * it is host or device according to the address + * + * @param devPtr [IN] destination address pointer + * @param maxCount [IN] Max length of destination address memory + * @param value [IN] set value + * @param count [IN] the number of byte to set + * @param stream [IN] asynchronized task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtSynchronizeStream + */ +ACL_FUNC_VISIBILITY aclError aclrtMemsetAsync(void *devPtr, size_t maxCount, int32_t value, size_t count, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief create stream instance + * + * @param stream [OUT] the created stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtCreateStream(aclrtStream *stream); + +/** + * @ingroup AscendCL + * @brief destroy stream instance + * + * @par Function + * Can only destroy streams created through the aclrtCreateStream interface + * + * @par Restriction + * Before calling the aclrtDestroyStream interface to destroy + * the specified Stream, you need to call the aclrtSynchronizeStream interface + * to ensure that the tasks in the Stream have been completed. + * + * @param stream [IN] the stream to destroy + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtCreateStream | aclrtSynchronizeStream + */ +ACL_FUNC_VISIBILITY aclError aclrtDestroyStream(aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief block the host until all tasks + * in the specified stream have completed + * + * @param stream [IN] the stream to wait + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtSynchronizeStream(aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Blocks the operation of the specified Stream until + * the specified Event is completed. + * Support for multiple streams waiting for the same event. + * + * @param stream [IN] the wait stream If using thedefault Stream, set NULL + * @param event [IN] the event to wait + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtStreamWaitEvent(aclrtStream stream, aclrtEvent event); + +/** + * @ingroup AscendCL + * @brief set group + * + * @par Function + * set the task to the corresponding group + * + * @param groupId [IN] group id + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtGetGroupCount | aclrtGetAllGroupInfo | aclrtGetGroupInfoDetail + */ +ACL_FUNC_VISIBILITY aclError aclrtSetGroup(int32_t groupId); + +/** + * @ingroup AscendCL + * @brief get the number of group + * + * @par Function + * get the number of group. if the number of group is zero, + * it means that group is not supported or group is not created. + * + * @param count [OUT] the number of group + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + */ +ACL_FUNC_VISIBILITY aclError aclrtGetGroupCount(uint32_t *count); + +/** + * @ingroup AscendCL + * @brief create group information + * + * @retval null for failed. + * @retval OtherValues success. + * + * @see aclrtDestroyGroupInfo + */ +ACL_FUNC_VISIBILITY aclrtGroupInfo *aclrtCreateGroupInfo(); + +/** + * @ingroup AscendCL + * @brief destroy group information + * + * @param groupInfo [IN] pointer to group information + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtCreateGroupInfo + */ +ACL_FUNC_VISIBILITY aclError aclrtDestroyGroupInfo(aclrtGroupInfo *groupInfo); + +/** + * @ingroup AscendCL + * @brief get all group information + * + * @param groupInfo [OUT] pointer to group information + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtGetGroupCount + */ +ACL_FUNC_VISIBILITY aclError aclrtGetAllGroupInfo(aclrtGroupInfo *groupInfo); + +/** + * @ingroup AscendCL + * @brief get detail information of group + * + * @param groupInfo [IN] pointer to group information + * @param groupIndex [IN] group index value + * @param attr [IN] group attribute + * @param attrValue [OUT] pointer to attribute value + * @param valueLen [IN] length of attribute value + * @param paramRetSize [OUT] pointer to real length of attribute value + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtGetGroupCount | aclrtGetAllGroupInfo + */ +ACL_FUNC_VISIBILITY aclError aclrtGetGroupInfoDetail(const aclrtGroupInfo *groupInfo, int32_t groupIndex, + aclrtGroupAttr attr, void *attrValue, size_t valueLen, + size_t *paramRetSize); + +/** + * @ingroup AscendCL + * @brief checking whether current device and peer device support the p2p feature + * + * @param canAccessPeer [OUT] pointer to save the checking result + * @param deviceId [IN] current device id + * @param peerDeviceId [IN] peer device id + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtDeviceEnablePeerAccess | aclrtDeviceDisablePeerAccess + */ +ACL_FUNC_VISIBILITY aclError aclrtDeviceCanAccessPeer(int32_t *canAccessPeer, int32_t deviceId, int32_t peerDeviceId); + +/** + * @ingroup AscendCL + * @brief enable the peer device to support the p2p feature + * + * @param peerDeviceId [IN] the peer device id + * @param flags [IN] reserved field, now it must be zero + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtDeviceCanAccessPeer | aclrtDeviceDisablePeerAccess + */ +ACL_FUNC_VISIBILITY aclError aclrtDeviceEnablePeerAccess(int32_t peerDeviceId, uint32_t flags); + +/** + * @ingroup AscendCL + * @brief disable the peer device to support the p2p function + * + * @param peerDeviceId [IN] the peer device id + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclrtDeviceCanAccessPeer | aclrtDeviceEnablePeerAccess + */ +ACL_FUNC_VISIBILITY aclError aclrtDeviceDisablePeerAccess(int32_t peerDeviceId); + +/** + * @ingroup AscendCL + * @brief Obtain the free memory and total memory of specified attribute. + * the specified memory include normal memory and huge memory. + * + * @param attr [IN] the memory attribute of specified device + * @param free [OUT] the free memory of specified device + * @param total [OUT] the total memory of specified device. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtGetMemInfo(aclrtMemAttr attr, size_t *free, size_t *total); + +/** + * @ingroup AscendCL + * @brief Set the timeout interval for waitting of op + * + * @param timeout [IN] op wait timeout + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtSetOpWaitTimeout(uint32_t timeout); + +#ifdef __cplusplus +} +#endif + +#endif // INC_EXTERNAL_ACL_ACL_RT_H_ diff --git a/inc/external/acl/acl_tdt.h b/inc/external/acl/acl_tdt.h new file mode 100644 index 00000000..c357518d --- /dev/null +++ b/inc/external/acl/acl_tdt.h @@ -0,0 +1,276 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef INC_EXTERNAL_ACL_ACL_TDT_H_ +#define INC_EXTERNAL_ACL_ACL_TDT_H_ + +#include "acl/acl_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum acltdtTensorType { + ACL_TENSOR_DATA_UNDEFINED = -1, + ACL_TENSOR_DATA_TENSOR, + ACL_TENSOR_DATA_END_OF_SEQUENCE, + ACL_TENSOR_DATA_ABNORMAL +}; + +typedef struct acltdtDataItem acltdtDataItem; +typedef struct acltdtDataset acltdtDataset; +typedef struct acltdtChannelHandle acltdtChannelHandle; + +/** + * @ingroup AscendCL + * @brief Get tensor type from item + * + * @param dataItem [IN] pointer to the data item + * + * @retval Tensor type. + * @retval ACL_DT_UNDEFINED if dataItem is null + */ +ACL_FUNC_VISIBILITY acltdtTensorType acltdtGetTensorTypeFromItem(const acltdtDataItem *dataItem); + +/** + * @ingroup AscendCL + * @brief Get data type from item + * + * @param dataItem [IN] pointer to the data item + * + * @retval Data type. + * @retval ACL_DT_UNDEFINED if dataItem is null + */ +ACL_FUNC_VISIBILITY aclDataType acltdtGetDataTypeFromItem(const acltdtDataItem *dataItem); + +/** + * @ingroup AscendCL + * @brief Get data address from item + * + * @param dataItem [IN] pointer to data item + * + * @retval null for failed + * @retval OtherValues success + */ +ACL_FUNC_VISIBILITY void *acltdtGetDataAddrFromItem(const acltdtDataItem *dataItem); + +/** + * @ingroup AscendCL + * @brief Get data size from item + * + * @param dataItem [IN] pointer to data item + * + * @retval 0 for failed + * @retval OtherValues success + */ +ACL_FUNC_VISIBILITY size_t acltdtGetDataSizeFromItem(const acltdtDataItem *dataItem); + +/** + * @ingroup AscendCL + * @brief Get dim's number from item + * + * @param dataItem [IN] pointer to data item + * + * @retval 0 for failed + * @retval OtherValues success + */ +ACL_FUNC_VISIBILITY size_t acltdtGetDimNumFromItem(const acltdtDataItem *dataItem); + +/** + * @ingroup AscendCL + * @brief Get dims from item + * + * @param dataItem [IN] the struct of data item + * @param dims [IN|OUT] pointer to the dims of dataTtem + * @param dimNum [IN] the size of the dims + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acltdtGetDimsFromItem(const acltdtDataItem *dataItem, int64_t *dims, size_t dimNum); + +/** + * @ingroup AscendCL + * @brief Create the struct of data item + * + * @param tdtType [IN] Tdt tensor type + * @param dims [IN] pointer of tdtDataItem's dims + * @param dimNum [IN] Dim number + * @param dataType [IN] Data type + * @param data [IN] Data pointer + * @param size [IN] Data size + * + * @retval null for failed + * @retval OtherValues success + * + * @see acltdtDestroyDataItem + */ +ACL_FUNC_VISIBILITY acltdtDataItem *acltdtCreateDataItem(acltdtTensorType tdtType, const int64_t *dims, size_t dimNum, + aclDataType dataType, void *data, size_t size); + +/** + * @ingroup AscendCL + * @brief Destroy the struct of data item + * + * @param dataItem [IN] pointer to the data item + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtCreateDataItem + */ +ACL_FUNC_VISIBILITY aclError acltdtDestroyDataItem(acltdtDataItem *dataItem); + +/** + * @ingroup AscendCL + * @brief Create the tdt dataset + * + * @retval null for failed + * @retval OtherValues success + * + * @see acltdtDestroyDataset + */ +ACL_FUNC_VISIBILITY acltdtDataset *acltdtCreateDataset(); + +/** + * @ingroup AscendCL + * @brief Destroy the tdt dataset + * + * @param dataset [IN] pointer to the dataset + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtCreateDataset + */ +ACL_FUNC_VISIBILITY aclError acltdtDestroyDataset(acltdtDataset *dataset); + +/** + * @ingroup AscendCL + * @brief Get the data item + * + * @param dataset [IN] pointer to the dataset + * @param index [IN] index of the dataset + * + * @retval null for failed + * @retval OtherValues success + * + * @see acltdtAddDataItem + */ +ACL_FUNC_VISIBILITY acltdtDataItem *acltdtGetDataItem(const acltdtDataset *dataset, size_t index); + +/** + * @ingroup AscendCL + * @brief Get the data item + * + * @param dataset [OUT] pointer to the dataset + * @param dataItem [IN] pointer to the data item + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtGetDataItem + */ +ACL_FUNC_VISIBILITY aclError acltdtAddDataItem(acltdtDataset *dataset, acltdtDataItem *dataItem); + +/** + * @ingroup AscendCL + * @brief Get the size of dataset + * + * @param dataset [IN] pointer to the dataset + * + * @retval 0 for failed + * @retval OtherValues success + */ +ACL_FUNC_VISIBILITY size_t acltdtGetDatasetSize(const acltdtDataset *dataset); + +/** + * @ingroup AscendCL + * @brief Stop the channel + * + * @param handle [IN] pointer to the channel handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtCreateChannel | acltdtDestroyChannel + */ +ACL_FUNC_VISIBILITY aclError acltdtStopChannel(acltdtChannelHandle *handle); + +/** + * @ingroup AscendCL + * @brief Create the channel + * + * @param deviceId [IN] the device id + * @param name [IN] the channel's name + * + * @retval null for failed + * @retval OtherValues success + * + * @see acltdtStopChannel | acltdtDestroyChannel + */ +ACL_FUNC_VISIBILITY acltdtChannelHandle *acltdtCreateChannel(uint32_t deviceId, const char *name); + +/** + * @ingroup AscendCL + * @brief Destroy the channel + * + * @param handle [IN] pointer to the channel handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtCreateChannel | acltdtStopChannel + */ +ACL_FUNC_VISIBILITY aclError acltdtDestroyChannel(acltdtChannelHandle *handle); + +/** + * @ingroup AscendCL + * @brief Send tensor to device + * + * @param handle [IN] pointer to the channel handle + * @param dataset [IN] pointer to the dataset + * @param timeout [IN] to be reserved, now it must be -1 + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtReceiveTensor + */ +ACL_FUNC_VISIBILITY aclError acltdtSendTensor(const acltdtChannelHandle *handle, const acltdtDataset *dataset, + int32_t timeout); + +/** + * @ingroup AscendCL + * @brief Receive tensor from device + * + * @param handle [IN] pointer to the channel handle + * @param dataset [OUT] pointer to the dataset + * @param timeout [IN] to be reserved, now it must be -1 + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtSendTensor + */ +ACL_FUNC_VISIBILITY aclError acltdtReceiveTensor(const acltdtChannelHandle *handle, acltdtDataset *dataset, + int32_t timeout); + +#ifdef __cplusplus +} +#endif + +#endif // INC_EXTERNAL_ACL_ACL_TDT_H_ diff --git a/inc/external/acl/error_codes/ge_error_codes.h b/inc/external/acl/error_codes/ge_error_codes.h new file mode 100644 index 00000000..cafc5a64 --- /dev/null +++ b/inc/external/acl/error_codes/ge_error_codes.h @@ -0,0 +1,75 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef INC_EXTERNAL_GE_GE_ERROR_CODES_H_ +#define INC_EXTERNAL_GE_GE_ERROR_CODES_H_ + +#if defined(_MSC_VER) +#ifdef FUNC_VISIBILITY +#define GE_FUNC_VISIBILITY _declspec(dllexport) +#else +#define GE_FUNC_VISIBILITY +#endif +#else +#ifdef FUNC_VISIBILITY +#define GE_FUNC_VISIBILITY __attribute__((visibility("default"))) +#else +#define GE_FUNC_VISIBILITY +#endif +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif +static const uint32_t ACL_ERROR_GE_PARAM_INVALID = 145000; +static const uint32_t ACL_ERROR_GE_EXEC_NOT_INIT = 145001; +static const uint32_t ACL_ERROR_GE_EXEC_MODEL_PATH_INVALID = 145002; +static const uint32_t ACL_ERROR_GE_EXEC_MODEL_ID_INVALID = 145003; +static const uint32_t ACL_ERROR_GE_EXEC_MODEL_DATA_SIZE_INVALID = 145006; +static const uint32_t ACL_ERROR_GE_EXEC_MODEL_ADDR_INVALID = 145007; +static const uint32_t ACL_ERROR_GE_EXEC_MODEL_QUEUE_ID_INVALID = 145008; +static const uint32_t ACL_ERROR_GE_EXEC_LOAD_MODEL_REPEATED = 145009; +static const uint32_t ACL_ERROR_GE_DYNAMIC_INPUT_ADDR_INVALID = 145011; +static const uint32_t ACL_ERROR_GE_DYNAMIC_INPUT_LENGTH_INVALID = 145012; +static const uint32_t ACL_ERROR_GE_DYNAMIC_BATCH_SIZE_INVALID = 145013; +static const uint32_t ACL_ERROR_GE_AIPP_BATCH_EMPTY = 145014; +static const uint32_t ACL_ERROR_GE_AIPP_NOT_EXIST = 145015; +static const uint32_t ACL_ERROR_GE_AIPP_MODE_INVALID = 145016; +static const uint32_t ACL_ERROR_GE_OP_TASK_TYPE_INVALID = 145017; +static const uint32_t ACL_ERROR_GE_OP_KERNEL_TYPE_INVALID = 145018; +static const uint32_t ACL_ERROR_GE_PLGMGR_PATH_INVALID = 145019; +static const uint32_t ACL_ERROR_GE_FORMAT_INVALID = 145020; +static const uint32_t ACL_ERROR_GE_SHAPE_INVALID = 145021; +static const uint32_t ACL_ERROR_GE_DATATYPE_INVALID = 145022; +static const uint32_t ACL_ERROR_GE_MEMORY_ALLOCATION = 245000; +static const uint32_t ACL_ERROR_GE_MEMORY_OPERATE_FAILED = 245001; +static const uint32_t ACL_ERROR_GE_INTERNAL_ERROR = 545000; +static const uint32_t ACL_ERROR_GE_LOAD_MODEL = 545001; +static const uint32_t ACL_ERROR_GE_EXEC_LOAD_MODEL_PARTITION_FAILED = 545002; +static const uint32_t ACL_ERROR_GE_EXEC_LOAD_WEIGHT_PARTITION_FAILED = 545003; +static const uint32_t ACL_ERROR_GE_EXEC_LOAD_TASK_PARTITION_FAILED = 545004; +static const uint32_t ACL_ERROR_GE_EXEC_LOAD_KERNEL_PARTITION_FAILED = 545005; +static const uint32_t ACL_ERROR_GE_EXEC_RELEASE_MODEL_DATA = 545006; +static const uint32_t ACL_ERROR_GE_COMMAND_HANDLE = 545007; +static const uint32_t ACL_ERROR_GE_GET_TENSOR_INFO = 545008; +static const uint32_t ACL_ERROR_GE_UNLOAD_MODEL = 545009; + +#ifdef __cplusplus +} // namespace ge +#endif +#endif // INC_EXTERNAL_GE_GE_ERROR_CODES_H_ diff --git a/inc/external/acl/error_codes/rt_error_codes.h b/inc/external/acl/error_codes/rt_error_codes.h new file mode 100644 index 00000000..a1392cc6 --- /dev/null +++ b/inc/external/acl/error_codes/rt_error_codes.h @@ -0,0 +1,109 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef __INC_EXTERNEL_RT_ERROR_CODES_H__ +#define __INC_EXTERNEL_RT_ERROR_CODES_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static const int32_t ACL_RT_SUCCESS = 0; // success + +static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid +static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id +static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null +static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context +static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context +static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal +static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned +static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed +static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed +static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream +static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread +static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set +static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create +static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream +static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type +static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle +static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type +static const int32_t ACL_ERROR_RT_WAIT_TIMEOUT = 107019; // wait timeout + +static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support +static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error +static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error +static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow +static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device +static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail +static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission +static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource +static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource +static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource +static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource +static const int32_t ACL_ERROR_RT_NO_CDQ_RESOURCE = 207011; // no cdq resource + +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout +static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception +static const int32_t ACL_ERROR_RT_CDQ_BATCH_ABNORMAL = 507037; // cdq alloc batch abnormal + +static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error +static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error +static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect + +#ifdef __cplusplus +} +#endif + +#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/inc/external/acl/ops/acl_cblas.h b/inc/external/acl/ops/acl_cblas.h new file mode 100644 index 00000000..3d81eb2b --- /dev/null +++ b/inc/external/acl/ops/acl_cblas.h @@ -0,0 +1,334 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef INC_EXTERNAL_ACL_OPS_ACL_CBLAS_H_ +#define INC_EXTERNAL_ACL_OPS_ACL_CBLAS_H_ + +#include "acl/acl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum aclTransType { ACL_TRANS_N, ACL_TRANS_T, ACL_TRANS_NZ, ACL_TRANS_NZ_T } aclTransType; + +typedef enum aclComputeType { ACL_COMPUTE_HIGH_PRECISION, ACL_COMPUTE_LOW_PRECISION } aclComputeType; + +/** + * @ingroup AscendCL + * @brief perform the matrix-vector multiplication + * + * @param transA [IN] transpose type of matrix A + * @param m [IN] number of rows of matrix A + * @param n [IN] number of columns of matrix A + * @param alpha [IN] pointer to scalar used for multiplication. + * of same type as dataTypeC + * @param a [IN] pointer to matrix A + * @param lda [IN] leading dimension used to store the matrix A + * @param dataTypeA [IN] datatype of matrix A + * @param x [IN] pointer to vector x + * @param incx [IN] stride between consecutive elements of vector x + * @param dataTypeX [IN] datatype of vector x + * @param beta [IN] pointer to scalar used for multiplication. + * of same type as dataTypeC If beta == 0, + * then y does not have to be a valid input + * @param y [IN|OUT] pointer to vector y + * @param incy [IN] stride between consecutive elements of vector y + * @param dataTypeY [IN] datatype of vector y + * @param type [IN] computation type + * @param stream [IN] stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclblasGemvEx(aclTransType transA, int m, int n, const void *alpha, const void *a, int lda, + aclDataType dataTypeA, const void *x, int incx, aclDataType dataTypeX, + const void *beta, void *y, int incy, aclDataType dataTypeY, + aclComputeType type, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief create a handle for performing the matrix-vector multiplication + * + * @param transA [IN] transpose type of matrix A + * @param m [IN] number of rows of matrix A + * @param n [IN] number of columns of matrix A + * @param dataTypeA [IN] datatype of matrix A + * @param dataTypeX [IN] datatype of vector x + * @param dataTypeY [IN] datatype of vector y + * @param type [IN] computation type + * @param handle [OUT] pointer to the pointer to the handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemvEx(aclTransType transA, int m, int n, aclDataType dataTypeA, + aclDataType dataTypeX, aclDataType dataTypeY, + aclComputeType type, aclopHandle **handle); + +/** + * @ingroup AscendCL + * @brief perform the matrix-vector multiplication + * + * @param transA [IN] transpose type of matrix A + * @param m [IN] number of rows of matrix A + * @param n [IN] number of columns of matrix A + * @param alpha [IN] pointer to scalar used for multiplication + * @param a [IN] pointer to matrix A + * @param lda [IN] leading dimension used to store the matrix A + * @param x [IN] pointer to vector x + * @param incx [IN] stride between consecutive elements of vector x + * @param beta [IN] pointer to scalar used for multiplication. + * If beta value == 0, + * then y does not have to be a valid input + * @param y [IN|OUT] pointer to vector y + * @param incy [IN] stride between consecutive elements of vector y + * @param type [IN] computation type + * @param stream [IN] stream + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclblasHgemv(aclTransType transA, int m, int n, const aclFloat16 *alpha, + const aclFloat16 *a, int lda, const aclFloat16 *x, int incx, + const aclFloat16 *beta, aclFloat16 *y, int incy, aclComputeType type, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief create a handle for performing the matrix-vector multiplication + * + * @param transA [IN] transpose type of matrix A + * @param m [IN] number of rows of matrix A + * @param n [IN] number of columns of matrix A + * @param type [IN] computation type + * @param handle [OUT] pointer to the pointer to the handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemv(aclTransType transA, int m, int n, aclComputeType type, + aclopHandle **handle); + +/** + * @ingroup AscendCL + * @brief perform the matrix-vector multiplication + * + * @param transA [IN] transpose type of matrix A + * @param m [IN] number of rows of matrix A + * @param n [IN] number of columns of matrix A + * @param alpha [IN] pointer to scalar used for multiplication + * @param a [IN] pointer to matrix A + * @param lda [IN] leading dimension used to store the matrix A + * @param x [IN] pointer to vector x + * @param incx [IN] stride between consecutive elements of vector x + * @param beta [IN] pointer to scalar used for multiplication. + * If beta value == 0, + * then y does not have to be a valid input + * @param y [IN|OUT] pointer to vector y + * @param incy [IN] stride between consecutive elements of vector y + * @param type [IN] computation type + * @param stream [IN] stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclblasS8gemv(aclTransType transA, int m, int n, const int32_t *alpha, const int8_t *a, + int lda, const int8_t *x, int incx, const int32_t *beta, int32_t *y, + int incy, aclComputeType type, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief create a handle for performing the matrix-vector multiplication + * + * @param transA [IN] transpose type of matrix A + * @param m [IN] number of rows of matrix A + * @param n [IN] number of columns of matrix A + * @param handle [OUT] pointer to the pointer to the handle + * @param type [IN] computation type + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemv(aclTransType transA, int m, int n, aclComputeType type, + aclopHandle **handle); + +/** + * @ingroup AscendCL + * @brief perform the matrix-matrix multiplication + * + * @param transA [IN] transpose type of matrix A + * @param transB [IN] transpose type of matrix B + * @param transC [IN] transpose type of matrix C + * @param m [IN] number of rows of matrix A and matrix C + * @param n [IN] number of columns of matrix B and matrix C + * @param k [IN] number of columns of matrix A and rows of matrix B + * @param alpha [IN] pointer to scalar used for multiplication. of same type as dataTypeC + * @param matrixA [IN] pointer to matrix A + * @param lda [IN] leading dimension array used to store matrix A + * @param dataTypeA [IN] datatype of matrix A + * @param matrixB [IN] pointer to matrix B + * @param ldb [IN] leading dimension array used to store matrix B + * @param dataTypeB [IN] datatype of matrix B + * @param beta [IN] pointer to scalar used for multiplication. + * of same type as dataTypeC If beta == 0, + * then matrixC does not have to be a valid input + * @param matrixC [IN|OUT] pointer to matrix C + * @param ldc [IN] leading dimension array used to store matrix C + * @param dataTypeC [IN] datatype of matrix C + * @param type [IN] computation type + * @param stream [IN] stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclblasGemmEx(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, + int k, const void *alpha, const void *matrixA, int lda, + aclDataType dataTypeA, const void *matrixB, int ldb, aclDataType dataTypeB, + const void *beta, void *matrixC, int ldc, aclDataType dataTypeC, + aclComputeType type, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief create a handle for performing the matrix-matrix multiplication + * + * @param transA [IN] transpose type of matrix A + * @param transB [IN] transpose type of matrix B + * @param transC [IN] transpose type of matrix C + * @param m [IN] number of rows of matrix A and matrix C + * @param n [IN] number of columns of matrix B and matrix C + * @param k [IN] number of columns of matrix A and rows of matrix B + * @param dataTypeA [IN] datatype of matrix A + * @param dataTypeB [IN] datatype of matrix B + * @param dataTypeC [IN] datatype of matrix C + * @param type [IN] computation type + * @param handle [OUT] pointer to the pointer to the handle + * @param type [IN] computation type + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForGemmEx(aclTransType transA, aclTransType transB, aclTransType transC, + int m, int n, int k, aclDataType dataTypeA, + aclDataType dataTypeB, aclDataType dataTypeC, + aclComputeType type, aclopHandle **handle); + +/** + * @ingroup AscendCL + * @brief perform the matrix-matrix multiplication + * + * @param transA [IN] transpose type of matrix A + * @param transB [IN] transpose type of matrix B + * @param transC [IN] transpose type of matrix C + * @param m [IN] number of rows of matrix A and matrix C + * @param n [IN] number of columns of matrix B and matrix C + * @param k [IN] number of columns of matrix A and rows of matrix B + * @param alpha [IN] pointer to scalar used for multiplication + * @param matrixA [IN] pointer to matrix A + * @param lda [IN] leading dimension used to store the matrix A + * @param matrixB [IN] pointer to matrix B + * @param ldb [IN] leading dimension used to store the matrix B + * @param beta [IN] pointer to scalar used for multiplication. + * If beta value == 0, + * then matrixC does not have to be a valid input + * @param matrixC [IN|OUT] pointer to matrix C + * @param ldc [IN] leading dimension used to store the matrix C + * @param type [IN] computation type + * @param stream [IN] stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclblasHgemm(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, + int k, const aclFloat16 *alpha, const aclFloat16 *matrixA, int lda, + const aclFloat16 *matrixB, int ldb, const aclFloat16 *beta, + aclFloat16 *matrixC, int ldc, aclComputeType type, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief create a handle for performing the matrix-matrix multiplication + * + * @param transA [IN] transpose type of matrix A + * @param transB [IN] transpose type of matrix B + * @param transC [IN] transpose type of matrix C + * @param m [IN] number of rows of matrix A and matrix C + * @param n [IN] number of columns of matrix B and matrix C + * @param k [IN] number of columns of matrix A and rows of matrix B + * @param type [IN] computation type + * @param handle [OUT] pointer to the pointer to the handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForHgemm(aclTransType transA, aclTransType transB, aclTransType transC, + int m, int n, int k, aclComputeType type, + aclopHandle **handle); + +/** + * @ingroup AscendCL + * @brief perform the matrix-matrix multiplication + * + * @param transA [IN] transpose type of matrix A + * @param transB [IN] transpose type of matrix B + * @param transC [IN] transpose type of matrix C + * @param m [IN] number of rows of matrix A and matrix C + * @param n [IN] number of columns of matrix B and matrix C + * @param k [IN] number of columns of matrix A and rows of matrix B + * @param alpha [IN] pointer to scalar used for multiplication + * @param matrixA [IN] pointer to matrix A + * @param lda [IN] leading dimension used to store the matrix A + * @param matrixB [IN] pointer to matrix B + * @param ldb [IN] leading dimension used to store the matrix B + * @param beta [IN] pointer to scalar used for multiplication. + * If beta value == 0, + * then matrixC does not have to be a valid input + * @param matrixC [IN|OUT] pointer to matrix C + * @param ldc [IN] leading dimension used to store the matrix C + * @param type [IN] computation type + * @param stream [IN] stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclblasS8gemm(aclTransType transA, aclTransType transB, aclTransType transC, int m, int n, + int k, const int32_t *alpha, const int8_t *matrixA, int lda, + const int8_t *matrixB, int ldb, const int32_t *beta, int32_t *matrixC, + int ldc, aclComputeType type, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief create a handle for performing the matrix-matrix multiplication + * + * @param transA [IN] transpose type of matrix A + * @param transB [IN] transpose type of matrix B + * @param transC [IN] transpose type of matrix C + * @param m [IN] number of rows of matrix A and matrix C + * @param n [IN] number of columns of matrix B and matrix C + * @param k [IN] number of columns of matrix A and rows of matrix B + * @param type [IN] computation type + * @param handle [OUT] pointer to the pointer to the handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclblasCreateHandleForS8gemm(aclTransType transA, aclTransType transB, aclTransType transC, + int m, int n, int k, aclComputeType type, + aclopHandle **handle); + +#ifdef __cplusplus +} +#endif + +#endif // INC_EXTERNAL_ACL_OPS_ACL_CBLAS_H_ diff --git a/inc/external/acl/ops/acl_dvpp.h b/inc/external/acl/ops/acl_dvpp.h new file mode 100644 index 00000000..dcaa3936 --- /dev/null +++ b/inc/external/acl/ops/acl_dvpp.h @@ -0,0 +1,2568 @@ +/** + * Copyright 2019-2020 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. + */ + +#if !defined(ENABLE_DVPP_INTERFACE) +#if defined(_MSC_VER) +#error message("if you want to use dvpp funtions ,please use the macro definition (ENABLE_DVPP_INTERFACE).") +#else +#error "if you want to use dvpp funtions ,please use the macro definition (ENABLE_DVPP_INTERFACE)." +#endif +#endif + +#ifndef INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ +#define INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ + +#include +#include +#include "acl/acl.h" +#include "acl/acl_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct acldvppPicDesc acldvppPicDesc; +typedef struct acldvppBatchPicDesc acldvppBatchPicDesc; +typedef struct acldvppRoiConfig acldvppRoiConfig; +typedef struct acldvppResizeConfig acldvppResizeConfig; +typedef struct acldvppBorderConfig acldvppBorderConfig; +typedef struct acldvppLutMap acldvppLutMap; +typedef struct acldvppChannelDesc acldvppChannelDesc; +typedef struct acldvppJpegeConfig acldvppJpegeConfig; +typedef struct aclvdecChannelDesc aclvdecChannelDesc; +typedef struct acldvppStreamDesc acldvppStreamDesc; +typedef struct aclvdecFrameConfig aclvdecFrameConfig; +typedef struct aclvencChannelDesc aclvencChannelDesc; +typedef struct aclvencFrameConfig aclvencFrameConfig; +typedef struct acldvppHist acldvppHist; +typedef void (*aclvdecCallback)(acldvppStreamDesc *input, acldvppPicDesc *output, void *userData); +typedef void (*aclvencCallback)(acldvppPicDesc *input, acldvppStreamDesc *output, void *userdata); + +// Supported Pixel Format +enum acldvppPixelFormat { + PIXEL_FORMAT_YUV_400 = 0, // 0 + PIXEL_FORMAT_YUV_SEMIPLANAR_420 = 1, // 1 + PIXEL_FORMAT_YVU_SEMIPLANAR_420 = 2, // 2 + PIXEL_FORMAT_YUV_SEMIPLANAR_422 = 3, // 3 + PIXEL_FORMAT_YVU_SEMIPLANAR_422 = 4, // 4 + PIXEL_FORMAT_YUV_SEMIPLANAR_444 = 5, // 5 + PIXEL_FORMAT_YVU_SEMIPLANAR_444 = 6, // 6 + PIXEL_FORMAT_YUYV_PACKED_422 = 7, // 7 + PIXEL_FORMAT_UYVY_PACKED_422 = 8, // 8 + PIXEL_FORMAT_YVYU_PACKED_422 = 9, // 9 + PIXEL_FORMAT_VYUY_PACKED_422 = 10, // 10 + PIXEL_FORMAT_YUV_PACKED_444 = 11, // 11 + PIXEL_FORMAT_RGB_888 = 12, // 12 + PIXEL_FORMAT_BGR_888 = 13, // 13 + PIXEL_FORMAT_ARGB_8888 = 14, // 14 + PIXEL_FORMAT_ABGR_8888 = 15, // 15 + PIXEL_FORMAT_RGBA_8888 = 16, // 16 + PIXEL_FORMAT_BGRA_8888 = 17, // 17 + PIXEL_FORMAT_YUV_SEMI_PLANNER_420_10BIT = 18, // 18 + PIXEL_FORMAT_YVU_SEMI_PLANNER_420_10BIT = 19, // 19 + PIXEL_FORMAT_YVU_PLANAR_420 = 20, // 20 + PIXEL_FORMAT_YVU_PLANAR_422, + PIXEL_FORMAT_YVU_PLANAR_444, + PIXEL_FORMAT_RGB_444 = 23, + PIXEL_FORMAT_BGR_444, + PIXEL_FORMAT_ARGB_4444, + PIXEL_FORMAT_ABGR_4444, + PIXEL_FORMAT_RGBA_4444, + PIXEL_FORMAT_BGRA_4444, + PIXEL_FORMAT_RGB_555, + PIXEL_FORMAT_BGR_555, + PIXEL_FORMAT_RGB_565, + PIXEL_FORMAT_BGR_565, + PIXEL_FORMAT_ARGB_1555, + PIXEL_FORMAT_ABGR_1555, + PIXEL_FORMAT_RGBA_1555, + PIXEL_FORMAT_BGRA_1555, + PIXEL_FORMAT_ARGB_8565, + PIXEL_FORMAT_ABGR_8565, + PIXEL_FORMAT_RGBA_8565, + PIXEL_FORMAT_BGRA_8565, + PIXEL_FORMAT_RGB_BAYER_8BPP = 50, + PIXEL_FORMAT_RGB_BAYER_10BPP, + PIXEL_FORMAT_RGB_BAYER_12BPP, + PIXEL_FORMAT_RGB_BAYER_14BPP, + PIXEL_FORMAT_RGB_BAYER_16BPP, + PIXEL_FORMAT_BGR_888_PLANAR = 70, + PIXEL_FORMAT_HSV_888_PACKAGE, + PIXEL_FORMAT_HSV_888_PLANAR, + PIXEL_FORMAT_LAB_888_PACKAGE, + PIXEL_FORMAT_LAB_888_PLANAR, + PIXEL_FORMAT_S8C1, + PIXEL_FORMAT_S8C2_PACKAGE, + PIXEL_FORMAT_S8C2_PLANAR, + PIXEL_FORMAT_S16C1, + PIXEL_FORMAT_U8C1, + PIXEL_FORMAT_U16C1, + PIXEL_FORMAT_S32C1, + PIXEL_FORMAT_U32C1, + PIXEL_FORMAT_U64C1, + PIXEL_FORMAT_S64C1, + PIXEL_FORMAT_YUV_SEMIPLANAR_440 = 1000, + PIXEL_FORMAT_YVU_SEMIPLANAR_440, + PIXEL_FORMAT_FLOAT32, + PIXEL_FORMAT_BUTT, + PIXEL_FORMAT_UNKNOWN = 10000 +}; + +// Stream Format +enum acldvppStreamFormat { H265_MAIN_LEVEL = 0, H264_BASELINE_LEVEL, H264_MAIN_LEVEL, H264_HIGH_LEVEL }; + +// Supported Channel Mode +enum acldvppChannelMode { DVPP_CHNMODE_VPC = 1, DVPP_CHNMODE_JPEGD = 2, DVPP_CHNMODE_JPEGE = 4 }; + +// Supported Border Type +enum acldvppBorderType { BORDER_CONSTANT = 0, BORDER_REPLICATE, BORDER_REFLECT, BORDER_REFLECT_101 }; + +// Venc parameter type +enum aclvencChannelDescParamType { + ACL_VENC_THREAD_ID_UINT64 = 0, + ACL_VENC_CALLBACK_PTR, + ACL_VENC_PIXEL_FORMAT_UINT32, + ACL_VENC_ENCODE_TYPE_UINT32, + ACL_VENC_PIC_WIDTH_UINT32, + ACL_VENC_PIC_HEIGHT_UINT32, + ACL_VENC_KEY_FRAME_INTERVAL_UINT32, + ACL_VENC_BUF_ADDR_PTR, + ACL_VENC_BUF_SIZE_UINT32, + ACL_VENC_RC_MODE_UINT32, + ACL_VENC_SRC_RATE_UINT32, + ACL_VENC_MAX_BITRATE_UINT32, + ACL_VENC_MAX_IP_PROP_UINT32 +}; + +// Jpeg picture format +enum acldvppJpegFormat { + ACL_JPEG_CSS_444 = 0, + ACL_JPEG_CSS_422, + ACL_JPEG_CSS_420, + ACL_JPEG_CSS_GRAY, + ACL_JPEG_CSS_440, + ACL_JPEG_CSS_411, + ACL_JPEG_CSS_UNKNOWN = 1000 +}; + +/** + * @ingroup AscendCL + * @brief alloc device memory for dvpp. + * + * @par Function + * @li It's mainly used for allocating memory to device media data processing. + * The requested memory meets the data processing requirements. + * After calling this interface to request memory, + * you must release the memory using the acldvppFree interface. + * @li When calling the acldvppMalloc interface to apply for memory, + * the size entered by the user is aligned upwards to 32 integer multiples, + * and an additional 32 bytes are applied. + * + * @par Restriction + * If the user uses the acldvppMalloc interface to apply for a large block of + * memory and divide and manage the memory by himself, + * when applying for memory, the user needs to align up to 32 integer + * times + 32 bytes (ALIGN_UP [len] +32 words) according to + * the actual data size of each picture Section) to manage memory. + * + * @param devPtr [OUT] memory pointer. + * @param size [IN] memory size. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppFree + */ +ACL_FUNC_VISIBILITY aclError acldvppMalloc(void **devPtr, size_t size); + +/** + * @ingroup AscendCL + * @brief free device memory for dvpp. + * + * @par Function + * Free the memory requested through the acldvppMalloc interface + * @param devPtr [IN] memory pointer to free. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppMalloc + */ +ACL_FUNC_VISIBILITY aclError acldvppFree(void *devPtr); + +/** + * @ingroup AscendCL + * @brief create DvppChannelDesc. + * + * @par Function + * Create a channel for image data processing. + * The same channel can be reused + * and is no longer available after destruction + * + * @retval null for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY acldvppChannelDesc *acldvppCreateChannelDesc(); + +/** + * @ingroup AscendCL + * @brief destroy dvppChannelDesc. + * + * @par Function + * Can only destroy channels created by the acldvppCreateChannel interface + * @param channelDesc [IN] the channel description. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannelDesc | acldvppDestroyChannel + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyChannelDesc(acldvppChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get dvpp channel Id. + * + * @par Restriction + * Interface calling sequence: + * acldvppCreateChannelDesc --> acldvppCreateChannel --> + * acldvppGetChannelDescChannelId + * + * @param channelDesc [IN] the channel description. + * + * @retval channel id. + * + * @see acldvppCreateChannelDesc | acldvppCreateChannel + */ +ACL_FUNC_VISIBILITY uint64_t acldvppGetChannelDescChannelId(const acldvppChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Create dvpp picture description. + * + * @retval null for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY acldvppPicDesc *acldvppCreatePicDesc(); + +/** + * @ingroup AscendCL + * @brief Destroy dvpp picture description. + * + * @par Function + * Can only destroy picture description information created + * through acldvppCreatePicDesc interface. + * @param picDesc [IN] dvpp picture description. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreatePicDesc + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyPicDesc(acldvppPicDesc *picDesc); + +/** + * @ingroup AscendCL + * @brief Set dvpp picture description's data. + * + * @param picDesc [OUT] dvpp picture description. + * @param dataDev [IN] dvpp picture dataDev.Must be the memory + * requested using the acldvppMalloc interface. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppMalloc + */ +ACL_FUNC_VISIBILITY aclError acldvppSetPicDescData(acldvppPicDesc *picDesc, void *dataDev); + +/** + * @ingroup AscendCL + * @brief Set dvpp picture description's size. + * + * @param picDesc [OUT] dvpp picture description. + * @param size dvpp [IN] picture size. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetPicDescSize(acldvppPicDesc *picDesc, uint32_t size); + +/** + * @ingroup AscendCL + * @brief Set dvpp picture description's format. + * + * @param picDesc [OUT] dvpp picture description. + * @param format [IN] dvpp picture format. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetPicDescFormat(acldvppPicDesc *picDesc, acldvppPixelFormat format); + +/** + * @ingroup AscendCL + * @brief Set dvpp picture description's width. + * + * @param picDesc [OUT] dvpp picture description. + * @param width [IN] dvpp picture width. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetPicDescWidth(acldvppPicDesc *picDesc, uint32_t width); + +/** + * @ingroup AscendCL + * @brief Set dvpp picture description's height. + * + * @param picDesc [OUT] dvpp picture description. + * @param height [IN] dvpp picture height. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetPicDescHeight(acldvppPicDesc *picDesc, uint32_t height); + +/** + * @ingroup AscendCL + * @brief Set dvpp picture description's widthStride. + * + * @par Restriction + * Width alignment requirements: + * @li The minimum stride is 32 and the maximum is 4096 * 4 + * (that is, an image in argb format with a width of 4096); + * @li For 8K scaling, widthStride is required to be aligned to 2; + * @li For non 8K scaling, the calculation formula for widthStride + * is different for different image formats: + * @li yuv400sp, yuv420sp, yuv422sp, yuv444sp: input image width aligned to 16 + * @li yuv422packed: input image width * 2 and then align to 16 + * @li yuv444packed, rgb888: input image width alignment * 3, alignment to 16 + * @li xrgb8888: input image width * 4, align to 16 + * @li HFBC:input image width + * + * @param picDesc [OUT] dvpp picture description. + * @param widthStride [IN] dvpp picture widthStride. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetPicDescWidthStride(acldvppPicDesc *picDesc, uint32_t widthStride); + +/** + * @ingroup AscendCL + * @brief Set dvpp picture description's heightStride. + * + * @par Restriction + * Height alignment requirements: + * @li The height of the input image is aligned to 2. + * High stride minimum 6 and maximum 4096. + * + * @param picDesc [OUT] dvpp picture description. + * @param heightStride [IN] dvpp picture heightStride. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetPicDescHeightStride(acldvppPicDesc *picDesc, uint32_t heightStride); + +/** + * @ingroup AscendCL + * @brief Set dvpp picture description's retcode. + * + * @param picDesc [OUT] dvpp picture description. + * @param retCode [IN] dvpp picture retcode. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetPicDescRetCode(acldvppPicDesc *picDesc, uint32_t retCode); + +/** + * @ingroup AscendCL + * @brief Get picture data. + * + * @param picDesc [IN] dvpp picture description. + * + * @retval picture data addr. + * @retval default nullptr. + */ +ACL_FUNC_VISIBILITY void *acldvppGetPicDescData(const acldvppPicDesc *picDesc); + +/** + * @ingroup AscendCL + * @brief Get picture data size. + * + * @param picDesc [IN] dvpp picture description. + * + * @retval picture data size. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescSize(const acldvppPicDesc *picDesc); + +/** + * @ingroup AscendCL + * @brief Get dvpp picture desc's format. + * + * @param picDesc [IN] dvpp picture description. + * + * @retval format + * @retval default PIXEL_FORMAT_YUV_400. + */ +ACL_FUNC_VISIBILITY acldvppPixelFormat acldvppGetPicDescFormat(const acldvppPicDesc *picDesc); + +/** + * @ingroup AscendCL + * @brief Get dvpp picture desc's width. + * + * @param picDesc [IN] dvpp picture description. + * + * @retval width. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescWidth(const acldvppPicDesc *picDesc); + +/** + * @ingroup AscendCL + * @brief Get dvpp picture desc's height. + * + * @param picDesc [IN] dvpp picture description. + * + * @retval height. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescHeight(const acldvppPicDesc *picDesc); + +/** + * @ingroup AscendCL + * @brief Get dvpp picture desc's widthStride. + * + * @par Restriction + * Width alignment requirements: + * @li The minimum stride is 32 and the maximum is 4096 * 4 + * (that is, an image in argb format with a width of 4096); + * @li For 8K scaling, widthStride is required to be aligned to 2; + * @li For non 8K scaling, the calculation formula for widthStride + * is different for different image formats: + * @li yuv400sp, yuv420sp, yuv422sp, yuv444sp: input image width aligned to 16 + * @li yuv422packed: input image width * 2 and then align to 16 + * @li yuv444packed, rgb888: input image width alignment * 3, alignment to 16 + * @li xrgb8888: input image width * 4, align to 16 + * @li HFBC:input image width + * + * @param picDesc [IN] dvpp picture description. + * + * @retval stride width. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescWidthStride(const acldvppPicDesc *picDesc); + +/** + * @ingroup AscendCL + * @brief Get dvpp picture desc's heightStride. + * + * @par Restriction + * Height alignment requirements: + * @li The height of the input image is aligned to 2. + * High stride minimum 6 and maximum 4096. + * + * @param picDesc [IN] dvpp picture description. + * + * @retval stride height. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescHeightStride(const acldvppPicDesc *picDesc); + +/** + * @ingroup AscendCL + * @brief Get dvpp picture desc's retcode. + * + * @param picDesc [IN] dvpp picture description. + * + * @retval ret code. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetPicDescRetCode(const acldvppPicDesc *picDesc); + +/** + * @ingroup AscendCL + * @brief Create dvpp roi config. + * + * @param left [IN] the left offset, must be even + * @param right [IN] the right offset, must be odd + * @param top [IN] the top offset, must be even + * @param bottom [IN] the bottom offset, must be odd + * + * @retval null for failed. + * @retval other success + */ +ACL_FUNC_VISIBILITY acldvppRoiConfig *acldvppCreateRoiConfig(uint32_t left, uint32_t right, uint32_t top, + uint32_t bottom); + +/** + * @ingroup AscendCL + * @brief Destroy dvpp roi config. + * + * @par Function + * Destroys data created through the acldvppCreateRoiConfig interface + * @param roiConfig [IN] dvpp roi config. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateRoiConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyRoiConfig(acldvppRoiConfig *roiConfig); + +/** + * @ingroup AscendCL + * @brief Set left of RoiConfig. + * + * @param config [OUT] RoiConfig + * @param left [IN] left offset + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfigLeft(acldvppRoiConfig *config, uint32_t left); + +/** + * @ingroup AscendCL + * @brief Set right of RoiConfig. + * + * @param config [OUT] RoiConfig + * @param right [IN] right offset + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfigRight(acldvppRoiConfig *config, uint32_t right); + +/** + * @ingroup AscendCL + * @brief Set top of RoiConfig. + * + * @param config [OUT] RoiConfig + * @param top [IN] top offset + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfigTop(acldvppRoiConfig *config, uint32_t top); + +/** + * @ingroup AscendCL + * @brief Set bottom of RoiConfig. + * + * @param config [OUT] RoiConfig + * @param bottom [IN] bottom offset + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfigBottom(acldvppRoiConfig *config, uint32_t bottom); + +/** + * @ingroup AscendCL + * @brief Set RoiConfig. + * + * @param config [OUT] RoiConfig + * @param left [IN] left offset + * @param right [IN] right offset + * @param top [IN] top offset + * @param bottom [IN] bottom offset + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetRoiConfig(acldvppRoiConfig *config, uint32_t left, uint32_t right, uint32_t top, + uint32_t bottom); + +/** + * @ingroup AscendCL + * @brief Create dvpp resize config. + * The specified scaling algorithm is not supported. + * The default scaling algorithm is "nearest neighbor interpolation". + * + * @retval null for failed. + * @retval other success. + */ +ACL_FUNC_VISIBILITY acldvppResizeConfig *acldvppCreateResizeConfig(); + +/** + * @ingroup AscendCL + * @brief Destroy dvpp resize config. + * + * @par Function + * Destroys the scaling configuration data created by + * the acldvppCreateResizeConfig interface + * + * @param resizeConfig [IN] resize config. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateResizeConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyResizeConfig(acldvppResizeConfig *resizeConfig); + +/** + * @ingroup AscendCL + * @brief Create jpege config. + * + * @retval null for failed. + * @retval other success. + */ +ACL_FUNC_VISIBILITY acldvppJpegeConfig *acldvppCreateJpegeConfig(); + +/** + * @ingroup AscendCL + * @brief Destroy jpege config. + * + * @par Function + * Destroys the encoding configuration data created by + * the acldvppCreateJpegeConfig interface + * @param jpegeConfig [IN] config pointer to destroy. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateJpegeConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyJpegeConfig(acldvppJpegeConfig *jpegeConfig); + +/** + * @ingroup AscendCL + * @brief Set jpege config's level. + * + * @param jpegeConfig [OUT] Call the acldvppCreateJpegeConfig + * interface to create acldvppJpegeConfig data + * @param level [IN] Encoding quality range [0, 100], + * where level 0 encoding quality is similar to level 100, + * and the smaller the value in [1, 100], + * the worse the quality of the output picture. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetJpegeConfigLevel(acldvppJpegeConfig *jpegeConfig, uint32_t level); + +/** + * @ingroup AscendCL + * @brief Get jpege config's level. + * + * @param jpegeConfig [IN] jpege config. + * + * @retval compression level. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetJpegeConfigLevel(const acldvppJpegeConfig *jpegeConfig); + +/** + * @ingroup AscendCL + * @brief create vdecChannelDesc.Channel description information + * when creating a video data processing channel. + * + * @retval null for failed. + * @retval other success + */ +ACL_FUNC_VISIBILITY aclvdecChannelDesc *aclvdecCreateChannelDesc(); + +/** + * @ingroup AscendCL + * @brief destroy vdecChannelDesc. + * + * @par Function + * Can only destroy aclvdecChannelDesc type created + * through aclvdecCreateChannelDesc interface + * @param channelDesc [IN] channel description. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + + * @see aclvdecCreateChannelDesc + */ +ACL_FUNC_VISIBILITY aclError aclvdecDestroyChannelDesc(aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Set vdec channel description's channel id. + * + * @param channelDesc [OUT] vdec channel description. + * @param channelId [IN] decoding channel id: 0~15. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescChannelId(aclvdecChannelDesc *channelDesc, uint32_t channelId); + +/** + * @ingroup AscendCL + * @brief Set vdec channel description's thread id. + * + * @param channelDesc [OUT] vdec channel description. + * @param threadId [IN] thread id. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescThreadId(aclvdecChannelDesc *channelDesc, uint64_t threadId); + +/** + * @ingroup AscendCL + * @brief Set vdec channel description's callback function. + * + * @param channelDesc [OUT] vdec channel description. + * @param callback [IN] function callback.Function prototype: + * void (* aclvdecCallback) + * (acldvppStreamDesc * input, acldvppPicDesc * output, void* userdata) + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclvdecCallback + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescCallback(aclvdecChannelDesc *channelDesc, aclvdecCallback callback); + +/** + * @ingroup AscendCL + * @brief Set vdec channel description's video encoding type. + * + * @param channelDesc [OUT] vdec channel description. + * @param enType [IN] video encoding type. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescEnType(aclvdecChannelDesc *channelDesc, acldvppStreamFormat enType); + +/** + * @ingroup AscendCL + * @brief Set vdec channel description's out picture format. + * + * @param channelDesc [OUT] vdec channel description. + * @param outPicFormat [IN] out picture format (acldvppPixelFormat). + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutPicFormat(aclvdecChannelDesc *channelDesc, + acldvppPixelFormat outPicFormat); + +/** + * @ingroup AscendCL + * @brief Set vdec channel description's out picture width. + * + * @param channelDesc [OUT] vdec channel description. + * @param outPicWidth [IN] out picture width. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutPicWidth(aclvdecChannelDesc *channelDesc, uint32_t outPicWidth); + +/** + * @ingroup AscendCL + * @brief Set vdec channel description's out picture height. + * + * @param channelDesc [OUT] vdec channel description. + * @param outPicHeight [IN] out picture height. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutPicHeight(aclvdecChannelDesc *channelDesc, uint32_t outPicHeight); + +/** + * @ingroup AscendCL + * @brief Set vdec channel description's reference frame num. + * + * @param channelDesc [OUT] vdec channel description. + * @param refFrameNum [IN] reference frame num. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescRefFrameNum(aclvdecChannelDesc *channelDesc, uint32_t refFrameNum); + +/** + * @ingroup AscendCL + * @brief Set vdec channel description's bit depth. + * + * @param channelDesc [OUT] vdec channel description. + * @param bitDepth [IN] bit depth. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescBitDepth(aclvdecChannelDesc *channelDesc, uint32_t bitDepth); + +/** + * @ingroup AscendCL + * @brief Get vdec channel description's channel id. + * + * @param channelDesc [IN] vdec channel description. + * + * @retval decoding channel id: 0~15. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t aclvdecGetChannelDescChannelId(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get vdec channel description's thread id. + * + * @param channelDesc [IN] vdec channel description. + * + * @retval thread id. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint64_t aclvdecGetChannelDescThreadId(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get vdec channel description's callback function. + * + * @param channelDesc [IN] vdec channel description. + * + * @retval function callback.Function prototype: + * void (* aclvdecCallback) + * (acldvppStreamDesc * input, acldvppPicDesc * output, void* userdata) + * @retval default null. + * + * @see aclvdecCallback + */ +ACL_FUNC_VISIBILITY aclvdecCallback aclvdecGetChannelDescCallback(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get vdec channel description's video encoding type. + * + * @param channelDesc [IN] vdec channel description. + * + * @retval video encoding type. + * @retval default H265_MAIN_LEVEL. + */ +ACL_FUNC_VISIBILITY acldvppStreamFormat aclvdecGetChannelDescEnType(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get vdec channel description's out picture format. + * + * @param channelDesc [IN] vdec channel description. + * + * @retval out picture format. + * @retval default DVPP_OUTPUT_YUV420SP_UV. + */ +ACL_FUNC_VISIBILITY acldvppPixelFormat aclvdecGetChannelDescOutPicFormat(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get vdec channel description's out picture width. + * + * @param channelDesc [IN] vdec channel description. + * + * @retval out picture width. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t aclvdecGetChannelDescOutPicWidth(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get vdec channel description's out picture height. + * + * @param channelDesc [IN] vdec channel description. + * + * @retval out picture height (for vdec malloc memory). + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t aclvdecGetChannelDescOutPicHeight(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get vdec channel description's bit depth. + * + * @param channelDesc [IN] vdec channel description. + * + * @retval bit depth. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t aclvdecGetChannelDescBitDepth(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get vdec channel description's reference frame num. + * + * @param channelDesc [IN] vdec channel description. + * + * @retval reference frame num. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t aclvdecGetChannelDescRefFrameNum(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief create vencChannelDesc. + * + * @retval null for failed, other success + */ +ACL_FUNC_VISIBILITY aclvencChannelDesc *aclvencCreateChannelDesc(); + +/** + * @ingroup AscendCL + * @brief destroy vencChannelDesc. + * + * @param channelDesc [IN] channel desc. + * + * @retval ACL_SUCCESS:success, other:failed + */ +ACL_FUNC_VISIBILITY aclError aclvencDestroyChannelDesc(aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Set decoding thread id for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param threadId [IN] thread id + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescThreadId(aclvencChannelDesc *channelDesc, uint64_t threadId); + +/** + * @ingroup AscendCL + * @brief Set func callback for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param callback [IN] func callback + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescCallback(aclvencChannelDesc *channelDesc, aclvencCallback callback); + +/** + * @ingroup AscendCL + * @brief Set video encoding type for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param enType [IN] video encoding type + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescEnType(aclvencChannelDesc *channelDesc, acldvppStreamFormat enType); + +/** + * @ingroup AscendCL + * @brief Set pic format for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param picFormat [IN] pic format + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescPicFormat(aclvencChannelDesc *channelDesc, + acldvppPixelFormat picFormat); + +/** + * @ingroup AscendCL + * @brief Set out pic width for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param picWidth [IN] pic width + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescPicWidth(aclvencChannelDesc *channelDesc, uint32_t picWidth); + +/** + * @ingroup AscendCL + * @brief Set pic height for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param picHeight [IN] pic height + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescPicHeight(aclvencChannelDesc *channelDesc, uint32_t picHeight); + +/** + * @ingroup AscendCL + * @brief Set key frame interval for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param keyFrameInterval [IN] Interval of key frame + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescKeyFrameInterval(aclvencChannelDesc *channelDesc, + uint32_t keyFrameInterval); + +/** + * @ingroup AscendCL + * @brief Set output buffer address for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param bufAddr [IN] output buffer address + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescBufAddr(aclvencChannelDesc *channelDesc, void *bufAddr); + +/** + * @ingroup AscendCL + * @brief Set output buffer size for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param bufSize [IN] output buffer size + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescBufSize(aclvencChannelDesc *channelDesc, uint32_t bufSize); + +/** + * @ingroup AscendCL + * @brief Set rc model for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param rcMode [IN] venc rc mode(VBR=1, CBR=2) + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescRcMode(aclvencChannelDesc *channelDesc, uint32_t rcMode); + +/** + * @ingroup AscendCL + * @brief Set source rate for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param srcRate [IN] source rate + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescSrcRate(aclvencChannelDesc *channelDesc, uint32_t srcRate); + +/** + * @ingroup AscendCL + * @brief Set max bit rate for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param maxBitRate [IN] max bit rate + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescMaxBitRate(aclvencChannelDesc *channelDesc, uint32_t maxBitRate); + +/** + * @ingroup AscendCL + * @brief Set venc parameter for venc channel desc. + * + * @param channelDesc [OUT] venc channel desc + * @param paramType [IN] parameter type + * @param length [IN] parameter length + * @param param [IN] pointer to parameter value + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencSetChannelDescParam(aclvencChannelDesc *channelDesc, + aclvencChannelDescParamType paramType, size_t length, + const void *param); + +/** + * @ingroup AscendCL + * @brief Get output buffer address for venc channel desc. + * + * @param channelDesc[IN] venc channel desc + * + * @retval output buffer address + */ +ACL_FUNC_VISIBILITY void *aclvencGetChannelDescBufAddr(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get output buffer size for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval output buffer size + */ +ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescBufSize(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get decoding channel id for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval decoding channel id: 0~15, default 0 + */ +ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescChannelId(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get decoding thread id for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval thread id, default 0 + */ +ACL_FUNC_VISIBILITY uint64_t aclvencGetChannelDescThreadId(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get func callback for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval func callback, default null + */ +ACL_FUNC_VISIBILITY aclvencCallback aclvencGetChannelDescCallback(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get video encoding type for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval video encoding type, default H265_MAIN_LEVEL + */ +ACL_FUNC_VISIBILITY acldvppStreamFormat aclvencGetChannelDescEnType(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get pic format for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval pic format + */ +ACL_FUNC_VISIBILITY acldvppPixelFormat aclvencGetChannelDescPicFormat(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get pic width for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval pic width, default 0 + */ +ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescPicWidth(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get pic height for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval pic height, default 0 + */ +ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescPicHeight(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Get interval of key frame for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval interval of key frame, default 0 + */ +ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescKeyFrameInterval(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * + * @brief Get rc mode for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval rc mode, default 0 + */ +ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescRcMode(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * + * @brief Get source rate for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval source rate, default 0 + */ +ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescSrcRate(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * + * @brief Get max bit rate for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * + * @retval max bit rate, default 0 + */ +ACL_FUNC_VISIBILITY uint32_t aclvencGetChannelDescMaxBitRate(const aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * + * @brief Get venc parameter for venc channel desc. + * + * @param channelDesc [IN] venc channel desc + * @param paramType [IN] parameter type + * @param length [IN] parameter length + * @param paramRetSize [OUT] pointer to parameter real length + * @param param [OUT] pointer to parameter value + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError aclvencGetChannelDescParam(const aclvencChannelDesc *channelDesc, + aclvencChannelDescParamType paramType, size_t length, + size_t *paramRetSize, void *param); + +/** + * @ingroup AscendCL + * @brief get forced restart of I-frame interval from config + * + * @param config [IN] venc frame config + * + * @retval 0: Not forced; 1: Forced restart of I-frame -1: error + */ +ACL_FUNC_VISIBILITY uint8_t aclvencGetFrameConfigForceIFrame(const aclvencFrameConfig *config); + +/** + * @ingroup AscendCL + * @brief get forced restart of I-frame interval from config + * + * @param config [IN] venc frame config + * + * @retval Whether it is the end frame: 0: no; 1: end frame + */ +ACL_FUNC_VISIBILITY uint8_t aclvencGetFrameConfigEos(const aclvencFrameConfig *config); + +/** + * @ingroup AscendCL + * @brief set single frame encoding configuration parameters + * + * @param config [OUT] venc frame config + * @param forceFrame [IN] forced restart of I-frame interval: 0: Not forced; 1: Forced restart of I-frame + * + * @retval ACL_SUCCESS for ok, others for fail + */ +ACL_FUNC_VISIBILITY aclError aclvencSetFrameConfigForceIFrame(aclvencFrameConfig *config, uint8_t forceIFrame); + +/** + * @ingroup AscendCL + * @brief set single frame encoding configuration parameters + * + * @param config [OUT] venc frame config + * @param eos [IN] Whether it is the end frame: 0: no; 1: end frame + * + * @retval ACL_SUCCESS for ok, others for fail + */ +ACL_FUNC_VISIBILITY aclError aclvencSetFrameConfigEos(aclvencFrameConfig *config, uint8_t eos); + +/** + * @ingroup AscendCL + * @brief dvpp venc destroy frame config + * + * @param config [IN] venc frame config + * + * @retval ACL_SUCCESS for ok, others for fail + */ +ACL_FUNC_VISIBILITY aclError aclvencDestroyFrameConfig(aclvencFrameConfig *config); + +/** + * @ingroup AscendCL + * @brief Create dvpp venc frame config. + * + * @retval null for failed, other aclvencFrameConfig ptr + */ +ACL_FUNC_VISIBILITY aclvencFrameConfig *aclvencCreateFrameConfig(); + +/** + * @ingroup AscendCL + * @brief Create dvpp venc channel. + * + * @param channelDesc [IN|OUT] venc channel desc + * + * @retval ACL_SUCCESS for ok, others for fail + */ +ACL_FUNC_VISIBILITY aclError aclvencCreateChannel(aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Destroy dvpp venc channel. + * + * @param channelDesc [IN] venc channel desc + * + * @retval ACL_SUCCESS for ok, others for fail + */ +ACL_FUNC_VISIBILITY aclError aclvencDestroyChannel(aclvencChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief dvpp venc launch send frame task. + * + * @param channelDesc [IN] venc channel desc + * @param input [IN] input picture desc + * @param reserve [IN] reserve parameter + * @param config [IN] dvpp frame config + * @param userdata [IN] user callback function + * + * @retval ACL_SUCCESS for ok, others for fail + */ +ACL_FUNC_VISIBILITY aclError aclvencSendFrame(aclvencChannelDesc *channelDesc, acldvppPicDesc *input, void *reserve, + aclvencFrameConfig *config, void *userdata); + +/** + * @ingroup AscendCL + * @brief Create dvpp stream description. + * + * @retval null for failed. + * @retval other success. + */ +ACL_FUNC_VISIBILITY acldvppStreamDesc *acldvppCreateStreamDesc(); + +/** + * @ingroup AscendCL + * @brief Destroy dvpp stream description. + * + * @par Function + * Can only destroy acldvppStreamDesc type created through + * acldvppCreateStreamDesc interface. + * + * @param streamDesc [IN] dvpp stream description. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateStreamDesc + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyStreamDesc(acldvppStreamDesc *streamDesc); + +/** + * @ingroup AscendCL + * @brief Set stream description's data addr. + * + * @param streamDesc [OUT] dvpp stream description. + * @param dataDev [IN] data addr. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetStreamDescData(acldvppStreamDesc *streamDesc, void *dataDev); + +/** + * @ingroup AscendCL + * @brief Set stream description's data size. + * + * @param streamDesc [OUT] dvpp stream description. + * @param size [IN] data size. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetStreamDescSize(acldvppStreamDesc *streamDesc, uint32_t size); + +/** + * @ingroup AscendCL + * @brief Set stream description's format. + * + * @param streamDesc [OUT] dvpp stream description. + * @param format [IN] stream format. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetStreamDescFormat(acldvppStreamDesc *streamDesc, acldvppStreamFormat format); + +/** + * @ingroup AscendCL + * @brief Set stream description's timestamp. + * + * @param streamDesc [OUT] dvpp stream description. + * @param timestamp [IN] current timestamp. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetStreamDescTimestamp(acldvppStreamDesc *streamDesc, uint64_t timestamp); + +/** + * @ingroup AscendCL + * @brief Set stream description's ret code. + * + * @param streamDesc [OUT] dvpp stream description. + * @param retCode [IN] result code. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetStreamDescRetCode(acldvppStreamDesc *streamDesc, uint32_t retCode); + +/** + * @ingroup AscendCL + * @brief Set stream description's eos. + * + * @param streamDesc [OUT] dvpp stream description. + * @param eos [IN] end flag of sequence. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetStreamDescEos(acldvppStreamDesc *streamDesc, uint8_t eos); + +/** + * @ingroup AscendCL + * @brief Get stream description's data addr. + * + * @param streamDesc [IN] dvpp stream description. + * + * @retval data addr. + * @retval deault nullptr. + */ +ACL_FUNC_VISIBILITY void *acldvppGetStreamDescData(const acldvppStreamDesc *streamDesc); + +/** + * @ingroup AscendCL + * @brief Get stream description's data size. + * + * @param streamDesc [IN] dvpp stream description. + * + * @retval data size. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetStreamDescSize(const acldvppStreamDesc *streamDesc); + +/** + * @ingroup AscendCL + * @brief Get stream description's format. + * + * @param streamDesc [IN] dvpp stream description. + * + * @retval stream format. + * @retval default ACL_DVPP_STREAM_H264. + */ +ACL_FUNC_VISIBILITY acldvppStreamFormat acldvppGetStreamDescFormat(const acldvppStreamDesc *streamDesc); + +/** + * @ingroup AscendCL + * @brief Get stream description's timestamp. + * + * @param streamDesc [IN] dvpp stream description. + * + * @retval current timestamp. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint64_t acldvppGetStreamDescTimestamp(const acldvppStreamDesc *streamDesc); + +/** + * @ingroup AscendCL + * @brief Get stream description's retCode. + * + * @param streamDesc [IN] dvpp stream description. + * + * @retval result code. + * @retval default 0. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetStreamDescRetCode(const acldvppStreamDesc *streamDesc); + +/** + * @ingroup AscendCL + * @brief Get stream description's eos. + * + * @param streamDesc [IN] dvpp stream description. + * + * @retval end flag of sequence. + * @retval default 0(false). + */ +ACL_FUNC_VISIBILITY uint8_t acldvppGetStreamDescEos(const acldvppStreamDesc *streamDesc); + +/** + * @ingroup AscendCL + * @brief Create vdec frame config. + * + * @retval null for failed. + * @retval other success. + */ +ACL_FUNC_VISIBILITY aclvdecFrameConfig *aclvdecCreateFrameConfig(); + +/** + * @ingroup AscendCL + * @brief Destroy vdec frame config. + * + * @par Function + * Can only destroy aclvdecFrameConfig type created through + * aclvdecCreateFrameConfig interface + * + * @param vdecFrameConfig [IN] vdec frame config. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclvdecCreateFrameConfig + */ +ACL_FUNC_VISIBILITY aclError aclvdecDestroyFrameConfig(aclvdecFrameConfig *vdecFrameConfig); + +/** + * @ingroup AscendCL + * @brief Get image width and height of jpeg. + * + * @param data [IN] image data in host memory + * @param size [IN] the size of image data + * @param width [OUT] the width of image from image header + * @param height [OUT] the height of image from image header + * @param components [OUT] the components of image from image header + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfo(const void *data, uint32_t size, uint32_t *width, uint32_t *height, + int32_t *components); + +/** + * @ingroup AscendCL + * @brief Get image width and height of jpeg. + * + * @param data [IN] image data in host memory + * @param size [IN] the size of image data + * @param width [OUT] the width of image from image header + * @param height [OUT] the height of image from image header + * @param components [OUT] the components of image from image header + * @param format [OUT] the format of image from image header + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppJpegGetImageInfoV2(const void *data, uint32_t size, uint32_t *width, + uint32_t *height, int32_t *components, + acldvppJpegFormat *format); + +/** + * @ingroup AscendCL + * @brief Predict encode size of jpeg image. + * + * @param inputDesc [IN] dvpp image desc + * @param config [IN] jpeg encode config + * @param size [OUT] the size predicted of image + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppJpegPredictEncSize(const acldvppPicDesc *inputDesc, + const acldvppJpegeConfig *config, uint32_t *size); + +/** + * @ingroup AscendCL + * @brief Predict decode size of jpeg image. + * + * @param data [IN] origin image data in host memory + * @param dataSize [IN] the size of origin image data + * @param outputPixelFormat [IN] the pixel format jpeg decode + * @param decSize [OUT] the size predicted for decode image + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppJpegPredictDecSize(const void *data, uint32_t dataSize, + acldvppPixelFormat outputPixelFormat, uint32_t *decSize); + +/** + * @ingroup AscendCL + * @brief Get image width and height of png. + * + * @param data [IN] image data in host memory + * @param size [IN] the size of image data + * @param width [OUT] the width of image from image header + * @param height [OUT] the height of image from image header + * @param components [OUT] the components of image from image header + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppPngGetImageInfo(const void *data, uint32_t dataSize, uint32_t *width, + uint32_t *height, int32_t *components); + +/** + * @ingroup AscendCL + * @brief Predict decode size of png image. + * + * @param data [IN] origin image data in host memory + * @param dataSize [IN] the size of origin image data + * @param outputPixelFormat [IN] the pixel format jpeg decode + * @param decSize [OUT] the size predicted for decode image + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppPngPredictDecSize(const void *data, uint32_t dataSize, + acldvppPixelFormat outputPixelFormat, uint32_t *decSize); + +/** + * @ingroup AscendCL + * @brief Create dvpp channel, the same channel can be reused + * and is no longer available after destruction. + * + * @param channelDesc [IN|OUT] the channel destruction + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannelDesc + */ +ACL_FUNC_VISIBILITY aclError acldvppCreateChannel(acldvppChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Destroy dvpp channel. + * + * @par Restriction + * Can only destroy channel created through the acldvppCreateChannel interface + * + * @param channelDesc [IN] the channel destruction + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyChannel(acldvppChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief dvpp vpc resize. + * + * @par Restriction + * Width alignment requirements: + * @li The minimum stride is 32 and the maximum is 4096 * 4 + * (that is, an image in argb format with a width of 4096); + * @li For 8K scaling, widthStride is required to be aligned to 2; + * @li For non 8K scaling, the calculation formula for widthStride + * is different for different image formats: + * @li yuv400sp, yuv420sp, yuv422sp, yuv444sp: input image width aligned to 16 + * @li yuv422packed: input image width * 2 and then align to 16 + * @li yuv444packed, rgb888: input image width alignment * 3, alignment to 16 + * @li xrgb8888: input image width * 4, align to 16 + * @li HFBC:input image width + * Height alignment requirements: + * @li The height of the input image is aligned to 2. + * High stride minimum 6 and maximum 4096. + * + * @param channelDesc [IN] the channel destruction + * @param inputDesc [IN] resize input picture destruction + * @param outputDesc [IN|OUT] resize output picture destruction + * @param resizeConfig [IN] resize config + * @param stream [IN] resize task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreatePicDesc + * | acldvppCreateResizeConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcResizeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppResizeConfig *resizeConfig, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc crop. + * + * @par Function + * crop the input picture according to the specified area, + * and then store the picture in the output memory as the output picture + * + * @par Restriction + * Width alignment requirements: + * @li The minimum stride is 32 and the maximum is 4096 * 4 + * (that is, an image in argb format with a width of 4096); + * @li For 8K scaling, widthStride is required to be aligned to 2; + * @li For non 8K scaling, the calculation formula for widthStride + * is different for different image formats: + * @li yuv400sp, yuv420sp, yuv422sp, yuv444sp: input image width aligned to 16 + * @li yuv422packed: input image width * 2 and then align to 16 + * @li yuv444packed, rgb888: input image width alignment * 3, alignment to 16 + * @li xrgb8888: input image width * 4, align to 16 + * @li HFBC:input image width + * Height alignment requirements: + * @li The height of the input image is aligned to 2. + * High stride minimum 6 and maximum 4096. + * + * @param channelDesc [IN] the channel destruction + * @param inputDesc [IN] crop input picture destruction + * @param outputDesc [IN|OUT] crop output picture destruction + * @param cropArea [IN] crop area config + * @param stream [IN] crop task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcCropAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc crop and resize config. + * + * @par Function + * crop the input picture with resize config according to the specified area, + * and then store the picture in the output memory as the output picture + * + * @par Restriction + * Width alignment requirements: + * @li The minimum stride is 32 and the maximum is 4096 * 4 + * (that is, an image in argb format with a width of 4096); + * @li For 8K scaling, widthStride is required to be aligned to 2; + * @li For non 8K scaling, the calculation formula for widthStride + * is different for different image formats: + * @li yuv400sp, yuv420sp, yuv422sp, yuv444sp: input image width aligned to 16 + * @li yuv422packed: input image width * 2 and then align to 16 + * @li yuv444packed, rgb888: input image width alignment * 3, alignment to 16 + * @li xrgb8888: input image width * 4, align to 16 + * @li HFBC:input image width + * Height alignment requirements: + * @li The height of the input image is aligned to 2. + * High stride minimum 6 and maximum 4096. + * + * @param channelDesc [IN] the channel destruction + * @param inputDesc [IN] crop input picture destruction + * @param outputDesc [IN|OUT] crop output picture destruction + * @param cropArea [IN] crop area config + * @param resizeConfig [IN] resize config + * @param stream [IN] crop and resize config task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, + acldvppResizeConfig *resizeConfig, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc batch crop. + * + * @par Function + * crop the input batch picture according to the specified area + * as the output batch pictures + * + * @param channelDesc [IN] the channel destruction + * @param srcBatchPicDescs [IN] crop input batch picture destruction + * @param roiNums [IN] roi config numbers + * @param size [IN] roiNum size + * @param dstBatchPicDescs [IN|OUT] crop output batch picture destruction + * @param cropAreas [IN] crop area configs + * @param stream [IN] crop batch task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAsync(acldvppChannelDesc *channelDesc, + acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, + uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc batch crop and resize config. + * + * @par Function + * crop the input batch picture with resize config according to the specified area + * as the output batch pictures + * + * @param channelDesc [IN] the channel destruction + * @param srcBatchPicDescs [IN] crop input batch picture destruction + * @param roiNums [IN] roi config numbers + * @param size [IN] roiNum size + * @param dstBatchPicDescs [IN|OUT] crop output batch picture destruction + * @param cropAreas [IN] crop area configs + * @param resizeConfig [IN] resize config + * @param stream [IN] crop batch and resize config task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateDvppConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeAsync(acldvppChannelDesc *channelDesc, + acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, + uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + acldvppResizeConfig *resizeConfig, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc crop and paste. + * + * @par Function + * crop the input picture according to the specified area, + * and paste the picture to the specified position of the target picture + * as the output picture + * + * @param channelDesc [IN] thechannel destruction + * @param inputDesc [IN] crop and paste input picture destruction + * @param outputDesc [IN|OUT] crop and paste output picture destruction + * @param cropArea [IN] crop area config + * @param pasteArea [IN] paste area config + * @param stream [IN] crop and paste task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateRoiConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcCropAndPasteAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, + acldvppRoiConfig *pasteArea, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc crop, resize config and paste. + * + * @par Function + * crop the input picture with resize config according to the specified area, + * and paste the picture to the specified position of the target picture + * as the output picture + * + * @param channelDesc [IN] thechannel destruction + * @param inputDesc [IN] crop and paste input picture destruction + * @param outputDesc [IN|OUT] crop and paste output picture destruction + * @param cropArea [IN] crop area config + * @param pasteArea [IN] paste area config + * @param resizeConfig [IN] resize config + * @param stream [IN] crop, paste and resize task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcCropResizePasteAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, acldvppRoiConfig *cropArea, + acldvppRoiConfig *pasteArea, + acldvppResizeConfig *resizeConfig, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc batch crop and paste. + * + * @par Function + * crop the input batch picture according to the specified area, + * and paste the pictures to the specified position of the target pictures + * as the output batch pictures + * + * @param channelDesc [IN] the channel destruction + * @param srcBatchPicDescs [IN] crop input batch picture destruction + * @param roiNums [IN] roi config numbers + * @param size [IN] roiNum size + * @param dstBatchPicDescs [IN|OUT] crop output batch picture destruction + * @param cropAreas [IN] crop area configs + * @param pasteAreas [IN] paste area configs + * @param stream [IN] crop batch task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc *channelDesc, + acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, + uint32_t size, acldvppBatchPicDesc *dstBatchPicDescs, + acldvppRoiConfig *cropAreas[], + acldvppRoiConfig *pasteAreas[], aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc batch crop, resize config and paste. + * + * @par Function + * crop the input batch picture with resize config according to the specified area, + * and paste the pictures to the specified position of the target pictures + * as the output batch pictures + * + * @param channelDesc [IN] the channel destruction + * @param srcBatchPicDescs [IN] crop input batch picture destruction + * @param roiNums [IN] roi config numbers + * @param size [IN] roiNum size + * @param dstBatchPicDescs [IN|OUT] crop output batch picture destruction + * @param cropAreas [IN] crop area configs + * @param pasteAreas [IN] paste area configs + * @param resizeConfig [IN] resize config + * @param stream [IN] crop batch and resize config task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizePasteAsync( + acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], acldvppRoiConfig *pasteAreas[], + acldvppResizeConfig *resizeConfig, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc jpeg decode. + * + * @par Function + * For different source picture formats, after decoding, + * output pictures in the following format: + * @li jpeg(444) -> YUV444SP:V is front U is back, + * YUV420 SP V is front U is back, YUV420SP U is front V is back; + * @li jpeg(422) -> YUV422SP:V is in front U is behind, + * YUV420SP V is in front U is behind, YUV420SP U is in front V is behind; + * @li jpeg(420) -> YUV420SP: + * V is front U is back, YUV420SP U is front V is back; + * @li jpeg(400) -> YUV420SP:UV data is filled with 0 x 80. + * + * @param channelDesc [IN] the channel destruction + * @param data [IN] decode input picture destruction's data + * @param size [IN] decode input picture destruction's size + * @param outputDesc [IN|OUT] decode output picture destruction + * @param stream [IN] decode task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreatePicDesc + */ +ACL_FUNC_VISIBILITY aclError acldvppJpegDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, + acldvppPicDesc *outputDesc, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc jpeg encode. + * + * @param channelDesc [IN] the channel destruction + * @param inputDesc [IN] encode input picture destruction + * @param data [OUT] encode output picture destruction's data + * @param size [IN|OUT] encode output picture destruction's size + * @param config [IN] jpeg encode config + * @param stream [IN] encode task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreateJpegeConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppJpegEncodeAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + const void *data, uint32_t *size, acldvppJpegeConfig *config, + aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc png decode. + * + * @param channelDesc [IN] the channel destruction + * @param data [IN] decode input picture destruction's data + * @param size [IN] decode input picture destruction's size + * @param outputDesc [IN|OUT] decode output picture destruction + * @param stream [IN] decode task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreatePicDesc + */ +ACL_FUNC_VISIBILITY aclError acldvppPngDecodeAsync(acldvppChannelDesc *channelDesc, const void *data, uint32_t size, + acldvppPicDesc *outputDesc, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Create vdec channel. + * + * @par Function + * Create a channel for video data processing, + * the same channel can be reused, + * and is no longer available after destruction + * + * @param channelDesc [IN|OUT] the channel destruction + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclvdecCreateChannelDesc + */ +ACL_FUNC_VISIBILITY aclError aclvdecCreateChannel(aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Destroy vdec channel. + * + * @par Function + * Can only destroy channels created by the aclvdecCreateChannel interface + * + * @param channelDesc [IN] the channel destruction + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclvdecCreateChannel + */ +ACL_FUNC_VISIBILITY aclError aclvdecDestroyChannel(aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief dvpp vdec send frame. + * + * @par Function + * Pass the input memory to be decoded + * and the decoded output memory to the decoder for decoding + * + * @param channelDesc [IN] vdec channel destruction + * @param input [IN] input stream destruction + * @param output [IN|OUT] output picture destruction + * @param config [IN] vdec frame config + * @param userData [IN] user data for callback function + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclvdecCreateChannel | acldvppCreateStreamDesc | acldvppCreatePicDesc + */ +ACL_FUNC_VISIBILITY aclError aclvdecSendFrame(aclvdecChannelDesc *channelDesc, acldvppStreamDesc *input, + acldvppPicDesc *output, aclvdecFrameConfig *config, void *userData); + +/** + * @ingroup AscendCL + * @brief dvpp vdec send skipped frame. + * + * @par Function + * Pass video frame to decoder + * + * @param channelDesc [IN] vdec channel destruction + * @param input [IN] input stream destruction + * @param config [IN] vdec frame config + * @param userData [IN] user data for callback function + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclvdecCreateChannel | acldvppCreateStreamDesc | acldvppCreatePicDesc | aclvdecSendFrame + */ +ACL_FUNC_VISIBILITY aclError aclvdecSendSkippedFrame(aclvdecChannelDesc *channelDesc, acldvppStreamDesc *input, + aclvdecFrameConfig *config, void *userData); + +/** + * @ingroup AscendCL + * @brief dvpp vpc convert color. + * + * @par Restriction + * @li outputDesc:Width height stride, No changes are allowed. Just configure 0 + * @par Function + * Convert color gamut + * + * @param channelDesc [IN] the channel destruction + * @param inputDesc [IN] convert color input picture destruction + * @param outputDesc [IN|OUT] convert color output picture destruction + * @param stream [IN] convert color task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreatePicDesc + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcConvertColorAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief dvpp vpc pyramid down. + * + * @par Restriction + * @li outputDesc:format only supported YUV400 + * @par Function + * Image pyramid down + * + * @param channelDesc [IN] the channel destruction + * @param inputDesc [IN] pyr down input picture destruction + * @param outputDesc [IN|OUT] pyr down output picture destruction + * @param reserve [IN] reserved param , must be nullptr + * @param stream [IN] pyr down task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreatePicDesc + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcPyrDownAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *inputDesc, + acldvppPicDesc *outputDesc, void *reserve, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Set dvpp channel mode. + * + * @param channelDesc [OUT] the channel destruction + * @param mode [IN] channel mode + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetChannelDescMode(acldvppChannelDesc *channelDesc, uint32_t mode); + +/** + * @ingroup AscendCL + * @brief Set resize config interpolation. + * + * @param resizeConfig [OUT] the resize config + * @param interpolation [IN] interpolation + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetResizeConfigInterpolation(acldvppResizeConfig *resizeConfig, + uint32_t interpolation); + +/** + * @ingroup AscendCL + * @brief Get resize config interpolation. + * + * @param resizeConfig [IN] the resize config + * + * @retval Interpolation of resize config. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetResizeConfigInterpolation(const acldvppResizeConfig *resizeConfig); + +/** + * @ingroup AscendCL + * @brief Set vdec channel out mode. + * + * @param channelDesc [OUT] the channel destruction + * @param outMode [IN] channel out mode + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescOutMode(aclvdecChannelDesc *channelDesc, uint32_t outMode); + +/** + * @ingroup AscendCL + * @brief Get vdec channel out mode. + * + * @param channelDesc [IN] the channel destruction + * + * @retval Out mode of channel destruction + * @retval default 0 + */ +ACL_FUNC_VISIBILITY uint32_t aclvdecGetChannelDescOutMode(const aclvdecChannelDesc *channelDesc); + +/** + * @ingroup AscendCL + * @brief Create dvpp batch picture description. + * + * @param batchSize [IN] batch size + * + * @retval null for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY acldvppBatchPicDesc *acldvppCreateBatchPicDesc(uint32_t batchSize); + +/** + * @ingroup AscendCL + * @brief Get dvpp picture description. + * + * @param batchPicDesc [IN] dvpp batch picture description. + * @param index [IN] index of batch + * + * @retval null for failed. + * @retval OtherValues Failure + * + * @see acldvppCreateBatchPicDesc + */ +ACL_FUNC_VISIBILITY acldvppPicDesc *acldvppGetPicDesc(acldvppBatchPicDesc *batchPicDesc, uint32_t index); + +/** + * @ingroup AscendCL + * @brief Destroy dvpp batch picture description. + * + * @par Function + * Can only destroy batch picture description information created + * through acldvppCreateBatchPicDesc interface. + * + * @param batchPicDesc [IN] dvpp batch picture description. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateBatchPicDesc + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyBatchPicDesc(acldvppBatchPicDesc *batchPicDesc); + +/** + * @ingroup AscendCL + * @brief Create dvpp lut map. + * + * @retval null for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY acldvppLutMap *acldvppCreateLutMap(); + +/** + * @ingroup AscendCL + * @brief Destroy lut map. + * + * @param lutMap [IN] lut map + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyLutMap(acldvppLutMap *lutMap); + +/** + * @ingroup AscendCL + * @brief Get lut map dims. + * + * @param lutMap [IN] lut map + * + * @retval 0 for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetLutMapDims(const acldvppLutMap *lutMap); + +/** + * @ingroup AscendCL + * @brief Get lut map data. + * + * @param lutMap [IN] lut map + * @param dim [IN] input dim of map + * @param data [OUT] the dim of lut map's data + * @param len [OUT] the dim of lut map's length + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acldvppGetLutMapData(const acldvppLutMap *lutMap, uint32_t dim, uint8_t **data, + uint32_t *len); +/** + * @ingroup AscendCL + * @brief Vpc equalize hist. + * + * @param channelDesc [IN] channel desc + * @param inputDesc [IN] input desc + * @param outputDesc [IN|OUT] output desc + * @param lutMap [IN] lut map param + * @param stream [IN] runtime stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel|acldvppCreatePicDesc|acldvppCreateLutMap + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcEqualizeHistAsync(const acldvppChannelDesc *channelDesc, + const acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, + const acldvppLutMap *lutMap, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Create dvpp border config. + * + * @retval null for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY acldvppBorderConfig *acldvppCreateBorderConfig(); + +/** + * @ingroup AscendCL + * @brief Set value of border config. + * + * @param borderConfig [OUT] border config + * @param index [IN] index of value array + * @param value [IN] value + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigValue(acldvppBorderConfig *borderConfig, uint32_t index, + double value); + +/** + * @ingroup AscendCL + * @brief Set border type of border config. + * + * @param borderConfig [OUT] border config + * @param borderType [IN] border type + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigBorderType(acldvppBorderConfig *borderConfig, + acldvppBorderType borderType); + +/** + * @ingroup AscendCL + * @brief Set top of border config. + * + * @param borderConfig [OUT] border config + * @param top [IN] top of border + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigTop(acldvppBorderConfig *borderConfig, uint32_t top); + +/** + * @ingroup AscendCL + * @brief Set bottom of border config. + * + * @param borderConfig [OUT] border config + * @param bottom [IN] bottom of border + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigBottom(acldvppBorderConfig *borderConfig, uint32_t bottom); + +/** + * @ingroup AscendCL + * @brief Set left of border config. + * + * @param borderConfig [OUT] border config + * @param left [IN] left of border + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigLeft(acldvppBorderConfig *borderConfig, uint32_t left); + +/** + * @ingroup AscendCL + * @brief Set right of border config. + * + * @param borderConfig [OUT] border config + * @param right [IN] right of border + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError acldvppSetBorderConfigRight(acldvppBorderConfig *borderConfig, uint32_t right); + +/** + * @ingroup AscendCL + * @brief Get value of border config. + * + * @param borderConfig [IN] border config + * @param index[IN] index of value array + * + * @retval invalid value is < 0, normal Value is >= 0 + */ +ACL_FUNC_VISIBILITY double acldvppGetBorderConfigValue(const acldvppBorderConfig *borderConfig, uint32_t index); + +/** + * @ingroup AscendCL + * @brief Get border type of border config. + * + * @param borderConfig [IN] border config + * @retval border type of border config + */ +ACL_FUNC_VISIBILITY acldvppBorderType acldvppGetBorderConfigBorderType(const acldvppBorderConfig *borderConfig); + +/** + * @ingroup AscendCL + * @brief Get right of border config. + * + * @param borderConfig [IN] border config + * + * @retval default 0, top value of border config + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetBorderConfigTop(const acldvppBorderConfig *borderConfig); + +/** + * @ingroup AscendCL + * @brief Get Bottom of border config. + * + * @param borderConfig [IN] border config + * + * @retval default 0, top value of border config + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetBorderConfigBottom(const acldvppBorderConfig *borderConfig); + +/** + * @ingroup AscendCL + * @brief Get left of border config. + * + * @param borderConfig [IN] border config + * + * @retval default 0, top value of border config + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetBorderConfigLeft(const acldvppBorderConfig *borderConfig); + +/** + * @ingroup AscendCL + * @brief Get right of border config. + * + * @param borderConfig [IN] border config + * + * @retval default 0, right value of border config + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetBorderConfigRight(const acldvppBorderConfig *borderConfig); + +/** + * @ingroup AscendCL + * @brief Destroy border config. + * + * @param borderConfig [IN] border config + * + * @retval ACL_SUCCESS for success, other for failure + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyBorderConfig(acldvppBorderConfig *borderConfig); + +/** + * @ingroup AscendCL + * @brief Vpc make border. + * + * @param channelDesc [IN] channel desc + * @param inputDesc [IN] input desc + * @param outputDesc [IN|OUT] output desc + * @param borderConfig [IN] border config param + * @param stream [IN] runtime stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel|acldvppCreatePicDesc|acldvppCreateBorderConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcMakeBorderAsync(const acldvppChannelDesc *channelDesc, + const acldvppPicDesc *inputDesc, acldvppPicDesc *outputDesc, + const acldvppBorderConfig *borderConfig, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Dvpp vpc calc hist. + * + * @param channelDesc [IN] the channel destruction + * @param srcPicDesc [IN] pyr down input picture destruction + * @param hist [IN|OUT] pyr down output picture destruction + * @param reserve [IN] reserved param, must be nullptr + * @param stream [IN] task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreatePicDesc | acldvppCreateHist + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcCalcHistAsync(acldvppChannelDesc *channelDesc, acldvppPicDesc *srcPicDesc, + acldvppHist *hist, void *reserve, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief Create vpc hist description. + * + * @retval null for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY acldvppHist *acldvppCreateHist(); + +/** + * @ingroup AscendCL + * @brief Destroy vpc hist description. + * + * @par Function + * Can only destroy hist description information created + * through acldvppCreateHist interface. + * + * @param hist [IN] vpc hist description. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateHist + */ +ACL_FUNC_VISIBILITY aclError acldvppDestroyHist(acldvppHist *hist); + +/** + * @ingroup AscendCL + * @brief Get dims of vpc hist description. + * + * @param hist [IN] vpc hist description. + * + * @retval dims of vpc hist description. + * + * @see acldvppCreateHist | acldvppVpcCalcHistAsync + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetHistDims(acldvppHist *hist); + +/** + * @ingroup AscendCL + * @brief Get data from vpc hist description by dim. + * + * @param hist [IN] vpc hist description. + * @param dim [IN] which dim to get data. + * @param data [OUT] address of output hist data. + * @param len [OUT] len of output hist data. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateHist | acldvppVpcCalcHistAsync + */ +ACL_FUNC_VISIBILITY aclError acldvppGetHistData(acldvppHist *hist, uint32_t dim, uint32_t **data, uint16_t *len); + +/** + * @ingroup AscendCL + * @brief Get dvpp calc hist process return code. + * + * @param hist [IN] vpc hist description. + * + * @retval Dvpp calc hist process return code. + * + * @see acldvppCreateHist | acldvppVpcCalcHistAsync + */ +ACL_FUNC_VISIBILITY uint32_t acldvppGetHistRetCode(acldvppHist *hist); + +/** + * @ingroup AscendCL + * @brief Set vpc hist description to 0. + * + * @par Function + * Can only clear hist description information created + * through acldvppCreateHist interface. + * + * @param hist [IN] vpc hist description. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateHist + */ +ACL_FUNC_VISIBILITY aclError acldvppClearHist(acldvppHist *hist); + +/** + * @ingroup AscendCL + * @brief dvpp vpc batch crop, resize config and make border. + * + * @par Function + * crop the input batch picture with resize config and border configs according to the specified area + * as the output batch pictures + * + * @param channelDesc [IN] the channel destruction + * @param srcBatchPicDescs [IN] crop input batch picture destruction + * @param roiNums [IN] roi config numbers + * @param size [IN] roiNum size + * @param dstBatchPicDescs [IN|OUT] crop output batch picture destruction + * @param cropAreas [IN] crop area configs + * @param borderCfgs [IN] border configs + * @param resizeConfig [IN] resize config + * @param stream [IN] crop batch, resize config and make border task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig + */ +ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeMakeBorderAsync( + acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], acldvppBorderConfig *borderCfgs[], + acldvppResizeConfig *resizeConfig, aclrtStream stream); + +#ifdef __cplusplus +} +#endif + +#endif // INC_EXTERNAL_ACL_OPS_ACL_DVPP_H_ diff --git a/inc/external/acl/ops/acl_fv.h b/inc/external/acl/ops/acl_fv.h new file mode 100644 index 00000000..4bd392c9 --- /dev/null +++ b/inc/external/acl/ops/acl_fv.h @@ -0,0 +1,348 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef INC_EXTERNAL_ACL_OPS_ACL_RETR_H_ +#define INC_EXTERNAL_ACL_OPS_ACL_RETR_H_ + +#include "acl/acl.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct aclfvInitPara aclfvInitPara; +typedef struct aclfvFeatureInfo aclfvFeatureInfo; +typedef struct aclfvRepoRange aclfvRepoRange; +typedef struct aclfvQueryTable aclfvQueryTable; +typedef struct aclfvSearchInput aclfvSearchInput; +typedef struct aclfvSearchResult aclfvSearchResult; + +// search operation type +enum aclfvSearchType { + SEARCH_1_N, // 1:N operation type + SEARCH_N_M // N:M operation type +}; + +/** + * @ingroup AscendCL + * @brief Create fv init param. + * + * @param fsNum [IN] The feature num + * + * @retval null for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY aclfvInitPara *aclfvCreateInitPara(uint64_t fsNum); + +/** + * @ingroup AscendCL + * @brief Destroy fv init param. + * + * @par Function + * Can only destroy fv init param information created + * through aclfvCreateInitPara interface. + * + * @param initPara [IN] fv init param. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclfvCreateInitPara + */ +ACL_FUNC_VISIBILITY aclError aclfvDestroyInitPara(aclfvInitPara *initPara); + +/** + * @ingroup AscendCL + * @brief set value for maxTopNumFor1N which in fv init param. + * + * @param initPara [IN|OUT] fv init param. + * @param maxTopNumFor1N [IN] maxTopNumFor1N value for init param. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclfvSet1NTopNum(aclfvInitPara *initPara, uint32_t maxTopNumFor1N); + +/** + * @ingroup AscendCL + * @brief set value for maxTopNumForNM which in fv init param. + * + * @param initPara [IN|OUT] fv init param. + * @param maxTopNumForNM [IN] maxTopNumForNM value for init param. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclfvSetNMTopNum(aclfvInitPara *initPara, uint32_t maxTopNumForNM); + +/** + * @ingroup AscendCL + * @brief Create fv feature info. + * + * @param id0 [IN] The first level library id0 + * @param id1 [IN] Secondary library id1 + * @param offset [IN] The offset of the first feature in the library + * @param featureLen [IN] Single feature length + * @param featureCount [IN] Single feature count + * @param featureData [IN] Feature value list + * @param featureDataLen [IN] Feature value list length + * + * @retval null for failed. + * @retval OtherValues success. + */ +ACL_FUNC_VISIBILITY aclfvFeatureInfo *aclfvCreateFeatureInfo(uint32_t id0, uint32_t id1, uint32_t offset, + uint32_t featureLen, uint32_t featureCount, + uint8_t *featureData, uint32_t featureDataLen); + +/** + * @ingroup AscendCL + * @brief Destroy fv feature info. + * + * @par Function + * Can only destroy fv feature info information created + * through aclfvCreateFeatureInfo interface. + * + * @param featureInfo [IN] fv feature info. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclfvCreateFeatureInfo + */ +ACL_FUNC_VISIBILITY aclError aclfvDestroyFeatureInfo(aclfvFeatureInfo *featureInfo); + +/** + * @ingroup AscendCL + * @brief Create fv repo range. + * + * @param id0Min [IN] id0 start value + * @param id0Min [IN] id0 max + * @param id1Min [IN] id0 start value + * @param id1Max [IN] id1 max + * + * @retval null for failed. OtherValues success + */ +ACL_FUNC_VISIBILITY aclfvRepoRange *aclfvCreateRepoRange(uint32_t id0Min, uint32_t id0Max, uint32_t id1Min, + uint32_t id1Max); + +/** + * @ingroup AscendCL + * @brief Destroy fv repo range. + * + * @par Function + * Can only destroy fv repo range information created + * through aclfvCreateRepoRange interface. + * + * @param repoRange [IN] fv repo range. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclfvCreateRepoRange + */ +ACL_FUNC_VISIBILITY aclError aclfvDestroyRepoRange(aclfvRepoRange *repoRange); + +/** + * @ingroup AscendCL + * @brief Create query table. + * + * @param queryCnt [IN] Number of tables, the maximum number is 6 + * @param tableLen [IN] Single table length, table length is 32KB + * @param tableData [IN] Feature value list + * @param tableDataLen [IN] The length of memory requested by the featureData pointer + * + * @retval null for failed. OtherValues success + */ +ACL_FUNC_VISIBILITY aclfvQueryTable *aclfvCreateQueryTable(uint32_t queryCnt, uint32_t tableLen, uint8_t *tableData, + uint32_t tableDataLen); + +/** + * @ingroup AscendCL + * @brief Destroy query table. + * + * @par Function + * Can only destroy query table information created + * through aclfvCreateQueryTable interface. + * + * @param queryTable [IN] query table. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclfvCreateQueryTable + */ +ACL_FUNC_VISIBILITY aclError aclfvDestroyQueryTable(aclfvQueryTable *queryTable); + +/** + * @ingroup AscendCL + * @brief Create search input. + * + * @param queryTable [IN] query table + * @param repoRange [IN] query repo range + * @param topk [IN] query topk + * + * @retval null for failed. OtherValues success + */ +ACL_FUNC_VISIBILITY aclfvSearchInput *aclfvCreateSearchInput(aclfvQueryTable *queryTable, aclfvRepoRange *repoRange, + uint32_t topk); + +/** + * @ingroup AscendCL + * @brief Destroy search input. + * + * @par Function + * Can only destroy search input information created + * through aclfvCreateSearchInput interface. + * + * @param searchInput [IN] search input. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclfvCreateSearchInput + */ +ACL_FUNC_VISIBILITY aclError aclfvDestroySearchInput(aclfvSearchInput *searchInput); + +/** + * @ingroup AscendCL + * @brief Create search result. + * + * @param queryCnt [IN] Retrieve the number of features + * @param resultNum [IN] The number of search results for each feature, the number is queryCnt + * @param resultNumDataLen [IN] resultNum memory length + * @param id0 [IN] Level 1 library id0 + * @param id1 [IN] Secondary library id1 + * @param resultOffset [IN] The offset of the bottom library corresponding + * to each feature retrieval result, total length topK * queryCnt + * @param resultDistance [IN] Distance, total length topK * queryCnt + * @param dataLen [IN] The memory size requested by + * id0\id1\reslutOffset\resultDistance + * + * @retval null for failed. OtherValues success + */ +ACL_FUNC_VISIBILITY aclfvSearchResult *aclfvCreateSearchResult(uint32_t queryCnt, uint32_t *resultNum, + uint32_t resultNumDataLen, uint32_t *id0, uint32_t *id1, + uint32_t *resultOffset, float *resultDistance, + uint32_t dataLen); + +/** + * @ingroup AscendCL + * @brief Destroy search result. + * + * @par Function + * Can only destroy search result information created + * through aclfvCreateSearchResult interface. + * + * @param searchResult [IN] search result. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclfvCreateSearchResult + */ +ACL_FUNC_VISIBILITY aclError aclfvDestroySearchResult(aclfvSearchResult *searchResult); + +/** + * @ingroup AscendCL + * @brief fv IP initialize. + * + * @param initPara [IN] fv init param. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure. + */ +ACL_FUNC_VISIBILITY aclError aclfvInit(aclfvInitPara *initPara); + +/** + * @ingroup AscendCL + * @brief release fv resources. + * + * @par Function + * Can only release fv resources created + * through aclfvInit interface. + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure. + * + * @see aclfvInit + */ +ACL_FUNC_VISIBILITY aclError aclfvRelease(); + +/** + * @ingroup AscendCL + * @brief fv repo add. + * + * @param type [IN] repo add type + * @param featureInfo [IN] add feature information + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure. + */ +ACL_FUNC_VISIBILITY aclError aclfvRepoAdd(aclfvSearchType type, aclfvFeatureInfo *featureInfo); + +/** + * @ingroup AscendCL + * @brief fv repo del. + * + * @param type [IN] repo delete type + * @param repoRange [IN] repo range information + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure. + */ +ACL_FUNC_VISIBILITY aclError aclfvRepoDel(aclfvSearchType type, aclfvRepoRange *repoRange); + +/** + * @ingroup AscendCL + * @brief fv accurate del. + * + * @param featureInfo [IN] accurate delete feature information + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure. + */ +ACL_FUNC_VISIBILITY aclError aclfvDel(aclfvFeatureInfo *featureInfo); + +/** + * @ingroup AscendCL + * @brief fv accurate modify. + * + * @param featureInfo [IN] accurate modify feature information + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure. + */ +ACL_FUNC_VISIBILITY aclError aclfvModify(aclfvFeatureInfo *featureInfo); + +/** + * @ingroup AscendCL + * @brief fv search. + * + * @param type [IN] search type + * @param searchInput [IN] search input + * @param searchRst [OUT] search result + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure. + */ +ACL_FUNC_VISIBILITY aclError aclfvSearch(aclfvSearchType type, aclfvSearchInput *searchInput, + aclfvSearchResult *searchRst); + +#ifdef __cplusplus +} +#endif + +#endif // INC_EXTERNAL_ACL_OPS_ACL_RETR_H_ diff --git a/inc/external/hccl/hccl.h b/inc/external/hccl/hccl.h new file mode 100644 index 00000000..8261adc4 --- /dev/null +++ b/inc/external/hccl/hccl.h @@ -0,0 +1,159 @@ +/** + * Copyright 2019-2020 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. + */ + +/** + * @file hccl.h + * @brief HCCL API + */ + +#ifndef HCCL_H_ +#define HCCL_H_ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * @brief Initialize HCCL. + * + * @param clusterInfo A string identifying the cluster info file path, include file name. + * @param rank A integer identifying the identify for the rank. + * @param comm A pointer identifying the initialized communication resource. + * @return HcclResult + * @see HcclCommDestroy() + */ +extern HcclResult HcclCommInitClusterInfo(const char *clusterInfo, uint32_t rank, HcclComm *comm); + +/** + * @brief Get hccl root info. + * + * @param rootInfo A pointer identifying the hccl root info. + * @return HcclResult + */ +extern HcclResult HcclGetRootInfo(HcclRootInfo *rootInfo); + +/** + * @brief Initialize HCCL with root info. + * + * @param nRanks A integer identifying the rank size of the cluster. + * @param rootInfo A struct identifying the hccl root info. + * @param rank A integer identifying the identify for the rank. + * @param comm A pointer identifying the initialized communication resource. + * @return HcclResult + * @see HcclCommDestroy() + */ +extern HcclResult HcclCommInitRootInfo(uint32_t nRanks, const HcclRootInfo *rootInfo, uint32_t rank, HcclComm *comm); + +/** + * @brief AllReduce operator. + * + * @param sendBuf A pointer identifying the input data address of the operator. + * @param recvBuf A pointer identifying the output data address of the operator. + * @param count An integer(u64) identifying the number of the output data. + * @param dataType The data type of the operator, must be one of the following types: int8, int16, int32, float16, + * float32. + * @param op The reduction type of the operator, must be one of the following types: sum, min, max, prod. + * @param comm A pointer identifying the communication resource based on. + * @param stream A pointer identifying the stream information. + * @return HcclResult + */ +extern HcclResult HcclAllReduce(void *sendBuf, void *recvBuf, uint64_t count, HcclDataType dataType, HcclReduceOp op, + HcclComm comm, aclrtStream stream); + +/** + * @brief Broadcast operator. + * + * @param buf A pointer identifying the data address of the operator. + * @param count An integer(u64) identifying the number of the data. + * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. + * @param root An integer(u32) identifying the the root rank in the operator. + * @param comm A pointer identifying the communication resource based on + * @param stream A pointer identifying the stream information. + * @return HcclResult + */ +extern HcclResult HcclBroadcast(void *buf, uint64_t count, HcclDataType dataType, uint32_t root, HcclComm comm, + aclrtStream stream); + +/** + * @brief ReduceScatter operator. + * + * @param sendBuf A pointer identifying the input data address of the operator. + * @param recvBuf A pointer identifying the output data address of the operator. + * @param recvCount An integer(u64) identifying the number of the output data. + * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. + * @param op The reduction type of the operator, must be one of the following types: sum, min, max, prod. + * @param comm A pointer identifying the communication resource based on. + * @param stream A pointer identifying the stream information. + * @return HcclResult + */ +extern HcclResult HcclReduceScatter(void *sendBuf, void *recvBuf, uint64_t recvCount, HcclDataType dataType, + HcclReduceOp op, HcclComm comm, aclrtStream stream); + +/** + * @brief AllGather operator. + * + * @param sendBuf A pointer identifying the input data address of the operator. + * @param recvBuf A pointer identifying the output data address of the operator. + * @param sendCount An integer(u64) identifying the number of the input data. + * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. + * @param comm A pointer identifying the communication resource based on. + * @param stream A pointer identifying the stream information. + * @return HcclResult + */ +extern HcclResult HcclAllGather(void *sendBuf, void *recvBuf, uint64_t sendCount, HcclDataType dataType, HcclComm comm, + aclrtStream stream); +/** + * @brief Get the rank size of this comm. + * + * @param comm A pointer identifying the communication resource based on. + * @param rankSize A pointer identifying the rank size. + * @return HcclResult + */ +extern HcclResult HcclGetRankSize(HcclComm comm, uint32_t *rankSize); + +/** + * @brief Get the rank id of this comm. + * + * @param comm A pointer identifying the communication resource based on. + * @param rankSize A pointer identifying the rank id. + * @return HcclResult + */ +extern HcclResult HcclGetRankId(HcclComm comm, uint32_t *rank); +/** + * @brief Barrier operator. + * + * @param comm A pointer identifying the communication resource based on. + * @param stream A pointer identifying the stream information. + * @return HcclResult + */ +extern HcclResult HcclBarrier(HcclComm comm, aclrtStream stream); + +/** + * @brief Destroy HCCL comm + * + * @param comm A pointer identifying the communication resource targetting + * @return HcclResult + * @see HcclCommInitClusterInfo() + */ +extern HcclResult HcclCommDestroy(HcclComm comm); + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // HCCL_H_ diff --git a/inc/external/hccl/hccl_types.h b/inc/external/hccl/hccl_types.h new file mode 100644 index 00000000..0e832396 --- /dev/null +++ b/inc/external/hccl/hccl_types.h @@ -0,0 +1,101 @@ +/** + * Copyright 2019-2020 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. + */ + +/** + * @file hccl_types.h + * @brief HCCL data type definition + * + */ + +#ifndef HCCL_TYPES_H_ +#define HCCL_TYPES_H_ + +#include + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +/** + * @brief HCCL functions return value definition + */ +typedef enum { + HCCL_SUCCESS = 0, /**< success */ + HCCL_E_PARA = 1, /**< parameter error */ + HCCL_E_PTR = 2, /**< empty pointer */ + HCCL_E_MEMORY = 3, /**< memory error */ + HCCL_E_INTERNAL = 4, /**< internal error */ + HCCL_E_NOT_SUPPORT = 5, /**< not support feature */ + HCCL_E_NOT_FOUND = 6, /**< not found specific resource */ + HCCL_E_UNAVAIL = 7, /**< resource unavailable */ + HCCL_E_SYSCALL = 8, /**< call system interface error */ + HCCL_E_TIMEOUT = 9, /**< timeout */ + HCCL_E_OPEN_FILE_FAILURE = 10, /**< open file fail */ + HCCL_E_TCP_CONNECT = 11, /**< tcp connect fail */ + HCCL_E_ROCE_CONNECT = 12, /**< roce connect fail */ + HCCL_E_TCP_TRANSFER = 13, /**< tcp transfer fail */ + HCCL_E_ROCE_TRANSFER = 14, /**< roce transfer fail */ + HCCL_E_RUNTIME = 15, /**< call runtime api fail */ + HCCL_E_DRV = 16, /**< call driver api fail */ + HCCL_E_PROFILING = 17, /**< call profiling api fail */ + HCCL_E_CCE = 18, /**< call cce api fail */ + HCCL_E_NETWORK = 19, /**< call network api fail */ + HCCL_E_RESERVED /**< reserved */ +} HcclResult; + +/** + * @brief handle to HCCL communicator + */ +typedef void *HcclComm; + +/** + * @brief HCCL Reduction opperation + */ +typedef enum { + HCCL_REDUCE_SUM = 0, /**< sum */ + HCCL_REDUCE_PROD = 1, /**< prod */ + HCCL_REDUCE_MAX = 2, /**< max */ + HCCL_REDUCE_MIN = 3, /**< min */ + HCCL_REDUCE_RESERVED /**< reserved */ +} HcclReduceOp; + +/** + * @brief HCCL data type + */ +typedef enum { + HCCL_DATA_TYPE_INT8 = 0, /**< int8 */ + HCCL_DATA_TYPE_INT16 = 1, /**< int16 */ + HCCL_DATA_TYPE_INT32 = 2, /**< int32 */ + HCCL_DATA_TYPE_FP16 = 3, /**< fp16 */ + HCCL_DATA_TYPE_FP32 = 4, /**< fp32 */ + HCCL_DATA_TYPE_INT64 = 5, /**< int64 */ + HCCL_DATA_TYPE_UINT64 = 6, /**< uint64 */ + HCCL_DATA_TYPE_RESERVED /**< reserved */ +} HcclDataType; + +const uint32_t HCCL_ROOT_INFO_BYTES = 4108; // 4108: root info length + +/** + * @brief HCCL root info + */ +typedef struct HcclRootInfoDef { + char internal[HCCL_ROOT_INFO_BYTES]; +} HcclRootInfo; + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // HCCL_TYPES_H_ diff --git a/inc/external/runtime/rt_error_codes.h b/inc/external/runtime/rt_error_codes.h new file mode 100644 index 00000000..a1392cc6 --- /dev/null +++ b/inc/external/runtime/rt_error_codes.h @@ -0,0 +1,109 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef __INC_EXTERNEL_RT_ERROR_CODES_H__ +#define __INC_EXTERNEL_RT_ERROR_CODES_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static const int32_t ACL_RT_SUCCESS = 0; // success + +static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid +static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id +static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null +static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context +static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context +static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal +static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned +static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed +static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed +static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream +static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread +static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set +static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create +static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream +static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type +static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle +static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type +static const int32_t ACL_ERROR_RT_WAIT_TIMEOUT = 107019; // wait timeout + +static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support +static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error +static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error +static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow +static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device +static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail +static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission +static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource +static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource +static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource +static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource +static const int32_t ACL_ERROR_RT_NO_CDQ_RESOURCE = 207011; // no cdq resource + +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout +static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception +static const int32_t ACL_ERROR_RT_CDQ_BATCH_ABNORMAL = 507037; // cdq alloc batch abnormal + +static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error +static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error +static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect + +#ifdef __cplusplus +} +#endif + +#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/inc/framework/ge_runtime/task_info.h b/inc/framework/ge_runtime/task_info.h index f59c6454..4530bff7 100644 --- a/inc/framework/ge_runtime/task_info.h +++ b/inc/framework/ge_runtime/task_info.h @@ -271,13 +271,14 @@ class FusionEndTaskInfo : public TaskInfo { class HcclTaskInfo : public TaskInfo { public: HcclTaskInfo(const std::string &op_name, uint32_t stream_id, const std::string hccl_type, void *input_data_addr, - void *output_data_addr, int64_t workspace_size, int64_t hccl_stream_num, + void *output_data_addr, void *workspace_addr, int64_t workspace_size, int64_t hccl_stream_num, const std::vector &private_def, void *ops_kernel_store, int32_t count, int64_t root_id, int64_t op_type, int64_t data_type, const std::string &group, bool dump_flag) : TaskInfo(op_name, stream_id, TaskInfoType::HCCL, dump_flag), hccl_type_(hccl_type), input_data_addr_(input_data_addr), output_data_addr_(output_data_addr), + workspace_addr_(workspace_addr), workspace_size_(workspace_size), hccl_stream_num_(hccl_stream_num), private_def_(private_def), @@ -292,6 +293,7 @@ class HcclTaskInfo : public TaskInfo { const std::string &hccl_type() const { return hccl_type_; } void *input_data_addr() const { return input_data_addr_; } void *output_data_addr() const { return output_data_addr_; } + void *workspace_addr() const { return workspace_addr_; } int64_t workspace_size() const { return workspace_size_; } int64_t hccl_stream_num() const { return hccl_stream_num_; } const std::vector &private_def() const { return private_def_; } @@ -306,6 +308,7 @@ class HcclTaskInfo : public TaskInfo { std::string hccl_type_; void *input_data_addr_; void *output_data_addr_; + void *workspace_addr_; int64_t workspace_size_; int64_t hccl_stream_num_; std::vector private_def_; diff --git a/metadef b/metadef index a725349b..21178899 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit a725349b65aef2940555af2ddb7b9461fbe0d5fd +Subproject commit 211788997dcc9aa63527541a44d511388c06bce5 diff --git a/scripts/format_source_code.sh b/scripts/format_source_code.sh new file mode 100755 index 00000000..1fd0b4f6 --- /dev/null +++ b/scripts/format_source_code.sh @@ -0,0 +1,107 @@ +#!/bin/bash +# Copyright 2019-2020 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. +# ============================================================================ + +set -e + +CLANG_FORMAT=$(which clang-format) || (echo "Please install 'clang-format' tool first"; exit 1) + +version=$("${CLANG_FORMAT}" --version | sed -n "s/.*\ \([0-9]*\)\.[0-9]*\.[0-9]*.*/\1/p") +if [[ "${version}" -lt "8" ]]; then + echo "clang-format's version must be at least 8.0.0" + exit 1 +fi + +CURRENT_PATH=$(pwd) +SCRIPTS_PATH=$(dirname "$0") + +echo "CURRENT_PATH=${CURRENT_PATH}" +echo "SCRIPTS_PATH=${SCRIPTS_PATH}" + +# print usage message +function usage() +{ + echo "Format the specified source files to conform the code style." + echo "Usage:" + echo "bash $0 [-a] [-c] [-l] [-h]" + echo "e.g. $0 -c" + echo "" + echo "Options:" + echo " -a format of all files" + echo " -c format of the files changed compared to last commit, default case" + echo " -l format of the files changed in last commit" + echo " -h Print usage" +} + +# check and set options +function checkopts() +{ + # init variable + mode="changed" # default format changed files + + # Process the options + while getopts 'aclh' opt + do + case "${opt}" in + a) + mode="all" + ;; + c) + mode="changed" + ;; + l) + mode="lastcommit" + ;; + h) + usage + exit 0 + ;; + *) + echo "Unknown option ${opt}!" + usage + exit 1 + esac + done +} + +# init variable +# check options +checkopts "$@" + +# switch to project root path, which contains clang-format config file '.clang-format' +cd "${SCRIPTS_PATH}/.." || exit 1 + +FMT_FILE_LIST='__format_files_list__' + +if [[ "X${mode}" == "Xall" ]]; then + find src -type f -name "*" | grep "\.h$\|\.cc$" > "${FMT_FILE_LIST}" || true + find inc -type f -name "*" | grep "\.h$\|\.cc$" >> "${FMT_FILE_LIST}" || true +elif [[ "X${mode}" == "Xchanged" ]]; then + # --diff-filter=ACMRTUXB will ignore deleted files in commit + git diff --diff-filter=ACMRTUXB --name-only | grep "^inc\|^src" | grep "\.h$\|\.cc$" >> "${FMT_FILE_LIST}" || true +else # "X${mode}" == "Xlastcommit" + git diff --diff-filter=ACMRTUXB --name-only HEAD~ HEAD | grep "^inc\|^src" | grep "\.h$\|\.cc$" > "${FMT_FILE_LIST}" || true +fi + +while read line; do + if [ -f "${line}" ]; then + ${CLANG_FORMAT} -i "${line}" + fi +done < "${FMT_FILE_LIST}" + +rm "${FMT_FILE_LIST}" +cd "${CURRENT_PATH}" || exit 1 + +echo "Specified cpp source files have been format successfully." diff --git a/third_party/fwkacllib/inc/cce/taskdown_common.hpp b/third_party/fwkacllib/inc/cce/taskdown_common.hpp index 3ecea523..7954162e 100644 --- a/third_party/fwkacllib/inc/cce/taskdown_common.hpp +++ b/third_party/fwkacllib/inc/cce/taskdown_common.hpp @@ -27,15 +27,16 @@ namespace cce { #define CC_FUSION_OP_MAX 32 typedef enum tagccKernelType { - CCE_AI_CORE = 0, /* cce aicore */ - CCE_AI_CPU = 1, /* cce aicpu */ - TE = 2, /* te operator*/ - CUSTOMIZED = 3, /* customized operator */ - TE_AI_CORE = 4, /* te aicore operator*/ - TE_AI_CPU = 5, /* te aicpu operator */ - AI_CPU = 6, /* aicpu */ - CUST_AI_CPU = 7, /* custom aicpu*/ - INVALID = 8, /* unknown kernel type */ + CCE_AI_CORE = 0, /* cce aicore */ + CCE_AI_CPU = 1, /* cce aicpu */ + TE = 2, /* te operator*/ + CUSTOMIZED = 3, /* customized operator */ + TE_AI_CORE = 4, /* te aicore operator*/ + TE_AI_CPU = 5, /* te aicpu operator */ + AI_CPU = 6, /* aicpu */ + CUST_AI_CPU = 7, /* custom aicpu*/ + HOST_CPU = 8, /* host cpu */ + INVALID = 10000 /* unknown kernel type */ } ccKernelType; typedef struct tagOpContext { diff --git a/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h b/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h old mode 100755 new mode 100644 diff --git a/third_party/fwkacllib/inc/hccl/base.h b/third_party/fwkacllib/inc/hccl/base.h index e57563b3..ffbf552b 100644 --- a/third_party/fwkacllib/inc/hccl/base.h +++ b/third_party/fwkacllib/inc/hccl/base.h @@ -124,27 +124,27 @@ struct HcomRemoteAccessAddrInfo { }; struct HcomAllToAllVParams { - void *sendbuf; - void *sendcounts; - void *sdispls; - HcclDataType sendtype; - void *recvbuf; - void *recvcounts; - void *rdispls; - HcclDataType recvtype; - const char *group; + void *sendbuf; // device mem + void *sendcounts; // device mem; Type: uint_64 + void *sdispls; // device mem; Type: uint_64 + HcclDataType sendtype; + void *recvbuf; // device mem + void *recvcounts; // device mem; Type: uint_64 + void *rdispls; // device mem; Type: uint_64 + HcclDataType recvtype; + const char *group; // not used now }; struct HcomGatherAllToAllVParams { - void *addrInfo; - void *addrInfoCountPerRank; - void *recvbuf; - void *recvcounts; - void *rdispls; - void *gatheredbuf; - s32 addrLength; - HcclDataType recvtype; - const char *group; + void *addrInfo; // device mem; contains host VA[uint_64]: [addr, length, addr, length, addr, length, ...] + void *addrInfoCountPerRank; // device mem; length: ranksize; contains addrInfoCounts for every rank + void *recvbuf; // device mem + void *recvcounts; // device mem; Type: uint_64 + void *rdispls; // device mem; Type: uint_64 + void *gatheredbuf; // device mem + s32 addrLength; + HcclDataType recvtype; + const char *group; // not used now }; #ifdef __cplusplus diff --git a/third_party/fwkacllib/inc/hccl/hccl_types.h b/third_party/fwkacllib/inc/hccl/hccl_types.h deleted file mode 100644 index 50a64795..00000000 --- a/third_party/fwkacllib/inc/hccl/hccl_types.h +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -/** - * @file hccl_types.h - * @brief HCCL data type definition - * - */ - -#ifndef HCCL_TYPES_H_ -#define HCCL_TYPES_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -/** - * @brief HCCL functions return value definition - */ -typedef enum { - HCCL_SUCCESS = 0, /**< success */ - HCCL_E_PARA = 1, /**< parameter error */ - HCCL_E_PTR = 2, /**< empty pointer */ - HCCL_E_MEMORY = 3, /**< memory error */ - HCCL_E_INTERNAL = 4, /**< internal error */ - HCCL_E_NOT_SUPPORT = 5, /**< not support feature */ - HCCL_E_NOT_FOUND = 6, /**< not found specific resource */ - HCCL_E_UNAVAIL = 7, /**< resource unavailable */ - HCCL_E_SYSCALL = 8, /**< call system interface error */ - HCCL_E_TIMEOUT = 9, /**< timeout */ - HCCL_E_OPEN_FILE_FAILURE = 10, /**< open file fail */ - HCCL_E_TCP_CONNECT = 11, /**< tcp connect fail */ - HCCL_E_ROCE_CONNECT = 12, /**< roce connect fail */ - HCCL_E_TCP_TRANSFER = 13, /**< tcp transfer fail */ - HCCL_E_ROCE_TRANSFER = 14, /**< roce transfer fail */ - HCCL_E_RUNTIME = 15, /**< call runtime api fail */ - HCCL_E_DRV = 16, /**< call driver api fail */ - HCCL_E_PROFILING = 17, /**< call profiling api fail */ - HCCL_E_CCE = 18, /**< call cce api fail */ - HCCL_E_NETWORK = 19, /**< call network api fail */ - HCCL_E_RESERVED /**< reserved */ -} HcclResult; - -/** - * @brief handle to HCCL communicator - */ -typedef void *HcclComm; - -/** - * @brief HCCL Reduction opperation - */ -typedef enum { - HCCL_REDUCE_SUM = 0, /**< sum */ - HCCL_REDUCE_PROD = 1, /**< prod */ - HCCL_REDUCE_MAX = 2, /**< max */ - HCCL_REDUCE_MIN = 3, /**< min */ - HCCL_REDUCE_RESERVED /**< reserved */ -} HcclReduceOp; - -/** - * @brief HCCL data type - */ -typedef enum { - HCCL_DATA_TYPE_INT8 = 0, /**< int8 */ - HCCL_DATA_TYPE_INT16 = 1, /**< int16 */ - HCCL_DATA_TYPE_INT32 = 2, /**< int32 */ - HCCL_DATA_TYPE_FP16 = 3, /**< fp16 */ - HCCL_DATA_TYPE_FP32 = 4, /**< fp32 */ - HCCL_DATA_TYPE_INT64 = 5, /**< int64 */ - HCCL_DATA_TYPE_UINT64 = 6, /**< uint64 */ - HCCL_DATA_TYPE_RESERVED /**< reserved */ -} HcclDataType; - -const uint32_t HCCL_ROOT_INFO_BYTES = 4108; // 4108: root info length - -/** - * @brief HCCL root info - */ -typedef struct HcclRootInfoDef { - char internal[HCCL_ROOT_INFO_BYTES]; -} HcclRootInfo; - -#ifdef __cplusplus -} -#endif // __cplusplus -#endif // HCCL_TYPES_H_ diff --git a/third_party/fwkacllib/inc/hccl/hcom.h b/third_party/fwkacllib/inc/hccl/hcom.h index 955764d6..bf1f395b 100644 --- a/third_party/fwkacllib/inc/hccl/hcom.h +++ b/third_party/fwkacllib/inc/hccl/hcom.h @@ -164,8 +164,22 @@ HcclResult HcomExecEnqueueRemoteAccess(const std::string& remoteAccessType, const std::vector& addrInfos, std::function callback); +/** + * @brief Put alltoallv communication operation into hcom executor. + * + * @param params information about alltoallv communication operation. + * @param callback callback after collective communication operation. + * @return HcclResult + */ HcclResult HcomExecEnqueueAllToAllV(HcomAllToAllVParams params, std::function callback); +/** + * @brief Put agther alltoallv communication operation into hcom executor. + * + * @param params information about agther alltoallv communication operation. + * @param callback callback after collective communication operation. + * @return HcclResult + */ HcclResult HcomExecEnqueueGatherAllToAllV(HcomGatherAllToAllVParams params, std::function callback); diff --git a/third_party/fwkacllib/inc/mmpa/mmpa_api.h b/third_party/fwkacllib/inc/mmpa/mmpa_api.h index 38a689ee..f8d5ccf3 100644 --- a/third_party/fwkacllib/inc/mmpa/mmpa_api.h +++ b/third_party/fwkacllib/inc/mmpa/mmpa_api.h @@ -56,6 +56,7 @@ #include #include #include +#include #include #include diff --git a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h index 993f36ba..3d196e41 100644 --- a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h +++ b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h @@ -550,6 +550,10 @@ MMPA_FUNC_VISIBILITY mmFileHandle mmShmOpen(const CHAR *name, INT32 oflag, mmMod MMPA_FUNC_VISIBILITY INT32 mmShmUnlink(const CHAR *name); MMPA_FUNC_VISIBILITY VOID *mmMmap(mmFd_t fd, mmSize_t size, mmOfft_t offset, mmFd_t *extra, INT32 prot, INT32 flags); MMPA_FUNC_VISIBILITY INT32 mmMunMap(VOID *data, mmSize_t size, mmFd_t *extra); + +MMPA_FUNC_VISIBILITY mmSize mmGetPageSize(); +MMPA_FUNC_VISIBILITY VOID *mmAlignMalloc(mmSize mallocSize, mmSize alignSize); +MMPA_FUNC_VISIBILITY VOID mmAlignFree(VOID *addr); #define MMPA_DLL_API #ifdef __cplusplus diff --git a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h index 49e97a5d..e6b6f71e 100644 --- a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h +++ b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h @@ -557,6 +557,10 @@ MMPA_FUNC_VISIBILITY mmFileHandle mmShmOpen(const CHAR *name, INT32 oflag, mmMod MMPA_FUNC_VISIBILITY INT32 mmShmUnlink(const CHAR *name); MMPA_FUNC_VISIBILITY VOID *mmMmap(mmFd_t fd, mmSize_t size, mmOfft_t offset, mmFd_t *extra, INT32 prot, INT32 flags); MMPA_FUNC_VISIBILITY INT32 mmMunMap(VOID *data, mmSize_t size, mmFd_t *extra); + +MMPA_FUNC_VISIBILITY mmSize mmGetPageSize(); +MMPA_FUNC_VISIBILITY VOID *mmAlignMalloc(mmSize mallocSize, mmSize alignSize); +MMPA_FUNC_VISIBILITY VOID mmAlignFree(VOID *addr); #ifdef __cplusplus #if __cplusplus } diff --git a/third_party/fwkacllib/inc/ops/aipp.h b/third_party/fwkacllib/inc/ops/aipp.h index bed984bd..86805f72 100644 --- a/third_party/fwkacllib/inc/ops/aipp.h +++ b/third_party/fwkacllib/inc/ops/aipp.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -65,6 +65,8 @@ in aipp config file, framework will auto add one input node to graph at last. \n *@par Third-party framework compatibility *Compatible with the TensorFlow operator AippData. +*@par Restrictions: +*Warning: This operator can be integrated only by configuring INSERT_OP_FILE of aclgrphBuildModel. Please do not use it directly. */ REG_OP(AippData) .INPUT(data, TensorType::ALL()) diff --git a/third_party/fwkacllib/inc/ops/all_ops.h b/third_party/fwkacllib/inc/ops/all_ops.h index 1ac83783..cc11f5f9 100644 --- a/third_party/fwkacllib/inc/ops/all_ops.h +++ b/third_party/fwkacllib/inc/ops/all_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -39,6 +39,7 @@ #include "image_ops.h" #include "internal_ops.h" #include "linalg_ops.h" +#include "list_ops.h" #include "logging_ops.h" #include "lookup_ops.h" #include "math_ops.h" diff --git a/third_party/fwkacllib/inc/ops/array_ops.h b/third_party/fwkacllib/inc/ops/array_ops.h index e1f64421..fd35b546 100644 --- a/third_party/fwkacllib/inc/ops/array_ops.h +++ b/third_party/fwkacllib/inc/ops/array_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -626,7 +626,7 @@ REG_OP(StopGradient) *x: A tensor. \n *@par Outputs: -*y: A tensor. \n +*y: A tensor with the same shape and contents as input. \n *@par Third-party framework compatibility *Compatible with the TensorFlow operator Identity. @@ -666,7 +666,7 @@ REG_OP(IdentityN) *@li axis: The dimension index at which to expand. \n *@par Outputs: -*y: A tensor. \n +*y: A tensor with the same data as input, with an additional dimension inserted at the index specified by axis. \n *@par Third-party framework compatibility *Compatible with the TensorFlow operator ExpandDims. @@ -713,7 +713,7 @@ REG_OP(Unsqueeze) *@par Outputs: *y: A tensor. \n -*@par Attention: +*@attention Constraints: *This operator cannot be directly called by the acllopExecute API. \n *@par Third-party framework compatibility @@ -1153,6 +1153,102 @@ REG_OP(EditDistance) .OUTPUT(output, TensorType({DT_FLOAT})) .OP_END_FACTORY_REG(EditDistance) +/** +* @brief sort_v2. + +* @par Inputs: +* @li x: An ND tensor of type float16. + +* @par Attributes: + +* @li axis: An optional int. The dimension to sort along. This value defaults to -1. +* @li descending: An optional bool. Controls the sorting order (ascending or descending). This value defaults to False. + +* @par Outputs: +* @li y: An ND tensor of type float16. + +* @attention Constraints: +* @li Axis should select the last dim. +* @li When the sorting data is less than 150K, it is recommended to use this tbe ops, + and the descending performance is better than the ascending. +* @li The upper limit of data on Ascend910 is 2000K. +*/ +REG_OP(SortV2) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .ATTR(axis, Int, -1) + .ATTR(descending, Bool, false) + .OP_END_FACTORY_REG(SortV2) + +/** +* @brief Expand the input tensor to a compatible shape. \n + +* @par Inputs: +* One inputs, including: +* @li x: A Tensor. Must be one of the following types: +* float16, float32, int32, int8 ,uint8. \n +* @li shape: A Tensor to specify the shape that the input tensor expanded to. \n + +* @par Outputs: +* @li y: A Tensor. Has the same type as "x", and the shape specified by input and attr shape \n + +* @par Third-party framework compatibility +* Compatible with the ONNX operator Expand. +*/ + +REG_OP(Expand) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) + .INPUT(shape, TensorType({DT_INT16, DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) + .OP_END_FACTORY_REG(Expand) + +/** +*@Returns a tensor containing the indices of all non-zero elements of input. \n + +*@par Inputs: +*@li x: A Tensor. Must be one of the following types: float16, float32, int32, int64. + +*@par Attributes: +* transpose: the output tensor will be transposed if true. \n + +*@par Outputs: +* y: A Tensor. Has the same type as "x" . \n + +*@par Third-party framework compatibility +*Compatible with the PyTorch operator NonZero. +*/ + +REG_OP(NonZero) + .INPUT(x, TensorType({DT_DOUBLE, DT_FLOAT, DT_FLOAT16, DT_INT8, DT_UINT8, DT_INT16, \ + DT_UINT16, DT_INT32, DT_UINT32, DT_INT64, DT_UINT64, DT_BOOL})) + .OUTPUT(y, TensorType({DT_INT64})) + .ATTR(transpose, Bool, false) + .OP_END_FACTORY_REG(NonZero) + +/** +* @brief Expand the input tensor to a compatible shape. \n + +* @par Inputs: +* One inputs, including: +* @li x: A Tensor. Must be one of the following types: +* float16, float32, int32, int8 ,uint8. \n + +* @par Attributes: +* @li shape: A required listInt to specify the shape that the input tensor expanded to. \n + + +* @par Outputs: +* @li y: A Tensor. Has the same type as "x", and the shape specified by input and attr shape \n + +* @par Third-party framework compatibility +* Compatible with the ONNX operator Expand. +*/ + +REG_OP(ExpandD) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) + .REQUIRED_ATTR(shape, ListInt) + .OP_END_FACTORY_REG(ExpandD) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_ARRAY_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/audio_ops.h b/third_party/fwkacllib/inc/ops/audio_ops.h index d9883253..f05135d1 100644 --- a/third_party/fwkacllib/inc/ops/audio_ops.h +++ b/third_party/fwkacllib/inc/ops/audio_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h b/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h new file mode 100644 index 00000000..d0800a08 --- /dev/null +++ b/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h @@ -0,0 +1,58 @@ +/** + * Copyright 2019 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. + */ + +/*! + * \file avg_pool_1d_ops.h + * \brief + */ +#ifndef OPS_BUILT_IN_OP_PROTO_INC_AVGPOOL1DOPS_H_ +#define OPS_BUILT_IN_OP_PROTO_INC_AVGPOOL1DOPS_H_ +#include "graph/operator_reg.h" + +namespace ge { +/** +*@brief Generate an auxiliary matrix . \n + +*@par Inputs: +* @li x: A tensor. Must be one of the following types:uint8, int8,int16, int32, + int64, float16, float, double.The format must be NHWC NCHW NC1HWC0. + +*@par Attributes: +*@li ksize: Kernel size. Input type is int. +*@li strides: Input type is int. +*@li pads: Input type is listInt . +*@li ceil_mode: Bool, default value is false. +*@li count_include_pad: Bool, default value is false. \n + +*@par Outputs: +*y_tensor: A tensor with the same types as "x" . \n +*@par Third-party framework compatibility + +*Compatible with the TensorFlow operator Unbatch. +*/ +REG_OP(AvgPool1DAvgMatrix) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT16, DT_UINT8, + DT_INT32, DT_INT64, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT16, DT_UINT8, + DT_INT32, DT_INT64, DT_DOUBLE})) + .REQUIRED_ATTR(ksize, Int) + .REQUIRED_ATTR(strides, Int) + .REQUIRED_ATTR(pads, ListInt) + .ATTR(ceil_mode, Bool, false) + .ATTR(count_include_pad, Bool, false) + .OP_END_FACTORY_REG(AvgPool1DAvgMatrix) +} +#endif \ No newline at end of file diff --git a/third_party/fwkacllib/inc/ops/batch_ops.h b/third_party/fwkacllib/inc/ops/batch_ops.h index 8a1c5a7b..ca4fe1db 100644 --- a/third_party/fwkacllib/inc/ops/batch_ops.h +++ b/third_party/fwkacllib/inc/ops/batch_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -64,10 +64,10 @@ the same types as "x_tensors" . It's a dynamic output. \n REG_OP(Batch) .DYNAMIC_INPUT(x_tensors, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, \ DT_INT16, DT_UINT16, DT_UINT8, DT_INT32, DT_INT64, DT_BOOL, DT_DOUBLE})) - .OUTPUT(y_index, TensorType({ DT_INT64 })) - .OUTPUT(y_id, TensorType({ DT_INT64 })) .DYNAMIC_OUTPUT(y_tensors, TensorType({DT_INT8, DT_UINT8, DT_INT16, \ DT_UINT16, DT_INT32, DT_INT64, DT_FLOAT, DT_FLOAT16, DT_DOUBLE, DT_BOOL})) + .OUTPUT(y_index, TensorType({ DT_INT64 })) + .OUTPUT(y_id, TensorType({ DT_INT64 })) .REQUIRED_ATTR(num_batch_threads, Int) .REQUIRED_ATTR(max_batch_size, Int) .ATTR(max_enqueued_batches, Int, 10) @@ -107,11 +107,13 @@ across multiple sessions . \n REG_OP(Unbatch) .INPUT(x_tensor, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, \ - DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE})) + DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ + DT_COMPLEX64, DT_COMPLEX128})) .INPUT(index, TensorType({DT_INT64})) .INPUT(id, TensorType({DT_INT64})) .OUTPUT(y_tensor, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, \ - DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE})) + DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ + DT_COMPLEX64, DT_COMPLEX128})) .REQUIRED_ATTR(timeout_micros, Int) .ATTR(container, String, "") .ATTR(shared_name, String, "") @@ -146,13 +148,16 @@ across multiple sessions . \n REG_OP(UnbatchGrad) .INPUT(x_input, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, \ - DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE})) + DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ + DT_COMPLEX64, DT_COMPLEX128})) .INPUT(index, TensorType({DT_INT64})) .INPUT(grad, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, \ - DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE})) + DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ + DT_COMPLEX64, DT_COMPLEX128})) .INPUT(id, TensorType({DT_INT64})) .OUTPUT(y_grad, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, \ - DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE})) + DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE, DT_FLOAT16, \ + DT_COMPLEX64, DT_COMPLEX128})) .ATTR(container, String, "") .ATTR(shared_name, String, "") .OP_END_FACTORY_REG(UnbatchGrad) diff --git a/third_party/fwkacllib/inc/ops/bitwise_ops.h b/third_party/fwkacllib/inc/ops/bitwise_ops.h index 5c83e161..dac78118 100644 --- a/third_party/fwkacllib/inc/ops/bitwise_ops.h +++ b/third_party/fwkacllib/inc/ops/bitwise_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -25,6 +25,35 @@ namespace ge { +/** +*@brief Element-wise computes the bitwise left-shift of x and y . \n + +*@par Inputs: +*Input "x" is a k-dimensional tensor. Inputs "num_lower" and "num_upper" +are 0D scalars. +* @li x: A Tensor. Must be one of the following types: int8, int16, int32, +int64, uint8, uint16, uint32, uint64. +* @li y: A Tensor. Has the same type as "x". \n + +*@par Outputs: +* z: A Tensor. Has the same type as "x". \n + +*@attention Constraints: +*Unique runs on the Ascend AI CPU, which delivers poor performance. \n + +*@par Third-party framework compatibility +*Compatible with the TensorFlow operator LeftShift. +*/ + +REG_OP(LeftShift) + .INPUT(x, TensorType({DT_INT8, DT_INT16, DT_INT32, DT_INT64, \ + DT_UINT8, DT_UINT16, DT_UINT32, DT_UINT64})) + .INPUT(y, TensorType({DT_INT8, DT_INT16, DT_INT32, DT_INT64, \ + DT_UINT8, DT_UINT16, DT_UINT32, DT_UINT64})) + .OUTPUT(z, TensorType({DT_INT8, DT_INT16, DT_INT32, DT_INT64, \ + DT_UINT8, DT_UINT16, DT_UINT32, DT_UINT64})) + .OP_END_FACTORY_REG(LeftShift) + /** *@brief Element-wise computes the bitwise right-shift of x and y . \n diff --git a/third_party/fwkacllib/inc/ops/boosted_trees_ops.h b/third_party/fwkacllib/inc/ops/boosted_trees_ops.h index 550e8b7d..08e54824 100644 --- a/third_party/fwkacllib/inc/ops/boosted_trees_ops.h +++ b/third_party/fwkacllib/inc/ops/boosted_trees_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h b/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h index e20607bf..890c52ae 100644 --- a/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h +++ b/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/condtake_ops.h b/third_party/fwkacllib/inc/ops/condtake_ops.h index 5e91eb07..029cffbf 100644 --- a/third_party/fwkacllib/inc/ops/condtake_ops.h +++ b/third_party/fwkacllib/inc/ops/condtake_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/control_flow_ops.h b/third_party/fwkacllib/inc/ops/control_flow_ops.h index 7196b14f..e5bd3534 100644 --- a/third_party/fwkacllib/inc/ops/control_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/control_flow_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -96,7 +96,7 @@ REG_OP(RefMerge) * Otherwise, the data is forwarded to "output_false" . \n *@par Inputs: - *@li data: The tensor to be forwarded. \ n + *@li data: The tensor to be forwarded. \n * Must be one of the following types: float16, float32, float64, * int8, int16, int32, int64, uint8, uint16, uint32, uint64, bool. *@li pred: A boolean scalar. The output port that will receive data . \n @@ -387,12 +387,12 @@ REG_OP(ControlTrigger) *@par Inputs: * Three inputs, including: -*@li x: One dimensional tensore of type int32, specifying queried shape, max size is 8. -*@li data_seq: One dimensional tensore of type int32, specifying the mapped table is queried. -*@li level_index: One dimensional tensore of type int32, specifying secondary index. \n +*@li x: One dimensional tensor of type int32, specifying queried shape, max size is 128. +*@li data_seq: One dimensional tensor of type int32, specifying the mapped table is queried. +*@li level_index: One dimensional tensor of type int32, specifying secondary index. \n *@par Outputs: -*@li y: A Tensor with shape [batch, 8], of type int32, specifying index of shape in the map. +*@li y: A Tensor with shape [8], of type int32, specifying index of shape in the map. *@par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. */ diff --git a/third_party/fwkacllib/inc/ops/correlation.h b/third_party/fwkacllib/inc/ops/correlation.h new file mode 100644 index 00000000..caebba50 --- /dev/null +++ b/third_party/fwkacllib/inc/ops/correlation.h @@ -0,0 +1,52 @@ +/** + * Copyright 2020 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. + */ + +/*! + * \file correlation.h + * \brief + */ +#ifndef GE_OP_CORRELATION_OPS_H +#define GE_OP_CORRELATION_OPS_H + +#include "graph/operator_reg.h" + +namespace ge { +/** +*@brief Computes a 2D Correlation given 4D "x" and "filter" tensors. +* +*@par Inputs: +* @li filter: A 4D tensor of filters. +* @li x: A 4D tensor of input images, batch number must equal to batch +* number of "filter", and channel must equal to channel of "filter". +* +*@par Attributes: +* @li groups: set correlation mode, must be 1 or channel. +* +*@par Outputs: +*y: A Tensor. Has the same type as "x". + +*@par Third-party framework compatibility +* Compatible with caffe correlation custom operator. +*/ +REG_OP(Correlation) + .INPUT(filter, TensorType({DT_FLOAT16, DT_INT8})) + .INPUT(x, TensorType({DT_FLOAT16, DT_INT8})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_INT32})) + .ATTR(groups, Int, 1) + .OP_END_FACTORY_REG(Correlation) +} // namespace ge + +#endif // GE_OP_NN_CALCULATION_OPS_H diff --git a/third_party/fwkacllib/inc/ops/ctc_ops.h b/third_party/fwkacllib/inc/ops/ctc_ops.h index 2c75fd09..e907b828 100644 --- a/third_party/fwkacllib/inc/ops/ctc_ops.h +++ b/third_party/fwkacllib/inc/ops/ctc_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -137,6 +137,87 @@ REG_OP(CTCBeamSearchDecoder) .OUTPUT(log_probability, TensorType({DT_FLOAT, DT_DOUBLE})) .OP_END_FACTORY_REG(CTCBeamSearchDecoder) +/** +*@brief The Connectionist Temporal Classification loss. + +*@par Inputs: +*@li log_probs: Tensor of size (T, N, C), where T =input length, N =batch size, + and C = number of classes (including blank). + It represent the logarithmized probabilities of the outputs. +*@li targets: Tensor of size (N, S), where S= max target length. + It represent the target sequences. +*@li input_lengths: Tuple or tensor of size (N). It represent the lengths of the inputs. +*@li target_lengths: Tuple or tensor of size (N). It represent lengths of the targets. + +*@par Outputs: +*@li neg_log_likelihood: A loss value which is differentiable with respect to each input node. +*@li log_alpha: The probability of possible trace of input to target. + +*@par Attributes: +*@li blank : Blank label. Default 0. +*@li reduction: Specifies the reduction to apply to the output. Default: 'mean'. +*@li zero_infinity : Whether to zero infinite losses and the associated gradients. + +*@par Third-party framework compatibility +* Compatible with Pytorch CTCLoss operator. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(CTCLossV2) + .INPUT(log_probs, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(targets, TensorType({DT_INT32, DT_INT64})) + .INPUT(input_lengths, TensorType({DT_INT32, DT_INT64})) + .INPUT(target_lengths, TensorType({DT_INT32, DT_INT64})) + .OUTPUT(neg_log_likelihood, TensorType({DT_FLOAT, DT_DOUBLE})) + .OUTPUT(log_alpha, TensorType({DT_FLOAT, DT_DOUBLE})) + .ATTR(blank, Int, 0) + .ATTR(reduction, String, "mean") + .ATTR(zero_infinity, Bool, false) + .OP_END_FACTORY_REG(CTCLossV2) + +/** +*@brief The Connectionist Temporal Classification loss grad. + +*@par Inputs: +*@li grad_out: Gradient renewal coefficient. Tensor of size (N), where N = batch size. +*@li log_probs: Tensor of size (T, N, C), where T =input length, N =batch size, + and C = number of classes (including blank). + It represent the logarithmized probabilities of the outputs. +*@li targets: Tensor of size (N, S), where S= max target length. + It represent the target sequences. +*@li input_lengths: Tuple or tensor of size (N). It represent the lengths of the inputs. +*@li target_lengths: Tuple or tensor of size (N). It represent lengths of the targets. +*@li neg_log_likelihood: A loss value which is differentiable with respect to each input node. +*@li log_alpha: The probability of possible trace of input to target. + +*@par Outputs: +*@li grad: Tensor of size (T, N, C), The grad of Connectionist Temporal Classification loss. + +*@par Attributes: +*@li blank : Blank label. Default 0. +*@li reduction: Specifies the reduction to apply to the output. Default: 'mean'. +*@li zero_infinity : Whether to zero infinite losses and the associated gradients. + +*@par Third-party framework compatibility +* Compatible with Pytorch CTCLoss operator. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(CTCLossV2Grad) + .INPUT(grad_out, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(log_probs, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(targets, TensorType({DT_INT32, DT_INT64})) + .INPUT(input_lengths, TensorType({DT_INT32, DT_INT64})) + .INPUT(target_lengths, TensorType({DT_INT32, DT_INT64})) + .INPUT(neg_log_likelihood, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(log_alpha, TensorType({DT_FLOAT, DT_DOUBLE})) + .OUTPUT(grad, TensorType({DT_FLOAT, DT_DOUBLE})) + .ATTR(blank, Int, 0) + .ATTR(reduction, String, "mean") + .ATTR(zero_infinity, Bool, false) + .OP_END_FACTORY_REG(CTCLossV2Grad) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_CTC_OPS_H_ \ No newline at end of file diff --git a/third_party/fwkacllib/inc/ops/data_flow_ops.h b/third_party/fwkacllib/inc/ops/data_flow_ops.h index bb937a75..6021f4e3 100644 --- a/third_party/fwkacllib/inc/ops/data_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/data_flow_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -908,7 +908,7 @@ REG_OP(TensorArray) .OUTPUT(handle, TensorType({DT_RESOURCE})) .OUTPUT(flow, TensorType({DT_FLOAT})) .REQUIRED_ATTR(dtype, Type) - .ATTR(element_shape, ListInt, ge::UNKNOWN_SHAPE) + .ATTR(element_shape, ListInt, ge::UNKNOWN_RANK) .ATTR(dynamic_size, Bool, false) .ATTR(clear_after_read, Bool, true) .ATTR(identical_element_shapes, Bool, false) @@ -963,7 +963,7 @@ REG_OP(TensorArrayConcat) DT_QUINT8, DT_QINT32})) .OUTPUT(lengths, TensorType({DT_INT64})) .REQUIRED_ATTR(dtype, Type) - .ATTR(element_shape_except0, ListInt, ge::UNKNOWN_SHAPE) + .ATTR(element_shape_except0, ListInt, ge::UNKNOWN_RANK) .OP_END_FACTORY_REG(TensorArrayConcat) /** @@ -999,7 +999,7 @@ REG_OP(TensorArrayGather) DT_STRING, DT_COMPLEX64, DT_COMPLEX128, DT_QINT8, DT_QUINT8, DT_QINT32})) .REQUIRED_ATTR(dtype, Type) - .ATTR(element_shape, ListInt, ge::UNKNOWN_SHAPE) + .ATTR(element_shape, ListInt, ge::UNKNOWN_RANK) .OP_END_FACTORY_REG(TensorArrayGather) /** @@ -1430,6 +1430,24 @@ REG_OP(OrderedMapClear) .ATTR(shared_name, String, "") .OP_END_FACTORY_REG(OrderedMapClear) +/** +*@brief FakeQueue, support tf api FixedLengthRecordReader. \n + +*@par Inputs: +*Including: +* @li resource: A Tensor of type DT_RESOURCE. + +*@par Outputs: +*handle: A Tensor of type DT_STRING ref. \n + +*@par Third-party framework compatibility +*Compatible with the TensorFlow operator FakeQueue. +*/ +REG_OP(FakeQueue) + .INPUT(resource, TensorType({DT_RESOURCE})) + .OUTPUT(handle, TensorType({DT_STRING})) + .OP_END_FACTORY_REG(FakeQueue) + /** *@brief Returns the number of incomplete elements in the underlying container. \n @@ -2258,6 +2276,7 @@ REG_OP(LruCache) .ATTR(shared_name, String, "LruCache") .ATTR(cache_size, Int, 100000) .ATTR(load_factor, Float, 1) + .REQUIRED_ATTR(dtype, Type) .OP_END_FACTORY_REG(LruCache) /** @@ -2277,9 +2296,9 @@ REG_OP(CacheAdd) .INPUT(cache, TensorType({DT_RESOURCE})) .INPUT(ids, TensorType({DT_INT64, DT_INT32, DT_UINT64, DT_UINT32})) .OUTPUT(swap_in_id, TensorType({DT_INT64, DT_INT32, DT_UINT64, DT_UINT32})) - .OUTPUT(swap_in_idx, TensorType({DT_INT64})) + .OUTPUT(swap_in_idx, TensorType({DT_INT64, DT_INT32, DT_UINT64, DT_UINT32})) .OUTPUT(swap_out_id, TensorType({DT_INT64, DT_INT32, DT_UINT64, DT_UINT32})) - .OUTPUT(swap_out_idx, TensorType({DT_INT64})) + .OUTPUT(swap_out_idx, TensorType({DT_INT64, DT_INT32, DT_UINT64, DT_UINT32})) .OP_END_FACTORY_REG(CacheAdd) /** @@ -2295,9 +2314,65 @@ REG_OP(CacheAdd) REG_OP(CacheRemoteIndexToLocal) .INPUT(cache, TensorType({DT_RESOURCE})) .INPUT(ids, TensorType({DT_INT64, DT_INT32, DT_UINT64, DT_UINT32})) - .OUTPUT(local_idx, TensorType({DT_INT64})) + .OUTPUT(local_idx, TensorType({DT_INT64, DT_INT32, DT_UINT64, DT_UINT32})) .OP_END_FACTORY_REG(CacheRemoteIndexToLocal) +/** +*@brief CacheAllToLocalIndex, get id in cache +*@par Inputs: +*cache: resource data +*local_idx: id in cache. +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(CacheAllIndexToLocal) + .INPUT(cache, TensorType({DT_RESOURCE})) + .OUTPUT(local_idx, TensorType({DT_INT64, DT_INT32, DT_UINT64, DT_UINT32})) + .REQUIRED_ATTR(dtype, Type) + .OP_END_FACTORY_REG(CacheAllIndexToLocal) + +/** +*@brief DynamicGetNext, dynamic get next data +*@par Inputs: +*x: the iterator, all types are available +*@par Outputs: +*y: the date in iterator, all types are available +*@par Attributes: +*output_types: types of all outputs +*output_shapes: shapes of all outputs +*_dynamic_graph_execute_mode: dynamic graph execution mode, +value is one of lazy_recompile and dynamic_execute +*_getnext_inputs_shape_range: shape ranges of outputs, +it works where _dynamic_graph_execute_mode is dynamic_execute +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(DynamicGetNext) + .INPUT(x, TensorType::ALL()) + .DYNAMIC_OUTPUT(y, TensorType::ALL()) + .ATTR(output_types, ListType, {}) + .ATTR(output_shapes, ListListInt, {{}, {}}) + .ATTR(_dynamic_graph_execute_mode, String, "lazy_recompile") + .ATTR(_getnext_inputs_shape_range, String, "") + .OP_END_FACTORY_REG(DynamicGetNext) + +/** +*@brief AdpGetNext +*@par Outputs: +*y: the data in iterator, all types are available +*@par Attributes: +*output_types: types of all outputs +*output_shapes: shapes of all outputs +*queue_name: cdqm queue name +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(AdpGetNext) + .DYNAMIC_OUTPUT(y, TensorType::ALL()) + .ATTR(output_types, ListType, {}) + .ATTR(output_shapes, ListListInt, {{}, {}}) + .ATTR(queue_name, String, "") + .OP_END_FACTORY_REG(AdpGetNext) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_DATA_FLOW_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index c64bc138..f61e2939 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. @@ -28,10 +28,13 @@ namespace ge { *@par Inputs: *Dynamic inputs, including: -* @li x: A list of Tensor objects, each with same shape and type. The supported types are: +*x: A list of Tensor objects, each with same shape and type. The supported types are: * float16, float32, double, int32, uint8, int16, int8, complex64, int64, * qint8, quint8, qint32, uint16, complex128, uint32, uint64. It's a dynamic input. \n +*@par Attributes: +*N: An required attribute of type int32, means nums of inputs. \n + *@par Outputs: *y: A Tensor. Has the same shape and type as the elements of "x". \n @@ -122,7 +125,8 @@ REG_OP(MinimumGrad) *@par Inputs: *One input: *x:A Tensor. Must be one of the following types: bool, float16, float, int8, int32, uint32, uint8, - int64, uint64, int16, uint16, double, complex64, complex128, qint8, quint8, qint16, quint16, qint32. \n + int64, uint64, int16, uint16, double, complex64, complex128, qint8, quint8, qint16, quint16, qint32. + For float32 type, the actual calculation on the chip is based on float16. \n *@par Attributes: *dst_type: An required attribute of type int32, specifying the dst data type. \n @@ -142,6 +146,8 @@ REG_OP(Cast) /** *@brief Returns the truth value of (x1 >= x2) element-wise. \n +*when input is int32 and (x2 - x1) > 2**31 or < -2**31 +*aicore accuracy is not guaranteed \n *@par Inputs: *Two inputs, including: @@ -163,6 +169,8 @@ REG_OP(GreaterEqual) /** *@brief Returns the truth value of (x1 < x2) element-wise. \n +*when input is int32 and (x2 - x1) > 2**31 or < -2**31 +*aicore accuracy is not guaranteed \n *@par Inputs: *Two inputs, including: @@ -322,8 +330,8 @@ REG_OP(Sub) *@brief computes the absolute value of a tensor. \n *@par Inputs: -*One inputs, including: -* @li x: A Tensor. Must be one of the following types: float16, float32, double, int32, int64. \n +*One input, including: \n +*x: A Tensor. Must be one of the following types: float16, float32, double, int32, int64. \n *@par Outputs: *y: A Tensor. Has the same type as "x". \n @@ -563,6 +571,8 @@ REG_OP(InvGrad) /** *@brief: Returns the truth value of (x <= y) element-wise. \n +*when input is int32 and (x2 - x1) > 2**31 or < -2**31 +*aicore accuracy is not guaranteed \n *@par Inputs: * Two inputs, including: @@ -611,6 +621,15 @@ REG_OP(Log1p) *@par Outputs: *y: A Tensor. Has the same type as "x1". + +*@attention Constraints: +*@li x2: The input data does not support 0 +*@li When NUM exceeds 2048 , the accuracy of operator cannot guarantee the +*requirement of double thousandths in the mini form +*@li Due to different architectures, the calculation results of this operator +*on NPU and CPU may be inconsistent +*@li If shape is expressed as (D1,D2... ,Dn), then D1*D2... *DN<=1000000,n<=8 + *@par Third-party framework compatibility *Compatible with the TensorFlow operator Mod. */ @@ -1020,7 +1039,7 @@ REG_OP(BesselI1e) * y = log_base(shift + scale * x), with "base" > 0. \n * @par Inputs: -* @li x: A Tensor of type complex64, complex128, float16, float32 or double. \n +* x: A Tensor of type complex64, complex128, float16, float32 or double. \n * @par Attributes: * @li base: An optional float32, specifying the base "e". Defaults to "-1.0" @@ -1065,7 +1084,7 @@ REG_OP(Log) * uint8, int8, uint16, int16, int32, int64, complex64, complex128. \n * @attention Constraints: -* @li "x1" and "x2" have incompatible shapes or types. \n +* "x1" and "x2" have incompatible shapes or types. \n * @par Third-party framework compatibility * Compatible with the TensorFlow operator Multiply. @@ -1451,6 +1470,8 @@ REG_OP(ReciprocalGrad) /** *@brief Returns the truth value of (x1 > x2) element-wise. \n +*when input is int32 and (x2 - x1) > 2**31 or < -2**31 +*aicore accuracy is not guaranteed \n *@par Inputs: *@li x1: A Tensor of type float16, float32, double, int64, int32, int16, int8, @@ -2042,6 +2063,15 @@ REG_OP(FloorDiv) * *@par Outputs: *y: Result remainder. + +*@attention Constraints: +*@li x2: The input data does not support 0 +*@li When NUM exceeds 2048 , the accuracy of operator cannot guarantee the +*requirement of double thousandths in the mini form +*@li Due to different architectures, the calculation results of this operator +*on NPU and CPU may be inconsistent +*@li If shape is expressed as (D1,D2... ,Dn), then D1*D2... *DN<=1000000,n<=8 + *@par Third-party framework compatibility * Compatible with the TensorFlow operator FloorMod. */ @@ -2168,6 +2198,14 @@ REG_OP(Tan) *@par Outputs: *y: A Tensor. Has the same type as "x1". \n +*@attention Constraints: +*@li x2: The input data does not support 0 +*@li When NUM exceeds 2048 , the accuracy of operator cannot guarantee the +*requirement of double thousandths in the mini form +*@li Due to different architectures, the calculation results of this operator +*on NPU and CPU may be inconsistent +*@li If shape is expressed as (D1,D2... ,Dn), then D1*D2... *DN<=1000000,n<=8 + *@par Third-party framework compatibility *@li Compatible with the TensorFlow operator TruncateMod. */ @@ -2424,6 +2462,25 @@ REG_OP(Eltwise) .ATTR(coeff, ListFloat, {}) .OP_END_FACTORY_REG(Eltwise) +/** + *@brief Computes the inverse error function of each element of input. \n + + *@par Inputs: + *One inputs, including: + * @li input_x: A tensor. Must be one of the following types: + * float16, float32. \n + + *@par Outputs: + *y: A Tensor with the same type and shape of input_x's. \n + + *@par Third-party framework compatibility + *Compatible with the Pytorch operator Erfinv. \n + */ +REG_OP(Erfinv) + .INPUT(input_x, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(output_y, TensorType({DT_FLOAT, DT_FLOAT16})) + .OP_END_FACTORY_REG(Erfinv) + /** *@brief Computes element-wise population count. \n @@ -2829,9 +2886,9 @@ REG_OP(AdamApplyOneAssign) *Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(LambApplyOptimizerAssign) - .INPUT(input0, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(input1, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(input2, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(grad, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(inputv, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(inputm, TensorType({DT_FLOAT16,DT_FLOAT})) .INPUT(input3, TensorType({DT_FLOAT16,DT_FLOAT})) .INPUT(mul0_x, TensorType({DT_FLOAT16,DT_FLOAT})) .INPUT(mul1_x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -2842,6 +2899,8 @@ REG_OP(LambApplyOptimizerAssign) .INPUT(do_use_weight, TensorType({DT_FLOAT16,DT_FLOAT})) .INPUT(weight_decay_rate, TensorType({DT_FLOAT16,DT_FLOAT})) .OUTPUT(output0, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(inputv, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(inputm, TensorType({DT_FLOAT16,DT_FLOAT})) .OP_END_FACTORY_REG(LambApplyOptimizerAssign) /** @@ -2873,7 +2932,8 @@ REG_OP(LambApplyWeightAssign) .INPUT(input1, TensorType({DT_FLOAT16,DT_FLOAT})) .INPUT(input2, TensorType({DT_FLOAT16,DT_FLOAT})) .INPUT(input3, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(input4, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(input_param, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(input_param, TensorType({DT_FLOAT16,DT_FLOAT})) .OP_END_FACTORY_REG(LambApplyWeightAssign) /** @@ -3183,12 +3243,14 @@ REG_OP(Fills) *@brief Add tensor with scale. \n *@par Inputs: -*Five inputs, including: -* @li x1: A Tensor. Must be one of the following types:int32,int16, float16, float32. -* @li x2: A scale. Must be float. \n +*One input, including: \n +*x: A Tensor. Must be one of the following types:int32,int16, float16, float32. \n + +*@par Attributes: +*value: A scale. Must be float. \n *@par Outputs: -*@li y: A Tensor. Has the same type and shape as "x1". \n +*y: A Tensor. Has the same type and shape as "x1". \n *@par Third-party framework compatibility: * Compatible with the Pytorch operator adds. @@ -3329,8 +3391,441 @@ REG_OP(TensorRedirect) .OUTPUT(output_x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8, DT_INT64, DT_INT16, DT_UINT16, DT_UINT64, DT_UINT32})) .OP_END_FACTORY_REG(TensorRedirect) -} // namespace ge +/** +* @brief Performs the element-wise division of tensor x2 by tensor x3, +* multiply the result by the scalar value and add it to tensor x1 + +* @par Inputs: +* Three inputs, including: +* @li input_data: A mutable input Tensor. Must be one of the following types: +* float16, float32. +* @li x1: A mutable input Tensor of the same type as x1. +* @li x2: A mutable input Tensor of the same type as x1. +* @li value: A mutable input Tensor. Must be one of the following types: +* float16, float32, int32. \n + +* @par Outputs: +* @li y: A mutable Tensor. Has the same type as "x1". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Addcdiv. +*/ +REG_OP(Addcdiv) + .INPUT(input_data, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(value, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(Addcdiv) + +/** +* @brief Performs the element-wise multiplication of tensor x2 by tensor x3, +* multiply the result by the scalar value and add it to tensor input_data + + +* @par Inputs: +* Three inputs, including: +* @li input_data: A mutable input Tensor. Must be one of the following types: +* float16, float32, int8, int32, uint8. +* @li x1: A mutable input Tensor of the same type as x1. +* @li x2: A mutable input Tensor of the same type as x1. +* @li value: A tensor which includes only one element of the same type as x1. \n + +* @par Outputs: +* @li y: A mutable output Tensor. Has the same type as "x1". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Addcmul. +*/ +REG_OP(Addcmul) + .INPUT(input_data, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8 })) + .INPUT(x1, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8 })) + .INPUT(x2, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8 })) + .INPUT(value, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8 })) + .OUTPUT(y, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8 })) + .OP_END_FACTORY_REG(Addcmul) +/** +* @brief Computes the result of x2 * alpha + x1. + +* @par Inputs: +* @li x1: An ND tensor of type float16, float32, int32. +* @li x2: An ND tensor of type float16, float32, int32. +* @li alpha: A scalar tensor of type float16, float32. \n + +* @par Outputs: +* @li y: An ND tensor tensor with the same shape and type as "x1". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Axpy. +*/ +REG_OP(AxpyV2) + .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .INPUT(alpha, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OP_END_FACTORY_REG(AxpyV2) + +/** +* @brief Computes the result of x1 - x2. + +* @par Inputs: +* @li x1: An ND tensor of type float16, float, int32. +* @li x2: An ND tensor of type float16, float, int32. \n + +* @par Outputs: +* @li y: An ND tensor tensor with the same type as "x1". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Sub. +*/ +REG_OP(PtSub) + .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OP_END_FACTORY_REG(PtSub) + +/** +* @brief Add the partial values of two tensors in format NC1HWC0. + +* @par Inputs: +* @li x1: A Tensor in 5HD, and must be one of the following types: float16, +* float32. \n +* @li x2: A Tensor of the same type as "x1", and the same shape as "x1", +* except for the C1 value. \n + +* @par Attributes: +* @li x1_c1_offset: A required int. Offset value of C1 in "x1". \n +* @li x2_c1_offset: A required int. Offset value of C1 in "x2". \n +* @li c1_len: A required int. C1 len of "y". The value must be less than +* the difference between C1 and offset in "x1" and "x2". \n + +* @par Outputs: +* @li y: A Tensor of the same type as "x1", and the same shape as "x1", +* except for the C1 value. Record the result after adding. \n +*/ +REG_OP(StrideAdd) + .INPUT(x1, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(x2, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .OUTPUT(y, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .REQUIRED_ATTR(x1_c1_offset, Int) + .REQUIRED_ATTR(x2_c1_offset, Int) + .REQUIRED_ATTR(c1_len, Int) + .OP_END_FACTORY_REG(StrideAdd) + +/** +* @brief Compare two tensors are totally equal or not, only output a bool value" + +* @par Inputs: +* Two inputs, including: +* @li input_x: A Tensor. the first tensor. \n +* @li input_y: A Tensor. the second tensor. \n + +* @par Outputs: +* @li output_z: A Tensor. Bool type, compare result of the two inputs. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch equal operator. \n +*/ +REG_OP(TensorEqual) + .INPUT(input_x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) + .INPUT(input_y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) + .OUTPUT(output_z, TensorType({DT_BOOL})) + .OP_END_FACTORY_REG(TensorEqual) + +/** + * @brief Element-wise min of each of the input tensors (with Numpy-style broadcasting support). + * All inputs and outputs must have the same data type. This operator supports multidirectional + * (i.e., Numpy-style) broadcasting + * + * @par inputs + * one input including: + * @li x: dynamic input A Tensor. Must be one of the following types: float32, float16, double, int32, int64 + * + * @par output + * one output including: + * @li y:A Tensor of the same type as x + * + */ +REG_OP(MaxN) + .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_FLOAT64, DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_FLOAT64, DT_INT32, DT_INT64})) + .OP_END_FACTORY_REG(MaxN) + + +/** + * @brief Calculates x * maske * value. + * + * @par Inputs: + * @li x: An tensor of type float16 or float32, specifying the input to the data layer. + * @li mask: An tensor of type int8 or float16 or float32, be same shape with x. \n + * + * @par Attributes: + * value: A optional float. \n + * + * @par Outputs: + * y: The output tensor of type float16 or float32. + @ li y:A Tensor of the same type and shape as x + * + */ +REG_OP(MaskedScale) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT32})) + .INPUT(mask, TensorType({DT_INT8, DT_FLOAT16, DT_FLOAT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT32})) + .REQUIRED_ATTR(value, Float) + .OP_END_FACTORY_REG(MaskedScale) + +/** + * @brief Calculate the lerp function. \n + + * @par Inputs: + * Three inputs, including: + * @li start: A tensor. Must be one of the following types: + * float16, float32. \n + * @li end: A tensor. Must be one of the following types: + * float16, float32. \n + * @li weight: A tensor. Must be one of the following types: + * float16, float32. \n + + * @par Outputs: + * y: A Tensor with the same type and shape of input_x's. \n + + * @par Third-party framework compatibility + * Compatible with the Pytorch operator Lerp. \n + */ +REG_OP(Lerp) + .INPUT(start, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(end, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(weight, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(Lerp) + +/** +*@brief Returns the num value of abs(x1-x2) > atol+rtol*abs(x2) element-wise. \n + +* +*@par Inputs: +*@li x1: A tensor. Must be one of the following types: float32, int32, uint8, int8, float16 +*@li x2: A tensor of the same type as "x1". +* +*@par Attributes: +* atol: Defaults to "1e-05". +* rtol: Defaults to "1e-03". +* +*@par Outputs: +* num: A tensor of type float32. +* +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* +*/ +REG_OP(DataCompare) + .INPUT(x1, TensorType({ DT_FLOAT16, DT_FLOAT,DT_INT8, DT_UINT8, DT_INT32 })) + .INPUT(x2, TensorType({ DT_FLOAT16, DT_FLOAT,DT_INT8, DT_UINT8, DT_INT32 })) + .OUTPUT(num, TensorType({DT_FLOAT})) + .ATTR(atol, Float, 1e-5) + .ATTR(rtol, Float, 1e-3) + .OP_END_FACTORY_REG(DataCompare) + +/** +*@brief Hardmax(element in input, axis) = 1 if the element is the first maximum value along the specified axis, 0 +*otherwise The input does not need to explicitly be a 2D vector.The "axis" attribute indicates the dimension along +*which Hardmax will be performed.The output tensor has the same shape and contains the Hardmax values of the +*corresponding input. +* +*@par inputs +*one input including: +*@li x: input A Tensor.Must be one of the following types:float32,float16 +* +*@par Attributes: +*@li axis:A required int attribute that decides which dimension will be used to cal the hard_max +* +*@par output: +*one output including: +*@li y:A Tensor of the same type as x +* +*/ +REG_OP(HardMax) + .INPUT(x, TensorType({ DT_FLOAT16, DT_FLOAT })) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(axis, Int, -1) + .OP_END_FACTORY_REG(HardMax) + +/** +* @brief Computes the dot product (inner product) of two tensors. This function does not broadcast. + +* @par Inputs: +* Two inputs, including: +* @li input_x: A Tensor. the first tensor must be 1d. \n +* @li input_y: A Tensor. the second tensor must be 1d. \n + +* @par Outputs: +* @li output: A Tensor. Result of the two inputs, must be 1d. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch dot operator. \n +*/ +REG_OP(Dot) + .INPUT(input_x, TensorType({DT_FLOAT, DT_FLOAT16, DT_UINT8, DT_INT8, DT_INT32})) + .INPUT(input_y, TensorType({DT_FLOAT, DT_FLOAT16, DT_UINT8, DT_INT8, DT_INT32})) + .OUTPUT(output, TensorType({DT_FLOAT, DT_FLOAT16, DT_UINT8, DT_INT8, DT_INT32})) + .OP_END_FACTORY_REG(Dot) + +/** +*@brief Returns a new tensor with boolean elements representing \n +*if each element of input is “close” to the corresponding element of other \n + +*@par Inputs: +*Two inputs, including: +* @li x1: A tensor. Must be one of the following types: +* float16, float32, int32. \n +* @li x2: A tensor with the same type and shape of x1's. \n + +*@par Attributes: +*@li rtol: An optional float.Defaults to 1e-05. \n +*@li atol: An optional float.Defaults to 1e-08. \n +*@li equal_nan: An optional bool.Defaults to false. \n + +*@par Outputs: +*y: A Tensor bool with the same shape of x1's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator isclose. \n +*/ +REG_OP(IsClose) + .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OUTPUT(y, TensorType({DT_BOOL})) + .ATTR(rtol, Float, 1e-05) + .ATTR(atol, Float, 1e-08) + .ATTR(equal_nan, Bool, false) + .OP_END_FACTORY_REG(IsClose) + +/** +* @brief Returns the reverse tensor of the ArgMax operator of a tensor. \n + +* @par Inputs: +* three input, including: +* var: A Tensor of type float16, float32, int32 or int8. \n +* indices: A Tensor of type int32. \n +* updates: A Tensor of type float16, float32, int32 or int8. \n + +* @par Attributes: +* @li dimension: An integer of type int, specifying the axis information of the index with the maximum value.\n + +* @par Outputs: +* y: A Tensor of type float16, float32, int32 or int8. \n +* +*@attention Constraints: +*@li indices: only support int32,and shape same to "updates" +*@li The value range of "dimension" is [-dims, dims - 1]. "dims" is the dimension length of "x". +*@li y:A Tensor, the type and shape is same to "var" \n + +*@par Third-party framework compatibility +* not support all scene like pytorch operator scatter +* exp: +* var.shape=[2,3,4,5], dim=2, the shape of indices and updates should be [2,3,5] +* not support the shape of indices and updates is [2,3,2,5] like pytorch operator scatter. \n +*/ +REG_OP(ArgMaxGrad) + .INPUT(var, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) + .INPUT(indices, TensorType({DT_INT32})) + .INPUT(updates, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) + .REQUIRED_ATTR(dimension, Int) + .OP_END_FACTORY_REG(ArgMaxGrad) + +/** +* @brief Returns the reverse tensor of the ArgMax operator of a tensor. \n + +* @par Inputs: +* three input, including: +* var: A Tensor of type float16, float32, int32 or int8. \n +* indices: A Tensor of type int32. \n +* updates: A Tensor of type float16, float32, int32 or int8. \n +* assist: A Tensor of int32,also a assist matrix and it's shape must match the shape of var \n + +* @par Attributes: +* @li dimension: An integer of type int, specifying the axis information of the index with the maximum value.\n + +* @par Outputs: +* y: A Tensor of type float16, float32, int32 or int8. \n + +*@attention Constraints: +*@li indices: only support int32,and shape same to "updates" +*@li The value range of "dimension" is [-dims, dims - 1]. "dims" is the dimension length of "x". +*@li y:A Tensor, the type and shape is same to "var" \n + +*@par Third-party framework compatibility +* not support all scene like pytorch operator scatter +* exp: +* var.shape=[2,3,4,5], dim=2, the shape of indices and updates should be [2,3,5] +* not support the shape of indices and updates is [2,3,2,5] like pytorch operator scatter. \n +*/ +REG_OP(ArgMaxGradD) + .INPUT(var, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) + .INPUT(indices, TensorType({DT_INT32})) + .INPUT(updates, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) + .INPUT(assist, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) + .REQUIRED_ATTR(dimension, Int) + .OP_END_FACTORY_REG(ArgMaxGradD) + +/** +*@brief Calculates the reversed outputs of the function "AddMatMatElements" +* c = c * beta + alpha * a * b + +*@par Inputs: +*Three inputs, including: +* @li c: A mutable Tensor. Must be one of the following types: +* float16, float32. +* @li a: A mutable Tensor of the same type as "c". +* @li b: A mutable Tensor of the same type as "c". +* @li beta: A mutable scalar of the same type as "c". +* @li alpha: A mutable scalar of the same type as "c". \n + +*@par Outputs: +* @li c: A mutable Tensor. Has the same type as "c". \n + +*@par Third-party framework compatibility +* Compatible with the TensorFlow operator AddMatMatElements. +*/ +REG_OP(AddMatMatElements) + .INPUT(c, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(a, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(b, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(beta, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(alpha, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(c, TensorType({DT_FLOAT, DT_FLOAT16})) + .OP_END_FACTORY_REG(AddMatMatElements) + +/** +*@brief Returns cosine similarity between x1 and x2,computed along dim. \n + +*@par Inputs: +*Two inputs, including: +* @li input_x1: A tensor. Must be the following types: +* float32. \n + +*@par Inputs: +*@li input_x2: A tensor. Must of the following types: +* float32. \n + +*@par Outputs: +*@li output_y: A Tensor with the same type of input_x's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator CosineSimilarity. \n +*/ +REG_OP(CosineSimilarity) + .INPUT(input_x1, TensorType({DT_FLOAT})) /* "First operand." */ + .INPUT(input_x2, TensorType({DT_FLOAT})) /* "Second operand." */ + .OUTPUT(output_y, TensorType({DT_FLOAT})) /* "Result, has same element type as two inputs" */ + .ATTR(dim, Int, 1) + .ATTR(eps, Float, 1e-8) + .OP_END_FACTORY_REG(CosineSimilarity) + +} // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_ELEWISE_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/functional_ops.h b/third_party/fwkacllib/inc/ops/functional_ops.h index 598d3ad3..b09ac058 100644 --- a/third_party/fwkacllib/inc/ops/functional_ops.h +++ b/third_party/fwkacllib/inc/ops/functional_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/get_data_ops.h b/third_party/fwkacllib/inc/ops/get_data_ops.h index 33dc4f14..e5518ef8 100644 --- a/third_party/fwkacllib/inc/ops/get_data_ops.h +++ b/third_party/fwkacllib/inc/ops/get_data_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/globalavgpool.h b/third_party/fwkacllib/inc/ops/globalavgpool.h new file mode 100644 index 00000000..06f03d30 --- /dev/null +++ b/third_party/fwkacllib/inc/ops/globalavgpool.h @@ -0,0 +1,49 @@ +/** + * Copyright 2019 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. + */ + +/*! + * \file globalavgpool.h + * \brief + */ +#ifndef OPS_BUILT_IN_OP_PROTO_INC_GLOBALAVERAGEPOOL_H_ +#define OPS_BUILT_IN_OP_PROTO_INC_GLOBALAVERAGEPOOL_H_ + +#include "graph/operator_reg.h" + +namespace ge { +/** +*@brief GlobalAveragePool consumes an input tensor X and applies average pooling across the values in the same channel. +This is equivalent to AveragePool with kernel size equal to the spatial dimension of input tensor \n + +*@par Inputs: +*@li x: Input data tensor from the previous operator; dimensions for image case are (N x C x H x W), +where N is the batch size, C is the number of channels, and H and W are the height and the width of the data. +For non image case, the dimensions are in the form of (N x C x D1 x D2 ... Dn), where N is the batch size. + +*@par Outputs: +*y: Output data tensor from pooling across the input tensor. The output tensor has the same rank as the input. +The first two dimensions of output shape are the same as the input (N x C), while the other dimensions are all 1 + +*@par Restrictions: +*Warning: This operator can be integrated only by configuring INSERT_OP_FILE of aclgrphBuildModel. Please do not use it directly. +*/ +REG_OP(GlobalAveragePool) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OP_END_FACTORY_REG(GlobalAveragePool) +} // namespace ge + +#endif // OPS_BUILT_IN_OP_PROTO_INC_GLOBALAVGPOOL_H_ \ No newline at end of file diff --git a/third_party/fwkacllib/inc/ops/hcom_ops.h b/third_party/fwkacllib/inc/ops/hcom_ops.h index b90b225e..497f6a68 100644 --- a/third_party/fwkacllib/inc/ops/hcom_ops.h +++ b/third_party/fwkacllib/inc/ops/hcom_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. @@ -45,8 +45,6 @@ REG_OP(HcomAllGather) .OUTPUT(y, TensorType({DT_FLOAT, DT_INT32, DT_INT8, DT_INT16, DT_FLOAT16, DT_INT64, DT_UINT64})) .REQUIRED_ATTR(rank_size, Int) .REQUIRED_ATTR(group, String) - .ATTR(alpha, Float, 1.0) - .ATTR(beta, Float, 0.0) .OP_END_FACTORY_REG(HcomAllGather) /** @@ -77,8 +75,6 @@ REG_OP(HcomAllReduce) .REQUIRED_ATTR(group, String) .ATTR(fusion, Int, 1) .ATTR(fusion_id, Int, -1) - .ATTR(alpha, Float, 1.0) - .ATTR(beta, Float, 0.0) .OP_END_FACTORY_REG(HcomAllReduce) /** @@ -91,7 +87,7 @@ REG_OP(HcomAllReduce) input of this rank will be broadcast to other ranks. * @li fusion: A required integer identifying if the op need to fusion,the default value is none fusion - * @li fusion: A required integer identifying the fusion id if para fusion + * @li fusion_id: A required integer identifying the fusion id if para fusion is set. * @li group: A required string identifying the group name of ranks participating in the op. @@ -109,10 +105,39 @@ REG_OP(HcomBroadcast) .REQUIRED_ATTR(group, String) .ATTR(fusion, Int, 0) .ATTR(fusion_id, Int, -1) - .ATTR(alpha, Float, 1.0) - .ATTR(beta, Float, 0.0) .OP_END_FACTORY_REG(HcomBroadcast) +/** + * @brief preforms reduction from others rank to rootrank + * @par Inputs: +* @li root_rank: A required integer identifying the root rank in the op + the reduction result will be on this root rank + * x: A tensor. Must be one of the following types: int8, int16, int32, float16, + float32. + * @par Attributes: + * @li reduction: A required string identifying the reduction operation to + perform.The supported operation are: "sum", "max", "min", "prod". + * @li group: A required string identifying the group name of ranks + participating in the op. + * @li fusion: An optional integer identifying the fusion flag of the op. + 0: no fusion; 1 (default): fusion; 2: fusion the ops by fusion id. + * @li fusion_id: An optional integer identifying the fusion id of the op. + * The HcomReduce ops with the same fusion id will be fused. + * @par Outputs: + * y: A Tensor. Has the same type as "x". + * @attention Constraints: + *"group" is limited to 128 characters. Use "hccl_world_group" + as the name of a world group. + */ +REG_OP(HcomReduce) + .INPUT(x, TensorType({DT_FLOAT, DT_INT32, DT_INT8, DT_INT16, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_INT32, DT_INT8, DT_INT16, DT_FLOAT16})) + .REQUIRED_ATTR(root_rank, Int) + .REQUIRED_ATTR(reduction, String) + .REQUIRED_ATTR(group, String) + .ATTR(fusion, Int, 0) + .ATTR(fusion_id, Int, -1) + .OP_END_FACTORY_REG(HcomReduce) /** * @brief Performs reduction across all input tensors, scattering in equal blocks among ranks, each rank getting a chunk of data based on its rank @@ -139,8 +164,6 @@ REG_OP(HcomReduceScatter) .REQUIRED_ATTR(reduction, String) .REQUIRED_ATTR(group, String) .REQUIRED_ATTR(rank_size, Int) - .ATTR(alpha, Float, 1.0) - .ATTR(beta, Float, 0.0) .OP_END_FACTORY_REG(HcomReduceScatter) /** @@ -167,8 +190,6 @@ REG_OP(HcomSend) .REQUIRED_ATTR(group, String) .REQUIRED_ATTR(sr_tag, Int) .REQUIRED_ATTR(dest_rank, Int) - .ATTR(alpha, Float, 1.0) - .ATTR(beta, Float, 0.0) .OP_END_FACTORY_REG(HcomSend) /** @@ -202,8 +223,6 @@ REG_OP(HcomReceive) .REQUIRED_ATTR(src_rank, Int) .REQUIRED_ATTR(shape, ListInt) .REQUIRED_ATTR(dtype, Type) - .ATTR(alpha, Float, 1.0) - .ATTR(beta, Float, 0.0) .OP_END_FACTORY_REG(HcomReceive) /** @@ -219,6 +238,15 @@ REG_OP(HcomRemoteRead) .REQUIRED_ATTR(dtype, Type) .OP_END_FACTORY_REG(HcomRemoteRead) +/** + * @brief Performs Remote Ref Read of input tensors + * @par Inputs: + * remote: A tensor. describing the remote memory address to read: u64 remoteId, u64 addrRemote, u64 length + * cache_var: The local base address + * local_offset: Skip step length + * @par Outputs: + * cache_var: The local base address + */ REG_OP(HcomRemoteRefRead) .INPUT(remote, TensorType({DT_UINT64})) .INPUT(cache_var, TensorType({DT_UINT64})) @@ -239,11 +267,90 @@ REG_OP(HcomRemoteWrite) .INPUT(local, TensorType::ALL()) .OP_END_FACTORY_REG(HcomRemoteWrite) +/** + * @brief Performs Remote Write of input tensors + * @par Inputs: + * remote: A tensor. describing the remote memory address to write: u64 remoteId, u64 addrRemote, u64 length + * @par Inputs: + * local: A Tensor. whose value is length / size_of(Type) + */ REG_OP(HcomRemoteScatterWrite) .INPUT(remote, TensorType({DT_INT64, DT_UINT64})) .INPUT(local, TensorType::ALL()) .OPTIONAL_INPUT(local_offset, TensorType({DT_UINT64})) .OP_END_FACTORY_REG(HcomRemoteScatterWrite) +/** + * @brief All ranks send different amount of data to, and receive different + amount of data from, all ranks. + * @par Inputs: + * Five inputs, including: + * @li send_data: A tensor. the memory to send. + * @li send_counts: A list, where entry i specifies the number of elements in + send_data to send to rank i. + * @li send_displacements: A list, where entry i specifies the displacement + (offset from sendbuf) from which to send data to rank i. + * @li recv_counts: A list, where entry i specifies the number of + elements to receive from rank i. + * @li recv_displacements: A list, , where entry i specifies the displacement + (offset from recv_data) to which data from rank i should be written. + * @par Outputs: + * recv_data: A Tensor has same element type as send_data. + * @par Attributes: + * @li group: A string identifying the group name of ranks participating in + the op. +* @attention all ranks participating in the op should be full-mesh networking + using the RDMA. + */ +REG_OP(HcomAllToAllV) + .INPUT(send_data, TensorType({DT_FLOAT, DT_INT32, DT_INT8, DT_INT16, DT_FLOAT16, DT_INT64, DT_UINT64})) + .INPUT(send_counts, TensorType({DT_INT64})) + .INPUT(send_displacements, TensorType({DT_INT64})) + .INPUT(recv_counts, TensorType({DT_INT64})) + .INPUT(recv_displacements, TensorType({DT_INT64})) + .OUTPUT(recv_data, TensorType({DT_FLOAT, DT_INT32, DT_INT8, DT_INT16, DT_FLOAT16, DT_INT64, DT_UINT64})) + .REQUIRED_ATTR(group, String) + .OP_END_FACTORY_REG(HcomAllToAllV) + +/** + * @brief All ranks send different amount of data to, and receive different + amount of data from, all ranks. And concat all data descripting by addrinfo + togather into output gathered. + * @par Inputs: + * Four inputs, including: + * @li addrinfo: A tensor, descripting the memory info(address, length) to send. + * @li addrinfo_count_per_rank: A list, where entry i specifies the number of + elements in send_data to send to rank i. + * @li recv_counts: A list, where entry i specifies the number of + elements to receive from rank i. + * @li recv_displacements: A list, , where entry i specifies the displacement + (offset from recv_data) to which data from rank i should be written. + * @par Outputs: + * Two outputs, including: + * @li recv_data: A Tensor has same element type as dtype. + * @li gathered: A Tensor has same element type as dtype. + * @par Attributes: + * @li group: A string identifying the group name of ranks participating in + the op. + * @li dtype: Datatype of send buffer elements. + * @li addr_length: descripting the element memory length in the addrinfo. + -2: all element memory length in the addrinfo is the same, but it is unknown. + -1: all element memory length is unknown. + >0: all element memory length in the addrinfo is the same. the attr value is the memory length. + * @attention all ranks participating in the op should be full-mesh networking + using the RDMA. + */ +REG_OP(HcomGatherAllToAllV) + .INPUT(addrinfo, TensorType({DT_UINT64})) + .INPUT(addrinfo_count_per_rank, TensorType({DT_INT64})) + .INPUT(recv_counts, TensorType({DT_INT64})) + .INPUT(recv_displacements, TensorType({DT_INT64})) + .OUTPUT(recv_data, TensorType({DT_FLOAT, DT_INT32, DT_INT8, DT_INT16, DT_FLOAT16, DT_INT64, DT_UINT64})) + .OUTPUT(gathered, TensorType({DT_FLOAT, DT_INT32, DT_INT8, DT_INT16, DT_FLOAT16, DT_INT64, DT_UINT64})) + .REQUIRED_ATTR(group, String) + .REQUIRED_ATTR(dtype, Type) + .REQUIRED_ATTR(addr_length, Int) + .OP_END_FACTORY_REG(HcomGatherAllToAllV) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_HCOM_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/hvd_ops.h b/third_party/fwkacllib/inc/ops/hvd_ops.h index a49ec5ed..00299ef7 100644 --- a/third_party/fwkacllib/inc/ops/hvd_ops.h +++ b/third_party/fwkacllib/inc/ops/hvd_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/third_party/fwkacllib/inc/ops/image_ops.h b/third_party/fwkacllib/inc/ops/image_ops.h index ce3262f9..6909345a 100644 --- a/third_party/fwkacllib/inc/ops/image_ops.h +++ b/third_party/fwkacllib/inc/ops/image_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -24,6 +24,22 @@ #include "graph/operator_reg.h" namespace ge { +/** +*@brief Decode the frame(s) of a GIF-encoded image to a uint8 tensor . \n + +*@par Inputs: +*@li contents:A Tensor of type string. 0-D. The GIF-encoded image. \n + +*@par Outputs: +*image:A Tensor of type uint8. \n + +*@par Third-party framework compatibility +*Compatible with tensorflow DecodeGif operator. +*/ +REG_OP(DecodeGif) + .INPUT(contents, TensorType({DT_STRING})) + .OUTPUT(image, TensorType({DT_UINT8})) + .OP_END_FACTORY_REG(DecodeGif) /** *@brief Adjust the hue of one or more images . \n @@ -31,11 +47,12 @@ namespace ge { *@par Inputs: *Input images is a tensor of at least 3 dimensions. The last dimension is interpretted as channels, and must be three. Inputs include: -*@li images:A Tensor of type float. Images to adjust. At least 3-D. +*@li images:A Tensor of type float. Images to adjust. At least 3-D. The format +must be NHWC. *@li delta:A Tensor of type float. A float delta to add to the hue . \n *@par Outputs: -*y:A Tensor of type float . \n +*y:A Tensor of type float. The format must be NHWC. \n *@attention Constraints: *Input images is a tensor of at least 3 dimensions. The last dimension is @@ -57,11 +74,12 @@ REG_OP(AdjustHue) *@par Inputs: *Input images is a tensor of at least 3 dimensions. The last dimension is interpretted as channels, and must be three. Inputs include: -*@li images:A Tensor of type float. Images to adjust. At least 3-D. +*@li images:A Tensor of type float. Images to adjust. At least 3-D. The format +must be NHWC. *@li scale:A Tensor of type float. A float scale to add to the saturation . \n *@par Outputs: -*y:A Tensor of type float . \n +*y:A Tensor of type float. The format must be NHWC. \n *@attention Constraints: *Input images is a tensor of at least 3 dimensions. The last dimension is @@ -83,11 +101,12 @@ REG_OP(AdjustSaturation) *@par Inputs: *Input images is a tensor of at least 3 dimensions. The last 3 dimensions are interpreted as '[height, width, channels]'. Inputs include: -*@li images:A Tensor of type float. Images to adjust. At least 3-D. +*@li images:A Tensor of type float. Images to adjust. At least 3-D. The format +must be NHWC. *@li scale:A Tensor of type float. A float multiplier for adjusting contrast . \n *@par Outputs: -*y:A Tensor of type float . \n +*y:A Tensor of type float. The format must be NHWC. \n *@attention Constraints: *Input images is a tensor of at least 3 dimensions. The last dimension is @@ -112,7 +131,7 @@ nearest neighbor sampling to a common output size specified by crop_size . \n *Input images must be a 4-D tensor. Inputs include: *@li images:A Tensor. Must be one of the following types:uint8, uint16, int8, int16, int32, int64, float16, float, double. A 4-D tensor of shape -[batch, image_height, image_width, depth]. +[batch, image_height, image_width, depth]. The format must be NHWC. *@li boxes: A Tensor of type float. A 2-D tensor of shape [num_boxes, 4]. *@li box_index: A Tensor of type int32. A 1-D tensor of shape [num_boxes] with int32 values in [0, batch). @@ -127,7 +146,7 @@ extrapolation, when applicable. NearestNeighbor . \n *@par Outputs: -*y:A Tensor of type float . \n +*y:A Tensor of type float. The format must be NHWC. \n *@attention Constraints: *Input images must be a 4-D tensor . \n @@ -193,7 +212,9 @@ boxes tensor . \n *@par Inputs: *Input images and grads must be a 4-D tensor. Inputs include: *@li grads: A 4-D tensor of shape [num_boxes, crop_height, crop_width, depth]. +The format must be NHWC. *@li images: A 4-D tensor of shape [batch, image_height, image_width, depth]. +The format must be NHWC. Both image_height and image_width need to be positive. *@li boxes: A 2-D tensor of shape [num_boxes, 4]. The i-th row of the tensor specifies the coordinates of a box in the box_ind[i] image and is specified in @@ -233,6 +254,7 @@ images tensor . \n *@par Inputs: *Input grads must be a 4-D tensor. Inputs include: *@li grads: A 4-D tensor of shape [num_boxes, crop_height, crop_width, depth]. +The format must be NHWC. *@li boxes: A 2-D tensor of shape [num_boxes, 4]. The i-th row of the tensor specifies the coordinates of a box in the box_ind[i] image and is specified in normalized coordinates [y1, x1, y2, x2]. @@ -248,7 +270,8 @@ method: A string specifying the interpolation method. Only 'bilinear' is supported for now . \n *@par Outputs: -*y:A 4-D tensor of shape [batch, image_height, image_width, depth] . \n +*y:A 4-D tensor of shape [batch, image_height, image_width, depth]. The format +must be NHWC. \n *@attention Constraints: *Input grads must be a 4-D tensor . \n @@ -273,6 +296,7 @@ REG_OP(CropAndResizeGradImage) *@par Inputs: *Input x must be a 4-D tensor. Inputs include: *@li x: A 4-D float tensor of shape [batch_size, height, width, channels]. +The format must be NHWC. *@li size: A 1-D tensor of 2 elements containing the size of the glimpses to extract. The glimpse height must be specified first, following by the glimpse width. @@ -293,7 +317,7 @@ uniform_noise . \n *@par Outputs: *y:A tensor representing the glimpses [batch_size, glimpse_height, -glimpse_width, channels] . \n +glimpse_width, channels]. The format must be NHWC. \n *@attention Constraints: *Input x must be a 4-D tensor . \n @@ -340,7 +364,8 @@ REG_OP(HSVToRGB) *@par Inputs: *Input images must be a 4-D tensor. Inputs include: -*@li images: 4-D with shape [batch, height, width, channels]. +*@li images: 4-D with shape [batch, height, width, channels]. The format must +be NHWC. *@li size: A 1-D int32 Tensor of 2 elements: new_height, new_width. The new size for the images. *@li min: A Tensor of type float. @@ -354,6 +379,7 @@ the values at the corner pixels. Defaults to false. *@par Outputs: *@li resized_images: 4-D with shape [batch, new_height, new_width, channels]. +The format must be NHWC. *@li y_min: A Tensor of type float. *@li y_max: A Tensor of type float . \n @@ -381,7 +407,8 @@ REG_OP(QuantizedResizeBilinear) *@par Inputs: *Input images must be a 4-D tensor. Inputs include: -*@li images: 4-D with shape [batch, height, width, channels]. +*@li images: 4-D with shape [batch, height, width, channels]. The format must +be NHWC. *@li size: A 1-D int32 Tensor of 2 elements: new_height, new_width. The new size for the images . \n @@ -391,7 +418,8 @@ output tensors are aligned, preserving the values at the corner pixels. Defaults to false . \n *@par Outputs: -*y: 4-D with shape [batch, new_height, new_width, channels] . \n +*y: 4-D with shape [batch, new_height, new_width, channels]. The format must +be NHWC. \n *@attention Constraints: *Input images can be of different types but output images are always float . \n @@ -414,10 +442,10 @@ REG_OP(ResizeArea) *@par Inputs: *Input grads must be a 4-D tensor. Inputs include: *@li grads: A Tensor of type float. 4-D with shape [batch, height, width, -channels]. +channels]. The format must be NHWC. *@li original_image: A Tensor. Must be one of the following types: float, double. 4-D with shape [batch, orig_height, orig_width, channels], The image -tensor that was resized . \n +tensor that was resized. The format must be NHWC. \n *@par Attributes: *@li align_corners: An optional bool. Defaults to False. If true, the centers @@ -426,10 +454,10 @@ false. *@li half_pixel_centers: An optional bool. Defaults to False . \n *@par Outputs: -*y: A Tensor. Has the same type as original_image . \n +*y: A Tensor. Has the same type as original_image. The format must be NHWC. \n *@attention Constraints: -*Input images can be of different types but output images are always float . \n +*Input images can be of different types but output images are always float . *@par Third-party framework compatibility *Compatible with tensorflow ResizeBicubicGrad operator. @@ -448,7 +476,8 @@ REG_OP(ResizeBicubicGrad) *@par Inputs: *Input images must be a 4-D tensor. Inputs include: -*@li images: 4-D with shape [batch, height, width, channels]. +*@li images: 4-D with shape [batch, height, width, channels]. The format +must be NHWC. *@li size: A 1-D int32 Tensor of 2 elements: new_height, new_width. The new size for the images . \n @@ -459,10 +488,11 @@ Defaults to false. *@li half_pixel_centers: An optional bool. Defaults to False . \n *@par Outputs: -*y: 4-D with shape [batch, new_height, new_width, channels] . \n +*y: 4-D with shape [batch, new_height, new_width, channels]. The format +must be NHWC. \n *@attention Constraints: -*Input images can be of different types but output images are always float . \n +*Input images can be of different types but output images are always float . *@par Third-party framework compatibility *Compatible with tensorflow ResizeBicubic operator. @@ -483,7 +513,7 @@ REG_OP(ResizeBicubic) *@par Inputs: *Input grads must be a 4-D tensor. Inputs include: *@li grads: A Tensor. Must be one of the following types: uint8, int8, int32, -float16, float, double. 4-D with shape [batch, height, width, channels]. +float16, float, double. Must set the format, supported format list ["NCHW, NHWC"] *@li size: A 1-D int32 Tensor of 2 elements: orig_height, orig_width. The original input size . \n @@ -550,9 +580,8 @@ REG_OP(ResizeNearestNeighborV2GradD) *@par Inputs: *Input grads must be a 4-D tensor. Inputs include: -*@li grads: A Tensor of type float32. 4-D with shape [batch, height, width, -channels]. -*@li original_image: A Tensor. 4-D with shape [batch, orig_height, orig_width, +*@li grads: A Tensor of type float32. Must set the format, supported format list ["NCHW, NHWC"] +*@li original_image: A Tensor. 4-D shape. Must set the format, supported format list ["NCHW, NHWC"] channels], The image tensor that was resized . \n *@par Attributes: @@ -583,7 +612,7 @@ REG_OP(ResizeBilinearV2Grad) *@par Inputs: *Input images must be a 4-D tensor. Inputs include: -*@li x: 4-D with shape [batch, height, width, channels]. +*@li x: 4-D tensor. Must set the format, supported format list ["NCHW, NHWC"] *@li size: A 1-D int32 Tensor of 2 elements: new_height, new_width. The new size for the images . \n @@ -639,6 +668,62 @@ REG_OP(RGBToHSV) /** *@brief Generate a single randomly distorted bounding box for an image . \n +*@par Inputs: +*Input images must be a 4-D tensor. Inputs include: +*@li image_size: 1-D, containing [height, width, channels]. +*@li bounding_boxes: 3-D with shape [batch, N, 4] describing the N bounding +boxes associated with the image. \n + +*@par Attributes: +*@li seed: If either seed or seed2 are set to non-zero, the random number +generator is seeded by the given seed. Otherwise, it is seeded by a random seed. +*@li seed2: A second seed to avoid seed collision. +*@li min_object_covered: The cropped area of the image must contain at least +this fraction of any bounding box supplied. The value of this parameter should +be non-negative. In the case of 0, the cropped area does not need to overlap +any of the bounding boxes supplied . +*@li aspect_ratio_range: The cropped area of the image must have an aspect +ratio = width / height within this range. +*@li max_attempts: Number of attempts at generating a cropped region of the +image of the specified constraints. After max_attempts failures, return the +entire image. +*@li use_image_if_no_bounding_boxes: Controls behavior if no bounding boxes +supplied. If true, assume an implicit bounding box covering the whole input. +If false, raise an error . \n + +*@par Outputs: +*@li begin: 1-D, containing [offset_height, offset_width, 0]. +*@li size: 1-D, containing [target_height, target_width, -1]. +*@li bboxes: 3-D with shape [1, 1, 4] containing the distorted bounding box . \n + +*@attention Constraints: +*Input images can be of different types but output images are always float . \n + +*@par Third-party framework compatibility +*Compatible with tensorflow SampleDistortedBoundingBox operator. +*/ + +REG_OP(SampleDistortedBoundingBox) + .INPUT(image_size, TensorType({ DT_UINT8, DT_INT8, DT_INT16, \ + DT_INT32, DT_INT64 })) + .INPUT(bounding_boxes, TensorType({ DT_FLOAT })) + .OUTPUT(begin, TensorType({ DT_UINT8, DT_INT8, DT_INT16, \ + DT_INT32, DT_INT64 })) + .OUTPUT(size, TensorType({ DT_UINT8, DT_INT8, DT_INT16, \ + DT_INT32, DT_INT64 })) + .OUTPUT(bboxes, TensorType({ DT_FLOAT })) + .ATTR(seed, Int, 0) + .ATTR(seed2, Int, 0) + .ATTR(min_object_covered, Float, 0.1f) + .ATTR(aspect_ratio_range, ListFloat, { 0.75f, 1.33f }) + .ATTR(area_range, ListFloat, { 0.05f, 1.0f }) + .ATTR(max_attempts, Int, 100) + .ATTR(use_image_if_no_bounding_boxes, Bool, false) + .OP_END_FACTORY_REG(SampleDistortedBoundingBox) + +/** +*@brief Generate a single randomly distorted bounding box for an image . \n + *@par Inputs: *Input images must be a 4-D tensor. Inputs include: *@li image_size: 1-D, containing [height, width, channels]. @@ -697,7 +782,7 @@ REG_OP(SampleDistortedBoundingBoxExt2) *@par Inputs: *Input x must be a 4-D tensor. Inputs include: -*@li x: 4-D with shape [batch, height, width, channels]. +*@li x: 4-D tensor. Must set the format, supported format list ["NCHW, NHWC"]. *@li size: A 1-D int32 Tensor of 2 elements: new_height, new_width. The new size for the images . \n @@ -729,12 +814,12 @@ REG_OP(ResizeNearestNeighborV2) *@par Inputs: *Input images must be a 4-D tensor. Inputs include: *@li images: A Tensor. Must be one of the following types: float. 4-D with -shape [batch, height, width, depth]. A batch of images. +shape [batch, height, width, depth]. A batch of images. The format must be NHWC. *@li boxes: A Tensor of type float32. 3-D with shape [batch, num_bounding_boxes, 4] containing bounding boxes . \n *@par Outputs: -*A Tensor. Has the same type as images . \n +*A Tensor. Has the same type as images. The format must be NHWC. \n *@attention Constraints: *Input images must be a 4-D tensor . \n @@ -1002,6 +1087,88 @@ REG_OP(EncodePng) .ATTR(compression, Int, -1) .OP_END_FACTORY_REG(EncodePng) + +/** +*@brief PNG-decode an image. +*@par Inputs: +*contents: 0-D. PNG-decoded image . + +*@par Attributes: +*channels: graph channels \n +*dtype: type of image + +*@par Outputs: +*image: is a 3-D uint8 or uint16 Tensor of shape [height, width, channels] +where channels is: 1: for grayscale; 2: for grayscale + alpha; 3: for RGB; +4: for RGBA . \n + +*@par Third-party framework compatibility +*Compatible with tensorflow DecodePng operator. +*/ +REG_OP(DecodePng) + .INPUT(contents, TensorType({DT_STRING})) + .OUTPUT(image, TensorType({DT_UINT8, DT_UINT16})) + .ATTR(dtype, Type, DT_UINT8) + .ATTR(channels, Int, 0) + .OP_END_FACTORY_REG(DecodePng) + +/** +*@brief Bmp-decode an image. \n + +*@par Inputs: +*@li contents: A Tensor of type string. 0-D. The BMP-encoded image. \n + +*@par Attributes: +*@li channels: Decode the desired number of color channels of the image. \n + +*@par Outputs: +*image: A Tensor dtype of uint8. + +* @par Third-party framework compatibility +* Compatible with tensorflow DecodeBmp operator. +*/ + +REG_OP(DecodeBmp) + .INPUT(contents, TensorType({DT_STRING})) + .OUTPUT(image, TensorType({DT_UINT8})) + .ATTR(channels, Int, 0) + .OP_END_FACTORY_REG(DecodeBmp) + +/** +*@brief Function parse image from string to int. \n + +*@par Inputs: +*@li contents: A Tensor of type string. 0-D. The JPEG-encoded image. \n +*@li crop_window: 1-D. The crop window: [crop_y, crop_x, crop_height, crop_width]. \n + +*@par Attributes: +*@li channels: An optional int. Defaults to 0. Number of color channels for the +*decoded image. +*@li ratio: An optional int. Defaults to 1. Downscaling ratio. +*@li fancy_upscaling: An optional bool. Defaults to True. If true use a slower +*but nicer upscaling of the chroma planes +*@li try_recover_truncated: An optional bool. Defaults to False. If true try to +*recover an image from truncated input. +*@li acceptable_fraction: An optional float. Defaults to 1. The minimum required +fraction of lines before a truncated input is accepted. +*@li dct_method: An optional string. Defaults to "". string specifying a hint +*about the algorithm used for decompression. \n + +*@par Outputs: +*image: A Tensor dtype of uint8. +*/ +REG_OP(DecodeAndCropJpeg) + .INPUT(contents, TensorType({DT_STRING})) + .INPUT(crop_window, TensorType({DT_INT32})) + .OUTPUT(image, TensorType({DT_UINT8})) + .ATTR(channels, Int, 0) + .ATTR(ratio, Int, 1) + .ATTR(fancy_upscaling, Bool, true) + .ATTR(try_recover_truncated, Bool, false) + .ATTR(acceptable_fraction, Float, 1.0) + .ATTR(dct_method, String, "") + .OP_END_FACTORY_REG(DecodeAndCropJpeg) + /** *@brief Resizes "images" to "size" using bilinear interpolation . \n @@ -1316,6 +1483,55 @@ REG_OP(CombinedNonMaxSuppression) .ATTR(clip_boxes, Bool, true) .OP_END_FACTORY_REG(CombinedNonMaxSuppression) +/** +*@brief Resizes "images" with "offset" using bilinear interpolation. \n + +*@par Inputs: +*@li img: input image, A 4-D tensor of shape `[n, h, w, c]`. +*@li warp_offset: the resize offset A 4-D float tensor of shape `[n, h, w, 2]`, 2 means (x, y) for offset point. + +*@par Outputs: +*warp_img: A Tensor after resize. \n +*/ +REG_OP(IMGWarp) + .INPUT(img, TensorType({DT_UINT8, DT_FLOAT16, DT_FLOAT32})) + .INPUT(warp_offset, TensorType({DT_FLOAT32})) + .OUTPUT(warp_img, TensorType({DT_UINT8, DT_FLOAT16, DT_FLOAT32})) + .OP_END_FACTORY_REG(IMGWarp) + +/** +*@brief Resizes "images" with "offset" using bilinear interpolation. \n + +*@par Inputs: +*@li img: input image, A 4-D tensor of shape `[n, h, w, c]`. +*@li map_offset: the resize offset A 4-D float tensor of shape `[n, h, w, 2]`, 2 means (x, y) for resize point. + +*@par Outputs: +*map_img: A Tensor after resize. \n +*/ +REG_OP(Remap) + .INPUT(img, TensorType({DT_UINT8, DT_FLOAT16, DT_FLOAT32})) + .INPUT(map_offset, TensorType({DT_FLOAT32})) + .OUTPUT(map_img, TensorType({DT_UINT8, DT_FLOAT16, DT_FLOAT32})) + .OP_END_FACTORY_REG(Remap) + +/** +*@brief Resizes "images" with "offset" using bilinear interpolation. \n + +*@par Inputs: +*@li img: input image, A 5-D tensor of shape `[n, 4, c, h, w]`, +and 4 mean input[(h_top, w_left), (h_top, w_right), (h_bottom, w_left), (h_bottom, w_right)]. +*@li warp_index: the resize offset A 4-D float tensor of shape `[n, 2, h, w]`, 2 means (x, y) for resize point. + +*@par Outputs: +*remap_img: A Tensor after ResizeBilinear, A 4-D tensor of shape `[n, c, h, w]`. \n +*/ +REG_OP(IMGWarpResize) + .INPUT(img, TensorType({DT_FLOAT32})) + .INPUT(warp_index, TensorType({DT_FLOAT32})) + .OUTPUT(warp_img, TensorType({DT_FLOAT32})) + .OP_END_FACTORY_REG(IMGWarpResize) + /** *@brief Function spatial transformer . \n @@ -1342,6 +1558,383 @@ REG_OP(SpatialTransformerD) .ATTR(use_default_theta, ListBool, {}) .OP_END_FACTORY_REG(SpatialTransformerD) -} // namespace ge +/** +* @brief Resize the input tensor. \n +currently, only support resize image tensor using nearest neighbor and linear interpolation. + +* @par Inputs: +* Input x must be a 4-D tensor. Inputs include: \n +* @li x: A Tensor. Must be one of the following types: uint8, int8, int16, \n +int32, int64, float16, float, double. 4-D with shape [batch, height, width, channels] \n +or shape [batch, channels, height, width]. +* @li roi: A 1-D float Tensor. only takes effect when attr coordinate_transformation_mode \n +is "tf_crop_and_resize" +* @li scales: A 1-D float Tensor, the scale array along each dimension, Only one of \n +'scales' and 'sizes' can be specified. +* @li sizes: A 1-D int64 Tensor, The size of the output tensor. nly one of \n +'scales' and 'sizes' can be specified. If 'size' is specified, then set scales \n +to empty data (zero shape) in this operator's input list. + +* @par Attributes: +* @li coordinate_transformation_mode: String. Defaults to half_pixel. how to transform \n +the coordinate in the resized tensor to the coordinate in the original tensor. \n +other optional: pytorch_half_pixel, align_corners, asymmetric, tf_half_pixel_for_nn, \n +tf_crop_and_resize. +* @li cubic_coeff_a: Float. Defaults to -0.75, only used in cubic interpolation. \n +other optional: -0.5 +* @li exclude_outside: Int. Defaults to 0, If set to 1, the weight of sampling \n +locations outside the tensor will be set to 0 and the weight will be renormalized \n +so that their sum is 1.0. +* @li extrapolation_value: Float. Defaults to 0.0f. When coordinate_transformation_mode \n +is "tf_crop_and_resize" and x_original is outside the range [0, length_original - 1], \n +this value is used as the corresponding output value. +* @li mode: String. Defaults to nearest. Three interpolation modes: nearest (default), \n +linear and cubic. +* @li nearest_mode: String. Defaults to round_prefer_floor. Four modes: round_prefer_floor, \n +round_prefer_ceil, floor, ceil. Only used by nearest interpolation. + +* @par Outputs: +* y: A Tensor. Has the same type as x. + +* @attention Constraints: \n +* Input x must be a 4-D tensor. + +* @par Third-party framework compatibility +* Compatible with tensorflow ResizeNearestNeighborV2 operator. +*/ + +REG_OP(Resize) + .INPUT(x, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, DT_INT32, + DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(roi, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(scales, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(sizes, TensorType({DT_INT64})) + .OUTPUT(y, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, DT_INT32, + DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .ATTR(coordinate_transformation_mode, String, "half_pixel") + .ATTR(cubic_coeff_a, Float, -0.75) + .ATTR(exclude_outside, Int, 0) + .ATTR(extrapolation_value, Float, 0) + .ATTR(mode, String, "nearest") + .ATTR(nearest_mode, String, "round_prefer_floor") + .OP_END_FACTORY_REG(Resize) + +/** +*@brief Function parse image from string to int. \n + +*@par Inputs: +*@li contents: A Tensor of type string. 0-D. The JPEG-encoded image. \n + +*@par Attributes: +*@li channels: An optional int. Defaults to 0. Number of color channels for the decoded image. +*@li ratio: An optional int. Defaults to 1. Downscaling ratio. +*@li fancy_upscaling: An optional bool. Defaults to True. If true use a slower but nicer upscaling of the chroma planes +*@li try_recover_truncated: An optional bool. Defaults to False. If true try to recover an image from truncated input. +*@li acceptable_fraction: An optional float. Defaults to 1. The minimum required fraction of lines before a truncated input is accepted. +*@li dct_method: An optional string. Defaults to "". string specifying a hint about the algorithm used for decompression. \n + +*@par Outputs: +*image: A Tensor dtype of uint8. +*/ +REG_OP(DecodeJpeg) + .INPUT(contents, TensorType({DT_STRING})) + .OUTPUT(image, TensorType({DT_UINT8})) + .ATTR(channels, Int, 0) + .ATTR(ratio, Int, 1) + .ATTR(fancy_upscaling, Bool, true) + .ATTR(try_recover_truncated, Bool, false) + .ATTR(acceptable_fraction, Float, 1.0) + .ATTR(dct_method, String, "") + .OP_END_FACTORY_REG(DecodeJpeg) + +/** +*@brief Image warping using per-pixel flow vectors. \n + +*@par Inputs: +*@li image: 4-D Tensor with shape `[batch, height, width, channels]`. +*@li flow: 4-D Tensor with shape `[batch, height, width, 2]`. \n + +*@par Outputs: +*y: Returns 4-D with the same shape and dtype as `image`. \n +*/ +REG_OP(DenseImageWarp) + .INPUT(image, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(flow, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .OP_END_FACTORY_REG(DenseImageWarp) + +/** +*@brief Calculate the resize_d function. \n + +*@par Inputs: +*One inputs, including: +* @li x: A tensor. Must be one of the following types: +* float16, float32. \n + +*@par Attributes: +*@li sizes: An optional listInt. \n +*@li scales: An optional listFloat. + Defaults to none. \n +*@li roi: An optional listInt. + Defaults to none. \n +*@li coordinate_transformation_mode: An optional String. + Defaults to "half_pixel". \n +*@li cubic_coeff_a: An optional float. + Defaults to -0.75. \n +*@li exclude_outside: An optional int. + Defaults to 0. \n +*@li extrapolation_value: An optional float. + Defaults to 0.0. \n +*@li mode: An optional String. + Defaults to "nearest". \n +*@li nearest_mode: An optional String. + Defaults to "round_prefer_floor". \n + +*@par Outputs: +*y: A Tensor with the same type of x's, + shape depends on x and sizes. \n +*/ +REG_OP(ResizeD) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(sizes, ListInt) + .ATTR(scales, ListFloat, {}) + .ATTR(roi, ListInt, {}) + .ATTR(coordinate_transformation_mode, String, "half_pixel") + .ATTR(cubic_coeff_a, Float, -0.75) + .ATTR(exclude_outside, Int, 0) + .ATTR(extrapolation_value, Float, 0.0) + .ATTR(mode, String, "nearest") + .ATTR(nearest_mode, String, "round_prefer_floor") + .OP_END_FACTORY_REG(ResizeD) + +/** +*@brief Calculate the resize_grad_d function. \n + +*@par Inputs: +*One inputs, including: +* @li grads: A tensor. Must be one of the following types: +* float16, float32. \n + +*@par Attributes: +*@li original_size: An optional listInt. \n +*@li roi: An optional listInt. + Defaults to none. \n +*@li scales: An optional listFloat. + Defaults to none. \n +*@li coordinate_transformation_mode: An optional String. + Defaults to "half_pixel". \n +*@li cubic_coeff_a: An optional float. + Defaults to -0.75. \n +*@li exclude_outside: An optional int. + Defaults to 0. \n +*@li extrapolation_value: An optional float. + Defaults to 0.0. \n +*@li mode: An optional String. + Defaults to "nearest". \n +*@li nearest_mode: An optional String. + Defaults to "round_prefer_floor". \n + +*@par Outputs: +*y: A Tensor with the same type of x's, + shape depends on x and sizes. \n +*/ +REG_OP(ResizeGradD) + .INPUT(grads, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(original_size, ListInt) + .ATTR(roi, ListInt, {}) + .ATTR(scales, ListFloat, {}) + .ATTR(coordinate_transformation_mode, String, "half_pixel") + .ATTR(cubic_coeff_a, Float, -0.75) + .ATTR(exclude_outside, Int, 0) + .ATTR(extrapolation_value, Float, 0.0) + .ATTR(mode, String, "nearest") + .ATTR(nearest_mode, String, "round_prefer_floor") + .OP_END_FACTORY_REG(ResizeGradD) + +/** +*@brief Computes the gradients of DenseImageWarp with respect to image and flow. \n + +*@par Inputs: +*@li grad: gradients with respect to DenseImageWarp output. +*@li image: 4-D Tensor with shape `[batch, height, width, channels]`. +*@li flow: 4-D Tensor with shape `[batch, height, width, 2]`. \n + +*@par Outputs: +*grad_image: Returns 4-D with the same shape and dtype as `image`. +*grad_flow: Returns 4-D with the same shape and dtype as `flow`. \n +*/ +REG_OP(DenseImageWarpGrad) + .INPUT(grad, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(image, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(flow, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(grad_image, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(grad_flow, TensorType({DT_FLOAT, DT_FLOAT16})) + .OP_END_FACTORY_REG(DenseImageWarpGrad) + +/** +*@brief This operation samples input X by using interpolation based on flow field grid, + which is usually gennerated by affine_grid. The grid of shape [N, H, W, 2] is the concatenation of + (x, y) coordinates with shape [N, H, W] each, where x is indexing the 4th dimension (in width dimension) of + input data x and y is indexng the 3rd dimention (in height dimension), finally results is + the interpolation value of 4 nearest corner points. The output tensor shape will be [N, C, H, W]. + +*@par Inputs: +*@li x: 4-D Tensor with shape `[batch, channels, height, width]`. +*@li grid: flow field grid, 4-D Tensor with shape `[batch, height, width, 2]`. + +*@par Attributes: +*@li interpolation_mode: An optional string specifying the interpolation method. Only 'bilinear' is + supported for now . +*@li padding_mode: An optional string specifying the pad method. Only 'zeros' is supported for now . +*@li align_corners: An optional bool. If "true", the centers of the corner + pixels of the input and output tensors are aligned. Defaults to "false" . + +*@par Outputs: +*y: Returns 4-D Tensor with the same dtype as `X`. + +*@par Third-party framework compatibility +*Compatible with pytorch GridSampler2D operator. + +*@par Restrictions: +*Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(GridSampler2D) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(grid, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(interpolation_mode, String, "bilinear") + .ATTR(padding_mode, String, "zeros") + .ATTR(align_corners, Bool, false) + .OP_END_FACTORY_REG(GridSampler2D) + +/** +*@brief This operation unnormalize input Grid, which is usually gennerated by affine_grid. + +*@par Inputs: +*@li grid: flow field grid, 4-D Tensor with shape `[batch, height, width, 2]`. +*@li assist: Assist matrix, a 4-D tensor of type float16. + +*@par Attributes: +*@li align_corners: An optional bool. If "true", the centers of the corner + pixels of the input and output tensors are aligned. Defaults to "false" . + +*@par Outputs: +*diff: Returns 4-D Tensor with the same shape and dtype as `grid`. +*position: Returns 4-D Tensor with the same shape as `grid`. +*/ +REG_OP(GridUnnormal) + .INPUT(grid, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(assist, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(diff, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(position, TensorType({DT_INT32})) + .ATTR(align_corners, Bool, false) + .OP_END_FACTORY_REG(GridUnnormal) + +/** +*@brief This operation unfold input X based on unnormalized grid, which is gennerated by GridUnnormal. + +*@par Inputs: +*@li x: 4-D Tensor with shape `[batch, channels, height, width]`. +*@li position: 4-D Tensor with shape `[batch, output_height, output_width, 2]`. + +*@par Attributes: +*@li padding_mode: An optional string specifying the pad method. Only 'zeros' is supported for now . + +*@par Outputs: +*y: Returns 4-D Tensor with the same dtype as `x`. +*/ +REG_OP(ImageUnfold) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(position, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(padding_mode, String, "zeros") + .OP_END_FACTORY_REG(ImageUnfold) + +/** +*@brief This operation select images to warp_images according to offsets. + +*@par Inputs: +*@li images: 4-D Tensor with shape `[batch, height, width, 3]`. +*@li offsets: 4-D Tensor with shape `[batch, 4, new_height, new_width]`. + +*@par Outputs: +*warp_images: Returns 5-D Tensor with shape +`[batch, 4, new_height, new_width, 3]` and the same dtype as `images`. +*/ +REG_OP(IMGWarpOffsets) + .INPUT(images, TensorType({DT_UINT8, DT_FLOAT16, DT_FLOAT})) + .INPUT(offsets, TensorType({DT_FLOAT, DT_INT32})) + .OUTPUT(warp_images, TensorType({DT_UINT8, DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(IMGWarpOffsets) + +/** +*@brief This operation samples 3d input x by using interpolation based on flow field grid, + which is usually gennerated by affine_grid. + +*@par Inputs: +*@li x: 5-D Tensor with shape `[batch, channels, depth, height, width]`. +*@li grid: flow field grid, 5-D Tensor with shape `[batch, depth, height, width, 2]`. + +*@par Attributes: +*@li interpolation_mode: An optional string specifying the interpolation method. +*@li padding_mode: An optional string specifying the pad method. +*@li align_corners: An optional bool. If "true", the centers of the corner + pixels of the input and output tensors are aligned. Defaults to "false" . + +*@par Outputs: +*y: Returns 5-D Tensor with the same dtype as `x`. + +*@par Third-party framework compatibility +*Compatible with pytorch GridSampler3D operator. + +*@par Restrictions: +*Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(GridSampler3D) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(grid, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .ATTR(interpolation_mode, String, "bilinear") + .ATTR(padding_mode, String, "zeros") + .ATTR(align_corners, Bool, false) + .OP_END_FACTORY_REG(GridSampler3D) +/** +*@brief Computes the gradients of GridSampler3D. + +*@par Inputs: +*@li grad: 5-D Tensor with shape `[batch, channels, depth, height, width]`. +*@li x: 5-D Tensor with shape `[batch, channels, depth, height, width]`. +*@li grid: flow field grid, 5-D Tensor with shape `[batch, depth, height, width, 2]`. + +*@par Attributes: +*@li interpolation_mode: An optional string specifying the interpolation method. +*@li padding_mode: An optional string specifying the pad method. +*@li align_corners: An optional bool. If "true", the centers of the corner + pixels of the input and output tensors are aligned. Defaults to "false" . + +*@par Outputs: +*dx: Returns 5-D Tensor with the same dtype and shape as `x`. +*dgrid: Returns 5-D Tensor with the same dtype and shape as `grid`. + +*@par Third-party framework compatibility +*Compatible with pytorch GridSampler3DGrad operator. + +*@par Restrictions: +*Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(GridSampler3DGrad) + .INPUT(grad, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(grid, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(dx, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(dgrid, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .ATTR(interpolation_mode, String, "bilinear") + .ATTR(padding_mode, String, "zeros") + .ATTR(align_corners, Bool, false) + .OP_END_FACTORY_REG(GridSampler3DGrad) + +} // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_IMAGE_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/internal_ops.h b/third_party/fwkacllib/inc/ops/internal_ops.h index 9dde14a5..bcc3f1c3 100644 --- a/third_party/fwkacllib/inc/ops/internal_ops.h +++ b/third_party/fwkacllib/inc/ops/internal_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/linalg_ops.h b/third_party/fwkacllib/inc/ops/linalg_ops.h index 7a6fbc59..69c77bf6 100644 --- a/third_party/fwkacllib/inc/ops/linalg_ops.h +++ b/third_party/fwkacllib/inc/ops/linalg_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -61,8 +61,8 @@ REG_OP(CholeskyGrad) *@par Inputs: *The input x has to be symmetric and positive definite.Inputs include: -*x:A Tensor. Must be one of the following types: double, float32. Shape -is [..., M, M] . \n +*x:A Tensor. Must be one of the following types: double, float32, float16, +complex64, complex128. Shape is [..., M, M] . \n *@par Outputs: *y:A Tensor. Has the same type as x . \n @@ -76,10 +76,31 @@ form square matrices. */ REG_OP(Cholesky) - .INPUT(x, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(x, TensorType({DT_FLOAT, DT_DOUBLE, \ + DT_FLOAT16, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, \ + DT_FLOAT16, DT_COMPLEX64, DT_COMPLEX128})) .OP_END_FACTORY_REG(Cholesky) +/** +*@brief Computes the outer product of two 1D vectors . \n + +*@par Inputs: +*The input x1 and x2 has to be a 1D vector.Inputs include: +*@li x1:A Tensor. Must be one of the following types: float16, float32. +Shape is [N] . \n +*@li x2:A Tensor. Must have the same type as x. Shape is [M] . \n + +*@par Outputs: +*y:A Tensor. Has the same type as x . \n +*/ + +REG_OP(Ger) + .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(Ger) + /** *@brief Computes the sign and the log of the absolute value of the determinant of one or more square matrices . \n @@ -87,8 +108,8 @@ of one or more square matrices . \n *@par Inputs: *The input x is a tensor of shape [N, M, M] whose inner-most 2 dimensions form square matrices. Inputs include: -*x:A Tensor. Must be one of the following types: double, float32. Shape is -[..., M, M] . \n +*x:A Tensor. Must be one of the following types: double, float32, +complex64, complex128. Shape is [..., M, M] . \n *@par Outputs: *@li y:A Tensor. Has the same type as x. @@ -103,9 +124,9 @@ form square matrices. \n */ REG_OP(LogMatrixDeterminant) - .INPUT(x, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(sign, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(x, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(sign, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .OP_END_FACTORY_REG(LogMatrixDeterminant) /** @@ -114,8 +135,8 @@ REG_OP(LogMatrixDeterminant) *@par Inputs: *The input x is a tensor of shape [N, M, M] whose inner-most 2 dimensions form square matrices. Inputs include: -*x:A Tensor. Must be one of the following types: double, float32. Shape is -[..., M, M] . \n +*x:A Tensor. Must be one of the following types: double, float32, complex64, +complex128. Shape is [..., M, M] . \n *@par Outputs: *y:A Tensor. Has the same type as x . \n @@ -129,8 +150,8 @@ form square matrices. */ REG_OP(MatrixDeterminant) - .INPUT(x, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(x, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .OP_END_FACTORY_REG(MatrixDeterminant) /** @@ -140,8 +161,7 @@ their adjoints (conjugate transposes) . \n *@par Inputs: *The input x is a tensor of shape [..., M, M] whose inner-most 2 dimensions form square matrices. Inputs include: -*x:A Tensor. Must be one of the following types: double, float. Shape is -[..., M, M] . \n +*x:A Tensor of input. Shape is [..., M, M] . \n *@par Attributes: *adjoint:An optional bool. Defaults to False.Boolean indicating whether to @@ -159,8 +179,8 @@ form square matrices. \n */ REG_OP(MatrixInverse) - .INPUT(x, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(x, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .ATTR(adjoint, Bool, false) .OP_END_FACTORY_REG(MatrixInverse) @@ -169,8 +189,7 @@ REG_OP(MatrixInverse) *@par Inputs: *The input rhs must have the same type as matrix. Inputs include: -*@li matrix:A Tensor. Must be one of the following types: double, float. -Shape is [..., M, M]. +*@li matrix:A Tensor of input. Shape is [..., M, M]. *@li rhs:A Tensor. Must have the same type as matrix. Shape is [..., M, K] . \n *@par Attributes: @@ -189,9 +208,9 @@ dimensions form square matrices. \n */ REG_OP(MatrixSolve) - .INPUT(matrix, TensorType({DT_FLOAT, DT_DOUBLE})) - .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(matrix, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .ATTR(adjoint, Bool, false) .OP_END_FACTORY_REG(MatrixSolve) @@ -221,8 +240,8 @@ dimensions form square matrices. \n */ REG_OP(MatrixSolveLs) - .INPUT(matrix, TensorType({DT_FLOAT, DT_DOUBLE})) - .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(matrix, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .INPUT(l2, TensorType({DT_DOUBLE})) .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) .ATTR(fast, Bool, true) @@ -234,8 +253,7 @@ matrices by backsubstitution . \n *@par Inputs: *The input rhs must have the same type as matrix. Inputs include: -*@li matrix: A Tensor. Must be one of the following types: double, float. -Shape is [..., M, M]. +*@li matrix: A Tensor. Shape is [..., M, M]. *@li rhs:A Tensor. Must have the same type as matrix. Shape is [..., M, K] . \n *@par Attributes: @@ -256,9 +274,9 @@ dimensions form square matrices. \n */ REG_OP(MatrixTriangularSolve) - .INPUT(matrix, TensorType({DT_FLOAT, DT_DOUBLE})) - .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(matrix, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .ATTR(lower, Bool, true) .ATTR(adjoint, Bool, false) .OP_END_FACTORY_REG(MatrixTriangularSolve) @@ -268,8 +286,7 @@ REG_OP(MatrixTriangularSolve) *@par Inputs: *The input shape of x must be [..., M, N]. Inputs include: -*x:A Tensor whose shape is [..., M, N]. Must be one of the following types: -double, float . \n +*x:A Tensor whose shape is [..., M, N]. \n *@par Attributes: *full_matrices: An optional bool. Defaults to False. If true, compute @@ -289,9 +306,12 @@ dimensions form matrices of size [M, N]. \n */ REG_OP(Qr) - .INPUT(x, TensorType({ DT_FLOAT16, DT_FLOAT, DT_DOUBLE })) - .OUTPUT(q, TensorType({ DT_FLOAT16, DT_FLOAT, DT_DOUBLE })) - .OUTPUT(r, TensorType({ DT_FLOAT16, DT_FLOAT, DT_DOUBLE })) + .INPUT(x, TensorType({ DT_FLOAT16, DT_FLOAT, DT_DOUBLE, \ + DT_COMPLEX64, DT_COMPLEX128 })) + .OUTPUT(q, TensorType({ DT_FLOAT16, DT_FLOAT, DT_DOUBLE, \ + DT_COMPLEX64, DT_COMPLEX128 })) + .OUTPUT(r, TensorType({ DT_FLOAT16, DT_FLOAT, DT_DOUBLE, \ + DT_COMPLEX64, DT_COMPLEX128 })) .ATTR(full_matrices, Bool, false) .OP_END_FACTORY_REG(Qr) @@ -320,12 +340,40 @@ form square matrices. \n */ REG_OP(SelfAdjointEig) - .INPUT(x, TensorType({ DT_DOUBLE, DT_FLOAT })) - .OUTPUT(eigen_value, TensorType({ DT_DOUBLE, DT_FLOAT })) - .OUTPUT(eigen_vector, TensorType({ DT_DOUBLE, DT_FLOAT })) + .INPUT(x, TensorType({ DT_DOUBLE, DT_FLOAT, DT_COMPLEX64, DT_COMPLEX128 })) + .OUTPUT(eigen_value, TensorType({ DT_DOUBLE, DT_FLOAT, DT_COMPLEX64, DT_COMPLEX128 })) + .OUTPUT(eigen_vector, TensorType({ DT_DOUBLE, DT_FLOAT, DT_COMPLEX64, DT_COMPLEX128 })) .ATTR(compute_v, Bool, true) .OP_END_FACTORY_REG(SelfAdjointEig) +/** +*@brief Computes the sign and the log of the absolute value of the determinant +of one or more square matrices . \n + +*@par Inputs: +*The input x is a tensor of shape [N, M, M] whose inner-most 2 dimensions +form square matrices. Inputs include: +*x:A Tensor. Must be one of the following types: double, float32, float16 +Shape is [..., M, M] . \n + +*@par Outputs: +*@li y:A Tensor. Has the same type as x. +*@li sign:A Tensor. Has the same type as x . \n + +*@attention Constraints: +*The input x is a tensor of shape [N, M, M] whose inner-most 2 dimensions +form square matrices. \n + +*@par Third-party framework compatibility +*Compatible with tensorflow LogMatrixDeterminant operator. +*/ + +REG_OP(Slogdet) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(sign, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OP_END_FACTORY_REG(Slogdet) + /** *@brief Computes the singular value decompositions of one or more matrices . \n @@ -384,8 +432,8 @@ of the rows encoded as a list of indices in `0..M-1`. Shape is `[..., M]` . \n */ REG_OP(Lu) - .INPUT(input, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(lu, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(input, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(lu, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .OUTPUT(p, TensorType({DT_INT32, DT_INT64})) .REQUIRED_ATTR(output_idx_type, Type) .OP_END_FACTORY_REG(Lu) @@ -404,8 +452,8 @@ y: Shape is `[..., M, M]` . \n */ REG_OP(MatrixSquareRoot) - .INPUT(input, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(input, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .OP_END_FACTORY_REG(MatrixSquareRoot) /** @@ -424,9 +472,9 @@ y: Tensor of shape `[..., M, K]` containing the solutions \n */ REG_OP(TridiagonalSolve) - .INPUT(diagonals, TensorType({DT_FLOAT, DT_DOUBLE})) - .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(diagonals, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .ATTR(partial_pivoting, Bool, true) .OP_END_FACTORY_REG(TridiagonalSolve) diff --git a/third_party/fwkacllib/inc/ops/list_ops.h b/third_party/fwkacllib/inc/ops/list_ops.h new file mode 100644 index 00000000..a1b622e9 --- /dev/null +++ b/third_party/fwkacllib/inc/ops/list_ops.h @@ -0,0 +1,504 @@ +/** + * Copyright 2019 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. + */ + +/*! + * \file list_ops.h + * \brief + */ +#ifndef OPS_BUILT_IN_OP_PROTO_INC_LIST_OPS_H_ +#define OPS_BUILT_IN_OP_PROTO_INC_LIST_OPS_H_ + +#include +#include "graph/operator_reg.h" +#include "graph/operator.h" + +namespace ge { + +/** +*@brief Creates and returns an empty tensor list. \n + +*@par Inputs: +*@li element_shape: A shape compatible with that of elements in the list. +*@li max_num_elements: The maximum number of elements. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li handle: An empty tensor list . \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow EmptyTensorList operator. +*/ +REG_OP(EmptyTensorList) + .INPUT(element_shape, TensorType({DT_INT32,DT_INT64})) + .INPUT(max_num_elements, TensorType({DT_INT32})) + .OUTPUT(handle, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(EmptyTensorList) + +/** +*@brief Returns a list which has the passed-in `Tensor` as last element +and the other elements of the given list in `input_handle`. \n + +*@par Inputs: +*@li input_handle: The old list. +*@li tensor: The tensor to put on the list. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li output_handle:A list with the elements of old list followed by tensor. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListPushBack operator. +*/ +REG_OP(TensorListPushBack) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(tensor, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL,DT_RESOURCE, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .OUTPUT(output_handle, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListPushBack) + +/** +*@brief The last element of the input list as well as a +list with all but that element. \n + +*@par Inputs: +*@li input_handle: The input list. +*@li element_shape: A shape compatible with that of elements in the list. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li output_handle:A list with the elements of the old list followed by tensor. +*@li tensor:The withdrawn last element of the list. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListPopBack operator. +*/ +REG_OP(TensorListPopBack) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(element_shape, TensorType({DT_INT32})) + .OUTPUT(output_handle, TensorType({DT_VARIANT})) + .OUTPUT(tensor, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL,DT_RESOURCE, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListPopBack) + +/** +*@brief The number of tensors in the input tensor list. \n + +*@par Inputs: +*@li input_handle: The input list. \n + +*@par Outputs: +*@li length:The number of tensors in the list. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListLength operator. +*/ +REG_OP(TensorListLength) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .OUTPUT(length, TensorType({DT_INT32})) + .OP_END_FACTORY_REG(TensorListLength) + +/** +*@brief The shape of elements in the input tensor list. \n + +*@par Inputs: +*@li input_handle: The input list. \n + +*@par Attributes: +*@li shape_type: The type of shape in the list. \n + +*@par Outputs: +*@li element_shape:A shape compatible with that of elements in the list. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListElementShape operator. +*/ +REG_OP(TensorListElementShape) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .OUTPUT(element_shape, TensorType({DT_INT32,DT_INT64})) + .ATTR(shape_type, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListElementShape) + +/** +*@brief List of the given size with empty elements. \n + +*@par Inputs: +*@li element_shape: A shape compatible with that of elements in the list. +*@li num_elements: The number of elements to reserve. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. +*@li shape_type: The type of shape in the list. \n + +*@par Outputs: +*@li handle: An output tensor list . \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListReserve operator. +*/ +REG_OP(TensorListReserve) + .INPUT(element_shape, TensorType({DT_INT32,DT_INT64})) + .INPUT(num_elements, TensorType({DT_INT32})) + .OUTPUT(handle, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .ATTR(shape_type, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListReserve) + +/** +*@brief Get input tensor list elements of index position. \n + +*@par Inputs: +*@li input_handle: The input list. +*@li index: A tensor of position. +*@li element_shape: A shape compatible with that of elements in the list. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li item: An output tensor value of index position . \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListGetItem operator. +*/ +REG_OP(TensorListGetItem) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(index, TensorType({DT_INT32})) + .INPUT(element_shape, TensorType({DT_INT32})) + .OUTPUT(item, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListGetItem) + +/** +*@brief Sets the index-th position of the list to contain the given tensor. \n + +*@par Inputs: +*@li input_handle: The input list. +*@li index: The position in the list to which the tensor will be assigned. +*@li item: The element to be assigned to that position. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li output_handle: An output tensor list . \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListSetItem operator. +*/ +REG_OP(TensorListSetItem) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(index, TensorType({DT_INT32})) + .INPUT(item, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL,DT_RESOURCE, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .OUTPUT(output_handle, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListSetItem) + +/** +*@brief Push tensor to list. \n + +*@par Inputs: +*@li input_handles: The input tensor lists. +*@li tensor: The tensor push into tensor list. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li output_handles: The output tensor lists. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListPushBackBatch operator. +*/ +REG_OP(TensorListPushBackBatch) + .INPUT(input_handles, TensorType({DT_VARIANT})) + .INPUT(tensor, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .OUTPUT(output_handles, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListPushBackBatch) + +/** +*@brief Stacks all tensors in the list. \n + +*@par Inputs: +*@li input_handle: The input tensor list. +*@li element_shape: A shape compatible with that of elements in the tensor. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. +*@li num_elements: The number of elements in the list. \n + +*@par Outputs: +*@li tensor: The tensor of list. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListStack operator. +*/ +REG_OP(TensorListStack) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(element_shape, TensorType({DT_INT32})) + .OUTPUT(tensor, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .ATTR(element_dtype, Type, DT_INT32) + .ATTR(num_elements, Int, -1) + .OP_END_FACTORY_REG(TensorListStack) + +/** +*@brief Concats all tensors in the list along the 0th dimension. +Requires that all tensors have the same shape except the first dimension. \n + +*@par Inputs: +*@li input_handle: The input list. +*@li element_shape: The shape of the uninitialized elements in the list. +If the first dimension is not -1, it is assumed that all list elements have +the same leading dim. +*@li leading_dims: The list of leading dims of uninitialized list elements. Used if +the leading dim of input_handle.element_shape or the element_shape input arg +is not already set. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li tensor: The concated result. +*@li lengths: Output tensor containing sizes of the 0th dimension of tensors +in the list, used for computing the gradient. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListConcatV2 operator. +*/ +REG_OP(TensorListConcatV2) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(element_shape, TensorType({DT_INT32,DT_INT64})) + .INPUT(leading_dims, TensorType({DT_INT64})) + .OUTPUT(tensor, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .OUTPUT(lengths, TensorType({DT_INT64})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListConcatV2) + +/** +*@brief Splits a tensor into a list. \n + +*@par Inputs: +*@li tensor: The input tensor. +*@li element_shape: A shape compatible with that of elements in the tensor. +*@li lengths: Vector of sizes of the 0th dimension of tensors in the list. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li output_handle: The list. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListSplit operator. +*/ +REG_OP(TensorListSplit) + .INPUT(tensor, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .INPUT(element_shape, TensorType({DT_INT32,DT_INT64})) + .INPUT(lengths, TensorType({DT_INT64})) + .OUTPUT(output_handle, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListSplit) + +/** +*@brief Creates a TensorList which, when stacked, has the value of `tensor`. \n + +*@par Inputs: +*@li tensor: The input tensor. +*@li element_shape: The shape of elements in the list. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li output_handle: An output tensor list . \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListFromTensor operator. +*/ +REG_OP(TensorListFromTensor) + .INPUT(tensor, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .INPUT(element_shape, TensorType({DT_INT32,DT_INT64})) + .OUTPUT(output_handle, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListFromTensor) + +/** +*@brief Resizes the list. \n + +*@par Inputs: +*@li input_handle: The input tensor list. +*@li size: size of the output list. \n + +*@par Outputs: +*@li output_handle: The output tensor list. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListResize operator. +*/ +REG_OP(TensorListResize) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(size, TensorType({DT_INT32})) + .OUTPUT(output_handle, TensorType({DT_VARIANT})) + .OP_END_FACTORY_REG(TensorListResize) + +/** +*@brief Creates a Tensor by indexing into the TensorList. \n + +*@par Inputs: +*@li input_handle: The input tensor list. +*@li indices: The indices used to index into the list. +*@li element_shape: The shape of elements in the list. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li values: The tensor. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListGather operator. +*/ +REG_OP(TensorListGather) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(indices, TensorType({DT_INT32})) + .INPUT(element_shape, TensorType({DT_INT32})) + .OUTPUT(values, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListGather) + +/** +*@brief Creates a TensorList by indexing into a Tensor. \n + +*@par Inputs: +*@li tensor: The input tensor. +*@li indices: The indices used to index into the list. +*@li element_shape: The shape of the elements in the list (can be less specified than +the shape of the tensor). +*@li num_elements: The size of the output list. Must be large enough to accommodate +the largest index in indices. If -1, the list is just large enough to include +the largest index in indices. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li output_handle: The TensorList. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListScatterV2 operator. +*/ +REG_OP(TensorListScatterV2) + .INPUT(tensor, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .INPUT(indices, TensorType({DT_INT32})) + .INPUT(element_shape, TensorType({DT_INT32,DT_INT64})) + .INPUT(num_elements, TensorType({DT_INT32})) + .OUTPUT(output_handle, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListScatterV2) + +/** +*@brief Scatters tensor at indices in an input list. \n + +*@par Inputs: +*@li input_handle: The input tensor list. +*@li tensor: The input tensor. +*@li indices: The indices used to index into the list. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li output_handle: The TensorList. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListScatterIntoExistingList operator. +*/ +REG_OP(TensorListScatterIntoExistingList) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(tensor, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE,DT_INT8, + DT_INT16,DT_INT32,DT_INT64,DT_UINT8,DT_UINT16,DT_QINT8,DT_QUINT8, + DT_QINT16,DT_QUINT16,DT_QINT32,DT_BOOL, + DT_STRING,DT_COMPLEX64,DT_COMPLEX128})) + .INPUT(indices, TensorType({DT_INT32})) + .OUTPUT(output_handle, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListScatterIntoExistingList) + +/** +*@brief Concat two tensor lists to a new tensor list. \n + +*@par Inputs: +*@li input_a: The input tensor list A. +*@li input_b: The input tensor list B. \n + +*@par Attributes: +*@li element_dtype: The type of elements in the list. \n + +*@par Outputs: +*@li output: The output list. \n + +*@par Third-party framework compatibility. +*Compatible with tensorflow TensorListConcatLists operator. +*/ +REG_OP(TensorListConcatLists) + .INPUT(input_a, TensorType({DT_VARIANT})) + .INPUT(input_b, TensorType({DT_VARIANT})) + .OUTPUT(output, TensorType({DT_VARIANT})) + .ATTR(element_dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(TensorListConcatLists) +} // namespace ge + +#endif // OPS_BUILT_IN_OP_PROTO_INC_LIST_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/logging_ops.h b/third_party/fwkacllib/inc/ops/logging_ops.h index bc8ae2b8..03be7757 100644 --- a/third_party/fwkacllib/inc/ops/logging_ops.h +++ b/third_party/fwkacllib/inc/ops/logging_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/lookup_ops.h b/third_party/fwkacllib/inc/ops/lookup_ops.h index b37ab048..5d928e5a 100644 --- a/third_party/fwkacllib/inc/ops/lookup_ops.h +++ b/third_party/fwkacllib/inc/ops/lookup_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/math_ops.h b/third_party/fwkacllib/inc/ops/math_ops.h index 149e0e37..319bcf70 100644 --- a/third_party/fwkacllib/inc/ops/math_ops.h +++ b/third_party/fwkacllib/inc/ops/math_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -222,6 +222,24 @@ REG_OP(Bucketize) .REQUIRED_ATTR(boundaries, ListFloat) .OP_END_FACTORY_REG(Bucketize) +/** +*@brief Returns a new tensor with the truncated integer values of the elements of input. \n + +*@par Inputs: +*One inputs, including: +* @li input_x: A tensor. Must be one of the following types: float16, float32, int8, uint8, int32. \n + +*@par Outputs: +*y: A tensor with the same type and shape of input_x \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator Trunc. \n +*/ +REG_OP(Trunc) + .INPUT(input_x, TensorType({DT_FLOAT16,DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8})) + .OUTPUT(output_y, TensorType({DT_FLOAT16,DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8})) + .OP_END_FACTORY_REG(Trunc) + /** *@brief Computes the sum along sparse segments of a tensor . \n @@ -365,6 +383,27 @@ REG_OP(GetNext) .ATTR(channel_name, String, "") .OP_END_FACTORY_REG(GetNext) +/** +*@brief Get dynamic dims after GetNext. \n + +*@par Inputs: +*input: A nested structure of Tensor objects, from GetNext's output. \n + +*@par Attributes: +*@li shape_info: GE shape_info for each inputs, -1 means unknow dim. +*@li N: Inputs number. \n + +*@par Outputs: +*dims: GE unknow dims, a vector of int64. \n +*/ + +REG_OP(GetDynamicDims) + .DYNAMIC_INPUT(input, TensorType({DT_INT32, DT_INT64})) + .OUTPUT(dims, TensorType({DT_INT32, DT_INT64})) + .REQUIRED_ATTR(shape_info, ListInt) + .REQUIRED_ATTR(N, Int) + .OP_END_FACTORY_REG(GetDynamicDims) + /** *@brief End of sequence . \n @@ -494,6 +533,29 @@ REG_OP(NextAfter) .OUTPUT(output, TensorType({DT_FLOAT, DT_DOUBLE})) .OP_END_FACTORY_REG(NextAfter) +/** +*@brief Calculate the P-norm distance between vectors function. \n + +*@par Inputs: +*One inputs, including: +* @li input_x: A tensor. Must be one of the following types: +* float16, float32. \n + +*@par Attributes: +*@li p: An optional float.Defaults to 2. \n + +*@par Outputs: +*y: A Tensor with the same type and shape of input_x's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator Pdist. \n +*/ +REG_OP(Pdist) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(p, Float, 2.0) + .OP_END_FACTORY_REG(Pdist) + /** *@brief Compute element-wise finiteness, return a boolean tensor. @@ -624,6 +686,7 @@ REG_OP(NLLLoss) .OUTPUT(y, TensorType({DT_FLOAT})) .OUTPUT(total_weight, TensorType({DT_FLOAT})) .ATTR(reduction, String, "mean") + .ATTR(ignore_index, Int, -100) .OP_END_FACTORY_REG(NLLLoss) /** @@ -653,6 +716,7 @@ REG_OP(NLLLossGrad) .INPUT(total_weight, TensorType({DT_FLOAT})) .OUTPUT(x_grad, TensorType({DT_FLOAT})) .ATTR(reduction, String, "mean") + .ATTR(ignore_index, Int, -100) .OP_END_FACTORY_REG(NLLLossGrad) /** @@ -710,6 +774,9 @@ REG_OP(IFMR) *@par Third-party framework compatibility *Compatible with mindspore + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(WtsARQ) @@ -741,6 +808,9 @@ REG_OP(WtsARQ) *@par Third-party framework compatibility *Compatible with mindspore + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(ActsULQ) @@ -748,8 +818,8 @@ REG_OP(ActsULQ) .INPUT(clamp_min, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(clamp_max, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) - .OUTPUT(clamp_min_mask, TensorType({DT_BOOL})) - .OUTPUT(clamp_max_mask, TensorType({DT_BOOL})) + .OUTPUT(clamp_min_mask, TensorType({DT_BOOL, DT_FLOAT16, DT_FLOAT})) + .OUTPUT(clamp_max_mask, TensorType({DT_BOOL, DT_FLOAT16, DT_FLOAT})) .OUTPUT(x_clamped_loss, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(fixed_min, Bool, false) .ATTR(num_bits, Int, 8) @@ -768,12 +838,15 @@ REG_OP(ActsULQ) *@par Third-party framework compatibility *Compatible with mindspore + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(ActsULQInputGrad) .INPUT(y_grad, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(clamp_min_mask, TensorType({DT_BOOL})) - .INPUT(clamp_max_mask, TensorType({DT_BOOL})) + .INPUT(clamp_min_mask, TensorType({DT_BOOL, DT_FLOAT16, DT_FLOAT})) + .INPUT(clamp_max_mask, TensorType({DT_BOOL, DT_FLOAT16, DT_FLOAT})) .OUTPUT(x_grad, TensorType({DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(ActsULQInputGrad) @@ -790,11 +863,14 @@ REG_OP(ActsULQInputGrad) *@par Third-party framework compatibility *Compatible with mindspore + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(ActULQClampMaxGrad) .INPUT(y_grad, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(clamp_max_mask, TensorType({DT_BOOL})) + .INPUT(clamp_max_mask, TensorType({DT_BOOL, DT_FLOAT16, DT_FLOAT})) .INPUT(x_clamped_loss, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(clamp_max_grad, TensorType({DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(ActULQClampMaxGrad) @@ -812,15 +888,208 @@ REG_OP(ActULQClampMaxGrad) *@par Third-party framework compatibility *Compatible with mindspore + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(ActULQClampMinGrad) .INPUT(y_grad, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(clamp_min_mask, TensorType({DT_BOOL})) + .INPUT(clamp_min_mask, TensorType({DT_BOOL, DT_FLOAT16, DT_FLOAT})) .INPUT(x_clamped_loss, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(clamp_min_grad, TensorType({DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(ActULQClampMinGrad) +/** +* @brief Computes Lp norm. + +* @par Inputs: +* @li x: An ND tensor of type float16, float32. \n +* +* @par Attributes: +* @li p: Int, "inf" or "-inf", default value is 2. +* @li axes: ListInt, {} means all axes will be computed. +* @li keepdim: Bool, default is false. +* @li epsilon: Float, default is 1e-12. \n + +* @par Outputs: +* @li y: An ND tensor of type float16, float32. The shape of y is depending +* on axes and keepdim. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator LpNorm. +*/ +REG_OP(LpNorm) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(p, Int, 2) + .ATTR(axes, ListInt, {}) + .ATTR(keepdim, Bool, false) + .ATTR(epsilon, Float, 1e-12) + .OP_END_FACTORY_REG(LpNorm) + +/** +* @brief get complex. + +* @par Inputs: +* @li real: An ND tensor of type float32. double +* @li imag: An ND tensor of type float32. double \n +* +* @par Outputs: +* @li out: An ND tensor of type complex64, complex128 \n +*/ +REG_OP(Complex) + .INPUT(real, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(imag, TensorType({DT_FLOAT, DT_DOUBLE})) + .OUTPUT(out, TensorType({DT_COMPLEX64, DT_COMPLEX128})) + .ATTR(Tout, Type, DT_COMPLEX64) + .OP_END_FACTORY_REG(Complex) + +/** +* @brief deal complex. + +* @par Inputs: +* @li input: An ND tensor of type complex64, complex128 \n +* +* @par Outputs: +* @li output: An ND tensor of type float32. double \n +*/ +REG_OP(Imag) + .INPUT(input, TensorType({DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(output, TensorType({DT_FLOAT, DT_DOUBLE})) + .ATTR(Tout, Type, DT_FLOAT) + .OP_END_FACTORY_REG(Imag) + +/** +* @brief deal complex. + +* @par Inputs: +* @li input: An ND tensor of type complex64, complex128 \n +* +* @par Outputs: +* @li output: An ND tensor of type float32. double \n +*/ +REG_OP(Angle) + .INPUT(input, TensorType({DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(output, TensorType({DT_FLOAT, DT_DOUBLE})) + .ATTR(Tout, Type, DT_FLOAT) + .OP_END_FACTORY_REG(Angle) + +/** +*@brief Computes the gradient of SoftMarginLossGrad. \n + +*@par Inputs: +*Three inputs, including: +* @li predict: A tensor. Must be one of the following types: +* float16, float32. \n +* @li label: A tensor with same shape of predict. Must be one of the following types: +* float16, float32. \n +* @li dout: A tensor with same shpae of predcit. Must be one of the following types: +* float16, float32. \n + +*@par Attributes: +* @li reduction: Specifies the reduction to apply to the output: +* 'none' | 'mean' | 'sum'. Default: 'mean'. \n + +*@par Outputs: +* gradient: A Tensor with the same type of predict. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator SoftMarginLoss Backward. \n +*/ +REG_OP(SoftMarginLossGrad) + .INPUT(predict, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(label, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(dout, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(gradient, TensorType({DT_FLOAT16,DT_FLOAT})) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(SoftMarginLossGrad) + +/** +*@brief Calculate the cross product of two tensors. \n + +*@par Inputs: +*One inputs, including: +* @li x1: A tensor. Must be one of the following types: +* float16, float32, int32, int8, uint8, int16. \n +* @li x2: A tensor. Must be one of the following types: +* float16, float32, int32, int8, uint8, int16. \n + +*@par Attributes: +*@li dim: the dimination of compute.Defaults to -65530. \n + +*@par Outputs: +*y: A Tensor with the same type and shape of x1's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator cross. \n +*/ +REG_OP(Cross) + .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8, DT_INT16})) + .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8, DT_INT16})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8, DT_INT16})) + .ATTR(dim, Int, -65530) + .OP_END_FACTORY_REG(Cross) + +/** + *@brief Computes batched the p-norm distance between each pair of + *the two collections of row vectors. \n + + *@par Inputs: + *Two inputs, including: + * @li x1: A tensor with shpae: BxPXM. Must be one of the following types: + * float16, float32. \n + * @li x2: A tensor with shpae: BxRxM. Must be one of the following types: + * float16, float32. \n + + *@par Attributes: + * @li p: An optional float >= 0 or inf. Defaults to 2.0. \n + + *@par Outputs: + * y: A Tensor with the same type of x1's and with shape BxPxR. \n + + *@par Third-party framework compatibility + *Compatible with the Pytorch operator Cdist. \n + */ +REG_OP(Cdist) + .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(p, Float, 2.0) + .OP_END_FACTORY_REG(Cdist) + +/** +*@brief Computes the grad of x1 in cdist. \n + +*@par Inputs: +*Four inputs, including: + * @li grad: Grad with shape BxPxR. Must be one of the following types: +* float16, float32. \n +* @li x1: A tensor with shpae: BxPXM. Must be one of the following types: +* float16, float32. \n +* @li x2: A tensor with shpae: BxRxM. Must be one of the following types: +* float16, float32. \n +* @li cdist: Output tensor of cdist forward with shpae: BxPXR. +* Must be one of the following types: float16, float32. \n + +*@par Attributes: +* @li p: An optional float >= 0 or inf. Defaults to 2.0. \n + +*@par Outputs: +* y: A Tensor with the same type and shape of x1's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator Cdist Backward. \n +*/ +REG_OP(CdistGrad) + .INPUT(grad, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(x1, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(x2, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(cdist, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT})) + .ATTR(p, Float, 2.0) + .OP_END_FACTORY_REG(CdistGrad) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATH_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index ed23d3f6..b317be37 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. @@ -38,8 +38,8 @@ namespace ge { * float32, int32. Has format [ND, NHWC] . \n *@par Attributes: -*@li transpose_a: A bool. If True, changes the shape of "x1" from [M, K] to [K, M]. -*@li transpose_b: A bool. If True, changes the shape of "x2" from [M, K] to [K, M] . \n +*@li transpose_x1: A bool. If True, changes the shape of "x1" from [M, K] to [K, M]. +*@li transpose_x2: A bool. If True, changes the shape of "x2" from [M, K] to [K, M] . \n *@par Outputs: *y: The result matrix Tensor. 2D. Must be one of the following types: float16, @@ -70,8 +70,8 @@ REG_OP(MatMul) * float32, int32. Has format [ND, NHWC] . \n *@par Attributes: -*@li transpose_a: A bool. If True, changes the shape of "x1" from [M, K] to [K, M]. -*@li transpose_b: A bool. If True, changes the shape of "x2" from [M, K] to [K, M] . \n +*@li transpose_x1: A bool. If True, changes the shape of "x1" from [M, K] to [K, M]. +*@li transpose_x2: A bool. If True, changes the shape of "x2" from [M, K] to [K, M] . \n *@par Outputs: *y: The result matrix Tensor. 2D. Must be one of the following types: float16, @@ -91,6 +91,36 @@ REG_OP(MatMulV2) .ATTR(offset_x, Int, 0) .OP_END_FACTORY_REG(MatMulV2) +/** +*@brief Multiplies matrix "a" by matrix "b", producing "a * b" . \n + +*@par Inputs: +*Two inputs, including: +* @li x1: A matrix Tensor. 2D. Must be one of the following types: int8. +* @li x2: A matrix Tensor. 2D. Must be one of the following types: int8. +* @li compress_index: A compress index matrix of type int8. +* @li bias: A 1D Tensor. Must be one of the following types: int32, float16. + +*@par Attributes: +*@li transpose_x1: A bool. If True, changes the shape of "x1" from [M, K] to [K, M]. +*@li transpose_x2: A bool. If True, changes the shape of "x2" from [M, K] to [K, M] . \n + +*@par Outputs: +*y: The result matrix Tensor. 2D. Must be one of the following types: float16, +* int32. \n + +*/ +REG_OP(MatMulV2Compress) + .INPUT(x1, TensorType({DT_INT8})) + .INPUT(x2, TensorType({DT_INT8})) + .INPUT(compress_index, TensorType({DT_INT8})) + .OPTIONAL_INPUT(bias, TensorType({DT_INT32, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_INT32, DT_FLOAT16})) + .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8})) + .ATTR(transpose_x1, Bool, false) + .ATTR(transpose_x2, Bool, false) + .ATTR(offset_x, Int, 0) + .OP_END_FACTORY_REG(MatMulV2Compress) /** *@brief Performs Matrix-to-matrix Multiply, producing c=alpha[0]*a*b+beta[0]*c . \n @@ -149,15 +179,15 @@ REG_OP(GEMM) *@brief Multiplies matrix "a" by matrix "b", producing "a * b" . \n *@par Inputs: -*Three inputs, including: +*Two inputs, including: * @li x1: A matrix Tensor. Must be one of the following types: float16, * float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ]. * @li x2: A matrix Tensor. Must be one of the following types: float16, * float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ] . \n *@par Attributes: -*@li adj_x: A bool. If True, changes the shape of "x1" from [B, M, K] to [B, K, M]. -*@li adj_y: A bool. If True, changes the shape of "x2" from [B, M, K] to [B, K, M] . \n +*@li adj_x1: A bool. If True, changes the shape of "x1" from [B, M, K] to [B, K, M]. +*@li adj_x2: A bool. If True, changes the shape of "x2" from [B, M, K] to [B, K, M] . \n *@par Outputs: *y: The result matrix Tensor. 2D or higher. Must be one of the following types: float16, @@ -175,6 +205,42 @@ REG_OP(BatchMatMul) .ATTR(adj_x2, Bool, false) .OP_END_FACTORY_REG(BatchMatMul) + +/** +* @brief Multiplies matrix "a" by matrix "b", producing "a * b" . \n + +* @par Inputs: +* Three inputs, including: +* @li x1: A matrix Tensor. Must be one of the following types: float16, +* float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ]. +* @li x2: A matrix Tensor. Must be one of the following types: float16, +* float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ] . \n +* @li bias: A matrix Tensor. Must be one of the following types: float16, +* float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ] . \n + +* @par Attributes: +* @li adj_x1: A bool. If True, changes the shape of "x1" from [B, M, K] to [B, K, M]. +* @li adj_x2: A bool. If True, changes the shape of "x2" from [B, M, K] to [B, K, M] . \n + +* @par Outputs: +* y: The result matrix Tensor. 2D or higher. Must be one of the following types: float16, +* float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ]. Has the same shape length as "x1" and "x2" . \n + +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator BatchMatmul. +*/ + +REG_OP(BatchMatMulV2) + .INPUT(x1, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) + .INPUT(x2, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) + .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .ATTR(adj_x1, Bool, false) + .ATTR(adj_x2, Bool, false) + .ATTR(offset_x, Int, 0) + .OP_END_FACTORY_REG(BatchMatMulV2) + /** *@brief Computes half the L2 norm of a tensor without the sqrt . \n @@ -334,7 +400,7 @@ REG_OP(MatrixSetDiagD) * int64, complex64, qint8, quint8, qint32, uint16, complex128, half, uint32, * uint64 *@li indices: An ND Tensor. -*Must be one of the following types: int32, int64 +*Must be one of the following types: int32 or int64 *@li updates: An ND Tensor. *Must be one of the following types: float16, float32, int8, uint8, double, * int64, complex64, qint8, quint8, qint32, uint16, complex128, half, uint32, @@ -378,6 +444,9 @@ REG_OP(ScatterNdUpdate) *@par Third-party framework compatibility * Compatible with the TensorFlow operator TensorScatterUpdate. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(TensorScatterUpdate) .INPUT(x, TensorType::BasicType()) @@ -386,6 +455,34 @@ REG_OP(TensorScatterUpdate) .OUTPUT(y, TensorType::BasicType()) .OP_END_FACTORY_REG(TensorScatterUpdate) +/** +*@brief Uses "updates" to update tensor "data" by "indices". \n + +*@par Inputs: +* Three inputs, including: +*@li data: An ND Tensor . \n +*Must be one of the following types: float16, float32, int32, int8, uint8 +*@li indices: An ND Tensor of type int32 or int64 +*@li updates: An Tensor. Same shape as indices. format:NCHW, NHWC . \n +*Must be one of the following types: float16, float32, int32, int8, uint8 + +*@par Attributes: +*@li axis: An optional attribute. Defaults to 0. + +*@par Outputs: +*y: A Tensor. Has the same type and format as input "data" . \n + +*@par Third-party framework compatibility +* Compatible with the ONNX operator ScatterElements. +*/ +REG_OP(ScatterElements) + .INPUT(data, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(indices, TensorType::IndexNumberType()) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .ATTR(axis, Int, 0) + .OP_END_FACTORY_REG(ScatterElements) + /** *@brief Adds sparse "updates" to a variable reference . \n @@ -394,7 +491,7 @@ REG_OP(TensorScatterUpdate) *@li var: An ND Tensor . \n *Must be one of the following types: float16, float32, int32, int8, uint8 -*@li indices: An ND Tensor of type int32 or int64. +*@li indices: An ND Tensor of type int32 or int64 *@li updates: An Tensor. format:NCHW, NHWC . \n @@ -412,10 +509,10 @@ REG_OP(TensorScatterUpdate) * Compatible with the TensorFlow operator ScatterAdd. */ REG_OP(ScatterAdd) - .INPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .INPUT(indices, TensorType::IndexNumberType()) - .INPUT(updates, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .OUTPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterAdd) @@ -428,7 +525,7 @@ REG_OP(ScatterAdd) *Must be one of the following types: float16, float, int32, int8, uint8 *@li indices: An ND Tensor. -*Must be one of the following types: int32 +*Must be one of the following types: int32 or int64 *@li updates: An ND Tensor. *Must be one of the following types: float16, float, int32, int8, uint8 @@ -443,10 +540,10 @@ REG_OP(ScatterAdd) * Compatible with the TensorFlow operator ScatterDiv. */ REG_OP(ScatterDiv) - .INPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .INPUT(indices, TensorType({DT_INT32})) - .INPUT(updates, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .OUTPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(indices, TensorType::IndexNumberType()) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterDiv) @@ -458,7 +555,7 @@ REG_OP(ScatterDiv) *@li var: An ND Tensor. *Must be one of the following types: float16, float, int32, int8, uint8 *@li indices: An ND Tensor. -*Must be one of the following types: int32 +*Must be one of the following types: int32 or int64 *@li updates: An ND Tensor. *Must be one of the following types: float16, float, int32, int8, uint8 *@par Attributes: @@ -472,10 +569,10 @@ REG_OP(ScatterDiv) * Compatible with the TensorFlow operator ScatterNdAdd. */ REG_OP(ScatterNdAdd) - .INPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .INPUT(indices, TensorType::IndexNumberType()) - .INPUT(updates, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .OUTPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterNdAdd) @@ -499,6 +596,9 @@ REG_OP(ScatterNdAdd) *@par Third-party framework compatibility * Compatible with the TensorFlow operator TensorScatterAdd. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(TensorScatterAdd) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) @@ -515,7 +615,7 @@ REG_OP(TensorScatterAdd) *@li var: An ND Tensor. *Must be one of the following types: float16, float, int32, int8, uint8 *@li indices: An ND Tensor. -*Must be one of the following types: int32, int64 +*Must be one of the following types: int32 or int64 *@li updates: An ND Tensor. *Must be one of the following types: float16, float, int32, int8, uint8 @@ -530,10 +630,10 @@ REG_OP(TensorScatterAdd) * Compatible with the TensorFlow operator ScatterNdSub. */ REG_OP(ScatterNdSub) - .INPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .INPUT(indices, TensorType::IndexNumberType()) - .INPUT(updates, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .OUTPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterNdSub) @@ -557,6 +657,9 @@ REG_OP(ScatterNdSub) *@par Third-party framework compatibility * Compatible with the TensorFlow operator TensorScatterSub. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(TensorScatterSub) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) @@ -573,7 +676,7 @@ REG_OP(TensorScatterSub) *@li var: An ND Tensor. *Must be one of the following types: float16, float, int32, int8, uint8 *@li indices: An ND Tensor. -*Must be one of the following types: int32, int64 +*Must be one of the following types: int32 or int64 *@li updates: An ND Tensor. *Must be one of the following types: float16, float, int32, int8, uint8 *@par Attributes: @@ -587,10 +690,10 @@ REG_OP(TensorScatterSub) * Compatible with the TensorFlow operator ScatterSub. */ REG_OP(ScatterSub) - .INPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .INPUT(indices, TensorType::IndexNumberType()) - .INPUT(updates, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .OUTPUT(var, TensorType({DT_FLOAT16, DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterSub) @@ -761,7 +864,7 @@ REG_OP(ConfusionMatrix) *@li var: An ND Tensor. *Must be one of the following types: float16, float, int32, int8, uint8 *@li indices: An ND Tensor. -*Must be one of the following types: int32 +*Must be one of the following types: int32 or int64 *@li updates: An ND Tensor . \n *Must be one of the following types: float16, float, int32, int8, uint8 @@ -778,7 +881,7 @@ REG_OP(ConfusionMatrix) */ REG_OP(ScatterMul) .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .INPUT(indices, TensorType({DT_INT32})) + .INPUT(indices, TensorType::IndexNumberType()) .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .ATTR(use_locking, Bool, false) @@ -791,13 +894,13 @@ REG_OP(ScatterMul) *@par Inputs: * Three inputs, including: *@li var: An ND Tensor. -*Must be one of the following types: float16, float, int32 +*Must be one of the following types: float16, float, int32, int8, uint8 *@li indices: An ND Tensor. -*Must be one of the following types: int32 +*Must be one of the following types: int32 or int64 *@li updates: An ND Tensor. -*Must be one of the following types: float16, float, int32 +*Must be one of the following types: float16, float, int32, int8, uint8 *@par Attributes: *use_locking: An optional bool. Defaults to "False". If "True", the operation @@ -810,10 +913,10 @@ REG_OP(ScatterMul) * Compatible with the TensorFlow operator ScatterMin. */ REG_OP(ScatterMin) - .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32})) - .INPUT(indices, TensorType({DT_INT32})) - .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32})) - .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32})) + .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(indices, TensorType::IndexNumberType()) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterMin) @@ -824,13 +927,13 @@ REG_OP(ScatterMin) * Three inputs, including: *@li var: An ND Tensor . \n -*Must be one of the following types: float16, float, int32 +*Must be one of the following types: float16, float, int32, int8, uint8 *@li indices: An NCHW, NHWC, or ND Tensor . \n -*Must be one of the following types: int32 +*Must be one of the following types: int32 or int64 *@li updates: An NCHW, NHWC, or ND Tensor . \n -*Must be one of the following types: float16, float, int32 +*Must be one of the following types: float16, float, int32, int8, uint8 *@par Attributes: *use_locking: An optional bool. Defaults to "False". @@ -843,10 +946,10 @@ REG_OP(ScatterMin) * Compatible with the TensorFlow operator ScatterMax. */ REG_OP(ScatterMax) - .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32})) - .INPUT(indices, TensorType({DT_INT32})) - .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32})) - .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32})) + .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(indices, TensorType::IndexNumberType()) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterMax) @@ -860,7 +963,7 @@ REG_OP(ScatterMax) *Must be one of the following types: float16, float, int32, int8, uint8 *@li indices: An ND Tensor . \n -*Must be one of the following types: int32 +*Must be one of the following types: int32 or int64 *@li updates: An ND Tensor . \n *Must be one of the following types: float16, float, int32, int8, uint8 @@ -876,10 +979,10 @@ REG_OP(ScatterMax) * Compatible with the TensorFlow operator ScatterUpdate. */ REG_OP(ScatterUpdate) - .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT8,DT_UINT8})) - .INPUT(indices, TensorType({DT_INT32})) - .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT8,DT_UINT8})) - .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT8,DT_UINT8})) + .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(indices, TensorType::IndexNumberType()) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterUpdate) @@ -979,6 +1082,137 @@ REG_OP(MatrixDiagV2) .OUTPUT(output, TensorType::BasicType()) .OP_END_FACTORY_REG(MatrixDiagV2) +/** +* @brief Add updates to var_out according to axis and indices. + +* @par Inputs: +* Three inputs, including: +* @li var: A Tensor. Must be one of the following types: +* float16, float32, int32, int8, uint8. +* @li indices: A Tensor of the indices, type should be int32. +* @li updates: A Tensor of the same type as "var". + +* @par Attributes: +* @li axis: An required int to specify the axis to perform indices add. + +* @par Outputs: +* @li var_out: A Tensor. Same as input "var". + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator index_add. + +* @par Restrictions: +* Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(IndexAdd) + .INPUT(var, TensorType({DT_INT32, DT_INT8, DT_UINT8, DT_FLOAT32, DT_FLOAT16})) + .INPUT(indices, TensorType({DT_INT32})) + .INPUT(updates, TensorType({DT_INT32, DT_INT8, DT_UINT8, DT_FLOAT32, DT_FLOAT16})) + .OUTPUT(var_out, TensorType({DT_INT32, DT_INT8, DT_UINT8, DT_FLOAT32, DT_FLOAT16})) + .ATTR(axis, Int, 0) + .OP_END_FACTORY_REG(IndexAdd) + +/** +*@brief: Returns the upper triangular part of a matrix (2-D tensor) or batch of matrices input \n + +*@par Inputs: +* Two inputs, including: +*@li x: A Tensor. Must be one of the following types: +* float16, float32, double, int32, uint8, int16, int8, complex64, int64, +* qint8, quint8, qint32, uint16, complex128, uint32, uint64. +*@li diagonal:(int, optional) – the diagonal to consider。\n + +*@par Outputs: +*y: A Tensor. Has the same type as "x" . \n + +*@par Third-party framework compatibility +* Compatible with the Pytorch operator Triu. +*/ +REG_OP(Triu) + .INPUT(x, TensorType::BasicType()) + .ATTR(diagonal, Int, 0) + .OUTPUT(y, TensorType::BasicType()) + .OP_END_FACTORY_REG(Triu) + +/** +*@brief: Returns the upper triangular part of a matrix (2-D tensor) or batch of matrices input \n + +*@par Inputs: +* Two inputs, including: +*@li x: A Tensor. Must be one of the following types: +* float16, float32, double, int32, uint8, int16, int8, complex64, int64, +* qint8, quint8, qint32, uint16, complex128, uint32, uint64. +*@li diagonal:(int, optional) – the diagonal to consider。\n + +*@par Outputs: +*y: A Tensor. Has the same type as "x" . \n + +*@par Third-party framework compatibility +* Compatible with the Pytorch operator Tril. +*/ +REG_OP(Tril) + .INPUT(x, TensorType::BasicType()) + .ATTR(diagonal, Int, 0) + .OUTPUT(y, TensorType::BasicType()) + .OP_END_FACTORY_REG(Tril) +/** +*@brief Concatenates a list of N tensors along the first dimension. +*@par Inputs: +* Two inputs, including: +* @li values: A list of Tensors. Must be one of the following types: int32, float16, float32. +* Tensors to be concatenated. All must have size 1 in the first dimension and same shape. +* It's a dynamic input. +* @li shape: A Tensor of the same type as "x". +* The final shape of the result. Should be equal to the shapes of any input +* but with the number of input values in the first dimension . \n + +*@par Attributes: +*equation: The subscripts for the Einstein summation. \n +*N: tensor size of input \n + +*@par Outputs: +*@li y: Sums the product of the elements of the input operands along dimensions specified + using a notation based on the Einstein summation convention. \n + +*@attention Constraints: +*Input N must be Int. \n + +*@par Third-party framework compatibility +*Compatible with Pytorch einsum operator. +*/ +REG_OP(Einsum) + .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .REQUIRED_ATTR(equation, String) + .REQUIRED_ATTR(N, Int) + .OP_END_FACTORY_REG(Einsum) + +/** +*@brief Returns a 2-D tensor with ones on the diagonal and zeros elsewhere. \n + +*@par Inputs: +*No inputs + +*@par Attributes: +*@li num_rows: An required int. \n +*@li num_columns: An optional int.Defaults to 0. \n +*@li batch_shape: An optional ListInt.Defaults to []. \n +*@li dtype: An optional int.Defaults to 0. \n + +*@par Outputs: +*y: A Tensor with targeted type and shape. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator Eye. \n +*/ +REG_OP(Eye) + .OUTPUT(y, TensorType::BasicType()) /* "Result, has targeted element type" */ + .REQUIRED_ATTR(num_rows, Int) + .ATTR(num_columns, Int, 0) + .ATTR(batch_shape, ListInt, {}) + .ATTR(dtype, Int, 0) + .OP_END_FACTORY_REG(Eye) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATRIX_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h index 0c6a5dff..9629976e 100644 --- a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -144,6 +144,64 @@ REG_OP(BatchNorm) /** *@brief Performs batch normalization . \n +*@par Inputs: +* Five inputs, including: (NHWC, NCHW, or NC1HWC0 supported) +*@li x: A 3D or 6D Tensor of type float16 or float32, with format NDHWC or NCDHW for 4D or NDC1HWC0 for 6D. +*@li scale: A Tensor of type float32. Must be 1D if input "x" is with format NDHWC or NCDHW. Must be 6D +if input "x" is with format NDC1HWC0. Specifies the scaling factor. +*@li offset: A Tensor of type float32. Must be 3D if input "x" is with format NDHWC or NCDHW. Must be 6D +if input "x" is with format NC1HWC0. Specifies the offset. +*@li mean: A Tensor of type float32. Must be 3D if input "x" is with format NDHWC or NCDHW. Must be 6D +if input "x" is with format NC1HWC0. Specifies the mean used for inference. Must be "None" if the +operation is used for training. +*@li variance: A Tensor of type float32. Must be 3D if input "x" is with format NHWC or NCHW. Must be +5D if input "x" is with format NC1HWC0. Specifies the variance used for inference. Must be "None" +if the operation is used for training . \n + +*@par Attributes: +*@li epsilon: An optional float32, specifying the small value added to variance to avoid dividing by zero. Defaults to "0.0001". +*@li data_format: An optional string, specifying the format of "x". Defaults to "NHWC". +*@li is_training: An optional bool, specifying if the operation is used for training or inference. Defaults to "True" . \n + +*@par Outputs: +* Five outputs, including: (NHWC, NCHW, or NC1HWC0 supported) +*@li y: A 3D or 6D Tensor of type float16 or float32 for the normalized "x", with format NDHWC or NCDHW for 4D or NDC1HWC0 for 6D. +*@li batch_mean: A Tensor of type float32. Must be 3D if input "x" is with format NDHWC or NCDHW. Must be 6D +if input "x" is with format NDC1HWC0. Specifies the mean of "x". +*@li batch_variance: A Tensor of type float32. Must be 1D if input "x" is with format NDHWC or NCDHW. +Must be 6D if input "x" is with format NDC1HWC0. Specifies the variance of "x". +*@li reserve_space_1: An optional Tensor of type float32. Must be 1D if input "x" is with format NDHWC or NCDHW. +Must be 6D if input "x" is with format NDC1HWC0. Specifies the mean of "x" for gradient computation. Pass "None" to skip this output. +*@li reserve_space_2: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. +Must be 6D if input "x" is with format NDC1HWC0. Specifies the variance of "x" for gradient computation. Pass "None" to skip this output . \n + +*@attention Constraints: +*@li If the operation is used for inference and outputs "reserve_space_1" and "reserve_space_2" are available, +then "reserve_space_1" has the same value as "mean" and "reserve_space_2" has the same value as "variance". +*@li For Ascend 310, the result accuracy fails to reach 1‰ due to the square root instruction . \n + +*@par Third-party framework compatibility +*@li Compatible with the TensorFlow operator fused_batch_norm. +*@li Compatible with the TensorFlow operator fused_batch_norm_v2. +*/ +REG_OP(BatchNorm3D) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(scale, TensorType({DT_FLOAT})) + .INPUT(offset, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(mean, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(variance, TensorType({DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(batch_mean, TensorType({DT_FLOAT})) + .OUTPUT(batch_variance, TensorType({DT_FLOAT})) + .OUTPUT(reserve_space_1, TensorType({DT_FLOAT})) + .OUTPUT(reserve_space_2, TensorType({DT_FLOAT})) + .ATTR(epsilon, Float, 0.0001) + .ATTR(data_format, String, "NCDHW") + .ATTR(is_training, Bool, true) + .OP_END_FACTORY_REG(BatchNorm3D) +/** +*@brief Performs batch normalization . \n + *@par Inputs: * Five inputs, including: (NHWC or NCHW supported) *@li x: A 4D Tensor of type float16 or float32. @@ -242,6 +300,52 @@ REG_OP(BatchNormGrad) /** *@brief Performs the backpropagation of BatchNorm . \n +*@par Inputs: +* Five inputs, including: +*@li y_backprop: A 3D or 6D Tensor of type float16 or float32, with format NDHWC, NCDHW, or NDC1HWC0, for the gradient. +*@li x: A 3D or 6D Tensor of type float16 or float32, with format NDHWC, NCDHW, or NDC1HWC0. +*@li scale: A 3D or 6D Tensor of type float32, with format NDHWC, NCDHW, or NDC1HWC0. +*@li reserve_space_1: A 3D or 6D Tensor of type float32, with format NDHWC, NCDHW, or NC1HWC0. It is an output of BatchNorm. +*@li reserve_space_2: A 3D or 6D Tensor of type float32, with format NDHWC, NCDHW, or NC1HWC0. It is an output of BatchNorm . \n + +*@par Attributes: +*@li epsilon: An optional float32. Defaults to "0.0001". A small float number added to the variance of "x". +*@li data_format: An optional string. Defaults to "NCDHW". +*@li is_training: An optional bool. Defaults to "true". Specifies the operation is for training (default) or inference . \n + +*@par Outputs: +*@li x_backprop: A Tensor of type float16 or float32, with format NHWC, NCHW, or NC1HWC0, for the offset of "x". +*@li scale_backprop: A Tensor of type float32, with format NDHWC, NCDHW, or NDC1HWC0, for the offset of "scale". +*@li *offset_backprop: A Tensor of type float32, with format NDHWC, NCDHW, or NDC1HWC0, for the offset of "offset". +*@li *reserve_space_4: A Tensor of type float32, with shape NDHWC, NCDHW, or NDC1HWC0. Pass "None" to skip this output. +*@li *reserve_space_5: A Tensor of type float32, with shape NDHWC, NCDHW, or NDC1HWC0. Pass "None" to skip this output . \n + +*@attention Constraints: +* The preceding layer of this operator must be operator BatchNorm . \n + +*@see BatchNorm +*@par Third-party framework compatibility +* Compatible with the TensorFlow operators FusedBatchNormGradV2 and FusedBatchNorm3DGrad. +*/ +REG_OP(BatchNorm3DGrad) + .INPUT(y_backprop, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(scale, TensorType({DT_FLOAT})) + .INPUT(reserve_space_1, TensorType({DT_FLOAT})) + .INPUT(reserve_space_2, TensorType({DT_FLOAT})) + .OUTPUT(x_backprop, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(scale_backprop, TensorType({DT_FLOAT})) + .OUTPUT(offset_backprop, TensorType({DT_FLOAT})) + .OUTPUT(reserve_space_4, TensorType({DT_FLOAT})) + .OUTPUT(reserve_space_5, TensorType({DT_FLOAT})) + .ATTR(epsilon, Float, 0.0001) + .ATTR(data_format, String, "NCDHW") + .ATTR(is_training, Bool, true) + .OP_END_FACTORY_REG(BatchNorm3DGrad) + +/** +*@brief Performs the backpropagation of BatchNorm . \n + *@par Inputs: * Five inputs, including: *@li y_backprop: A 4D Tensor of type float16 or float32, with format NHWC or NCHW, for the gradient. @@ -315,35 +419,7 @@ REG_OP(BNInference) .ATTR(use_global_stats, Bool,true) .ATTR(mode, Int,1) .OP_END_FACTORY_REG(BNInference) -/** -*@brief aicpu batch normalization host . \n -*@par Inputs: - -*@li mean: A Tensor of type float32 or float16. Must be 1D if input "x" Specifies the mean used for inference. -*@li variance: A Tensor of type float32 or float16 . Must be 1D if input "x" Specifies the variance used for inference. -*@li momentum: An optional float, mean and variance's Scale factor -*@par Attributes: -*@li epsilon: An optional float32, specifying the small value added to variance to avoid dividing by zero. Defaults to "0.00001". -*@li use_global_stats: mean inference mode , only can be "True". -*@li mode: An optional attr, not use -*@par Outputs: -*@li alpha: A Tensor of type float16 or float32 for the cpu calculate mean -*@li beta: A Tensor of type float16 or float32 for the cpu calculate variance -*/ -REG_OP(BnHost) - .INPUT(mean, TensorType({DT_FLOAT, DT_FLOAT16})) - .INPUT(variance, TensorType({DT_FLOAT, DT_FLOAT16})) - .INPUT(momentum, TensorType({DT_FLOAT16,DT_FLOAT})) - .OPTIONAL_INPUT(scale, TensorType({DT_FLOAT16,DT_FLOAT})) - .OPTIONAL_INPUT(offset, TensorType({DT_FLOAT16,DT_FLOAT})) - .ATTR(epsilon, Float, 0.00001) - .ATTR(mode, Int, 1) - .ATTR(use_global_stats, Bool, true) - .OUTPUT(alpha, TensorType({DT_FLOAT, DT_FLOAT16})) - .OUTPUT(beta, TensorType({DT_FLOAT, DT_FLOAT16})) - .OUTPUT(mu, TensorType({DT_FLOAT16,DT_FLOAT})) - .OP_END_FACTORY_REG(BnHost) /** *@brief Performs batch normalization . \n diff --git a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h index 35296870..98473c65 100644 --- a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -365,6 +365,25 @@ REG_OP(BiasAddGrad) * 4-D with shape [batch, out_height, out_width, out_channels] * or [batch, out_channels, out_height, out_width]. * Gradients with respect to the output of the convolution. + *\n + *\n + * The following are the supported data types and data formats: +*@verbatim + | Tensor | out_bckprop | filter | y + ------------|-------------|---------|-------- + | Data Type | float16 | float16 | float16 + | |-------------|---------|-------- + | | float32 | float32 | float32 + | |-------------|---------|-------- + | | float64 | float64 | float64 + ------------|-------------|---------|-------- + | Format | NCHW | NCHW | NCHW + | | NHWC | HWCN | NHWC +@endverbatim + * For float32 and float64 type, the actual calculation on the chip is based on + * float16. + *\n + * *@par Attributes: * Five attributes: * @li strides: A tuple/list of 4 integers. The stride of the sliding window @@ -377,8 +396,53 @@ REG_OP(BiasAddGrad) * channels. * @li data_format: An optional string from: "NHWC", "NCHW". Defaults to * "NHWC". Specify the data format of the input and output data. + *\n + *\n + * The following value range restrictions must be met: +*@verbatim + | Name | Field | Scope + -------------------|----------|-------------- + | input_size | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | Filter | H | [1, 255] + | | W | [1, 255] + -------------------|----------|-------------- + | out_backprop | H*strideH| [1, 4096] + | | W*strideW| [1, 4096] + -------------------|----------|-------------- + | y(fmap) | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | Stride | H | [1, 63] + | | W | [1, 63] + -------------------|----------|-------------- + | Padding | Top | [0, 255] + | | Bottom | [0, 255] + | | Left | [0, 255] + | | Right | [0, 255] + -------------------|----------|-------------- + | Dilation | H | [1, 255] + | | W | [1, 255] + +@endverbatim + * In Ascend910, fmap or out_backprop's H and W not support 1 when + * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 + * If filter_h = 1 and filter_w = 1, out_backprop_w * stride_h * stride_w < 4096 + *\n + * *@par Outputs: * y: A Tensor. Has the same type as filter,and has same format as input_size. + *\n + * out_backprop_height = (fmap_height + pad_top + pad_bottom - + * (dilation_h * (filter_height - 1) + 1)) + * / stride_h + 1 + *\n + * out_backprop_width = (fmap_width + pad_left + pad_right - + * (dilation_w * (filter_width - 1) + 1)) + * / stride_w + 1 + *\n + * *@par Third-party framework compatibility * Compatible with Tensorflow's conv2d_backprop_input */ @@ -454,6 +518,21 @@ REG_OP(Conv2DBackpropInputD) * @li bias: An optional tensor. Must have the same type as "y". * @li offset_w: An optional 1D tensor for quantized deconvolution. * Type is int8. Reserved.\n + *\n + *\n + * The following are the supported data types and data formats: +*@verbatim + | Tensor | x | filter | bias | y + ------------|---------|---------|---------|-------- + | Data Type | float16 | float16 | float16 | float16 + | |---------|---------|---------|-------- + | | int8 | int8 | int32 | int32 + ------------|---------|---------|---------|-------- + | Format | NCHW | NCHW | ND | NCHW +@endverbatim + * For int8, a dequant or requant operator must be followed. + *\n + * *@par Attributes: * Six attributes: * @li strides: A tuple or list of 2 integers. The stride of the sliding window @@ -467,9 +546,54 @@ REG_OP(Conv2DBackpropInputD) * @li data_format: An optional string from: "NCHW". Defaults to "NCHW". \n Specify the data format of the input and output data. * @li offset_x: An optional integer for quantized deconvolution. - * Defaults to "0". + * The negative offset added to the input image for int8 type. Ensure offset_x + * within the effective range of int8 [-128, 127]. Defaults to "0". + *\n + *\n + * The following value range restrictions must be met: +*@verbatim + | Name | Field | Scope + -------------------|----------|-------------- + | x (out_backprop) | H*strideH| [1, 4096] + | | W*strideW| [1, 4096] + -------------------|----------|-------------- + | Filter | H | [1, 255] + | | W | [1, 255] + -------------------|----------|-------------- + | y (fmap) | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | Stride | H | [1, 63] + | | W | [1, 63] + -------------------|----------|-------------- + | Padding | Top | [0, 255] + | | Bottom | [0, 255] + | | Left | [0, 255] + | | Right | [0, 255] + -------------------|----------|-------------- + | Dilation | H | [1, 255] + | | W | [1, 255] + -------------------|----------|-------------- + | Offset_x | | [-128, 127] + +@endverbatim + * In Ascend910, fmap or out_backprop's H and W not support 1 when + * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 + * If filter_h = 1 and filter_w = 1, out_backprop_w * stride_h * stride_w < 4096 + *\n + * *@par Outputs: * y: A Tensor. 4D tensor with shape [batch, channels, height, width]. + *\n + * out_backprop_height = (fmap_height + pad_top + pad_bottom - + * (dilation_h * (filter_height - 1) + 1)) + * / stride_h + 1 + *\n + * out_backprop_width = (fmap_width + pad_left + pad_right - + * (dilation_w * (filter_width - 1) + 1)) + * / stride_w + 1 + *\n + * * When type of x is float16, the type of y must be float16. * When type of x is int8, the type of y must be int32. */ @@ -502,6 +626,25 @@ REG_OP(Deconvolution) * [batch, out_height, out_width, out_channels] or [batch, out_channels, * out_height, out_width]. Gradients with respect to the output of the * convolution. + *\n + *\n + * The following are the supported data types and data formats: +*@verbatim + | Tensor | x | out_backprop | y + ------------|---------|--------------|--------- + | Data Type | float16 | float16 | float16 + | |---------|--------------|--------- + | | float32 | float32 | float32 + | |---------|--------------|--------- + | | float64 | float64 | float64 + |-----------|---------|--------------|--------- + | Format | NCHW | NCHW | NCHW + | | NHWC | NHWC | HWCN +@endverbatim + * For float32 and float64 type of x and outbackprop, the actual calculation on the chip + * is based on float16. + *\n + * *@par Attributes: * Five attributes: * @li strides: A tuple/list of 4 integers. The stride of the sliding window @@ -514,8 +657,52 @@ REG_OP(Deconvolution) * channels. * @li data_format: An optional string from: "NHWC", "NCHW". Defaults to * "NHWC". Specify the data format of the input and output data. + *\n +*\n +* The following value range restrictions must be met: +*@verbatim + | Name | Field | Scope + -------------------|----------|-------------- + | x(fmap) | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | Filter Size | H | [1, 255] + | | W | [1, 255] + -------------------|----------|-------------- + | out_backprop | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | y | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | Stride | H | [1, 63] + | | W | [1, 63] + -------------------|----------|-------------- + | Padding | Top | [0, 255] + | | Bottom | [0, 255] + | | Left | [0, 255] + | | Right | [0, 255] + -------------------|----------|-------------- + | Dilation | H | [1, 255] + | | W | [1, 255] + +@endverbatim + * In Ascend910, out_backprop's H and W not support 1 when + * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 + *\n + * *@par Outputs: * y: A Tensor. Has the same type as x, has the same format as filter_size. + *\n + * out_backprop_height = (in_height + pad_top + pad_bottom - + * (dilation_h * (filter_height - 1) + 1)) + * / stride_h + 1 + *\n + * out_backprop_width = (in_width + pad_left + pad_right - + * (dilation_w * (filter_width - 1) + 1)) + * / stride_w + 1 + *\n + * *@par Third-party framework compatibility * Compatible with Tensorflow's conv2d_backprop_filter */ @@ -597,16 +784,14 @@ REG_OP(Conv2DBackpropFilterD) | Tensor | x | filter | bias | y ------------|---------|---------|---------|-------- | Data Type | float16 | float16 | float16 | float16 - | |---------|---------|---------|-------- | | float32 | float32 | float32 | float32 - | |---------|---------|---------|-------- | | int8 | int8 | int32 | int32 ------------|---------|---------|---------|-------- | Format | NCHW | NCHW | ND | NCHW | | NHWC | HWCN | | NHWC @endverbatim * For float32 type, the actual calculation on the chip is based on -* float16. For int8, a dequant or requant operator must be followed. +* float16. *\n * *@par Attributes: @@ -617,8 +802,7 @@ REG_OP(Conv2DBackpropFilterD) * (top, bottom, left, right) side of the input. *@li dilations: Optional. A list of 4 integers. The dilation factor for each * dimension of input. The dimension order is determined by the data format of -* "x". The N and C dimensions must be set to 1. The H and W dimensions must be -* set to 1 for int8 type. Defaults to [1, 1, 1, 1]. +* "x". The N and C dimensions must be set to 1. Defaults to [1, 1, 1, 1]. *@li groups: Optional. An integer of type int32. The number of blocked * connections from input channels to output channels. In_channels and * out_channels must both be divisible by "groups". Defaults to 1. @@ -652,6 +836,8 @@ REG_OP(Conv2DBackpropFilterD) | Offset_x | | [-128, 127] @endverbatim +* The W dimension of the input image supports cases exceeding 4096, but it may +* cause compilation errors. *\n * *@par Outputs: @@ -666,21 +852,6 @@ REG_OP(Conv2DBackpropFilterD) * out_width = (in_width + pad_left + pad_right - * (dilation_w * (filter_width - 1) + 1)) * / stride_w + 1 -* -*@attention Constraints: -*@li The following restrictions on the output must be met: -*@verbatim - | Output | Restrictions - ----------|-------------------------------- - | H == 1 | H * W(input) == H * W(filter) - | W == 1 | - ----------|-------------------------------- - | H != 1 | W(input) == W(filter) - | W == 1 | Only for Ascend310 Hi3796V300CS -@endverbatim -* "H * W (input)" indicates the image size after padding and "H * W (filter)" -* indicates the filter size after dilation."W(input)" and W(filter) indicate -* the same rule on the W dimension. *\n * *@par Quantization supported or not @@ -778,7 +949,7 @@ REG_OP(Conv2DCompress) * With the format "HWCN" , the data is stored in the order of: [filter_height, * filter_width, in_channels / groups, out_channels]. *@li offsets: A 4D tensor of x-y coordinates offset and mask. With the format -* "NHWC", the data is stored in the order of: [batch, in_height, in_width, +* "NHWC", the data is stored in the order of: [batch, out_height, out_width, * deformable_groups * filter_height * filter_width * 3]. *@li bias: An optional 1D tensor of additive biases to the filter outputs. * The data is stored in the order of: [out_channels]. @@ -816,31 +987,20 @@ REG_OP(Conv2DCompress) *@li deformable_groups: Optional. An integer of type int32. The number of * deformable group partitions. In_channels must be divisible by * "deformable_groups". Defaults to 1. +*@li modulated: Optional. Specify version of DeformableConv2D, true means v2, +* false means v1, currently only support v2. *\n *\n * The following value range restrictions must be met: *@verbatim | Name | Field | Scope --------------------|--------|---------------------------- - | Input Image Size | H | [1, 100000] - | | W | [1, 4096] - --------------------|--------|---------------------------- - | Filter Size | H | [1, 255] - | | W | [1, 255] + | Input Image Size | H | [1, 100000 / filter_height] + | | W | [1, 4096 / filter_width] --------------------|--------|---------------------------- - | Stride | H | [1, 63] + | Filter Size | H | [1, 63] | | W | [1, 63] - --------------------|--------|---------------------------- - | Padding | Top | [0, 255] - | | Bottom | [0, 255] - | | Left | [0, 255] - | | Right | [0, 255] - ------------ -------|--------|---------------------------- - | Dilation | H | [1, 255] - | | W | [1, 255] @endverbatim -* "W(input)" indicate the image width after padding and W(filter) indicates the -* filter width after dilation. *\n * *@par Outputs: @@ -855,21 +1015,7 @@ REG_OP(Conv2DCompress) * out_width = (in_width + pad_left + pad_right - * (dilation_w * (filter_width - 1) + 1)) * / stride_w + 1 -* -*@attention Constraints: -*@li The following restrictions on the output must be met: -*@verbatim - | Output | Restrictions - ----------|-------------------------------- - | H == 1 | H * W(input) == H * W(filter) - | W == 1 | - ----------|-------------------------------- - | H != 1 | W(input) == W(filter) - | W == 1 | Only for Ascend310 Hi3796V300CS -@endverbatim -* "H * W(input)" indicates the image size after padding and "H * W(filter)" -* indicates the filter size after dilation. "W(input)" and W(filter) indicate -* the same rule on the W dimension. +*\n * *@par Quantization supported or not *@li No @@ -891,6 +1037,7 @@ REG_OP(DeformableConv2D) .ATTR(groups, Int, 1) .ATTR(data_format, String, "NHWC") .ATTR(deformable_groups, Int, 1) + .ATTR(modulated, Bool, true) .OP_END_FACTORY_REG(DeformableConv2D) /** @@ -916,12 +1063,12 @@ REG_OP(DeformableConv2D) *@par Attributes: * @li groups: Number of blocked connections from input channels to output - * channels. Reserved. + * channels. * @li data_format: An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. * @li dilations: A list of 5 integers. Specifies the dilation factor for each - * dimension of "x", now only support [1,1,1,1,1] - * The N and C dimensions must be 1. Has the same format as "x". + * dimension of "x". + * The N, C and D dimensions must be 1. Has the same format as "x". * @li offset_x: An optional int. Input offset, used for quantized inference. * Defaults to 0. Reserved . \n @@ -967,8 +1114,8 @@ REG_OP(Conv3D) *@par Required Attributes: * @li strides: A list of 5 integers. Specifies the stride of the sliding window - * for each dimension of "x". - * The N and C dimensions must be 1. Has the same format as "x". + * for each dimension of "out_backprop". + * The N and C dimensions must be 1. Has the same format as "out_backprop". * @li pads: A list of 6 integers. * Supports only padding along the D, H and W dimensions in sequence of head, * tail, top, bottom, left and right . \n @@ -976,14 +1123,15 @@ REG_OP(Conv3D) *@par Attributes: * Three attributes: * @li groups: Number of blocked connections from input channels to output - * channels. Reserved. + * channels. * @li data_format: An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. * @li dilations: A tuple/list of 5 integers, The dilation factor for each - * dimension of the input, now only support [1,1,1,1,1] + * dimension of the input. + * The N, C and D dimensions must be 1. Has the same format as "out_backprop". *@par Outputs: - * y: A Tensor. Has the same type as filter,and has same format as input_size + * y: A Tensor. Has the same type as filter,and has same format as "input_size" *@par Third-party framework compatibility * Compatible with Tensorflow's conv3d_backprop_input @@ -1011,8 +1159,8 @@ REG_OP(Conv3DBackpropInput) *@par Required Attributes: * @li strides: A list of 5 integers. Specifies the stride of the sliding window - * for each dimension of "x". - * The N and C dimensions must be 1. Has the same format as "x". + * for each dimension of "out_backprop". + * The N and C dimensions must be 1. Has the same format as "out_backprop". * @li pads: A list of 6 integers. Supports only padding along the D, H and W * dimensions in sequence of head, tail, top, bottom, left and right. * @li input_size: A tuple/list of type int32, int64. An integer vector @@ -1023,13 +1171,14 @@ REG_OP(Conv3DBackpropInput) *@par Attributes: * Three attributes: * @li groups: Number of blocked connections from input channels to output - * channels. Reserved. + * channels. * @li data_format: An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. * @li dilations: A tuple/list of 5 integers, The dilation factor for each - * dimension of input, now only support [1,1,1,1,1] + * dimension of input. + * The N, C and D dimensions must be 1. Has the same format as "out_backprop". *@par Outputs: - * y: A Tensor. Has the same type and data format as out_backprop. + * y: A Tensor. Has the same type and data format as "out_backprop". *@par Third-party framework compatibility * Compatible with Tensorflow's conv3d_backprop_input @@ -1072,9 +1221,7 @@ REG_OP(Conv3DBackpropInputD) * @li c_t: A optinal Tensor dtype of float16, float32. The cell state at time t . \n *@par Third-party framework compatibility: -* Compatible with the Pytorch operator adds. -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* Compatible with the Caffe operator LSTM. */ REG_OP(LSTM) .INPUT(x, TensorType({DT_FLOAT16})) @@ -1121,14 +1268,15 @@ REG_OP(LSTM) *@par Attributes: * Three attributes: * @li dilations: A tuple/list of 5 integers, The dilation factor for each - * dimension of input, now only support [1,1,1,1,1]. + * dimension of input. + * The N, C and D dimensions must be 1. Has the same format as "x". * @li groups: Number of blocked connections from input channels to output - * channels. Reserved. + * channels. * @li data_format: An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. *@par Outputs: - * y: A Tensor that has the same type as x + * y: A Tensor that has the same type as "x" * and the format is NDHWC, NCDHW or DHWCN. *@par Third-party framework compatibility * Compatible with Tensorflow's conv3d_backprop_filter @@ -1172,9 +1320,10 @@ REG_OP(Conv3DBackpropFilter) *@par Attributes: * Three attributes: * @li dilations: A tuple/list of 5 integers, The dilation factor for each - * dimension of input, now only support [1,1,1,1,1]. + * dimension of input. + * The N, C and D dimensions must be 1. Has the same format as "x". * @li groups: Number of blocked connections from input channels to output - * channels. Reserved. + * channels. * @li data_format: An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. @@ -1224,15 +1373,16 @@ REG_OP(Conv3DBackpropFilterD) *@par Attributes: * Five attributes: * @li groups: Number of blocked connections from input channels to output - * channels. Reserved. + * channels. * @li dilations: A tuple/list of 5 integers, - * The dilation factor for each dimension of input, now only support [1,1,1,1,1] + * The dilation factor for each dimension of input. + * The N, C and D dimensions must be 1. Has the same format as "x". * @li data_format: An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. * @li output_padding: The size will be added in the output shape. * @li offset_x: Input offset_x value. Reserved. *@par Outputs: - * y: A Tensor. Has the same type and format as x. + * y: A Tensor. Has the same type and format as "x". */ REG_OP(Conv3DTranspose) .INPUT(input_size, TensorType({DT_INT32, DT_INT64})) @@ -1273,15 +1423,16 @@ REG_OP(Conv3DTranspose) *@par Attributes: * Five attributes: * @li dilations: A tuple/list of 5 integers, The dilation factor for each - * dimension of input, now only support [1,1,1,1,1] + * dimension of input. + * The N, C and D dimensions must be 1. Has the same format as "x". * @li groups: Number of blocked connections from input channels to output - * channels. Reserved. + * channels. * @li data_format: An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. * @li output_padding: The size will be added in the output shape. * @li offset_x: Input offset_x value. Reserved. *@par Outputs: - * y: A Tensor. Has the same type and format as x. + * y: A Tensor. Has the same type and format as "x". *@par Restrictions: * Warning: THIS FUNCTION IS DEPRECATED. Please use Conv3DTranspose instead. */ @@ -1316,6 +1467,22 @@ REG_OP(Conv3DTransposeD) * or [out_channels, in_channel, filter_height, filter_width]. * @li bias: An optional 1D tensor of type float16 or int32. Format is "ND". * @li offset_w: An optional 1D tensor for quantized inference. Reserved. + *\n + *\n + * The following are the supported data types and data formats: +*@verbatim + | Tensor | x | filter | bias | y + ------------|---------|---------|---------|-------- + | Data Type | float16 | float16 | float16 | float16 + | |---------|---------|---------|-------- + | | int8 | int8 | int32 | int32 + ------------|---------|---------|---------|-------- + | Format | NCHW | NCHW | ND | NCHW + | | NHWC | HWCN | | NHWC +@endverbatim + * For int8, a dequant or requant operator must be followed. + *\n + * *@par Required Attributes: * @li strides: A required tuple/list of 4 integers. The stride of the sliding * window for H/W dimension. The index of H/W is same as data_format. @@ -1333,10 +1500,58 @@ REG_OP(Conv3DTransposeD) * @li output_padding: The size will be added in the output shape. Defaults * to [0, 0, 0, 0]. * @li offset_x: An optional int. Input offset, used for quantized inference. - * Defaults to "0". + * The negative offset added to the input image for int8 type. Ensure offset_x + * within the effective range of int8 [-128, 127]. Defaults to "0". + *\n + *\n + * The following value range restrictions must be met: +*@verbatim + | Name | Field | Scope + -------------------|----------|-------------- + | input_size | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | x (out_backprop) | H*strideH| [1, 4096] + | | W*strideW| [1, 4096] + -------------------|----------|-------------- + | filter | H | [1, 255] + | | W | [1, 255] + -------------------|----------|-------------- + | y (fmap) | H | [1, 4096] + | | W | [1, 4096] + -------------------|----------|-------------- + | Stride | H | [1, 63] + | | W | [1, 63] + -------------------|----------|-------------- + | Padding | Top | [0, 255] + | | Bottom | [0, 255] + | | Left | [0, 255] + | | Right | [0, 255] + -------------------|----------|-------------- + | Dilation | H | [1, 255] + | | W | [1, 255] + -------------------|----------|-------------- + | Offset_x | | [-128, 127] + +@endverbatim + * In Ascend910, fmap or out_backprop's H and W not support 1 when + * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 + * If filter_h = 1 and filter_w = 1, out_backprop_w * stride_h * stride_w < 4096 + *\n + * *@par Outputs: * y: A Tensor. A Tensor of type float16 or int32, and has same format as * input_size. + *\n + * out_backprop_height = (fmap_height + pad_top + pad_bottom - + * (dilation_h * (filter_height - 1) + 1)) + * / stride_h + 1 + *\n + * out_backprop_width = (fmap_width + pad_left + pad_right - + * (dilation_w * (filter_width - 1) + 1)) + * / stride_w + 1 + *\n + * */ REG_OP(Conv2DTranspose) .INPUT(input_size, TensorType({DT_INT32, DT_INT64})) @@ -1405,21 +1620,22 @@ REG_OP(Conv2DTransposeD) /** *@brief Computes the deformed convolution output with the expected input *@par Inputs: - * Four inputs: + * Two inputs: * @li x: A Tensor of type float16,float32 * @li offsets: A Tensor of type float16,float32.Deformation offset parameter. *@par Required Attributes: * @li strides: A tuple/list of 4 integers.The stride of the sliding window for * height and width for H/W dimension. - * @li pads: A tuple/list of 4 integers.Padding added to each dimension + * @li pads: A tuple/list of 4 integers.Padding added to H/W dimension * of the input. * @li ksize: A tuple/list of 2 integers.kernel size. *@par Attributes: - * Three attributes: + * Four attributes: * @li dilations: A tuple/list of 4 integers, The dilation factor for each dimension * of input. Defaults to [1, 1, 1, 1] * @li data_format: An optional string from: "NCHW", "NHWC". Defaults to "NCHW". Specify the data format of the input x. * @li deformable_groups: Specify the c-axis grouping number of input x. + * @li modulated: Specify version of DeformableConv2D, true means v2, false means v1 *@par Outputs: * y: A Tensor. A Tensor of type float16, float32. */ @@ -1433,7 +1649,69 @@ REG_OP(DeformableOffsets) .ATTR(dilations, ListInt, {1, 1, 1, 1}) .ATTR(data_format, String, "NCHW") .ATTR(deformable_groups, Int, 1) + .ATTR(modulated, Bool, true) .OP_END_FACTORY_REG(DeformableOffsets) +/** +*@brief Computes the gradients of DeformableOffsets with respect to input and offsets +*@par Inputs: + * Three inputs: + * @li grad: A Tensor of type float16,float32. gradients with respect to DeformableOffsets output + * @li x: A Tensor of type float16,float32. + * @li offsets: A Tensor of type float16,float32.Deformation offset parameter. +*@par Required Attributes: + * @li strides: A tuple/list of 4 integers.The stride of the sliding window for + * height and width for H/W dimension. + * @li pads: A tuple/list of 4 integers.Padding added to H/W dimension + * of the input. + * @li ksize: A tuple/list of 2 integers.kernel size. +*@par Attributes: + * Three attributes: + * @li dilations: A tuple/list of 4 integers, The dilation factor for each dimension + * of input. Defaults to [1, 1, 1, 1] + * @li data_format: An optional string from: "NCHW", "NHWC". Defaults to "NCHW". Specify the data format of the input x. + * @li deformable_groups: Specify the c-axis grouping number of input x. + * @li modulated: Specify version of DeformableConv2D, true means v2, false means v1. +*@par Outputs: + * grad_x: A Tensor of type float16, float32. Gradients with respect to input_x + * grad_offsets: A Tensor of type float16, float32. Gradients with respect to input_offsets +*/ +REG_OP(DeformableOffsetsGrad) + .INPUT(grad, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(offsets, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(grad_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(grad_offsets, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(pads, ListInt) + .REQUIRED_ATTR(ksize, ListInt) + .ATTR(dilations, ListInt, {1, 1, 1, 1}) + .ATTR(data_format, String, "NCHW") + .ATTR(deformable_groups, Int, 1) + .ATTR(modulated, Bool, true) + .OP_END_FACTORY_REG(DeformableOffsetsGrad) + +/** +*@brief Computes the deformed dilation output with the expected input +*@par Inputs: + * One inputs: + * @li x: A Tensor of type int8, float16, float32 +*@par Required Attributes: + * @li dilations: A tuple/list of integers. +*@par Attributes: + * Two attributes: + * @li padding_value: default value filling in blank + * @li pads: A tuple/list of integers. +*@par Outputs: + * y: A Tensor. A Tensor of type int8, float16, float32. +*/ +REG_OP(Dilation) + .INPUT(x, TensorType({DT_INT8, DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_INT8, DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(dilations, ListInt) + .ATTR(pads, ListInt, {}) + .ATTR(padding_value, Float, 0.0) + .OP_END_FACTORY_REG(Dilation) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_detect_ops.h b/third_party/fwkacllib/inc/ops/nn_detect_ops.h index a013fb33..5fa40ad6 100644 --- a/third_party/fwkacllib/inc/ops/nn_detect_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_detect_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -254,22 +254,22 @@ is min_size/sqrt(aspect_ratio), the width is min_size*sqrt(aspect_ratio). Defaul *@par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. */ - REG_OP(PriorBox) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(img, TensorType({DT_FLOAT16, DT_FLOAT})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) - .REQUIRED_ATTR(min_size, ListFloat) - .REQUIRED_ATTR(max_size, ListFloat) - .REQUIRED_ATTR(aspect_ratio, ListFloat) - .ATTR(img_h, Int, 0) - .ATTR(img_w, Int, 0) - .ATTR(step_h, Float, 0.0) - .ATTR(step_w, Float, 0.0) - .ATTR(flip, Bool, true) - .ATTR(clip, Bool, false) - .ATTR(offset, Float, 0.5) - .ATTR(variance, ListFloat, {0.1}) - .OP_END_FACTORY_REG(PriorBox); +REG_OP(PriorBox) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(img, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(min_size, ListFloat) + .REQUIRED_ATTR(max_size, ListFloat) + .REQUIRED_ATTR(aspect_ratio, ListFloat) + .ATTR(img_h, Int, 0) + .ATTR(img_w, Int, 0) + .ATTR(step_h, Float, 0.0) + .ATTR(step_w, Float, 0.0) + .ATTR(flip, Bool, true) + .ATTR(clip, Bool, false) + .ATTR(offset, Float, 0.5) + .ATTR(variance, ListFloat, {0.1}) + .OP_END_FACTORY_REG(PriorBox); /** *@brief Performs SSD prior box detection, with four additional matrices and the "aspect_ratio" attribute deleted compared to PriorBox . \n @@ -306,25 +306,25 @@ is min_size/sqrt(aspect_ratio), the width is min_size*sqrt(aspect_ratio). Defaul *@par Restrictions: *Warning: THIS FUNCTION IS DEPRECATED. Please use PriorBox instead. */ - REG_OP(PriorBoxD) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(img, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(data_h, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(data_w, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(box_height, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(box_width, TensorType({DT_FLOAT16, DT_FLOAT})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) - .REQUIRED_ATTR(min_size, ListFloat) - .REQUIRED_ATTR(max_size, ListFloat) - .ATTR(img_h, Int, 0) - .ATTR(img_w, Int, 0) - .ATTR(step_h, Float, 0.0) - .ATTR(step_w, Float, 0.0) - .ATTR(flip, Bool, true) - .ATTR(clip, Bool, false) - .ATTR(offset, Float, 0.5) - .ATTR(variance, ListFloat, {0.1}) - .OP_END_FACTORY_REG(PriorBoxD); +REG_OP(PriorBoxD) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(img, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(data_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(data_w, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(box_height, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(box_width, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(min_size, ListFloat) + .REQUIRED_ATTR(max_size, ListFloat) + .ATTR(img_h, Int, 0) + .ATTR(img_w, Int, 0) + .ATTR(step_h, Float, 0.0) + .ATTR(step_w, Float, 0.0) + .ATTR(flip, Bool, true) + .ATTR(clip, Bool, false) + .ATTR(offset, Float, 0.5) + .ATTR(variance, ListFloat, {0.1}) + .OP_END_FACTORY_REG(PriorBoxD); /** *@brief Performs SSD prior box detection, with four additional matrices and the "aspect_ratio" attribute deleted compared to PriorBox . \n @@ -358,22 +358,22 @@ is min_size/sqrt(aspect_ratio), the width is min_size*sqrt(aspect_ratio). Defaul *@par Restrictions: *Warning: THIS FUNCTION IS DEPRECATED. Please use PriorBox instead. */ - REG_OP(PriorBoxDV2) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(img, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(boxes, TensorType({DT_FLOAT16, DT_FLOAT})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) - .REQUIRED_ATTR(min_size, ListFloat) - .REQUIRED_ATTR(max_size, ListFloat) - .ATTR(img_h, Int, 0) - .ATTR(img_w, Int, 0) - .ATTR(step_h, Float, 0.0) - .ATTR(step_w, Float, 0.0) - .ATTR(flip, Bool, true) - .ATTR(clip, Bool, false) - .ATTR(offset, Float, 0.5) - .ATTR(variance, ListFloat, {0.1}) - .OP_END_FACTORY_REG(PriorBoxDV2); +REG_OP(PriorBoxDV2) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(img, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(boxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(min_size, ListFloat) + .REQUIRED_ATTR(max_size, ListFloat) + .ATTR(img_h, Int, 0) + .ATTR(img_w, Int, 0) + .ATTR(step_h, Float, 0.0) + .ATTR(step_w, Float, 0.0) + .ATTR(flip, Bool, true) + .ATTR(clip, Bool, false) + .ATTR(offset, Float, 0.5) + .ATTR(variance, ListFloat, {0.1}) + .OP_END_FACTORY_REG(PriorBoxDV2); /** *@brief Performs Position Sensitive ROI Pooling . \n @@ -531,10 +531,10 @@ as xx...xyy...yww...whh...hbb...bc0c0..c0c1c1...c1......cncn...cn . \n * It is a custom operator. It has no corresponding operator in Caffe. */ REG_OP(Yolo) - .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) - .OUTPUT(coord_data, TensorType({DT_FLOAT16,DT_FLOAT})) - .OUTPUT(obj_prob, TensorType({DT_FLOAT16,DT_FLOAT})) - .OUTPUT(classes_prob, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(coord_data, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(obj_prob, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(classes_prob, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(boxes, Int, 3) .ATTR(coords, Int, 4) .ATTR(classes, Int, 80) @@ -584,10 +584,10 @@ REG_OP(Yolo) * It is a custom operator. It has no corresponding operator in Caffe. */ REG_OP(YoloV2DetectionOutput) - .INPUT(coord_data, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(obj_prob, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(classes_prob, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(img_info, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(coord_data, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(obj_prob, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(classes_prob, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(img_info, TensorType({DT_FLOAT16, DT_FLOAT})) .REQUIRED_ATTR(biases, ListFloat) .ATTR(boxes, Int, 5) .ATTR(coords, Int, 4) @@ -598,7 +598,7 @@ REG_OP(YoloV2DetectionOutput) .ATTR(score_threshold, Float, 0.5) .ATTR(iou_threshold, Float, 0.45) .ATTR(pre_nms_topn, Int, 512) - .OUTPUT(box_out, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(box_out, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(box_out_num, TensorType({DT_INT32})) .OP_END_FACTORY_REG(YoloV2DetectionOutput) @@ -647,12 +647,12 @@ REG_OP(YoloV2DetectionOutput) *Warning: THIS FUNCTION IS DEPRECATED. Please use YoloV2DetectionOutput instead. */ REG_OP(YoloV2DetectionOutputD) - .INPUT(coord_data, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(obj_prob, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(classes_prob, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(img_info, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(windex, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(hindex, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(coord_data, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(obj_prob, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(classes_prob, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(img_info, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(windex, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(hindex, TensorType({DT_FLOAT16, DT_FLOAT})) .REQUIRED_ATTR(biases, ListFloat) .ATTR(boxes, Int, 5) .ATTR(coords, Int, 4) @@ -663,7 +663,7 @@ REG_OP(YoloV2DetectionOutputD) .ATTR(score_threshold, Float, 0.5) .ATTR(iou_threshold, Float, 0.45) .ATTR(pre_nms_topn, Int, 512) - .OUTPUT(box_out, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(box_out, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(box_out_num, TensorType({DT_INT32})) .OP_END_FACTORY_REG(YoloV2DetectionOutputD) @@ -707,16 +707,16 @@ REG_OP(YoloV2DetectionOutputD) * It is a custom operator. It has no corresponding operator in Caffe. */ REG_OP(YoloV3DetectionOutput) - .INPUT(coord_data_low, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(coord_data_mid, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(coord_data_high, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(obj_prob_low, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(obj_prob_mid, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(obj_prob_high, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(classes_prob_low, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(classes_prob_mid, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(classes_prob_high, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(img_info, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(coord_data_low, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(coord_data_mid, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(coord_data_high, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(obj_prob_low, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(obj_prob_mid, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(obj_prob_high, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(classes_prob_low, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(classes_prob_mid, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(classes_prob_high, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(img_info, TensorType({DT_FLOAT16, DT_FLOAT})) .REQUIRED_ATTR(biases_low, ListFloat) .REQUIRED_ATTR(biases_mid, ListFloat) .REQUIRED_ATTR(biases_high, ListFloat) @@ -729,7 +729,7 @@ REG_OP(YoloV3DetectionOutput) .ATTR(score_threshold, Float, 0.5) .ATTR(iou_threshold, Float, 0.45) .ATTR(pre_nms_topn, Int, 512) - .OUTPUT(box_out, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(box_out, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(box_out_num, TensorType({DT_INT32})) .OP_END_FACTORY_REG(YoloV3DetectionOutput) @@ -776,22 +776,22 @@ s *Warning: THIS FUNCTION IS DEPRECATED. Please use YoloV3DetectionOutput instead. */ REG_OP(YoloV3DetectionOutputD) - .INPUT(coord_data_low, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(coord_data_mid, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(coord_data_high, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(obj_prob_low, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(obj_prob_mid, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(obj_prob_high, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(classes_prob_low, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(classes_prob_mid, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(classes_prob_high, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(img_info, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(windex1, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(windex2, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(windex3, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(hindex1, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(hindex2, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(hindex3, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(coord_data_low, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(coord_data_mid, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(coord_data_high, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(obj_prob_low, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(obj_prob_mid, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(obj_prob_high, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(classes_prob_low, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(classes_prob_mid, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(classes_prob_high, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(img_info, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(windex1, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(windex2, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(windex3, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(hindex1, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(hindex2, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(hindex3, TensorType({DT_FLOAT16, DT_FLOAT})) .REQUIRED_ATTR(biases_low, ListFloat) .REQUIRED_ATTR(biases_mid, ListFloat) .REQUIRED_ATTR(biases_high, ListFloat) @@ -804,7 +804,7 @@ REG_OP(YoloV3DetectionOutputD) .ATTR(score_threshold, Float, 0.5) .ATTR(iou_threshold, Float, 0.45) .ATTR(pre_nms_topn, Int, 512) - .OUTPUT(box_out, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(box_out, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(box_out_num, TensorType({DT_INT32})) .OP_END_FACTORY_REG(YoloV3DetectionOutputD) @@ -848,7 +848,7 @@ There are three Yolo operators at Yolov3DetectionOutput's preceding layer on Yol * It is a custom operator. It has no corresponding operator in Caffe. */ REG_OP(YoloV3DetectionOutputV2) - .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) .REQUIRED_ATTR(biases, ListFloat) .ATTR(boxes, Int, 3) .ATTR(coords, Int, 4) @@ -862,7 +862,7 @@ REG_OP(YoloV3DetectionOutputV2) .ATTR(N, Int, 10) .ATTR(resize_origin_img_to_net, Bool, false) .ATTR(out_box_dim, Int, 3) - .OUTPUT(box_out, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(box_out, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(box_out_num, TensorType({DT_INT32})) .OP_END_FACTORY_REG(YoloV3DetectionOutputV2) @@ -910,9 +910,9 @@ REG_OP(YoloV3DetectionOutputV2) * Warning: THIS FUNCTION IS DEPRECATED. Please use YoloV3DetectionOutputV2 instead. */ REG_OP(YoloV3DetectionOutputV2D) - .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) - .DYNAMIC_INPUT(windex, TensorType({DT_FLOAT16,DT_FLOAT})) - .DYNAMIC_INPUT(hindex, TensorType({DT_FLOAT16,DT_FLOAT})) + .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .DYNAMIC_INPUT(windex, TensorType({DT_FLOAT16, DT_FLOAT})) + .DYNAMIC_INPUT(hindex, TensorType({DT_FLOAT16, DT_FLOAT})) .REQUIRED_ATTR(biases, ListFloat) .ATTR(boxes, Int, 3) .ATTR(coords, Int, 4) @@ -926,7 +926,7 @@ REG_OP(YoloV3DetectionOutputV2D) .ATTR(N, Int, 10) .ATTR(resize_origin_img_to_net, Bool, false) .ATTR(out_box_dim, Int, 3) - .OUTPUT(box_out, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(box_out, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(box_out_num, TensorType({DT_INT32})) .OP_END_FACTORY_REG(YoloV3DetectionOutputV2D) @@ -968,8 +968,9 @@ REG_OP(SPP) * Three inputs, including: *@li x: An NC1HWC0 tensor of type float16 or float32, describing the feature * map. -*@li rois: A tensor of type float16 or float32, with shape +*@li rois: A tensor of type float16 or float32, with 3D shape * [batch, 5, roi_max_num], describing the RIOs. +* roi_max_num must be less than or equal to 6000 and must be divided by 16. *@li roi_actual_num: A optional tensor of type int32, with shape [batch, 8], specifying * the number of ROIs per batch . \n @@ -1201,35 +1202,6 @@ REG_OP(RpnProposalsD) .OUTPUT(sorted_box, TensorType({DT_FLOAT16})) .OP_END_FACTORY_REG(RpnProposalsD) -/** -*@brief Computes Score Filte Pre-Sort function. - -*@par Inputs: -*Inputs include: -* @li rois: A Tensor. Must be float16. N-D with shape [N, 4]. -* @li cls_bg_prob: A Tensor. Must be float16. N-D with shape [N, 1]. - -*@par Attributes: -* @li score_threshold: required, float, threahold of topk process. -* @li k: required, Int, threahold of topk process. -* @li score_filter: bool, mark of score_filter. Defaults to "true" -* @li core_max_num: int, max number of core. Defaults to "8" -*@par Outputs: -* @li sorted_proposal: A Tensor. Must be float16. -* N-D with shape [8*6002, 8]. -* @li proposal_num: A Tensor. Must be uint32. N-D with shape [8, 8]. -*/ - -REG_OP(ScoreFiltePreSort) - .INPUT(rois, TensorType({DT_FLOAT16})) - .INPUT(cls_bg_prob, TensorType({DT_FLOAT16})) - .OUTPUT(sorted_proposal, TensorType({ DT_FLOAT16})) - .OUTPUT(proposal_num, TensorType({ DT_UINT32})) - .REQUIRED_ATTR(score_threshold, Float) - .REQUIRED_ATTR(k, Int) - .ATTR(score_filter, Bool, true) - .ATTR(core_max_num, Int, 8) - .OP_END_FACTORY_REG(ScoreFiltePreSort) /** *@brief Computes Score Filte Pre-Sort function. @@ -1383,6 +1355,7 @@ REG_OP(DecodeWheelsTarget) *@attention Constraints: * Only computation of float16 data is supported. +* Note: when the class num per image * max_size_per_class is too big, will compile fail with ERROR-insufficient memory */ REG_OP(BatchMultiClassNonMaxSuppression) .INPUT(boxes, TensorType({DT_FLOAT16})) @@ -1464,9 +1437,9 @@ REG_OP(NormalizeBBox) * y: A Tensor. Must have the same type as box_predictions. */ REG_OP(DecodeBboxV2) - .INPUT(boxes, TensorType({DT_FLOAT16,DT_FLOAT})) - .INPUT(anchors, TensorType({DT_FLOAT16,DT_FLOAT})) - .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(boxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(anchors, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(scales, ListFloat, {1.0, 1.0, 1.0, 1.0}) .ATTR(decode_clip, Float, 0.0) .ATTR(reversed_box, Bool, false) @@ -1477,7 +1450,8 @@ REG_OP(DecodeBboxV2) * *@par Inputs: *Inputs include: -* x: A Tensor. Must be float16 or float32. +* x: A Tensor. Dtype support: flaot16, flaot, int16, int8, + uint8, int32, int64. * *@par Attributes: * @li axis: optional, int. @@ -1485,16 +1459,364 @@ REG_OP(DecodeBboxV2) * *@par Outputs: * @li y1: A Tensor. Must have the same type as x. -* @li y2: A Tensor. Indices of y1 in x.Dtype must be int32. +* @li y2: A Tensor. Indices of y1 in x. Dtype must be int32. +* */ REG_OP(Sort) - .INPUT(x, TensorType({ DT_FLOAT16 })) - .OUTPUT(y1, TensorType({ DT_FLOAT16 })) - .OUTPUT(y2, TensorType({ DT_INT32 })) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT16, DT_INT8, + DT_UINT8, DT_INT32, DT_INT64})) + .OUTPUT(y1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT16, DT_INT8, + DT_UINT8, DT_INT32, DT_INT64})) + .OUTPUT(y2, TensorType({DT_INT32})) .ATTR(axis, Int, -1) .ATTR(descending, Bool, false) .OP_END_FACTORY_REG(Sort) +/** +*@brief Computes iou for input bboxes and gtboxes. + +*@par Inputs: +* Two inputs, including: +*@li bboxes: boxes, a 4D Tensor of type float16 with the shape (x0, x1, y0, y1), +*@li gtboxes: boxes, a 4D Tensor of type float16 with the shape (x0, x1, y0, y1).\n + +*@par Attributes: +*@li mode: A optional attribute of type string, whether judge the mode of iou. \n + +*@par Outputs: +*@li overlap: A 2D Tensor of type float16 with shape [n, m]. \n + +*@attention Constraints: +* Only computation of float16 data is supported. + +*@par Restrictions: +*Warning:THIS FUNCTION IS DEPRECATED. Please use Iou instead. +*/ +REG_OP(PtIou) + .INPUT(bboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(gtboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(overlap, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(mode, String, "iou") + .OP_END_FACTORY_REG(PtIou) + +/** +*@brief Greedily selects a subset of bounding boxes in descending order of +score . \n + +*@par Inputs: +*Input boxes and scores must be float16 type. Inputs include: +*@li boxes: A input tensor with shape [num_batches,spatial_dimension,4]. +The single box data format is indicated by center_point_box. +*@li scores: A input tensor with shape [num_batches,num_classes,spatial_dimension] +*@li max_output_size: A scalar integer tensor representing the maximum number +of boxes to be selected by non max suppression. +*@li iou_threshold: A 0-D float tensor representing the threshold for deciding +whether boxes overlap too much with respect to IOU. +*@li score_threshold: A 0-D float tensor representing the threshold for +deciding when to remove boxes based on score . \n + +*@par Attributes: +*center_point_box:Integer indicate the format of the box data. +The default is 0. 0 - the box data is supplied as [y1, x1, y2, x2] +where (y1, x1) and (y2, x2) are the coordinates of any diagonal pair +of box corners and the coordinates can be provided as normalized +(i.e., lying in the interval [0, 1]) or absolute.Mostly used for TF models. +1 - the box data is supplied as [x_center, y_center, width, height]. + Mostly used for Pytorch models. \n + +*@par Outputs: +*@li selected_indices: A 2-D integer tensor of shape [M] representing the +selected indices from the boxes tensor, where M <= max_output_size. \n + +*@attention Constraints: +*Input boxes and scores must be float16 type . \n + +*@par Third-party framework compatibility +*Compatible with onnx NonMaxSuppression operator. + +*@par Restrictions: +*Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ + +REG_OP(NonMaxSuppressionV6) + .INPUT(boxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(scores, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(max_output_size, TensorType({DT_INT32})) + .OPTIONAL_INPUT(iou_threshold, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(score_threshold, TensorType({DT_FLOAT})) + .OUTPUT(selected_indices, TensorType({DT_INT32})) + .ATTR(center_point_box, Int, 0) + .ATTR(max_boxes_size, Int, 0) + .OP_END_FACTORY_REG(NonMaxSuppressionV6) + +/** +*@brief Greedily selects a subset of bounding boxes in descending order of +score . \n + +*@par Inputs: +*Input boxes and scores must be float16 type. Inputs include: +*@li boxes: A input tensor with shape [num_batches,spatial_dimension,4]. +The single box data format is indicated by center_point_box. +*@li scores: A input tensor with shape [num_batches,num_classes,spatial_dimension] +*@li max_output_size: A scalar integer tensor representing the maximum number +of boxes to be selected by non max suppression. +*@li iou_threshold: A 0-D float tensor representing the threshold for deciding +whether boxes overlap too much with respect to IOU. +*@li score_threshold: A 0-D float tensor representing the threshold for +deciding when to remove boxes based on score . \n +*@li index_id: A input tensor with shape [num_batches,num_classes,spatial_dimension,3] +the last dim representing (batch_id,class_id,index_id) . \n + +*@par Attributes: +*center_point_box:Integer indicate the format of the box data. +The default is 0. 0 - the box data is supplied as [y1, x1, y2, x2] +where (y1, x1) and (y2, x2) are the coordinates of any diagonal pair +of box corners and the coordinates can be provided as normalized +(i.e., lying in the interval [0, 1]) or absolute.Mostly used for TF models. +1 - the box data is supplied as [x_center, y_center, width, height]. + Mostly used for Pytorch models. \n + +*@par Outputs: +*@li selected_indices: A 2-D integer tensor of shape [M] representing the +selected indices from the boxes tensor, where M <= max_output_size. \n + +*@attention Constraints: +*Input boxes and scores must be float16 type . \n + +*@par Third-party framework compatibility +*Compatible with onnx NonMaxSuppression operator. +*/ + +REG_OP(NonMaxSuppressionV7) + .INPUT(boxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(scores, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(max_output_size, TensorType({DT_INT32})) + .OPTIONAL_INPUT(iou_threshold, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(score_threshold, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(index_id, TensorType({DT_FLOAT16})) + .OUTPUT(selected_indices, TensorType({DT_INT32})) + .ATTR(center_point_box, Int, 0) + .ATTR(max_boxes_size, Int, 0) + .OP_END_FACTORY_REG(NonMaxSuppressionV7) + +/** +*@brief Obtains the ROI feature matrix from the feature map list. It is a customized fused operator for mmdetection. \n + +*@par Inputs: +* Three inputs, including: +*@li features: A 5HD Tensor list of type float32 or float16. +*@li rois: ROI position. A 2D Tensor of float32 or float16 with shape (N, 5). "N" indicates the number of ROIs, +* the value "5" indicates the indexes of images where the ROIs are located, "x0", "y0", "x1", and "y1". + +*@par Attributes: +*@li finest_scale: A optional attribute of type int, specifying the scale of calculate levels of "rois". +*@li roi_scale_factor: A optional attribute of type float32, specifying the rescaling of "rois" coordinates. +*@li spatial_scale: A optional attribute of type list float32, specifying the scaling ratio of "features" +* to the original image. +*@li pooled_height: A optional attribute of type int32, specifying the H dimension. +*@li pooled_width: A optional attribute of type int32, specifying the W dimension. +*@li sample_num: An optional attribute of type int32, specifying the horizontal and vertical sampling frequency +* of each output. If this attribute is set to "0", the sampling frequency is equal to the rounded up value of "rois", +* which is a floating point number. Defaults to "0". +*@li pool_mode: An optional attribute of type string to indicate pooling mode. Defaults to "avg" . \n +*@li aligned: An optional attribute of type bool, specifying the align to corner. Defaults to true . \n + +*@par Outputs: +* output: Outputs the feature sample of each ROI position. The format is 5HD Tensor of type float32 or float16. +* The axis N is the number of input ROIs. Axes H, W, and C are consistent with the values of "pooled_height", +* "pooled_width", and "features", respectively. + +*@par Third-party framework compatibility +*Compatible with mmdetection SingleRoIExtractor operator. +*/ +REG_OP(RoiExtractor) + .DYNAMIC_INPUT(features, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(rois, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(finest_scale, Int, 56) + .ATTR(roi_scale_factor, Float, 0) + .ATTR(spatial_scale, ListFloat, {1.f / 4, 1.f / 8, 1.f / 16, 1.f / 32}) + .ATTR(pooled_height, Int, 7) + .ATTR(pooled_width, Int, 7) + .ATTR(sample_num, Int, 0) + .ATTR(pool_mode, String, "avg") + .ATTR(aligned, Bool, true) + .OP_END_FACTORY_REG(RoiExtractor) + +/** +*@brief Performs Position Sensitive PS ROI Pooling . \n + +*@par Inputs: +* Two inputs, including: +*@li x: An NC1HWC0 tensor of type float16 or float32, describing the feature +* map, dimension C1 must be equal to +* (int(output_dim+15)/C0))*group_size*group_size. +*@li rois: A tensor of type float16 or float32, with shape +* [batch, 5, rois_num], describing the ROIs, each ROI consists of five +* elements: "batch_id", "x1", "y1", "x2", and "y2", which "batch_id" indicates +* the index of the input feature map, "x1", "y1", "x2", or "y2" must be +* greater than or equal to "0.0" . \n + +*@par Attributes: +*@li output_dim: A required int32, specifying the number of output channels, +* must be greater than 0. +*@li group_size: A required int32, specifying the number of groups to encode +* position-sensitive score maps, must be within the range (0, 128). +*@li spatial_scale: A required float32, scaling factor for mapping the input +* coordinates to the ROI coordinates . \n + +*@par Outputs: +*y: An NC1HWC0 tensor of type float16 or float32, describing the result +* feature map . \n + +*@attention Constraints: +* HC1HWC0: channel must be Group_size squared, rois_num is a multiple of 16 +*/ +REG_OP(PSROIPoolingV2) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(rois, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(spatial_scale, Float) + .REQUIRED_ATTR(output_dim, Int) + .REQUIRED_ATTR(group_size, Int) + .OP_END_FACTORY_REG(PSROIPoolingV2) + +/** +*@brief Performs Position Sensitive PS ROI Pooling Grad . \n + +*@par Inputs: +* Two inputs, including: +*@li x: An NC1HWC0 tensor of type float16 or float32, describing the result +* feature map . \n +*@li rois: A tensor of type float16 or float32, with shape +* [batch, 5, rois_num], describing the ROIs, each ROI consists of five +* elements: "batch_id", "x1", "y1", "x2", and "y2", which "batch_id" indicates +* the index of the input feature map, "x1", "y1", "x2", or "y2" must be +* greater than or equal to "0.0" . \n + +*@par Attributes: +*@li output_dim: A required int32, specifying the number of output channels, +* must be greater than 0. +*@li group_size: A required int32, specifying the number of groups to encode +* position-sensitive score maps, must be within the range (0, 128). +*@li spatial_scale: A required float32, scaling factor for mapping the input +* coordinates to the ROI coordinates . \n +*@li input_size: A required listInt, mapping the gradinput size: (H, W) + +*@par Outputs: +*y: An NC1HWC0 tensor of type float16 or float32, describing the feature +* map, dimension C1 must be equal to +* (int(output_dim+15)/C0))*group_size*group_size. + +*@attention Constraints: +* HC1HWC0: channel must be Group_size squared, rois_num is a multiple of 16 +*/ +REG_OP(PSROIPoolingGradV2D) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(rois, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(spatial_scale, Float) + .REQUIRED_ATTR(output_dim, Int) + .REQUIRED_ATTR(group_size, Int) + .REQUIRED_ATTR(input_size, ListInt) + .OP_END_FACTORY_REG(PSROIPoolingGradV2D) + +/** +*@brief Generate the responsible flags of anchor in a single feature map. + +*@par Inputs: +*@li gt_bboxes: Ground truth box, 2-D Tensor with shape `[batch, 4]`. + +*@par Attributes: +*@li featmap_size: The size of feature maps, listint. +*@li strides: Stride of current level, listint. +*@li num_base_anchors: The number of base anchors. + +*@par Outputs: +*flags: The valid flags of each anchor in a single level. +*/ +REG_OP(AnchorResponseFlags) + .INPUT(gt_bboxes, TensorType({DT_FLOAT})) + .OUTPUT(flags, TensorType({DT_UINT8})) + .REQUIRED_ATTR(featmap_size, ListInt) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(num_base_anchors, Int) + .OP_END_FACTORY_REG(AnchorResponseFlags) + +/** +*@brief Generates bounding boxes based on yolo's "anchor" and "ground-truth" boxes. +* It is a customized mmdetection operator . \n + +*@par Inputs: +* Three inputs, including: +*@li anchor_boxes: anchor boxes generated by the yolo training set. +* A 2D Tensor of type float32 or float16 with shape (N, 4). "N" indicates the number +* of ROIs, "N" indicates the number of ROIs, and the value "4" refers to (tx, ty, tw, th). +*@li gt_bboxes: target of the transformation, e.g, ground-truth boxes. +* A 2D Tensor of type float32 or float16 with shape (N, 4). +* "N" indicates the number of ROIs, and 4 indicates "dx", "dy", "dw", and "dh" . +*@li stride: Scale for each box. +* A 1D Tensor of type int32 shape (N,). +* "N" indicates the number of ROIs. \n + +*@par Attributes: +*@li performance_mode: select performance mode, "high_precision" or "high_performance". +* select "high_precision" when input type is float32, the output tensor precision +* will be smaller than 0.0001, select "high_performance" when input type is float32, +* the ops will be best performance, but precision will be only smaller than 0.005. + +*@par Outputs: +*encoded_bboxes: Bboxes generated based on "anchor_boxes" and "gt_bboxes". Have the +* same format and type as "anchor_boxes". +* +*@attention Constraints: +* input anchor boxes only support maximum N=20480. \n +*/ +REG_OP(YoloBoxesEncode) + .INPUT(anchor_boxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(gt_bboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(stride, TensorType({DT_INT32})) + .ATTR(performance_mode, String, "high_precision") + .OUTPUT(encoded_bboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(YoloBoxesEncode) + +/** +*@brief Performs Position Sensitive PS ROI Pooling Grad. + +*@par Inputs: +* Eight inputs, including: +*@li assigned_gt_inds: Tensor of type float16 or float32, shape (n, ) +*@li overlaps: A Tensor. Datatype is same as assigned_gt_inds. IOU between gt_bboxes and bboxes. shape(k, n) +*@li box_responsible_flags: A Tensor. Support uint8. Flag to indicate whether box is responsible. +*@li max_overlaps: A Tensor. Datatype is same as assigned_gt_inds. overlaps.max(axis=0). +*@li argmax_overlaps: A Tensor. Support int32. overlaps.argmax(axis=0). +*@li gt_max_overlaps: A Tensor. Datatype is same as assigned_gt_inds. overlaps.max(axis=1). +*@li gt_argmax_overlaps: A Tensor. Support int32. overlaps.argmax(axis=1). +*@li num_gts: A Tensor. Support int32. real k. shape (1, ) + +*@par Attributes: +*@li output_dim: float. IOU threshold for positive bboxes. +*@li group_size: float. minimum iou for a bbox to be considered as a positive bbox +*@li spatial_scale: bool. whether to assign all bboxes with the same highest overlap with some gt to that gt. + +*@par Outputs: +*@li assigned_gt_inds_pos: A Tensor. Support float16/float32. shape (n, ). +*/ +REG_OP(GridAssignPositive) + .INPUT(assigned_gt_inds, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(overlaps, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(box_responsible_flags, TensorType({ DT_UINT8 })) + .INPUT(max_overlaps, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(argmax_overlaps, TensorType({ DT_INT32 })) + .INPUT(gt_max_overlaps, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(gt_argmax_overlaps, TensorType({ DT_INT32 })) + .INPUT(num_gts, TensorType({ DT_INT32 })) + .OUTPUT(assigned_gt_inds_pos, TensorType({DT_FLOAT, DT_FLOAT16})) + .REQUIRED_ATTR(pos_iou_thr, Float) + .REQUIRED_ATTR(min_pos_iou, Float) + .REQUIRED_ATTR(gt_max_assign_all, Bool) + .OP_END_FACTORY_REG(GridAssignPositive) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_DETECT_OPS_H_ + diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index 35c4c7d4..b44c0780 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -55,7 +55,9 @@ REG_OP(LogSoftmaxGrad) *Two inputs, including: * @li features: A Tensor. Must be one of the following types: half, float32, double. * A "batch_size * num_classes" matrix. -* @li labels: A Tensor of the same type as "features". batch_size vector with values in [0, num_classes). +* @li labels: A Tensor. Must be one of the following types: 'int32', 'int64'. +* batch_size vector with values in [0, num_classes). +* This is the label for the given minibatch entry. *@par Outputs: @@ -105,6 +107,9 @@ REG_OP(SoftmaxCrossEntropyWithLogits) * @li grad_softmax: A Tensor. Has the same shape and type as "softmax". * The format is NC1HWC0 or DN . \n +*@par Attributes: +* axes: An optional list of ints. Defaults to "{-1}" . \n + *@par Outputs: *grad_x: A Tensor. Has the same shape and type as "softmax" . \n @@ -115,6 +120,7 @@ REG_OP(SoftmaxGrad) .INPUT(softmax, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .INPUT(grad_softmax, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) .OUTPUT(grad_x, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .ATTR(axes, ListInt, {-1}) .OP_END_FACTORY_REG(SoftmaxGrad) /** @@ -160,20 +166,20 @@ REG_OP(SigmoidCrossEntropyWithLogits) .OP_END_FACTORY_REG(SigmoidCrossEntropyWithLogits) /** -*@brief Computes the sigmoid cross entropy loss of "predict" and "target" . \n +*@brief Computes the sigmoid cross entropy loss of "predict" and "target". *@par Inputs: * four inputs, including: *@li predict: A multi-dimensional Tensor of type float16 or float32, specifying the predictive value. -*@li target: A multi-dimensional Tensor of type float16 or float32, specifying the target value . \n -*@li weight: An multi-dimensional Tensor, specifying the weight value. \n +*@li target: A multi-dimensional Tensor of type float16 or float32, specifying the target value. +*@li weight: An multi-dimensional Tensor, specifying the weight value. *@li pos_weight: An multi-dimensional Tensor, specifying the pos weight value. \n *@par Attributes: -*reduction: A character string from "none", "mean", and "sum", specifying the reduction type to be applied to the output. Defaults to "mean" . \n +*reduction: A character string from "none", "mean", and "sum", specifying the reduction type to be applied to the output. Defaults to "mean". \n *@par Outputs: -*loss: Sigmoid cross entropy between the predictive value and target value. Has the same dimensions as "predict" . \n +*loss: Sigmoid cross entropy between the predictive value and target value. Has the same dimensions as "predict". \n *@par Third-party framework compatibility * Compatible with PyTorch operator BCEWithLogitsLoss. @@ -330,6 +336,41 @@ REG_OP(SoftmaxV2) .ATTR(axes, ListInt, {-1}) .OP_END_FACTORY_REG(SoftmaxV2) +/** +*@brief Function softmax with dropoutDoMaskV3D + +*@par Inputs: +*Two inputs, including: +* @li x: A mutable Tensor. The type only support float16. +* @li mask: A mutable Tensor. Must met all of the following rules: +* shape of mask should be 1D. +* dtype of mask should be uint8. +* value of shape should met the following algorithm: +* value = (size(x) + 128 - 1) // 128 * 128 + +*@par Attributes: +* @li keep_prob: A mutable Tensor. Must met all of the following rules: +* shape of "keep_prob" should be (1,) or [1,]. +* Has the same type as "x" . \n +* @li axes: A list of int. The dimension softmax would be performed on. Defaults +* to "[-1]" . \n + +*@par Outputs: +*y1: A mutable Tensor. Has the same type as "x". +*y2: A mutable Tensor. Has the same type as "x". \n + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(SoftmaxV2WithDropOutDoMaskV3D) + .INPUT(x, TensorType({DT_FLOAT16})) + .INPUT(mask, TensorType({DT_UINT8})) + .OUTPUT(y1, TensorType({DT_FLOAT16})) + .OUTPUT(y2, TensorType({DT_FLOAT16})) + .REQUIRED_ATTR(keep_prob, Float) + .ATTR(axes, ListInt, {-1}) + .OP_END_FACTORY_REG(SoftmaxV2WithDropOutDoMaskV3D) + /** *@brief Computes log softmax activations . \n @@ -427,6 +468,33 @@ REG_OP(MVN) .ATTR(eps, Float, 1e-9) .OP_END_FACTORY_REG(MVN) +/** +*@brief Normalizes the input . \n + +*@par Inputs: +* One input: +*x: An NCHW tensor of type float16 or float32 . \n + +*@par Attributes: +*@li eps: An optional float32 epsilon for not dividing by zero. Defaults to "1e-9" . \n +*@li axes: A list of Intefers, along which axis to reduce. Defaults to "[0, 2, 3]" . \n + +*@par Outputs: +*y: An NCHW tensor of type float16 or float32 . \n + +*@attention Constraints: +* The input tensor must have the NCHW format, whose shape length must be 4. +*@par Third-party framework compatibility +* Compatible with the ONNX operator MeanVarianceNormalization. +*/ + +REG_OP(MVNV2) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) /* "First operand." */ + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) /* "Result, has same element type as inputs" */ + .ATTR(eps, Float, 1e-9) + .ATTR(axes, ListInt, {0, 2, 3}) + .OP_END_FACTORY_REG(MVNV2) + /** *@brief Normalizes the input "x1" . \n @@ -498,6 +566,31 @@ REG_OP(LayerNorm) .ATTR(epsilon, Float, 0.0000001) .OP_END_FACTORY_REG(LayerNorm) +/** +*@brief Returns a tensor where each sub-tensor of input along dimension +* dim is normalized such that the p-norm of the sub-tensor is lower than the value maxnorm. \n + +*@par Inputs: +*One input, including: +* @li x: A Tensor. Must be one of the following types: float16, float32 . \n + +*@par Attributes: +* @li p: Specify L_p norm, the type is float. +* @li dim: The processed dim, the type is int. +* @li maxnorm: Threshold for comparison, the type is float. \n + +*@par Outputs: +*One outputs, including: +* @li y: shape and dtype of output, should be same shape and type as input. +*/ +REG_OP(Renorm) + .INPUT(x, TensorType::BasicType()) + .OUTPUT(y, TensorType::BasicType()) + .REQUIRED_ATTR(p, Float) + .REQUIRED_ATTR(dim, Int) + .REQUIRED_ATTR(maxnorm, Float) + .OP_END_FACTORY_REG(Renorm) + /** *@brief LayerNormGrad operator interface implementation * calculating: dy, x, variance, mean, gamma @@ -586,6 +679,48 @@ REG_OP(LayerNormXBackprop) .OUTPUT(pd_x, TensorType({DT_FLOAT, DT_FLOAT16})) .OP_END_FACTORY_REG(LayerNormXBackprop) +/** +*@brief LayerNormXBackpropV2 operator interface implementation +* calculating: dy, x, variance, mean, gamma +* pd_xl = data_dy*data_gamma +* pd_var = np.sum(((-0.5)*pd_xl*(data_x - data_mean) +* np.power((data_variance + EPSLON), (-1.5))), +* reduce_axis, keepdims=True) +* pd_mean = np.sum(((-1.0)*pd_xl +* np.power((data_variance + EPSLON), (-0.5))), +* reduce_axis, keepdims=True) +* + pd_var*(1.0/m) +* np.sum(((-2.0)*(data_x - data_mean)), reduce_axis, keepdims=True) +* pd_x = pd_xl*np.power((data_variance + EPSLON), (-0.5)) + +* pd_var*(2.0/m)*(data_x - data_mean) + pd_mean*(1.0/m) +* res_for_gamma = (data_x - data_mean) * np.power((data_variance + EPSLON), (-0.5)) + +*@par Inputs: +*Five inputs, including: +* @li dy: A Tensor. Must be one of the following types: float16, float32. +* @li x: A Tensor. Must be one of the following types: float16, float32. +* @li variance: A Tensor. Must be one of the following types: float16, float32. +* @li mean: A Tensor. Must be one of the following types: float16, float32. +* @li gamma: A Tensor. Must be one of the following types: float16, float32 . \n + +*@par Outputs: +*Three outputs, including: +* @li pd_x: A Tensor. Must be one of the following types: float16, float32. +* @li res_for_gamma: A Tensor. Must be one of the following types: float32. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(LayerNormXBackpropV2) + .INPUT(dy, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(variance, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(mean, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(gamma, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(pd_x, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(res_for_gamma, TensorType({DT_FLOAT})) + .OP_END_FACTORY_REG(LayerNormXBackpropV2) + /** *@brief LayerNormBetaGammaBackprop operator interface implementation * calculating: dy, x, variance, mean @@ -629,6 +764,35 @@ REG_OP(LayerNormBetaGammaBackprop) .REQUIRED_ATTR(shape_gamma, ListInt) .OP_END_FACTORY_REG(LayerNormBetaGammaBackprop) +/** +*@brief LayerNormBetaGammaBackpropV2 operator interface implementation +* calculating: dy, x, variance, mean +* pd_gamma = np.sum((data_dy*res_for_gamma), param_axis, keepdims=True) +* pd_beta = np.sum(data_dy, param_axis, keepdims=True) + +*@par Inputs: +*Three inputs, including: +* @li dy: A Tensor. Must be one of the following types: float16, float32. +* @li x: A Tensor. Must be one of the following types: float16, float32. +* @li variance: A Tensor. Must be one of the following types: float16, float32. +* @li mean: A Tensor. Must be one of the following types: float16, float32 . \n + +*@par Outputs: +*Three outputs, including: +* @li pd_gamma: A Tensor. Must be one of the following types: float16, float32. +* @li pd_beta: A Tensor. Must be one of the following types: float16, float32. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(LayerNormBetaGammaBackpropV2) + .INPUT(dy, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(res_for_gamma, TensorType({DT_FLOAT})) + .OUTPUT(pd_gamma, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(pd_beta, TensorType({DT_FLOAT, DT_FLOAT16})) + .REQUIRED_ATTR(shape_gamma, ListInt) + .OP_END_FACTORY_REG(LayerNormBetaGammaBackpropV2) + /** *@brief Return "output" according to the algorithm of dropout_do_mask: * scale_x = x *(1 / keep_prob) @@ -656,7 +820,68 @@ REG_OP(DropOutDoMask) .INPUT(keep_prob, TensorType({DT_FLOAT, DT_FLOAT16})) .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) .OP_END_FACTORY_REG(DropOutDoMask) - + +/** +*@brief Return "output" according to the algorithm of dropout_do_mask: +* scale_x = x *(1 / keep_prob) +* output = select(mask == 1, scale_x, 0) + +*@par Inputs: +*Three inputs, including: +* @li x: A mutable Tensor. Must be one of the following types: +* float16, float32 +* @li mask: A mutable Tensor. Must met all of the following rules: +* shape of mask should be 1D. +* dtype of mask should be uint8. +* value of shape should met the following algorithm: +* value = (size(x) + 128 - 1) // 128 * 128 +* @li keep_prob: A mutable Tensor. Must met all of the following rules: +* shape of "keep_prob" should be (1,) or [1,]. +* Has the same type as "x" . \n + +*@par Output: +*y: A mutable Tensor. Has the same type as "x". +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(DropOutDoMaskV3) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(mask, TensorType({DT_UINT8})) + .INPUT(keep_prob, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .OP_END_FACTORY_REG(DropOutDoMaskV3) + +/** +*@brief Return "output" according to the algorithm of dropout_do_mask: +* scale_x = x *(1 / keep_prob) +* output = select(mask == 1, scale_x, 0) + +*@par Inputs: +*Two inputs, including: +* @li x: A mutable Tensor. Must be one of the following types: +* float16, float32 +* @li mask: A mutable Tensor. Must met all of the following rules: +* shape of mask should be 1D. +* dtype of mask should be uint8. +* value of shape should met the following algorithm: +* value = (size(x) + 128 - 1) // 128 * 128 +*@par Attributes: +* @li keep_prob: A mutable Tensor. Must met all of the following rules: +* shape of "keep_prob" should be (1,) or [1,]. +* Has the same type as "x" . \n + +*@par Output: +*y: A mutable Tensor. Has the same type as "x". +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(DropOutDoMaskV3D) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(mask, TensorType({DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .REQUIRED_ATTR(keep_prob, Float) + .OP_END_FACTORY_REG(DropOutDoMaskV3D) + /** *@brief Scales the input . \n @@ -703,7 +928,7 @@ REG_OP(Scale) *@par Inputs: *One input, including: -*@li x: A Tensor. Must be 4-D shape, and only support the following types: float16, float32 . \n +*x: A Tensor. Must be 4-D shape, and only support the following types: float16, float32 . \n *@par Attributes: *@li depth_radius: An optional int32, specifying the half-width of the normalization window. Defaults to "5". @@ -960,24 +1185,532 @@ REG_OP(INInferV2D) .OP_END_FACTORY_REG(INInferV2D) /** -*@brief Performs instance normalization for inference of InHost part. +* @brief InstanceNorm operator interface implementation. -*@par Inputs:\n -* One input, including: (NC1HWC0 supported) -* variance: A [N, C1, 1, 1, C0] Tensor of type float32, for the variance. +* @par Inputs: +* Three inputs, including: +* @li x: A Tensor. Must be one of the following types: float16, float32. +* @li gamma: A Tensor. Must be one of the following types: float16, float32. +* @li beta: A Tensor. Must be one of the following types: float16, float32. + +* @par Attributes: +* @li data_format: An attribute of type String \n +* @li epsilon: An attribute of type Float. \n + +* @par Outputs: +*Three outputs, including: +* @li y: A Tensor. Has the same type as "x". \n +* @li mean: A Tensor. Has the same type as "x". \n +* @li variance: A Tensor. Has the same type as "x". \n + +* @par Third-party framework compatibility +* Can be used by onnx InstanceNormalization +*/ +REG_OP(InstanceNorm) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(gamma, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(beta, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(mean, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(variance, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(data_format, String, "NDHWC") + .ATTR(epsilon, Float, 1e-6) + .OP_END_FACTORY_REG(InstanceNorm) + +/** +*@brief InstanceNormGrad operator interface implementation. + +*@par Inputs: +*Five inputs, including: +* @li dy: A Tensor. Must be one of the following types: float16, float32. +* @li x: A Tensor. Must be one of the following types: float16, float32. +* @li variance: A Tensor. Must be one of the following types: float16, float32. +* @li mean: A Tensor. Must be one of the following types: float16, float32. +* @li gamma: A Tensor. Must be one of the following types: float16, float32 . \n + +*@par Outputs: +*Three outputs, including: +* @li pd_x: A Tensor. Must be one of the following types: float16, float32. +* @li pd_gamma: A Tensor. Must be one of the following types: float16, float32. +* @li pd_beta: A Tensor. Must be one of the following types: float16, float32. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(InstanceNormGrad) + .INPUT(dy, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(variance, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(mean, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(gamma, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(pd_x, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(pd_gamma, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(pd_beta, TensorType({DT_FLOAT, DT_FLOAT16})) + .OP_END_FACTORY_REG(InstanceNormGrad) + +/** +*@brief InstanceNormXBackprop operator interface implementation. + +*@par Inputs: +*Five inputs, including: +* @li dy: A Tensor. Must be one of the following types: float16, float32. +* @li x: A Tensor. Must be one of the following types: float16, float32. +* @li variance: A Tensor. Must be one of the following types: float16, float32. +* @li mean: A Tensor. Must be one of the following types: float16, float32. +* @li gamma: A Tensor. Must be one of the following types: float16, float32 . \n + +*@par Outputs: +*Two outputs, including: +* @li pd_x: A Tensor. Must be one of the following types: float16, float32. +* @li res_for_gamma: A Tensor. Must be one of the following types: float32. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(InstanceNormXBackprop) + .INPUT(dy, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(variance, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(mean, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(gamma, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(pd_x, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(res_for_gamma, TensorType({DT_FLOAT})) + .OP_END_FACTORY_REG(InstanceNormXBackprop) + +/** +*@brief InstanceNormBetaGammaBackprop operator interface implementation. + +*@par Inputs: +*Two inputs, including: +* @li dy: A Tensor. Must be one of the following types: float16, float32. +* @li res_for_gamma: A Tensor. Must be one of the following types: float32.\n + +*@par Outputs: +*Two outputs, including: +* @li pd_gamma: A Tensor. Must be one of the following types: float16, float32. +* @li pd_beta: A Tensor. Must be one of the following types: float16, float32. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(InstanceNormBetaGammaBackprop) + .INPUT(dy, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(res_for_gamma, TensorType({DT_FLOAT})) + .OUTPUT(pd_gamma, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(pd_beta, TensorType({DT_FLOAT, DT_FLOAT16})) + .OP_END_FACTORY_REG(InstanceNormBetaGammaBackprop) + +/** +* @brief Computes Kl_div_loss_grad or Kl_div_loss_backward. \n + +* @par Inputs: +* Three inputs, including: +* @li grad: A Tensor. Must be one of the following types: float16, float32. +* Required. +* @li input: A Tensor. Has the same type as "grad". Required. +* @li target: A Tensor. Has the same type as "grad". Required. \n + +* @par Attributes: +* @li reduction: An optional attribute of type String. Defaults to "mean". \n +* @li log_target: An optional attribute of type Bool. Defaults to false. \n + +* @par Outputs: +* @li y: A Tensor. Has the same type as "grad". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator KlDivLossGrad. +*/ +REG_OP(KlDivLossGrad) + .INPUT(grad, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(input, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(target, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(reduction, String, "mean") + .ATTR(log_target, Bool, false) + .OP_END_FACTORY_REG(KlDivLossGrad) + +/** +* @brief Computes l1_loss_grad or l1_loss_backward. \n + +* @par Inputs: +* Three inputs, including: +* @li grads: A Tensor. Must be one of the following types: float16, float32. +* Required. +* @li predict: A Tensor. Has the same type as "grads". Required. +* @li label: A Tensor. Has the same type as "grads". Required. \n + +* @par Attributes: +* @li reduction: An optional attribute of type String. Defaults to "mean". \n + +* @par Outputs: +* @li y: A Tensor. Has the same type as "x". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator L1LossGrad. +*/ +REG_OP(L1LossGrad) + .INPUT(grads, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(predict, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(label, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(L1LossGrad) + +/** +* @brief Computes loss of lp, p=1,2,3.... + +* @par Inputs: +* @li predict: An ND tensor of type float16, float32. +* @li label: An ND tensor of type float16, float32. \n + +* @par Attributes: +* @li p: A required int attribute that decides which loss to compute, now the p only can be 1 to compute l1_loss. +* @li reduction: An optional string.Defaults to "mean". \n + +* @par Outputs: +* @li y: An ND tensor tensor with the same shape and type as "predict". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator LpLoss. +*/ +REG_OP(LpLoss) + .INPUT(predict, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(label, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(p, Int) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(LpLoss) + +/** +* @brief Computes gradients of mse loss. + +* @par Inputs: +* @li predict: An ND tensor of type float16, float32. +* @li label: An ND tensor of type float16, float32. +* @li dout: An ND tensor of type float16, float32. \n + +* @par Attributes: +* @li reduction: An optional string.Defaults to "mean". \n + +* @par Outputs: +* @li y: An ND tensor tensor with the same shape and type as "predict". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator MseLossGrad. +*/ +REG_OP(MseLossGrad) + .INPUT(predict, TensorType({DT_FLOAT32, DT_FLOAT16})) + .INPUT(label, TensorType({DT_FLOAT32, DT_FLOAT16})) + .INPUT(dout, TensorType({DT_FLOAT32, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT32, DT_FLOAT16})) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(MseLossGrad) + +/** +* @brief Computes mse loss. +* @par Inputs: +* two inputs, including: +* @li predict: An ND Tensor of dtype float16 or float32. +* @li label: An ND Tensor of dtype float16 or float32.\n +* +* @par Attributes: +* @li reduction:An optional str from sum, none, mean, Defaults to "mean".\n +* +* @par Outputs: +* @li y: when reduction=sum/mean, y is scale. when reduction=none, y has +* same type and shape as "predict".\n +*/ +REG_OP(MseLoss) + .INPUT(predict, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(label, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(MseLoss) + +/** +* @brief Calculates the reversed outputs of the function "smooth_l1_loss_v2". \n + +* @par Inputs: +* Three Inputs, including: +* @li predict: A Tensor. Must be one of the following types: +* float16, float32. +* @li label: A Tensor. Has the same type as "predict". +* @li dout: A Tensor. Has the same type as "predict". \n + +* @par Attributes: +* Two Attributes, including: +* @li sigma: An optional float. Defaults to 1.0. \n + +* @li reduction: An optional string. Defaults to "mean", +* Must be one of the following: "none", "mean", "sum". \n + +* @par Outputs: +* @li gradient: A Tensor. Has the same type as "predict". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator SmoothL1LossBackward. +*/ +REG_OP(SmoothL1LossGradV2) + .INPUT(predict, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(label, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(dout, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(gradient, TensorType({DT_FLOAT, DT_FLOAT16})) + .ATTR(sigma, Float, 1.0) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(SmoothL1LossGradV2) + +/** +* @brief Creates a criterion that uses a squared term if the absolute +* element-wise error falls below beta and an L1 term otherwise. It is +* less sensitive to outliers than the MSELoss and in some cases prevents +* exploding gradients. + +* @par Inputs: +* @li predict: A multi-dimensional Tensor of type float16 or float32, +* specifying the predictive value. \n +* @li label: A multi-dimensional Tensor of type float16 or float32, +* specifying the target value. \n + +* @par Attributes: +* @li sigma: An optional int. Specifies the threshold of loss. Defaults +* to "1.0". \n +* @li reduction: An optional str. Specifies the reduction to apply to +* the output: 'none' | 'mean' | 'sum'. 'none': no reduction will be applied, +* 'mean': the sum of the output will be divided by the number of elements in +* the output,'sum': the output will be summed. Default: 'mean'. \n + +* @par Outputs: +* @li loss: Indicates the loss between the predictive value and target value. +* Has the same dimensions as "predict". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator smooth_l1_loss. \n +*/ +REG_OP(SmoothL1LossV2) + .INPUT(predict, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(label, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .OUTPUT(loss, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .ATTR(sigma, Float, 1.0) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(SmoothL1LossV2) + +/** +* @brief Computes Centralization. result = x - mean(x, axes) + +* @par Inputs: +* @li x: An ND tensor of type float16, float32. +* @par Attributes: +* @li axes: The dimensions to reduce. Must be one of the following types: int, list, tuple, NoneType. +* Must be in the range [-rank(x), rank(x)). +* @par Outputs: +* @li y: A Tensor. Has the same type as "x". \n + +* @par Third-party framework compatibility +* custom operator \n +*/ +REG_OP(Centralization) + .INPUT(x, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .OUTPUT(y, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .ATTR(axes, ListInt, {-1}) + .OP_END_FACTORY_REG(Centralization) + +/** +*@brief Roll the tensor along the given dimension(s). +* Elements that are shifted beyond the last position are re-introduced at the first position. +* If a dimension is not specified, the tensor will be flattened before rolling and then restored to the original shape. \n + +*@par Inputs: +*One inputs, including: +* @li x: A tensor . Must be one of the following types: +* float16, float32, int32, uint32, int8, uint8. \n *@par Attributes: -* epsilon: An optional float32, specifying the small value added to -variance to avoid dividing by zero. Defaults to "0.00001" . \n +* @li shifts: The number of places by which the elements of the tensor are shifted. \n +* @li dims: Axis along which to roll. \n -*@par Outputs:\n -* variance_sqrt: A [N, C1, 1, 1, C0] Tensor of type float32, for the variance_sqrt. +*@par Outputs: +* y: A Tensor with the same type and shape of x's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator Roll. \n */ -REG_OP(InHost) - .INPUT(variance, TensorType({DT_FLOAT})) - .OUTPUT(variance_sqrt, TensorType({DT_FLOAT})) - .ATTR(epsilon, Float, 0.00001) - .OP_END_FACTORY_REG(InHost) +REG_OP(Roll) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_UINT32,DT_INT8,DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_UINT32,DT_INT8,DT_UINT8})) + .REQUIRED_ATTR(shifts, ListInt) + .ATTR(dims, ListInt, {}) + .OP_END_FACTORY_REG(Roll) + +/** + *@brief Calculate the loss. Creates a criterion that optimizes a two-class classification + logistic loss between input_x and input_y (containing 1 or -1). \n + + *@par Inputs: + *One inputs, including: + * @li input_x: A tensor. Must be one of the following types: + * float16, float32. \n + * @li input_y: A tensor. Must be one of the following types: + * float16, float32. \n + + *@par Attributes: + *@li lambd: An optional string.Defaults to "mean". \n + + *@par Outputs: + *output_z: while reduction == "none", A Tensor with the same type and shape of input_x's. \n + * while reduction == "sum" or "mean", A Tensor with the same type of input_x , shape of which is (1,) + + *@par Third-party framework compatibility + *Compatible with the Pytorch operator SoftMarginLoss. \n + */ +REG_OP(SoftMarginLoss) + .INPUT(input_x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(input_y, TensorType({DT_FLOAT, DT_FLOAT16})) + .ATTR(reduction, String, "mean") + .OUTPUT(output_z, TensorType({DT_FLOAT, DT_FLOAT16})) + .OP_END_FACTORY_REG(SoftMarginLoss) + +/** +* @brief Computes gradients of sigmoid_cross_entropy_with_logits_v2. + +* @par Inputs: +* @li predict: An ND tensor of type float16, float32. +* @li target: An ND tensor of type float16, float32. +* @li dout: An ND tensor of type float16, float32. +* @li weight: An optional ND tensor of type float16, float32. +* @li pos_weight: An optional ND tensor of type float16, float32. \n + +* @par Attributes: +* @li reduction: An optional string.Defaults to "mean". \n + +* @par Outputs: +* @li gradient: An ND tensor tensor with the same shape and type as "predict". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator SigmoidCrossEntropyWithLogitsGrad. +*/ +REG_OP(SigmoidCrossEntropyWithLogitsGradV2) + .INPUT(predict, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(target, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(dout, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(weight, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(pos_weight, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(gradient, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(SigmoidCrossEntropyWithLogitsGradV2) +/** + * @brief Calculate the PoissonNllLoss function. + * target∼Poisson(input)loss(input,target)=input−target∗log(input)+log(target!) \n + + * @par Inputs: + * Two inputs, including: + * @li input_x: A tensor. Must be one of the following types: + * float16, float32. \n + * + * @par Inputs: + * @li target: A tensor. Must be one of the following types: + * float16, float32. \n + + * @par Attributes: + * four Attributes, including: + * @li log_input: An optional bool. Defaults to "True" \n + * + * @par Attributes: + * @li full: An optional bool. Defaults to "False" \n + * + * @par Attributes: + * @li eps: An optional float. Defaults to "1e-8" \n + * + * @par Attributes: + * @li reduction: An optional string. Defaults to "mean" \n + + * @par Outputs: + * loss: A Tensor has same element type as two inputs. \n + + * @par Third-party framework compatibility + * Compatible with the Pytorch operator PoissonNllLoss. \n + */ +REG_OP(PoissonNllLoss) + .INPUT(input_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(target, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(loss, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(log_input, Bool, true) + .ATTR(full, Bool, false) + .ATTR(eps, Float, 1e-8) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(PoissonNllLoss) +/** + *@brief rnn_gen_mask + * @par Inputs: + * @li seq_length: A ND Tensor of type int32. Recoed the current length of each batch.\n + * + * @par Attributes: + * @li num_step: A required int.\n + * @li hidden_size: A required int. \n + * + * + * @par Output: + * y: A mutable Tensor of type float16, with the shape of [num_step, batch_size, hidden_size]. \n + * + */ +REG_OP(RnnGenMask) + .INPUT(seq_length, TensorType({DT_INT32})) + .OUTPUT(seq_mask, TensorType({DT_FLOAT16})) + .REQUIRED_ATTR(num_step, Int) + .REQUIRED_ATTR(hidden_size, Int) + .OP_END_FACTORY_REG(RnnGenMask) + +/** +* @brief Creates a criterion that optimizes a multi-class multi-classification hinge loss (margin-based loss) +* between input x (a 2D mini-batch Tensor) and output y (which is a 2D Tensor of target class indices) \n + +* @par Inputs: +* Two inputs, including: +* @li x: A tensor. Must be one of the following types: +* float16, float32. \n +* +* @par Inputs: +* @li target: A tensor. Must be the following types: +* int32. \n + +* @par Attributes: +* @li reduction: An optional string. Defaults to "mean" \n + +* @par Outputs: +* y: A Tensor has same element type as input x. \n +* is_target: A Tensor has same element type as input target. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator MultiLabelMarginLoss. \n +*/ +REG_OP(MultilabelMarginLoss) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(target, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(is_target, TensorType({DT_INT32})) + .ATTR(reduction, String, "mean") + .OP_END_FACTORY_REG(MultilabelMarginLoss) + +/** +*@brief Performs batch normalization . \n +*@par Inputs: +* Two inputs +*@li input_x: A Tensor. Support float32. shape (n, c, d). +*@li seq_len: A Tensor. Each batch normalize data num. Support Int32. Shape (n, ). \n +*@par Attributes: +*@li normalize_type: Str. Support "per_feature" or "all_features". +*@li epsilon: An optional float32, specifying the small value added to +variance to avoid dividing by zero. Defaults to "0.00001" . \n +*@par Outputs: +* One outputs +*@li output_y: A Tensor for the normalized "x".Support float32. shape (n, c, d).\n +*/ +REG_OP(NormalizeBatch) + .INPUT(input_x, TensorType({ DT_FLOAT })) + .INPUT(seq_len, TensorType({ DT_INT32 })) + .OUTPUT(output_y, TensorType({ DT_FLOAT })) + .REQUIRED_ATTR(normalize_type, String) + .ATTR(epsilon, Float, 0.00001) + .OP_END_FACTORY_REG(NormalizeBatch) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_NORM_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_ops.h b/third_party/fwkacllib/inc/ops/nn_ops.h index 9edc469a..49fd02fa 100644 --- a/third_party/fwkacllib/inc/ops/nn_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -20,7 +20,144 @@ */ #ifndef OPS_BUILT_IN_OP_PROTO_INC_NN_OPS_H_ #define OPS_BUILT_IN_OP_PROTO_INC_NN_OPS_H_ - +#include "graph/operator_reg.h" #include "nn_pooling_ops.h" +namespace ge { +/** +* @brief Says whether the targets are in the top "k" predictions . \n + +* @par Inputs: +* Three inputs, including: +* @li predictions: A 2D Tensor of type float32. A "batch_size * classes" tensor. +* @li targets: A 1D Tensor of type IndexNumberType. A batch_size tensor of class ids. +* @li k: A 1D Tensor of the same type as "targets". +* Specifies the number of top elements to look at for computing precision . \n + +* @par Outputs: +* precision: A Tensor of type bool . \n + +* @attention Constraints: +* @li targets must be non-negative tensor. + +* @par Third-party framework compatibility +* @li Compatible with the TensorFlow operator InTopKV2. +*/ +REG_OP(InTopKV2) + .INPUT(predictions, TensorType({DT_FLOAT})) + .INPUT(targets, TensorType(IndexNumberType)) + .INPUT(k, TensorType({IndexNumberType})) + .OUTPUT(precision, TensorType({DT_BOOL})) + .OP_END_FACTORY_REG(InTopKV2) + +/** +*@brief Performs batch normalization . \n + +*@par Inputs: +* Five inputs, including: (NHWC, NCHW, or NC1HWC0 supported) +*@li x: A 4D or 5D Tensor of type float16 or float32, with format NHWC or NCHW for 4D or NC1HWC0 for 5D. +*@li scale: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D +if input "x" is with format NC1HWC0. Specifies the scaling factor. +*@li offset: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D +if input "x" is with format NC1HWC0. Specifies the offset. +*@li mean: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D +if input "x" is with format NC1HWC0. Specifies the mean used for inference. Must be "None" if the +operation is used for training. +*@li variance: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be +5D if input "x" is with format NC1HWC0. Specifies the variance used for inference. Must be "None" +if the operation is used for training . \n + +*@par Attributes: +*@li epsilon: An optional float32, specifying the small value added to variance to avoid dividing by zero. Defaults to "0.0001". +*@li data_format: An optional string, specifying the format of "x". Defaults to "NHWC". +*@li is_training: An optional bool, specifying if the operation is used for training or inference. Defaults to "True" . \n + +*@par Outputs: +* Five outputs, including: (NHWC, NCHW, or NC1HWC0 supported) +*@li y: A 4D or 5D Tensor of type float16 or float32 for the normalized "x", with format NHWC or NCHW for 4D or NC1HWC0 for 5D. +*@li batch_mean: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D +if input "x" is with format NC1HWC0. Specifies the mean of "x". +*@li batch_variance: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. +Must be 5D if input "x" is with format NC1HWC0. Specifies the variance of "x". +*@li reserve_space_1: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. +Must be 5D if input "x" is with format NC1HWC0. Specifies the mean of "x" for gradient computation. Pass "None" to skip this output. +*@li reserve_space_2: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. +Must be 5D if input "x" is with format NC1HWC0. Specifies the variance of "x" for gradient computation. Pass "None" to skip this output . \n + +*@attention Constraints: +*@li If the operation is used for inference and outputs "reserve_space_1" and "reserve_space_2" are available, +then "reserve_space_1" has the same value as "mean" and "reserve_space_2" has the same value as "variance". +*@li For Ascend 310, the result accuracy fails to reach 1‰ due to the square root instruction . \n +*/ +REG_OP(FusedBatchNormV2) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(scale, TensorType({DT_FLOAT})) + .INPUT(offset, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(mean, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(variance, TensorType({DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(batch_mean, TensorType({DT_FLOAT})) + .OUTPUT(batch_variance, TensorType({DT_FLOAT})) + .OUTPUT(reserve_space_1, TensorType({DT_FLOAT})) + .OUTPUT(reserve_space_2, TensorType({DT_FLOAT})) + .ATTR(epsilon, Float, 0.0001) + .ATTR(data_format, String, "NHWC") + .ATTR(is_training, Bool, true) + .OP_END_FACTORY_REG(FusedBatchNormV2) + +/** + * @brief: Large amount of data sort.First operator of TopK. + * @par Inputs: + * two input, including: + * @li input_data: A Tensor. Data to be sorted. Support float16 + * @li input_index: A Tensor. Range(0, 2048). Datatype and format is same as input_data. + * @par Attributes: + * @li k_num: Int.Number to be sorted. + * @par Outputs: + * 1 output, including: + * @li output_proposal: A Tensor. Datatype and format is same as input_data. Proposal sorted for each channel. + */ +REG_OP(SegmentSort) + .INPUT(input_data, TensorType({DT_FLOAT16})) + .INPUT(input_index, TensorType({DT_FLOAT16})) + .OUTPUT(output_proposal, TensorType({DT_FLOAT16})) + .REQUIRED_ATTR(k_num, Int) + .OP_END_FACTORY_REG(SegmentSort) + +/** + * @brief: Large amount of data sort.Second operator of TopK. + * @par Inputs: + * two input, including: + * @li input_proposal: A Tensor. Proposal sorted for each channel. Support float16 + * @par Attributes: + * @li k_num: Int.Number to be sorted. + * @par Outputs: + * 1 output, including: + * @li output_proposal: A Tensor. Datatype and format is same as input_data. Proposal sorted for each channel. + */ +REG_OP(MultiMerge) + .INPUT(input_proposal, TensorType({DT_FLOAT16})) + .OUTPUT(output_proposal, TensorType({DT_FLOAT16})) + .REQUIRED_ATTR(k_num, Int) + .OP_END_FACTORY_REG(MultiMerge) + +/** + * @brief: Large amount of data sort.Third operator of TopK. + * @par Inputs: + * two input, including: + * @li input_proposal: A Tensor. Proposal sorted for each channel. Support float16 + * @par Attributes: + * @li k_num: Int.Number to be sorted. + * @par Outputs: + * 2 output, including: + * @li output_data: A Tensor. Datatype and format is same as input_data. Data sorted. + * @li output_index: A Tensor. int32. Data index. + */ +REG_OP(SingleMerge) + .INPUT(input_proposal, TensorType({DT_FLOAT16})) + .OUTPUT(output_data, TensorType({DT_FLOAT16})) + .OUTPUT(output_index, TensorType({DT_INT32})) + .REQUIRED_ATTR(k_num, Int) + .OP_END_FACTORY_REG(SingleMerge) +}// namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h index ab35ba47..80a21333 100644 --- a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -182,6 +182,128 @@ REG_OP(AvgPool3D) .ATTR(data_format, String, "NDHWC") .OP_END_FACTORY_REG(AvgPool3D) + +/** +*@brief Performs average pooling on the input. + +*@par Inputs: +*@li x: A 5-D Tensor of shape [batch, depth, height, width, channels] and type float16, float32, double. +*@li filter: An optional tensor of type float16, float32, double, fractal_z_3d layout. +*@li multiplier: An optional tensor of float16, float32, double. + +*@par Attributes: +*@li ksize: List of ints that has length 1, 3 or 5. The size of the window for each dimension of the input tensor. +*@li strides:List of ints that has length 1, 3 or 5. The stride of the sliding window for each dimension of the input tensor. +*@li pads: List of ints, implicit zero paddings on both sides of the input. +*@li ceil_mode: When true, will use ceil instead of floor in the formula to compute the output shape. +*@li count_include_pad: When true, will include the zero-padding in the averaging calculation. +*@li divisor_override: if specified, it will be used as divisor, otherwise size of the pooling region will be used. +*@li data_format: A string, format of input data . \n + +*@par Outputs: +*y: The average pooled output tensor . \n + +*@attention Constraints: +*@li "ksize" is in the range [1, 255]. "strides" is in the range [1, 63] + +*@par Third-party framework compatibility +* Compatible with the TensorFlow operator AvgPool3D. +*/ +REG_OP(AvgPool3DD) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .OPTIONAL_INPUT(filter, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .OPTIONAL_INPUT(multiplier, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .REQUIRED_ATTR(ksize, ListInt) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(pads, ListInt) + .ATTR(ceil_mode, Bool, false) + .ATTR(count_include_pad, Bool, true) + .ATTR(divisor_override, Int, 0) + .ATTR(data_format, String, "NDHWC") + .OP_END_FACTORY_REG(AvgPool3DD) + +/** +* @brief Computes AvgPool3DGrad function. + +* @par Inputs: +* @li orig_input_shape: An NDHWC tensor of type int32. +* @li grads: An NDHWC tensor of type float16, float32, or double. + +* @par Attributes: +* @li ksize: List of ints that has length 5. The size of the window for each dimension of the input tensor. +* @li strides:List of ints that has length 5. The stride of the sliding window for each dimension of the input tensor. +* @li pads: List of ints, implicit zero paddings on both sides of the input. +* @li ceil_mode: When true, will use ceil instead of floor in the formula to compute the output shape. +* @li count_include_pad: When true, will include the zero-padding in the averaging calculation. +* @li divisor_override: if specified, it will be used as divisor, otherwise size of the pooling region will be used. +* @li data_format: A string, format of input data. + +* @par Outputs: +* @output: A mutable tensor with the same shape and type as "orig_input_shape". + +* @attention Constraints: +* @li "ksize" is in the range [1, 255]. "strides" is in the range [1, 63] + +* @par Third-party framework compatibility +* @li Compatible with the TensorFlow operator AvgPoolGrad. +*/ + +REG_OP(AvgPool3DGrad) + .INPUT(orig_input_shape, TensorType({DT_INT32})) + .INPUT(grads, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .OUTPUT(output, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .REQUIRED_ATTR(ksize, ListInt) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(pads, ListInt) + .ATTR(ceil_mode, Bool, false) + .ATTR(count_include_pad, Bool, true) + .ATTR(divisor_override, Int, 0) + .ATTR(data_format, String, "NDHWC") + .OP_END_FACTORY_REG(AvgPool3DGrad) + +/** +* @brief Performs average pooling on the input. + +* @par Inputs: +* @li grads: An NDHWC tensor of type float16. +* @li filter: An optional tensor of type float16, fractal_z_3d layout. +* @li multiplier: An optional tensor of float16. + +* @par Attributes: +* @li orig_input_shape: List of ints that has length 5. The size of the window for each dimension of the input tensor. +* @li ksize: List of ints that has length 5. The size of the window for each dimension of the input tensor. +* @li strides:List of ints that has length 5. The stride of the sliding window for each dimension of the input tensor. +* @li pads: List of ints, implicit zero paddings on both sides of the input. +* @li ceil_mode: When true, will use ceil instead of floor in the formula to compute the output shape. +* @li count_include_pad: When true, will include the zero-padding in the averaging calculation. +* @li divisor_override: if specified, it will be used as divisor, otherwise size of the pooling region will be used. +* @li data_format: A string, format of input data . \n + +* @par Outputs: +* @output: The average pooled output tensor . \n + +* @attention Constraints: +* @li "ksize" is in the range [1, 255]. "strides" is in the range [1, 63] + +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator AvgPool3DGradD. +*/ +REG_OP(AvgPool3DGradD) + .INPUT(grads, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(filter, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(multiplier, TensorType({DT_FLOAT16})) + .OUTPUT(output, TensorType({DT_FLOAT16})) + .REQUIRED_ATTR(orig_input_shape, ListInt) + .REQUIRED_ATTR(ksize, ListInt) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(pads, ListInt) + .ATTR(ceil_mode, Bool, false) + .ATTR(count_include_pad, Bool, true) + .ATTR(divisor_override, Int, 0) + .ATTR(data_format, String, "NDHWC") + .OP_END_FACTORY_REG(AvgPool3DGradD) + /** *@brief Performs max_pool_ext2 on the input . \n @@ -278,8 +400,8 @@ No default value. specifying the stride of the sliding window for each dimension of the input tensor. No default value. *@li padding: A required string type of float16. -*@li pads: A list type of int32. Default value {0, 0, 0}. -*@li dilation: A list type of int32. Default value {1, 1, 1}. +*@li pads: A list type of int32. Default value {0,0,0,0,0,0}. +*@li dilation: A list type of int32. Default value {1,1,1,1,1,1}. *@li ceil_mode: A ceil mode number of int32 . Default value 0. *@li data_format: An optional string. Defaults to "NDHWC" . \n @@ -302,12 +424,37 @@ REG_OP(MaxPool3D) .REQUIRED_ATTR(ksize, ListInt) .REQUIRED_ATTR(strides, ListInt) .REQUIRED_ATTR(padding, String) - .ATTR(pads, ListInt, {0,0,0}) - .ATTR(dilation, ListInt, {1,1,1}) + .ATTR(pads, ListInt, {0,0,0,0,0,0}) + .ATTR(dilation, ListInt, {1,1,1,1,1,1}) .ATTR(ceil_mode, Int, 0) .ATTR(data_format, String, "NDHWC") .OP_END_FACTORY_REG(MaxPool3D) +/** +*@brief Applies a 2D adaptive max pooling over an input signal conposed of several input planes. \n +* The output is of size H x W, for any input size. + +* @par Inputs: +* One input, including: +* @li x: A Tensor. Must be one of the following data types: +* float16, float32, float64. \n + +* @par Attributes: +* @li output_size: A required list of 2 ints +* specifying the size (H,W) of the output tensor. \n + +* @par Outputs: +* @li y: A Tensor. Has the same data type as "x" \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator AdaptiveMaxPool2d. +*/ +REG_OP(AdaptiveMaxPool2d) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .OUTPUT(argmax, TensorType::IndexNumberType()) + .REQUIRED_ATTR(output_size, ListInt) + .OP_END_FACTORY_REG(AdaptiveMaxPool2d) /** * @brief Computes second-order gradients of the maxpooling3d function . \n @@ -477,8 +624,9 @@ REG_OP(MaxPoolV2) *@par Inputs: * One input: -*x: An NC1HWC0 Tensor. Supported type: float, double, int32, - * uint8, int16, int8, int64, uint16, half, uint32, uint64 . \n +* x: An 4D Tensor. Supported type: float, double, int32, + * uint8, int16, int8, int64, uint16, half, uint32, uint64. + * Must set the format, supported format list ["NCHW, NHWC"]. \n *@par Attributes: *@li ksize: A required list of int8, int16, int32, or int64 values, @@ -490,8 +638,8 @@ REG_OP(MaxPoolV2) *@li padding: A required string. No default value . \n *@par Outputs: -*y: A Tensor. Has the same type and format as input "x". -*argmax: A Tensor. Has the same type and format as input "x". +*@li y: A Tensor. Has the same type and format as input "x". +*@li argmax: A Tensor. Has the same type and format as input "x". *@attention Constraints: *@li "ksize" is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, * ksize[1] * ksize[2] <= 255. @@ -517,10 +665,12 @@ REG_OP(MaxPoolWithArgmax) *@par Inputs: * Three inputs, including: -*@li x: An NC1HWC0 tensor. Supported type: float, double, int32, +*@li x: An 4d tensor. Supported type: float, double, int32, * uint8, int16, int8, int64, uint16, half, uint32, uint64. -*@li grad: An NC1HWC0 tensor. Supported type: float, double, int32, + * Must set the format, supported format list ["NCHW, NHWC"] +*@li grad: An 4d tensor. Supported type: float, double, int32, * uint8, int16, int8, int64, uint16, half, uint32, uint64. + * Must set the format, supported format list ["NCHW, NHWC"] *@li argmx: An NC1HWC0 tensor of type int32 or int64 . \n *@par Attributes: @@ -741,7 +891,7 @@ REG_OP(AvgPoolV2Grad) * @brief Computes gradients of averagev2 pooling function. * @par Inputs: -* @li input_grad: An NHWC tensor of type float16, float32, or double. +*input_grad: An NHWC tensor of type float16, float32, or double. * @par Attributes: * @li orig_input_shape: A required tuple or list of type int32. @@ -759,10 +909,10 @@ REG_OP(AvgPoolV2Grad) * @li data_format: An optional string. Defaults to "NHWC". * @par Outputs: -* @out_grad: A mutable tensor with the same shape and type as "orig_input". +*out_grad: A mutable tensor with the same shape and type as "orig_input". * @par Third-party framework compatibility -* @li Compatible with the TensorFlow operator AvgPoolGrad. +*Compatible with the TensorFlow operator AvgPoolGrad. */ REG_OP(AvgPoolV2GradD) .INPUT(input_grad, TensorType({DT_FLOAT16})) @@ -1037,6 +1187,7 @@ REG_OP(MaxPool3DGrad) .OUTPUT(y, TensorType::RealNumberType()) .REQUIRED_ATTR(ksize, ListInt) .REQUIRED_ATTR(strides, ListInt) + .ATTR(padding, String, "SAME") .REQUIRED_ATTR(pads, ListInt) .ATTR(data_format, String, "NDHWC") .OP_END_FACTORY_REG(MaxPool3DGrad) @@ -1107,7 +1258,7 @@ REG_OP(AvgPool1DD) *@par Inputs: * One input: -*x: An NC1HWC0 Tensor of type float16. +*x: An 4d Tensor of type float16. Must set the format, supported format list ["NCHW, NHWC"]. *@par Attributes: *@li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for * each dimension of the input tensor. No default value. @@ -1148,9 +1299,9 @@ REG_OP(MaxPoolWithArgmaxV2) *@par Inputs: * Three inputs, including: -*@li x: An NC1HWC0 tensor of type float16. -*@li grad: An NC1HWC0 tensor of type float16. -*@li argmx: An NC1HWC0 tensor of type uint16 or int64 . \n +*@li x: An 4d tensor of type float16. Must set the format, supported format list ["NCHW, NHWC"] +*@li grad: An 4d tensor of type float16. Must set the format, supported format list ["NCHW, NHWC"] +*@li argmx: An 4d tensor of type uint16 or int64. Must set the format, supported format list ["NCHW, NHWC"] \n *@par Attributes: *@li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for @@ -1291,5 +1442,306 @@ REG_OP(MaxPoolV3Grad) .ATTR(global_pooling, Bool, false) .ATTR(ceil_mode, Bool, false) .OP_END_FACTORY_REG(MaxPoolV3Grad) + +/** +*@brief Performs Dilation2D on the input . \n + +*@par Inputs: +*x: A tensor of shape is 4d, format is support NHWC. +*filter: A tensor of shape is 3d, the type is same with x, and the c dimension is same with x. \n + +*@par Attributes: +*@li strides: A required list of 4 ints, specifying the stride of the sliding window. The strides of the N and C dimensions are 1. +*@li rates: A required list of 4 ints. The rates of the N and C dimensions are 1. +*@li padding_mode: A optional string. Defaults to "SAME", it support SAME and VALID. +*@li pads: An optional list of 4 ints. +*@li ceil_mode: An optional bool. Defaults to "false". Use ceil or floor to calculate the output size when padding_mode is "CALCULATED". +*@li data_format: An optional string, specifying the data format of "rates" and "strides", either "NCHW" or "NHWC" (default). \n + +*@par Outputs: +*y: The output tensor. Has the same type and format as input "x" . \n + +*@par Third-party framework compatibility +* Compatible with the TensorFlow operator Dilation2D. +*/ +REG_OP(Dilation2D) + .INPUT(x,TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .INPUT(filter,TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .OUTPUT(y,TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(rates, ListInt) + .ATTR(padding_mode, String, "SAME") + .ATTR(pads, ListInt, {0,0,0,0}) + .ATTR(ceil_mode, Bool, false) + .ATTR(data_format, String, "NHWC") + .OP_END_FACTORY_REG(Dilation2D) + +/** +*@brief Performs Dilation2DBackpropFilter on the input. \n + +*@par Inputs: +*x: A tensor of shape is 4d, format is support NHWC. +*filter: A tensor of shape is 3d, the type is same with x, and the c dimension is same with x. +*out_backprop: Has the same type and format as input x and the c dimension is same with x. \n + +*@par Attributes +*@li strides: A required list of 4 ints, specifying the stride of the sliding window. The strides of the N and C dimension are 1. +*@li rates: A required list of 4 ints, the rates of the N and C dimensions are 1. +*@li padding_mode: A optional string. Defaults to "SAME", it support SAME and VALID. +*@li pads: A optional list of 4 ints. +*@li ceil_mode: An optional bool. Defaults to "false". Use ceil or floor to calculate the output size when padding_mode is "CALCULATED". +*@li data_format: An optional string, specifying the data format of "rates" and "strides", either "NCHW" or "NHWC" (default). \n + +*@par Outputs: +*y: The output tensor. Has the same type and format as input "filter" . \n + +*@par Third-party framework compatibility +* Compatible with the TensorFlow operator Dilation2DBackpropFilter. +*/ + +REG_OP(Dilation2DBackpropFilter) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .INPUT(filter, + TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .INPUT(out_backprop, + TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .OUTPUT(y, + TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(rates, ListInt) + .ATTR(padding_mode, String, "SAME") + .ATTR(pads, ListInt, {0, 0, 0, 0}) + .ATTR(ceil_mode, Bool, false) + .ATTR(data_format, String, "NHWC") + .OP_END_FACTORY_REG(Dilation2DBackpropFilter) + +/** +*@brief Performs Dilation2DBackpropInput on the input. \n + +*@par Inputs: +*x: A tensor of shape is 4d, format is support NHWC. +*filter: A tensor of shape is 3d, the type is same with x, and the c dimension is same with x. +*out_backprop: Has the same type and format as input x and the c dimension is same with x. \n + +*@par Attributes +*@li strides: A required list of 4 ints, specifying the stride of the sliding window. The strides of the N and C dimension are 1. +*@li rates: A required list of 4 ints, the rates of the N and C dimensions are 1. +*@li padding_mode: A optional string. Defaults to "SAME", it support SAME and VALID. +*@li pads: A optional list of 4 ints. +*@li ceil_mode: An optional bool. Defaults to "false". Use ceil or floor to calculate the output size when padding_mode is "CALCULATED". +*@li data_format: An optional string, specifying the data format of "rates" and "strides", either "NCHW" or "NHWC" (default). \n + +*@par Outputs: +*y: The output tensor. Has the same type and format as input "x" . \n + +*@par Third-party framework compatibility +* Compatible with the TensorFlow operator Dilation2DBackpropInput. +*/ + +REG_OP(Dilation2DBackpropInput) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .INPUT(filter, + TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .INPUT(out_backprop, + TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .OUTPUT(y, + TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64, DT_UINT8, DT_INT16, DT_INT8, DT_UINT16})) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(rates, ListInt) + .ATTR(padding_mode, String, "SAME") + .ATTR(pads, ListInt, {0, 0, 0, 0}) + .ATTR(ceil_mode, Bool, false) + .ATTR(data_format, String, "NHWC") + .OP_END_FACTORY_REG(Dilation2DBackpropInput) + +/** +* @brief Applies a 2D adaptive average pooling over +* an input signal composed of several input planes. \n + +* @par Inputs: +* One input, including: +* @li x: A Tensor. Must be one of the following data types: +* float16, float32. \n + +* @par Attributes: +* @li output_size: A required list of 2 ints +* specifying the size (H,W) of the output tensor. \n + +* @par Outputs: +* @li y: A Tensor. Has the same data type as "x" \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator AdaptiveAvgPool2d. +*/ +REG_OP(AdaptiveAvgPool2d) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .REQUIRED_ATTR(output_size, ListInt) + .OP_END_FACTORY_REG(AdaptiveAvgPool2d) + +/** +* @brief Compute gradients of adaptive averagev2 pooling function. + +* @par Inputs: +* @li input_grad: A Tensor. Must be one of the following data types: +* float16, float32. + +* @par Attributes: +* @li orig_input_shape: A required tuple or list of type int32. + +* @par Outputs: +* @li output_grad: A tensor with the same type as "input_grad". + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator AdaptiveAvgPool2dGrad. +*/ +REG_OP(AdaptiveAvgPool2dGrad) + .INPUT(input_grad, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(output_grad, TensorType({DT_FLOAT, DT_FLOAT16})) + .REQUIRED_ATTR(orig_input_shape, ListInt) + .OP_END_FACTORY_REG(AdaptiveAvgPool2dGrad) + +/** +* @brief Performs the backpropagation of MaxPoolWithGradArgmaxV1. + +* @par Inputs: +* Three inputs, including: +* @li x: An NC1HWC0 tensor of type float16. +* @li grad: An NC1HWC0 tensor of type float16. +* @li argmax: An NC1HWC0 tensor of type uint16 or int64. \n + +* @par Attributes: +* @li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for +* each dimension of the input tensor. No default value. +* @li strides: A required list of int8, int16, int32, or int64 values, specifying the stride of the sliding window for +* each dimension of the input tensor. No default value. +* @li pads: A required listint. \n + +* @par Outputs: +* y: A Tensor. Has the same type and format as input "x". \n + +* @attention Constraints: +* @li "ksize" is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, ksize[1] * ksize[2] <= 255. +* @li "strides" is a list that has length 4: strides[0] = 1 or strides[3] = 1 +* @li "pads" is listint. +* @li "ceil_mode" defaults to False. +* @li "data_format" defaults to "NC1HWC0". \n + +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator MaxPoolGradWithArgmaxV1. +*/ + +REG_OP(MaxPoolGradWithArgmaxV1) + .INPUT(x, TensorType({DT_FLOAT16})) + .INPUT(grad, TensorType({DT_FLOAT16})) + .INPUT(argmax, TensorType({DT_UINT16})) + .OUTPUT(y, TensorType({DT_FLOAT16})) + .REQUIRED_ATTR(ksize, ListInt) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(pads, ListInt) + .ATTR(dtype, Int, 3) + .ATTR(dilation, ListInt, {1, 1, 1, 1}) + .ATTR(ceil_mode, Bool, false) + .OP_END_FACTORY_REG(MaxPoolGradWithArgmaxV1) + +/** +* @brief Performs max pooling on the input and outputs both max values and indices. + +* @par Inputs: +* One input: +* x: An NC1HWC0 Tensor of type float16. \n + +* @par Attributes: +* @li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for +* each dimension of the input tensor. No default value. +* @li strides: A required list of int8, int16, int32, or int64 values, specifying the stride of the sliding window for +* each dimension of the input tensor. No default value. +* @li pads: A required string. No default value. \n + +* @par Outputs: +* y: A Tensor. Has the same type and format as input "x". +* argmax: A Tensor. type:uint16, format:NC1HWC0. \n + +* @attention Constraints: +* @li "ksize" is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, ksize[1] * ksize[2] <= 255. +* @li "stride is a list that has length 4: strides[0] = 1 or strides[3] = 1, strides[1] <= 63, strides[0] >= 1, +* strides[2] <= 63, strides[2] >= 1. +* @li "pads" is listint. +* @li "ceil_mode" defaults to False. +* @li "data_format" defaults to "NC1HWC0". \n + +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator MaxPoolWithArgmaxV1. +*/ +REG_OP(MaxPoolWithArgmaxV1) + .INPUT(x, TensorType({DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT16})) + .OUTPUT(argmax, TensorType({DT_UINT16})) + .REQUIRED_ATTR(ksize, ListInt) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(pads, ListInt) + .ATTR(dtype, Int, 3) + .ATTR(dilation, ListInt, {1, 1, 1, 1}) + .ATTR(ceil_mode, Bool, false) + .OP_END_FACTORY_REG(MaxPoolWithArgmaxV1) + +/** +*@brief Randomly sample a subset of positive and negative examples,and overwrite +the label vector to the ignore value (-1) for all elements that are not +included in the sample.\n + +* @par Inputs: +* One input: +* labels: shape of labels,(N, ) label vector with values. \n + +* @par Attributes: +* @li batch_size_per_images: A require attribute of type int. +* @li positive_fraction: A require attribute of type float. + +*@par Outputs: +*y: The result of subSample. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator SubSample. +*@par Restrictions: +*Warning: This operator can be integrated only by MaskRcnn. Please do not use it directly. +*/ +REG_OP(SubSample) + .INPUT(labels, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_INT32})) + .REQUIRED_ATTR(batch_size_per_images, Int) + .REQUIRED_ATTR(positive_fraction, Float) + .OP_END_FACTORY_REG(SubSample) + +/** +*@brief Randomly sample a subset of positive and negative examples,and overwrite +the label vector to the ignore value (-1) for all elements that are not +included in the sample.\n + +* @par Inputs: +* two inputs, including: +* @li labels: shape of labels,(N, ) label vector with values:. +* @li shuffle_matrix: random matrix with shape (N, ). \n + +* @par Attributes: +* @li batch_size_per_images: A require attribute of type int. +* @li positive_fraction: A require attribute of type float. + +*@par Outputs: +*y: The result of subSample. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator SubSampleLabels. +*@par Restrictions: +*Warning: This operator can be integrated only by MaskRcnn. Please do not use it directly. +*/ +REG_OP(SubSampleLabels) + .INPUT(labels, TensorType({DT_INT32})) + .INPUT(shuffle_matrix, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_INT32})) + .REQUIRED_ATTR(batch_size_per_images, Int) + .REQUIRED_ATTR(positive_fraction, Float) + .OP_END_FACTORY_REG(SubSampleLabels) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_POOLING_OPS_H diff --git a/third_party/fwkacllib/inc/ops/nn_training_ops.h b/third_party/fwkacllib/inc/ops/nn_training_ops.h index 047fd6da..75e91aee 100644 --- a/third_party/fwkacllib/inc/ops/nn_training_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_training_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. @@ -2101,6 +2101,55 @@ REG_OP(FusedMulApplyMomentumExtern) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(FusedMulApplyMomentumExtern) +/** +*@brief Updates '*var' according to the momentum scheme. +* accum = accum * momentum - x1 * x2 * lr +* if use_nesterov is True: +* var += accum * momentum - x1 * x2 * lr +* else: +* var += accum +* +*@par Inputs: +*@li var: A mutable tensor. Must be one of the data types defined in +* TensorType::NumberType(). Should be from a Variable(). +*@li accum: A mutable tensor. Has the same type as "var". Should be from a +* Variable(). +*@li lr: A tensor for the learning rate. Has the same type as "var". Should be +* from a Variable(). +*@li x1: A Tensor has type TensorType::NumberType(). +*@li momentum: A scalar. Has the same type as "var". +*@li x2: A scalar has the same type as "var". +* +*@par Attributes: +*@li use_nesterov: An optional bool. Defaults to "False". +* If "True", var will be updated by using Nesterov momentum. +*@li use_locking: An optional bool. Defaults to "False". +* If "True", updating of the "var" tensor is protected by a lock; +* otherwise the behavior is undefined, but may exhibit less contention. +* +*@par Outputs: +* var: A mutable tensor. Has the same type as input "var". +* +*@attention Constraints: +* The input tensors must have the same shape. +* +*@par Third-party framework compatibility +* Compatible with the TensorFlow operator ResourceApplyKerasMomentum. +* +*/ +REG_OP(FusedMulApplyKerasMomentum) + .INPUT(var, TensorType::NumberType()) + .INPUT(accum, TensorType::NumberType()) + .INPUT(lr, TensorType::NumberType()) + .INPUT(x1, TensorType::NumberType()) + .INPUT(momentum, TensorType::NumberType()) + .INPUT(x2, TensorType::NumberType()) + .OUTPUT(var, TensorType::NumberType()) + .OUTPUT(accum, TensorType::NumberType()) + .ATTR(use_locking, Bool, false) + .ATTR(use_nesterov, Bool, false) + .OP_END_FACTORY_REG(FusedMulApplyKerasMomentum) + /** *@brief Update "g" according to the LARS algorithm . \n diff --git a/third_party/fwkacllib/inc/ops/no_op.h b/third_party/fwkacllib/inc/ops/no_op.h index 7834591c..b27b1fa0 100644 --- a/third_party/fwkacllib/inc/ops/no_op.h +++ b/third_party/fwkacllib/inc/ops/no_op.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h index e0e5dfc6..ca1c24eb 100644 --- a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h +++ b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. @@ -223,7 +223,29 @@ REG_OP(Relu6Grad) .INPUT(features, TensorType::RealNumberType()) .OUTPUT(backprops, TensorType::RealNumberType()) .OP_END_FACTORY_REG(Relu6Grad) - +/** +*@brief Calculate the elu_grad_v2 function. +*Applies the element-wise function: +* Computes the backward for the elu: if x>0, 1; otherwise elu() + alpha . +*@par Inputs: +*One inputs, including: +* @li grads: A tensor. Must be one of the following types: +* float16, float32. +* @li activations: A tensor. Must be one of the following types: +* float16, float32. +* +*@par Outputs: +*y: A Tensor with the same type and shape of grads's. +* +*@par Attributes: +*@li alpha: scalar parameter, default value = 1.0 +*/ +REG_OP(EluGradV2) + .INPUT(grads, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(activations, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .ATTR(alpha, Float, 1.0) + .OP_END_FACTORY_REG(EluGradV2) /** * @brief Compute sigmoid of "x" element-wise . \n @@ -508,6 +530,42 @@ REG_OP(Elu) .ATTR(alpha, Float, 1.0) .OP_END_FACTORY_REG(Elu) +/** +*@brief Continuously Differentiable Exponential Linear Uints: +* Perform the linear uint element-wise on the input tensor X using formula: +* max(0, x) + min(0, alpha * (exp(x/alpha) - 1)). \n + +*@par Inputs: +*x: A float16, float32, for the input data type . \n + +*@par Attributes: +*alpha1: A float32. Defines at which negative value the ELU saturates. Defaults to "1.0" . \n + +*@par Attributes: +*alpha2: A float32. Defines at which negative value the ELU saturates. Defaults to "1.0" . \n + +*@par Attributes: +*alpha3: A float32. Defines at which positive value the ELU saturates. Defaults to "1.0" . \n + +*@par Outputs: +*y: A float16, float32, for the normalized result . \n + +*@attention Constraints: +*@li The input is of type float16 or float32 . \n + +*@par Multiple batches supported or not +*Supported +*@par Third-party framework compatibility +*@li Compatible with ONNX's Celu operator +*/ +REG_OP(Celu) + .INPUT(x, TensorType({DT_FLOAT,DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT,DT_FLOAT16})) + .ATTR(alpha1, Float, 1.0) + .ATTR(alpha2, Float, 1.0) + .ATTR(alpha3, Float, 1.0) + .OP_END_FACTORY_REG(Celu) + /** *@brief Computes gradients for the exponential linear (Elu) operation. * @@ -640,6 +698,352 @@ REG_OP(Mish) .OUTPUT(y, TensorType({ DT_FLOAT,DT_FLOAT16 })) .OP_END_FACTORY_REG(Mish) +/** + * @brief: pytorch mish_grad operator. + * @par Inputs: + * three input, including: + * @li grad: A Tensor. shape, datatype and format is same as x + * @li x: A Tensor. Must be one of the following types: float16, float32 + * @li tanhx: A Tensor. shape, datatype and format is same as x + * @par Outputs: + * 1 output, including: + * @li x_grad: A Tensor. shape, datatype and format is same as x + */ + +REG_OP(MishGrad) + .INPUT(grad, TensorType({ DT_FLOAT,DT_FLOAT16 })) + .INPUT(x, TensorType({ DT_FLOAT,DT_FLOAT16 })) + .OPTIONAL_INPUT(tanhx, TensorType({ DT_FLOAT,DT_FLOAT16 })) + .OUTPUT(x_grad, TensorType({ DT_FLOAT,DT_FLOAT16 })) + .OP_END_FACTORY_REG(MishGrad) + +/** + * @brief pytorch hardtanh_backward operator. + * + * @par Inputs: + * 2 inputs, including: + * @li result, minimum tensor of the linear region range, + * datatype: float16/float32, format:ND/5HD. + * @li grad, maximum tensor of the linear region range, + * datatype:float16/float32, format:ND/5HD. \n + + * @par Attributes: + * 2 attributes, including: + * @li min_val, minimum value of the linear region range, datatype:float. + * @li max_val, maximum value of the linear region range, datatype:float. \n + + * @par Outputs: + * 1 output, including: + * @li y, hardtanh_backward output tensor, datatype and format is same as + * input result. \n + + * @attention Constraints: + * This operator only supports dataType: float16/float32, format: ND/5HD. \n + + * @par Third-party framework compatibility + * Compatible with the Pytorch operator HardtanhGrad. + */ +REG_OP(HardtanhGrad) + .INPUT(result, TensorType({ DT_FLOAT16, DT_FLOAT })) /* "First operand." */ + .INPUT(grad, TensorType({ DT_FLOAT16, DT_FLOAT })) /* "Second operand." */ + .OUTPUT(y, TensorType({ DT_FLOAT16, DT_FLOAT })) /* "Result, has same element type as two inputs" */ + .ATTR(min_val, Float, -1.0) + .ATTR(max_val, Float, 1.0) + .OP_END_FACTORY_REG(HardtanhGrad) + +/** +* @brief Calculates the softplus loss function with attributes of beta and threshold. \n + +* @par Inputs: +* One inputs, including: +* @li x: A mutable Tensor. Must be one of the following types: +* float16, float32. \n + +* @par Attributes: +* @li beta: An optional float. Defaults to "1.0" \n + +* @li threshold: An optional float. Defaults to "20.0" \n + +* @par Outputs: +* @li y: A mutable Tensor. Has the same type as "x" \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Softplus. +*/ +REG_OP(SoftplusV2) + .INPUT(x, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .OUTPUT(y, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .ATTR(beta, Float, 1.0) + .ATTR(threshold, Float, 20.0) + .OP_END_FACTORY_REG(SoftplusV2) + +/** +* @brief Calculates the reversed outputs of the function "softplus_v2". \n + +* @par Inputs: +* Two inputs, including: +* @li input_gradients: A mutable Tensor. Must be one of the following types: +* float16, float32. +* @li input_features: A mutable Tensor of the same type as "input_gradients" \n + +* @par Attributes: +* @li beta: An optional float. Defaults to "1.0" \n + +* @li threshold: An optional float. Defaults to "20.0" \n + +* @par Outputs: +* @li output_backprops: A mutable Tensor. Has the same type as "input_gradients" \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator SoftplusGrad. +*/ +REG_OP(SoftplusV2Grad) + .INPUT(input_gradients, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(input_features, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .OUTPUT(output_backprops, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .ATTR(beta, Float, 1.0) + .ATTR(threshold, Float, 20.0) + .OP_END_FACTORY_REG(SoftplusV2Grad) + +/** + * @brief ThresholdedRelu takes one input data (Tensor) and produces one output data (Tensor) + * where the rectified linear function, y = x for x > alpha, y = 0 otherwise, is applied to the tensor elementwise. + * + * @par inputs + * one input including: + * @li x: input A Tensor. Must be one of the following types: float32, float16 + * + * @par output + * one output including: + * @li y:A Tensor of the same type as x + * + */ +REG_OP(ThresholdedRelu) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(alpha, Float, 1.0) + .OP_END_FACTORY_REG(ThresholdedRelu) + +/** +* @brief Calculate the hard shrinkage function. \n + +* @par Inputs: +* One inputs, including: +* @li input_x: A tensor. Must be one of the following types: +* float16, float32. \n + +* @par Attributes: +* @li lambd: An optional float. Defaults to 0.5. \n + +* @par Outputs: +* y: A Tensor with the same dtype and shape of input_x's. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Hardshrink. \n +*/ +REG_OP(HardShrink) + .INPUT(input_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(lambd, Float, 0.5) + .OP_END_FACTORY_REG(HardShrink) + +/** +*@brief Calculate the hard shrink grad function. \n +* +* Computes the gradient for the HardShrink: if x > lambda or x < -lambda, x,otherwise 0 +* +*@par Inputs: +*Two inputs, including: +* @li gradients: A tensor. Must be one of the following types: +* float16, float32. \n +* @li features: A tensor. Must be one of the following types: +* float16, float32. \n +* +*@par Outputs: +*backprops: A Tensor with the same type and shape of features's. \n +* +*@par Attributes: +*@li lambd: An optional float.Defaults to 0.5. \n +* +*@par Third-party framework compatibility +*Compatible with the Pytorch operator Hardshrink_backward. \n +*/ + REG_OP(HardShrinkGrad) + .INPUT(gradients, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(features, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(backprops, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(lambd, Float, 0.5) + .OP_END_FACTORY_REG(HardShrinkGrad) + +/** +* @brief Calculate the hard sigmoid function. \n + +* @par Inputs: +* One inputs, including: +* @li input_x: A tensor. Must be one of the following types: +* float16, float32, int32. \n + +* @par Attributes: +* @li alpha: An optional float. Defaults to 0.16666666. \n +* @li beta: An optional float. Defaults to 0.5. \n + +* @par Outputs: +* y: A Tensor with the same dtype and shape of input_x's. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Hardsigmoid. \n +*/ +REG_OP(HardSigmoid) + .INPUT(input_x, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .OUTPUT(output_y, TensorType({DT_FLOAT, DT_FLOAT16})) + .ATTR(alpha, Float, 0.16666666) + .ATTR(beta, Float, 0.5) + .OP_END_FACTORY_REG(HardSigmoid) + +/** +* @brief Calculate the soft shrinkage function. \n + +* @par Inputs: +* One inputs, including: +* @li input_x: A tensor. Must be one of the following types: +* float16, float32. \n + +* @par Attributes: +* @li lambd: An optional float. Defaults to 0.5. \n + +* @par Outputs: +* y: A Tensor with the same dtype and shape of input_x's. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Softshrink. \n +*/ +REG_OP(SoftShrink) + .INPUT(input_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(lambd, Float, 0.5) + .OP_END_FACTORY_REG(SoftShrink) + +/** +* @brief Calculate the reversed outputs of the function "soft_shrink". \n + +* @par Inputs: +* Two inputs, including: +* @li input_grad: A tensor. Must be one of the following types: +* float16, float32. \n +* @li input_x: A tensor of the same dtype as "input_grad". \n + +* @par Attributes: +* @li lambd: An optional float. Defaults to 0.5. \n + +* @par Outputs: +* y: A Tensor of the same dtype and shape as "input_graxd". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator SoftShrinkGrad. \n +*/ +REG_OP(SoftShrinkGrad) + .INPUT(input_grad, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(input_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(lambd, Float, 0.5) + .OP_END_FACTORY_REG(SoftShrinkGrad) + +/** +*@brief Calculate the gradient of log simoid. \n + +*@par Inputs: +*Two inputs, including: +* @li grads: A tensor, gradient of previous layer. Must be one of the following types: +* float16, float32. \n +* @li features: A tensor, input of log sigmoid. Must be one of the following types: +* float16, float32. \n + +*@par Outputs: +*One outputs, including: +* @li backprops: A tensor with the same type of and shape of grads. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator LogSigmoidBackward. \n +*/ +REG_OP(LogSigmoidGrad) + .INPUT(grads, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(features, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(backprops, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(LogSigmoidGrad) + +/** +*@brief Calculate -ln(1+e^(-x)). \n + +*@par Inputs: +*One inputs, including: +* @li x: A tensor. Must be one of the following types: +* float16, float32. \n + +*@par Outputs: +*One outputs, including: +* @li y: A tensor with the same type and shape of x's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator LogSigmoid. \n +*/ +REG_OP(LogSigmoid) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) /* "input:x" */ + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) /* "output:y" */ + .OP_END_FACTORY_REG(LogSigmoid) + +/** +*@brief Calculate the backward outputs of the function "hard_sigmoid" \n + +*@par Inputs: +*One inputs, including: +* @li grads: A tensor. Must be one of the following types: +* float16, float32. \n +* @li input_x: A tensor. Must be one of the following types: +* float16, float32. \n + +*@par Outputs: +*One outputs, including: +* @li y: A tensor with the same type and shape of x's. \n + +* @par Attributes: +* @li alpha: An optional float. Defaults to 0.16666666. \n +* @li beta: An optional float. Defaults to 0.5. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator LogSigmoidGrad. \n +*/ +REG_OP(HardSigmoidGrad) + .INPUT(grads, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(input_x, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .ATTR(alpha, Float, 0.16666666) + .ATTR(beta, Float, 0.5) + .OP_END_FACTORY_REG(HardSigmoidGrad) + +/** +* @brief Calculate the shrink function. \n + +* @par Inputs: +* One inputs, including: +* @li input_x: A tensor. Must be one of the following types: +* float16, float32. \n + +* @par Attributes: +* @li lambd: An optional float. Defaults to 0.5. \n +* @li bias: An optional float. Defaults to 0.0. \n + +* @par Outputs: +* y: A Tensor with the same dtype and shape of input_x's. \n + +* @par Third-party framework compatibility +* Compatible with the ONNX operator Shrink. \n +*/ +REG_OP(Shrink) + .INPUT(input_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(lambd, Float, 0.5) + .ATTR(bias, Float, 0.0) + .OP_END_FACTORY_REG(Shrink) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NONLINEAR_FUC_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h b/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h index 8d7ef9f9..f36d2935 100644 --- a/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h +++ b/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/outfeed_ops.h b/third_party/fwkacllib/inc/ops/outfeed_ops.h index e0b783bc..53b9d701 100644 --- a/third_party/fwkacllib/inc/ops/outfeed_ops.h +++ b/third_party/fwkacllib/inc/ops/outfeed_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/pad_ops.h b/third_party/fwkacllib/inc/ops/pad_ops.h index f746b3b3..6854c866 100644 --- a/third_party/fwkacllib/inc/ops/pad_ops.h +++ b/third_party/fwkacllib/inc/ops/pad_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. @@ -101,7 +101,7 @@ REG_OP(FillD) */ REG_OP(BroadcastTo) .INPUT(x, TensorType::BasicType()) - .INPUT(shape, TensorType({DT_INT32})) + .INPUT(shape, TensorType({DT_INT32,DT_INT64})) .OUTPUT(y, TensorType::BasicType()) .OP_END_FACTORY_REG(BroadcastTo) @@ -161,7 +161,7 @@ REG_OP(Pad) *@brief Pads a tensor . \n *@par Inputs: -*x: A Tensor. Must be one of the following types: float16, float32, int8, uint8, int32 . \n +*x: A Tensor. Must be one of the following types: float16, float32, int32 . \n *@par Attributes: *paddings: An optional "vector>". Defaults to "{}". @@ -180,8 +180,8 @@ REG_OP(Pad) * Warning: THIS FUNCTION IS DEPRECATED. Please use Pad instead. */ REG_OP(PadD) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_UINT8, DT_FLOAT})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_UINT8, DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) .REQUIRED_ATTR(paddings, ListListInt) .OP_END_FACTORY_REG(PadD) @@ -213,7 +213,7 @@ REG_OP(PadV2) *@brief Pads a tensor . \n *@par Inputs: -*x: A Tensor. Must be one of the following types: float16, float32, int8, uint8, int32 . \n +*x: A Tensor. Must be one of the following types: float16, float32, int32 . \n *constant_values: A Tensor. Must have the same type as input. *@par Attributes: @@ -227,10 +227,7 @@ REG_OP(PadV2) *y: A Tensor of the same type as "x" . \n *@par Third-party framework compatibility: -* Compatible with TensorFlow operator Pad. -* -* @par Restrictions: -* Warning: THIS FUNCTION IS DEPRECATED. Please use Pad instead. +* Compatible with TensorFlow operator PadV2. */ REG_OP(PadV2D) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) @@ -272,42 +269,42 @@ REG_OP(PadV3) .ATTR(paddings_contiguous, Bool, true) .OP_END_FACTORY_REG(PadV3) -/** -*@brief Pads a tensor. - -*@par Inputs: -*x: A Tensor. Must be one of the following types: float16, float32, int8, uint8, int32. - -*@par Attributes: -* @li paddings: An required "vector>". -* For each dimension D of input, paddings[D, 0] indicates how many -* values to add before the contents of tensor in that dimension, -* and paddings[D, 1] indicates how many values to add after the -* contents of tensor in that dimension. -* @li constant_values: An optional int value for pad. -* @li mode: An optional string, Defaults to "constant", indicates paddings mode, -* support "constant", "reflect", "edge" -* @li paddings_contiguous: An optional bool value, Defaults to true. -* If true, paddings is arranged as [[begin0, end0], [begin1, end1], ...] -* If false, paddings is arranged as [[begin0, begin1], ..., [end0, end1], ...] - -*@par Outputs: -*y: A Tensor of the same type as "x". - -*@par Third-party framework compatibility: -* Compatible with ONNX operator Pad. - -* @par Restrictions: -* Warning: THIS FUNCTION IS DEPRECATED. Please use PadV3 instead. -*/ -REG_OP(PadV3D) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_UINT8})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_UINT8})) - .REQUIRED_ATTR(paddings, ListListInt) - .ATTR(constant_values, Int, 0) - .ATTR(mode, String, "constant") - .ATTR(paddings_contiguous, Bool, true) - .OP_END_FACTORY_REG(PadV3D) + /** + *@brief Pads a tensor. + + *@par Inputs: + *x: A Tensor. Must be one of the following types: float16, float32, int8, uint8, int32. + + *@par Attributes: + * @li paddings: An required "vector>". + * For each dimension D of input, paddings[D, 0] indicates how many + * values to add before the contents of tensor in that dimension, + * and paddings[D, 1] indicates how many values to add after the + * contents of tensor in that dimension. + * @li constant_values: An optional int value for pad. + * @li mode: An optional string, Defaults to "constant", indicates paddings mode, + * support "constant", "reflect", "edge" + * @li paddings_contiguous: An optional bool value, Defaults to true. + * If true, paddings is arranged as [[begin0, end0], [begin1, end1], ...] + * If false, paddings is arranged as [[begin0, begin1], ..., [end0, end1], ...] + + *@par Outputs: + *y: A Tensor of the same type as "x". + + *@par Third-party framework compatibility: + * Compatible with ONNX operator Pad. + + * @par Restrictions: + * Warning: THIS FUNCTION IS DEPRECATED. Please use PadV3 instead. + */ + REG_OP(PadV3D) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_UINT8})) + .REQUIRED_ATTR(paddings, ListListInt) + .ATTR(constant_values, Int, 0) + .ATTR(mode, String, "constant") + .ATTR(paddings_contiguous, Bool, true) + .OP_END_FACTORY_REG(PadV3D) /** *@brief Create a diagonal tensor @@ -403,5 +400,76 @@ REG_OP(EmbeddingRankId) .ATTR(mode, String, "mod") .OP_END_FACTORY_REG(EmbeddingRankId) +/** +*@brief EmbeddingLocalIndex, Sort statistics index according to rank_id \n + +*@par Inputs: +* @li addr_table: A 2D tensor which last dimension must be 3. +* @li index: A tensor with data type int32, int64, uint32, uint64. + +*@par Attributes: +* @li row_memory: The size of Embedding vector in a row, the default is 320. +* @li mode: String type, currently there are two options: 'mod' and 'order' + +*@par Outputs: +* @li local_idx:Index on each server. +* @li nums:The number of local_idx found on each server. +* @li recover_idx:The sorted local_idx element is at the position corresponding +* to the original input index. + +*@par Third-party framework compatibility +* Compatible with the TensorFlow operator Diag. +*/ +REG_OP(EmbeddingLocalIndex) + .INPUT(addr_table, TensorType({DT_UINT64})) + .INPUT(index, TensorType({DT_INT64,DT_INT32,DT_UINT32,DT_UINT64})) + .OUTPUT(local_idx, TensorType({DT_INT64,DT_INT32,DT_UINT32,DT_UINT64})) + .OUTPUT(nums, TensorType({DT_INT64,DT_INT32,DT_UINT32,DT_UINT64})) + .OUTPUT(recover_idx, TensorType({DT_INT64,DT_INT32,DT_UINT32,DT_UINT64})) + .ATTR(row_memory, Int, 320) + .ATTR(mode, String, "mod") + .OP_END_FACTORY_REG(EmbeddingLocalIndex) + +/** +* @brief Fill the value to a tensor has the specified shape. + +* @par Inputs: +* One inputs, including: +* @li dims: An Tensor, specify the shape that the value to fill. + +* @par Attributes: +* @li value: An optional float value. Defaults to 0.0. + +* @par Outputs: +* @li y: A Tensor. Has the shape specify by attr shape, and full of the value specify by attr value. + +* @par Third-party framework compatibility +* Compatible with the ONNX operator ConstantOfShape. +*/ +REG_OP(FillV2) + .INPUT(dims, TensorType({DT_INT16, DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT8, DT_INT16, DT_INT32, DT_INT64})) + .ATTR(value, Float, 0) + .OP_END_FACTORY_REG(FillV2) + +/** +* @brief Fill the value to a tensor has the specified shape. + +* @par Attributes: +* @li value: An optional float value. Defaults to 0.0. + +* @li dims: An required listInt to specify the shape that the value to fill. + +* @par Outputs: +* @li y: A Tensor. Has the shape specify by attr shape, and full of the value specify by attr value. + +* @par Third-party framework compatibility +* Compatible with the ONNX operator ConstantOfShape. +*/ +REG_OP(FillV2D) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT8, DT_UINT8, DT_INT16, DT_INT32, DT_INT64})) + .ATTR(value, Float, 0) + .REQUIRED_ATTR(dims, ListInt) + .OP_END_FACTORY_REG(FillV2D) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_PAD_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/parsing_ops.h b/third_party/fwkacllib/inc/ops/parsing_ops.h index 5c7adfd8..b625180a 100644 --- a/third_party/fwkacllib/inc/ops/parsing_ops.h +++ b/third_party/fwkacllib/inc/ops/parsing_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -51,6 +51,246 @@ REG_OP(StringToNumber) .ATTR(out_type, Type, DT_FLOAT) .OP_END_FACTORY_REG(StringToNumber) +/** +*@brief Convert serialized tensorflow.TensorProto prototype to Tensor. +*@brief Parse an Example prototype. +*@par Input: +*serialized: A Tensor of type string. +*dense_defaults: DYNAMIC INPUT Tensor type as string, float, int64. \n + +*@par Attributes: +*num_sparse: type int num of inputs sparse_indices , sparse_values, sparse_shapes +*out_type: output type +*sparse_keys: ListString +*sparse_types: types of sparse_values +*dense_keys: ListString +*dense_shapes: output of dense_defaults shape +*dense_types: output of dense_defaults type \n + +*@par Outputs: +*sparse_indices: A Tensor of type string. +*sparse_values: Has the same type as sparse_types. +*sparse_shapes: A Tensor of type int64 +*dense_values: Has the same type as dense_defaults. + +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +**/ +REG_OP(ParseSingleExample) + .INPUT(serialized, TensorType({DT_STRING})) + .DYNAMIC_INPUT(dense_defaults, TensorType({DT_STRING,DT_FLOAT,DT_INT64})) + .DYNAMIC_OUTPUT(sparse_indices, TensorType({DT_INT64})) + .DYNAMIC_OUTPUT(sparse_values, TensorType({DT_STRING,DT_FLOAT,DT_INT64})) + .DYNAMIC_OUTPUT(sparse_shapes, TensorType({DT_INT64})) + .DYNAMIC_OUTPUT(dense_values, TensorType({DT_STRING,DT_FLOAT,DT_INT64})) + .ATTR(num_sparse, Int, 0) + .ATTR(sparse_keys, ListString, {}) + .ATTR(dense_keys, ListString, {}) + .ATTR(sparse_types, ListType, {}) + .ATTR(Tdense, ListType, {}) + .ATTR(dense_shapes, ListListInt, {}) + .OP_END_FACTORY_REG(ParseSingleExample) + +/** +*@brief Decodes raw file into tensor . \n +*@par Input: +*bytes: A Tensor of type string. + +*@par Attributes: +*little_endian: bool ture +*out_type: output type + +*@par Outputs: +*Output: A Tensor +**/ +REG_OP(DecodeRaw) + .INPUT(bytes, TensorType({DT_STRING})) + .OUTPUT(output, TensorType({DT_BOOL,DT_FLOAT16,DT_DOUBLE,DT_FLOAT, + DT_INT64,DT_INT32,DT_INT8,DT_UINT8,DT_INT16, + DT_UINT16,DT_COMPLEX64,DT_COMPLEX128})) + .ATTR(out_type, Type, DT_FLOAT) + .ATTR(little_endian, Bool, true) + .OP_END_FACTORY_REG(DecodeRaw) + +/** +*@brief Convert serialized tensorflow.TensorProto prototype to Tensor. \n + +*@par Inputs: +*serialized: A Tensor of string type. Scalar string containing serialized +*TensorProto prototype. \n + +*@par Attributes: +*out_type: The type of the serialized tensor. The provided type must match the +*type of the serialized tensor and no implicit conversion will take place. \n + +*@par Outputs: +*output: A Tensor of type out_type. \n + +*@attention Constraints: +*The implementation for StringToNumber on Ascend uses AICPU, +*with badperformance. \n + +*@par Third-party framework compatibility +*@li compatible with tensorflow ParseTensor operator. +*/ +REG_OP(ParseTensor) + .INPUT(serialized, TensorType({DT_STRING})) + .OUTPUT(output, TensorType(DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT16, + DT_UINT16, DT_UINT8, DT_INT32, DT_INT64, DT_UINT32, + DT_UINT64, DT_BOOL, DT_DOUBLE, DT_STRING, + DT_COMPLEX64, DT_COMPLEX128})) + .ATTR(out_type, Type, DT_FLOAT) + .OP_END_FACTORY_REG(ParseTensor) + +/** +*@brief Converts each string in the input Tensor to the specified numeric +*type . \n + +*@par Inputs: +*Inputs include: +*records: Each string is a record/row in the csv and all records should have the +*same format. \n +*record_defaults: One tensor per column of the input record, with either a +*scalar default value for that column or an empty vector if the column is +*required. \n + +*@par Attributes: +*OUT_TYPE: The numeric type to interpret each string in string_tensor as . \n +*field_delim: char delimiter to separate fields in a record. \n +*use_quote_delim: If false, treats double quotation marks as regular characters +*inside of the string fields (ignoring RFC 4180, Section 2, Bullet 5). \n +*na_value: Additional string to recognize as NA/NaN. \n + +*@par Outputs: +*output: A Tensor. Has the same type as x . \n + +*@attention Constraints: +*The implementation for StringToNumber on Ascend uses AICPU, with bad +*performance. \n + +*@par Third-party framework compatibility +*@li compatible with tensorflow StringToNumber operator. +*/ +REG_OP(DecodeCSV) + .INPUT(records, TensorType({DT_STRING})) + .DYNAMIC_INPUT(record_defaults, TensorType({DT_FLOAT, DT_DOUBLE, DT_INT32, + DT_INT64, DT_STRING})) + .DYNAMIC_OUTPUT(output, TensorType({DT_FLOAT, DT_DOUBLE, DT_INT32, + DT_INT64, DT_STRING})) + .ATTR(OUT_TYPE, ListType, {}) + .ATTR(field_delim, String, ",") + .ATTR(use_quote_delim, Bool, true) + .ATTR(na_value, String, ",") + .ATTR(select_cols, ListInt, {}) + .OP_END_FACTORY_REG(DecodeCSV) + +/** +*@brief Convert serialized tensorflow.TensorProto prototype to Tensor. +*@brief Parse an Example prototype. +*@par Input: +*serialized: A Tensor of type string. \n +*name:A Tensor of type string. \n +*sparse_keys: Dynamic input tensor of string. \n +*dense_keys: Dynamic input tensor of string \n +*dense_defaults: Dynamic input tensor type as string, float, int64. \n + +*@par Attributes: +*Nsparse: Number of sparse_keys, sparse_indices and sparse_shapes \n +*Ndense: Number of dense_keys \n +*sparse_types: types of sparse_values \n +*Tdense: Type of dense_defaults dense_defaults and dense_values \n +*dense_shapes: output of dense_defaults shape \n + +*@par Outputs: +*sparse_indices: A Tensor of type string. \n +*sparse_values: Has the same type as sparse_types. \n +*sparse_shapes: A Tensor of type int64 \n +*dense_values: Has the same type as dense_defaults. \n +*@par Third-party framework compatibility \n +*@li compatible with tensorflow StringToNumber operator. \n +*/ +REG_OP(ParseExample) + .INPUT(serialized, TensorType({DT_STRING})) + .INPUT(name, TensorType({DT_STRING})) + .DYNAMIC_INPUT(sparse_keys, TensorType({DT_STRING})) + .DYNAMIC_INPUT(dense_keys, TensorType({DT_STRING})) + .DYNAMIC_INPUT(dense_defaults, TensorType({DT_FLOAT, DT_INT64, DT_STRING})) + .DYNAMIC_OUTPUT(sparse_indices, TensorType({DT_INT64})) + .DYNAMIC_OUTPUT(sparse_values, TensorType({DT_FLOAT, DT_INT64, DT_STRING})) + .DYNAMIC_OUTPUT(sparse_shapes, TensorType({DT_INT64})) + .DYNAMIC_OUTPUT(dense_values, TensorType({DT_FLOAT, DT_INT64, DT_STRING})) + .ATTR(Nsparse, Int, 0) + .ATTR(Ndense, Int, 0) + .ATTR(sparse_types, ListType, {}) + .ATTR(Tdense, ListType, {}) + .ATTR(dense_shapes, ListListInt, {}) + .OP_END_FACTORY_REG(ParseExample) + +/** +*@brief Transforms a scalar brain.SequenceExample proto (as strings) into typed +*tensors. +*@par Input: +*serialized: A Tensor of type string. \n +*feature_list_dense_missing_assumed_empty:A Tensor of type string. \n +*context_sparse_keys: Dynamic input tensor of string. \n +*context_dense_keys: Dynamic input tensor of string \n +*feature_list_sparse_keys: Dynamic input tensor of string \n +*feature_list_dense_keys: Dynamic input tensor of string \n +*context_dense_defaults: Dynamic input tensor of string, float, int64 \n +*debug_name: A Tensor of type string. \n + +*@par Attributes: +*Ncontext_sparse: Number of context_sparse_keys, context_sparse_indices and context_sparse_shapes \n +*Ncontext_dense: Number of context_dense_keys \n +*Nfeature_list_sparse: Number of feature_list_sparse_keys \n +*Nfeature_list_dense: Number of feature_list_dense_keys \n +*context_sparse_types: Types of context_sparse_values \n +*Tcontext_dense: Number of dense_keys \n +*feature_list_dense_types: Types of feature_list_dense_values \n +*context_dense_shapes: Shape of context_dense \n +*feature_list_sparse_types: Type of feature_list_sparse_values \n +*feature_list_dense_shapes: Shape of feature_list_dense \n + +*@par Outputs: +*context_sparse_indices: Dynamic output tensor of type int64. \n +*context_sparse_values: Dynamic output tensor of type string, float, int64. \n +*context_sparse_shapes: Dynamic output tensor of type int64 \n +*context_dense_values: Dynamic output tensor of type string, float, int64. \n +*feature_list_sparse_indices: Dynamic output tensor of type int64. \n +*feature_list_sparse_values: Dynamic output tensor of type string, float, int64. \n +*feature_list_sparse_shapes: Dynamic output tensor of type int64 \n +*feature_list_dense_values: Dynamic output tensor of type string, float, int64. \n +*@par Third-party framework compatibility \n +*@li compatible with tensorflow StringToNumber operator. \n +*/ +REG_OP(ParseSingleSequenceExample) + .INPUT(serialized, TensorType({DT_STRING})) + .INPUT(feature_list_dense_missing_assumed_empty, TensorType({DT_STRING})) + .DYNAMIC_INPUT(context_sparse_keys, TensorType({DT_STRING})) + .DYNAMIC_INPUT(context_dense_keys, TensorType({DT_STRING})) + .DYNAMIC_INPUT(feature_list_sparse_keys, TensorType({DT_STRING})) + .DYNAMIC_INPUT(feature_list_dense_keys, TensorType({DT_STRING})) + .DYNAMIC_INPUT(context_dense_defaults, TensorType({DT_FLOAT, DT_INT64, DT_STRING})) + .INPUT(debug_name, TensorType({DT_STRING})) + .DYNAMIC_OUTPUT(context_sparse_indices, TensorType({DT_INT64})) + .DYNAMIC_OUTPUT(context_sparse_values, TensorType({DT_FLOAT, DT_INT64, DT_STRING})) + .DYNAMIC_OUTPUT(context_sparse_shapes, TensorType({DT_INT64})) + .DYNAMIC_OUTPUT(context_dense_values, TensorType({DT_FLOAT, DT_INT64, DT_STRING})) + .DYNAMIC_OUTPUT(feature_list_sparse_indices, TensorType({DT_INT64})) + .DYNAMIC_OUTPUT(feature_list_sparse_values, TensorType({DT_FLOAT, DT_INT64, DT_STRING})) + .DYNAMIC_OUTPUT(feature_list_sparse_shapes, TensorType({DT_INT64})) + .DYNAMIC_OUTPUT(feature_list_dense_values, TensorType({DT_FLOAT, DT_INT64, DT_STRING})) + .ATTR(Ncontext_sparse, Int, 0) + .ATTR(Ncontext_dense, Int, 0) + .ATTR(Nfeature_list_sparse, Int, 0) + .ATTR(Nfeature_list_dense, Int, 0) + .ATTR(context_sparse_types, ListType, {}) + .ATTR(Tcontext_dense, ListType, {}) + .ATTR(feature_list_dense_types, ListType, {}) + .ATTR(context_dense_shapes, ListListInt, {}) + .ATTR(feature_list_sparse_types, ListType, {}) + .ATTR(feature_list_dense_shapes, ListListInt, {}) + .OP_END_FACTORY_REG(ParseSingleSequenceExample) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_PARSING_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/quantize_ops.h b/third_party/fwkacllib/inc/ops/quantize_ops.h index b53cfeb6..69d5e67e 100644 --- a/third_party/fwkacllib/inc/ops/quantize_ops.h +++ b/third_party/fwkacllib/inc/ops/quantize_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -60,6 +60,26 @@ REG_OP(Dequantize) .ATTR(mode, String, "MIN_COMBINED") .OP_END_FACTORY_REG(Dequantize) +/** +*@brief Quantizes the input . \n +*@par Inputs: +*x: shape and dtype of input_x. \n +*scales: shape and dtype of input_scales. \n +*zero_points: shape and dtype of input_zero_points \n +*@par Attributes: +*@li axis: the processed dim. \n +*@par Outputs: +*y: shape and dtype of output_y, should be same shape as input, dtype is same as the quantified type . \n +*/ +REG_OP(Quantize) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(scales, TensorType({DT_FLOAT})) + .INPUT(zero_points, TensorType({DT_INT8,DT_UINT8,DT_INT32})) + .OUTPUT(y, TensorType({DT_INT8,DT_UINT8,DT_INT32})) + .REQUIRED_ATTR(dtype, String) + .ATTR(axis, Int, 1) + .OP_END_FACTORY_REG(Quantize) + /** *@brief Quantizes the input . \n @@ -194,7 +214,7 @@ REG_OP(AscendRequant) *@brief Requantizes the input of int16 . \n *@par Inputs: -*@li x: An NC1HWC0 tensor of type int16, specifying the input. +*@li x0: An NC1HWC0 tensor of type int16, specifying the input. *@li req_scale: An NC1HWC0 tensor of type uint64, specifying the scaling ratio. *@li x1: An NC1HWC0 tensor of type int16 . \n @@ -203,22 +223,21 @@ REG_OP(AscendRequant) *@li relu_flag: A optional bool, specifying whether to perform ReLU, either "True" or "False". Defaults to "False" . \n *@par Outputs: -*@li y: The dequantized output tensor of type int8 and with format NC1HWC0. +*@li y0: The dequantized output tensor of type int8 and with format NC1HWC0. *@li y1: The dequantized output tensor of type int16 and with format NC1HWC0 . \n *@par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. */ REG_OP(AscendRequantS16) - .INPUT(x, TensorType({DT_INT16})) + .INPUT(x0, TensorType({DT_INT16})) .INPUT(req_scale, TensorType({DT_UINT64})) .OPTIONAL_INPUT(x1, TensorType({DT_INT16})) - .OUTPUT(y, TensorType({DT_INT8})) + .OUTPUT(y0, TensorType({DT_INT8})) .OUTPUT(y1, TensorType({DT_INT16})) .ATTR(dual_output, Bool, false) .ATTR(relu_flag, Bool, false) .OP_END_FACTORY_REG(AscendRequantS16) - } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_QUANTIZE_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/ragged_array_ops.h b/third_party/fwkacllib/inc/ops/ragged_array_ops.h index 9b31aa8e..20484623 100644 --- a/third_party/fwkacllib/inc/ops/ragged_array_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_array_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h b/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h index 13488a25..020e3da4 100644 --- a/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/ragged_math_ops.h b/third_party/fwkacllib/inc/ops/ragged_math_ops.h index 8af4f867..258b0ca1 100644 --- a/third_party/fwkacllib/inc/ops/ragged_math_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_math_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/random_ops.h b/third_party/fwkacllib/inc/ops/random_ops.h index b46da435..b65a68f1 100644 --- a/third_party/fwkacllib/inc/ops/random_ops.h +++ b/third_party/fwkacllib/inc/ops/random_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -356,6 +356,39 @@ REG_OP(DropOutGenMask) .ATTR(seed2, Int, 0) .OP_END_FACTORY_REG(DropOutGenMask) + +/** +*@brief Generate random uint8 mask for dropout v3 . \n + +*@par Inputs: +include: +*@li shape:The shape of the output tensor. +*@li prob:0-D. Prob of 1 . \n + +*@par Attributes: +*@li seed:If either seed or seed2 are set to be non-zero, the random number +*generator is seeded by the given seed. Otherwise, it is seeded by a random seed. +*@li seed2:A second seed to avoid seed collision . \n + +*@par Outputs: +*y:Output (1-D) random number using uint8 data format . \n + +*@attention Constraints: +*The output is aligned with 16 + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. + +*@see DropOutGenMaskV3() +*/ +REG_OP(DropOutGenMaskV3) + .INPUT(shape, TensorType({ DT_INT32, DT_INT64 })) + .INPUT(prob, TensorType({ DT_FLOAT16, DT_FLOAT })) + .OUTPUT(y, TensorType({ DT_UINT8 })) + .ATTR(seed, Int, 0) + .ATTR(seed2, Int, 0) + .OP_END_FACTORY_REG(DropOutGenMaskV3) + /** *@brief Generates values in an interval . \n @@ -495,6 +528,62 @@ REG_OP(ShuffleChannel) DT_UINT16, DT_INT32, DT_UINT32,DT_INT64,DT_UINT64})) .ATTR(group, Int, 1) .OP_END_FACTORY_REG(ShuffleChannel) + +/** + * @briefGenerate a tensor of samples from a multinomial + * distribution according to the probabilities of each of + * the possible outcomes. + * + * @par inputs + * one input including: + * @li x:Input tensor with shape [batch_size, class_size], + * where class_size is the number of all possible outcomes. + * Each value along the axis zero represents the unnormalized + * log-probability of each corresponding outcome in a batch. + * + * @par output + * one output including: + * @li y:Output tensor with shape [batch_size, sample_size], + * where sample_size is the number of times to sample. + * Each value along the axis zero represents the outcome of + * the corresponding sample in a batch. + * + * @par Restrictions: + * Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. + */ +REG_OP(MultinomialFuss) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_FLOAT64})) + .OUTPUT(y, TensorType({DT_INT32, DT_INT64})) + .ATTR(dtype, Int, 6) + .ATTR(sample_size, Int, 1) + .ATTR(seed, Float, 0) + .OP_END_FACTORY_REG(MultinomialFuss) + +/** +* @brief During training, randomly zeroes some of the elements of the input tensor +* with probability +* +* @par Inputs: +* @li x: A ND Tensor. Must be one of the following data types: Float, Float16 +* @li seed: A ND Tensor. Must be one of the following data types: Float +* +* @par Attributes: +* @li p: probability of an element to be zeroed +* +* @par Outputs: +* @li y: A tensor with the same shape and type as "x". +* @li mask: A tensor with the same shape and type as "x". +* @li new_seed: A tensor with the same shape and type as "seed". +*/ + +REG_OP(DropoutV2) + .INPUT(x, TensorType({ DT_FLOAT16, DT_FLOAT })) + .INPUT(seed, TensorType({ DT_FLOAT })) + .OUTPUT(y, TensorType({ DT_FLOAT16, DT_FLOAT })) + .OUTPUT(mask, TensorType({ DT_FLOAT })) + .OUTPUT(seed, TensorType({ DT_FLOAT })) + .REQUIRED_ATTR(p, Float) + .OP_END_FACTORY_REG(DropoutV2) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_RANDOM_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/reduce_ops.h b/third_party/fwkacllib/inc/ops/reduce_ops.h index 6f44093e..97c7b8e1 100644 --- a/third_party/fwkacllib/inc/ops/reduce_ops.h +++ b/third_party/fwkacllib/inc/ops/reduce_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. @@ -37,7 +37,7 @@ namespace ge { *@attention Constraints: * This operator is a BatchNorm fusion operator for updating the moving * averages for training. -* This operator is used in conjunction with BNTrainingUpdate. +* This operator is used in conjunction with BNTrainingReduce. */ REG_OP(BNTrainingReduce) .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -45,6 +45,27 @@ REG_OP(BNTrainingReduce) .OUTPUT(square_sum, TensorType({DT_FLOAT})) .OP_END_FACTORY_REG(BNTrainingReduce) +/** +*@brief Performs reduced batch normalization . \n + +*@par Inputs: +*x: A 6D Tensor of type float16 or float32, with format NDC1HWC0 . \n + +*@par Outputs: +*@li sum: A 3D Tensor of type float32 for SUM reduced "x". +*@li square_sum: A 3D Tensor of type float32 for SUMSQ reduced "x" . \n + +*@attention Constraints: +* This operator is a BatchNorm fusion operator for updating the moving +* averages for training. +* This operator is used in conjunction with BN3DTrainingReduce. +*/ +REG_OP(BN3DTrainingReduce) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(sum, TensorType({DT_FLOAT})) + .OUTPUT(square_sum, TensorType({DT_FLOAT})) + .OP_END_FACTORY_REG(BN3DTrainingReduce) + /** *@brief Performs the backpropagation of BatchNorm . \n @@ -88,6 +109,49 @@ REG_OP(BNTrainingReduceGrad) .ATTR(epsilon, Float, 0.0001) .OP_END_FACTORY_REG(BNTrainingReduceGrad) +/** +*@brief Performs the backpropagation of BatchNorm . \n + +*@par Inputs: +* Seven inputs, including: +*@li grads: A 6D Tensor of type float16 or float32, with format NDC1HWC0, for +* the gradient. +*@li x: A 6D Tensor of type float16 or float32, with format NDC1HWC0. +*@li diff_scale: A 6D Tensor of type float32, with format NDC1HWC0, +* for the mean of "x". +*@li diff_offset: A 6D Tensor of type float32, with format NDC1HWC0, +* for the variance of "x". +*@li scale: A 6D Tensor of type float32, with format NDC1HWC0. +*@li batch_mean: A 6D Tensor of type float32, with format NDC1HWC0, +* for the mean of "x". +*@li batch_variance: A 6D Tensor of type float32, with format NDC1HWC0, +* for the variance of "x" . \n + +*@par Attributes: +*epsilon: An optional float32. Defaults to "0.0001". A small float number +* added to the variance of "x" . \n + +*@par Outputs: +*y: A Tensor of type float16 or float32, with format NDC1HWC0, for the offset +* of "x" . \n + +*@attention Constraints: +* The preceding layer of this operator must be BN3DTrainingReduceGrad . \n + +*@see BN3DTrainingReduceGrad +*/ +REG_OP(BN3DTrainingReduceGrad) + .INPUT(grads, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(diff_scale, TensorType({DT_FLOAT})) + .INPUT(diff_offset, TensorType({DT_FLOAT})) + .INPUT(scale, TensorType({DT_FLOAT})) + .INPUT(batch_mean, TensorType({DT_FLOAT})) + .INPUT(batch_variance, TensorType({DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT})) + .ATTR(epsilon, Float, 0.0001) + .OP_END_FACTORY_REG(BN3DTrainingReduceGrad) + /** *@brief Performs reduced batch normalization . \n @@ -120,7 +184,7 @@ REG_OP(BNTrainingReduceGrad) *@attention Constraints: *@li This operator is a BatchNorm fusion operator for updating the moving averages for training. -*This operator is used in conjunction with BNTrainingReduce. +*This operator is used in conjunction with BNTrainingUpdate. *@li For Ascend 310, the result accuracy fails to reach 1‰ due to the square * root instruction. */ @@ -141,6 +205,59 @@ REG_OP(BNTrainingUpdate) .OUTPUT(batch_variance, TensorType({DT_FLOAT})) .OP_END_FACTORY_REG(BNTrainingUpdate) +/** +*@brief Performs reduced batch normalization . \n + +*@par Inputs: +* Seven inputs, including: (NDC1HWC0 supported) +*@li x: A 6D Tensor of type float16 or float32. +*@li sum: A 6D Tensor of type float32 for the output of operator +* BN3DTrainingUpdate. +*@li square_sum: A 6D Tensor of type float32 for the output of operator +* BN3DTrainingUpdate. +*@li scale: A 6D Tensor of type float32, for the scaling factor. +*@li offset: A 6D Tensor of type float32, for the scaling offset. +*@li mean: A 6D Tensor of type float32, for the updated mean. +*@li variance: A 6D Tensor of type float32, for the updated variance . \n + +*@par Attributes: +*@li epsilon: A required float32, specifying the small value added to variance +* to avoid dividing by zero. +*@li factor: A required float32, specifying the weight for updating the mean +* and variance . \n + +*@par Outputs: +* Five outputs, including: (NDC1HWC0 supported) +*@li y: A 6D Tensor of type float16 or float32, for normalized "x". +*@li mean: A 6D Tensor of type float32, for the updated mean. +*@li variance: A 6D Tensor of type float32, for the updated variance. +*@li batch_mean: A 6D Tensor of type float32, for the mean of "x". +*@li batch_variance: A 6D Tensor of type float32, for the variance of "x" . \n + +*@attention Constraints: +*@li This operator is a BatchNorm fusion operator for updating the moving +averages for training. +*This operator is used in conjunction with BN3DTrainingUpdate. +*@li For Ascend 310, the result accuracy fails to reach 1‰ due to the square +* root instruction. +*/ +REG_OP(BN3DTrainingUpdate) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(sum, TensorType({DT_FLOAT})) + .INPUT(square_sum, TensorType({DT_FLOAT})) + .INPUT(scale, TensorType({DT_FLOAT})) + .INPUT(offset, TensorType({DT_FLOAT})) + .INPUT(mean, TensorType({DT_FLOAT})) + .INPUT(variance, TensorType({DT_FLOAT})) + .REQUIRED_ATTR(factor, Float) + .REQUIRED_ATTR(epsilon, Float) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(mean, TensorType({DT_FLOAT})) + .OUTPUT(variance, TensorType({DT_FLOAT})) + .OUTPUT(batch_mean, TensorType({DT_FLOAT})) + .OUTPUT(batch_variance, TensorType({DT_FLOAT})) + .OP_END_FACTORY_REG(BN3DTrainingUpdate) + /** *@brief Performs batch normalization for inference . \n @@ -284,6 +401,40 @@ REG_OP(BNTrainingUpdateGrad) .OUTPUT(diff_offset, TensorType({DT_FLOAT})) .OP_END_FACTORY_REG(BNTrainingUpdateGrad) +/** +*@brief Performs the backpropagation of BatchNorm . \n + +*@par Inputs: +* Four inputs, including: +*@li grads: A 6D Tensor of type float16 or float32, with format NDC1HWC0, +* for the gradient. +*@li x: A 6D Tensor of type float16 or float32, with format NDC1HWC0. +*@li batch_mean: A 6D Tensor of type float32, with format NDC1HWC0, +* for the mean of "x". +*@li batch_variance: A 6D Tensor of type float32, with format NDC1HWC0, +* for the variance of "x" . \n + +*@par Attributes: +*epsilon: An optional float32. Defaults to "0.0001". A small float number +* added to the variance of "x" . \n + +*@par Outputs: +*@li diff_scale: A Tensor of type float32, with format NDC1HWC0, +* for the offset of "scale". +*@li diff_offset: A Tensor of type float32, with format NDC1HWC0, +* for the offset of "offset" . \n + +*/ +REG_OP(BN3DTrainingUpdateGrad) + .INPUT(grads, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(batch_mean, TensorType({DT_FLOAT})) + .INPUT(batch_variance, TensorType({DT_FLOAT})) + .ATTR(epsilon, Float, 0.0001) + .OUTPUT(diff_scale, TensorType({DT_FLOAT})) + .OUTPUT(diff_offset, TensorType({DT_FLOAT})) + .OP_END_FACTORY_REG(BN3DTrainingUpdateGrad) + /** *@brief Performs the backpropagation of BatchNorm for inference . \n @@ -635,8 +786,8 @@ REG_OP(ReduceMin) * Warning: THIS FUNCTION IS DEPRECATED. Please use ReduceMin instead. */ REG_OP(ReduceMinD) - .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT8,DT_UINT8})) - .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT8,DT_UINT8})) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT8,DT_UINT8,DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT8,DT_UINT8,DT_INT32})) .REQUIRED_ATTR(axes, ListInt) .ATTR(keep_dims, Bool, false) .OP_END_FACTORY_REG(ReduceMinD) @@ -747,14 +898,14 @@ REG_OP(Reduction) *@brief Computes the euclidean norm of elements across dimensions of a tensor . \n *@par Inputs: -*@li input_tensor: A Tensor. Must be one of the following types: float16, float32, int32. +*@li x: A Tensor. Must be one of the following types: float16, float32, int32. *@li axes: A Tensor of type int8 or int32. Specifies the dimensions to reduce. Defaults to "None" . \n *@par Attributes: *keep_dims: An optional bool. If "True", reduced dimensions will be retained. Defaults to "False" . \n *@par Outputs: -*output_tensor: A Tensor. Must be one of the following types: float16, float32, int32 . \n +*y: A Tensor. Must be one of the following types: float16, float32, int32 . \n *@attention Constraints: * If "axes = None", all dimensions will be reduced. "axes" must be in the range [-rank(input_shape), rank(input_shape)) . \n @@ -821,7 +972,7 @@ Defaults to "0.00001" . \n *batch_ variance: A Tensor of type float32 for the result variance . \n *@attention Constraints: -*For Ascend 310, the result accuracy fails to reach 1 due to the square root instruction. +*For Ascend 310, the result accuracy fails to reach 0.001 due to the square root instruction. */ REG_OP(INInferV2) .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -839,7 +990,7 @@ REG_OP(INInferV2) *@brief Performs reduced instance normalization . \n *@par Inputs: -*x: A Tensor of type float16 or float32, with format NC1HWC0 . \n +*x: A Tensor of type float16 or float32. \n *@par Outputs: *@li sum: A Tensor of type float32 for SUM reduced "x". @@ -862,19 +1013,19 @@ REG_OP(INTrainingReduceV2) *@par Inputs: * Seven inputs, including: (NC1HWC0supported) *@li x: A Tensor of type float16 or float32. -*@li sum: A T [N, C1, 1, 1, C0] ensor of type float32 for the output of operator INTrainingReduceV2. -*@li square_sum: A [N, C1, 1, 1, C0] Tensor of type float32 for the output of operator INTrainingReduceV2. -*@li gamma: A [N, C1, 1, 1, C0] Tensor of type float32, for the scaling gamma. -*@li beta: A [N, C1, 1, 1, C0] Tensor of type float32, for the scaling beta. -*@li mean: A [N, C1, 1, 1, C0] Tensor of type float32, for the updated mean. -*@li variance: A [N, C1, 1, 1, C0] Tensor of type float32, for the updated variance . \n +*@li sum: A Tensor of type float32 for the output of operator INTrainingReduceV2. +*@li square_sum: A Tensor of type float32 for the output of operator INTrainingReduceV2. +*@li gamma: A Tensor of type float32, for the scaling gamma. +*@li beta: A Tensor of type float32, for the scaling beta. +*@li mean: A Tensor of type float32, for the updated mean. +*@li variance: A Tensor of type float32, for the updated variance . \n *@par Attributes: *@li momentum: A required float32, specifying the momentum to update mean and var. *@li epsilon: A required float32, specifying the small value added to variance to avoid dividing by zero . \n *@par Outputs: -* Three outputs, including: (NC1HWC0 supported) +* Three outputs *@li y: A Tensor of type float16 or float32, for normalized "x". *@li batch_mean: A Tensor of type float32, for the updated mean. *@li batch_variance: A Tensor of type float32, for the updated variance . \n @@ -882,7 +1033,7 @@ REG_OP(INTrainingReduceV2) *@attention Constraints: *@li This operator is a InstanceNorm fusion operator for updating the moving averages for training. * This operator is used in conjunction with INTrainingReduceV2. -*@li For Ascend 310, the result accuracy fails to reach 1 due to the square root instruction. +*@li For Ascend 310, the result accuracy fails to reach 1‰ due to the square root instruction. */ REG_OP(INTrainingUpdateV2) .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -965,7 +1116,7 @@ for the updated variance. *@attention Constraints: *@li This operator is a InstanceNorm fusion operator for updating the moving averages for training. * This operator is used in conjunction with GNTrainingUpdate. -*@li For Ascend 310, the result accuracy fails to reach 1 due to the square root instruction. +*@li For Ascend 310, the result accuracy fails to reach 1‰ due to the square root instruction. */ REG_OP(GNTrainingUpdate) .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -982,6 +1133,98 @@ REG_OP(GNTrainingUpdate) .OUTPUT(batch_variance, TensorType({DT_FLOAT})) .OP_END_FACTORY_REG(GNTrainingUpdate) +/** +*@brief Joins a string Tensor across the given dimensions. \n + +*@par Inputs: +include: +*@li input:A Tensor of type string. The text to be processed. +*@li reduction_indices:A Tensor of type int. The text to be processed. + +*@par Attributes: +*@li keep_dims:A bool, An optional bool. Defaults to False. If True, retain reduced dimensions with length 1.. +*@li separator:string. + +*@par output: +*@li output::A Tensor of type string.. +*/ +REG_OP(ReduceJoin) + .INPUT(input, TensorType({DT_STRING})) + .INPUT(reduction_indices, TensorType({DT_INT32})) + .OUTPUT(output, TensorType({DT_STRING})) + .ATTR(keep_dims, Bool, true) + .ATTR(separator, String, "") + .OP_END_FACTORY_REG(ReduceJoin) + +/** +* @brief Calculates the standard deviation and average value of Tensors. + +* @par Inputs: +* @li x: A Tensor. Must be one of the following types: +* float16, float32. \n + +* @par Attributes: +* Three Attributes, including: +* @li dim: An optional listint, Defaults to "None". \n + +* @li unbiased: An optional bool. Defaults to "True". +* If "True", Use Bessel Correction. +* If "False", Do not use Bessel Correction. \n + +* @li keepdim: An optional bool. Defaults to "False". +* If "True", Keep the original tensor dimension. +* If "False", Do not keep the original tensor dimension. \n + +* @par Outputs: +* Two Outputs, including: +* @li y1: A Tensor. Has the same type as "x". +* @li y2: A Tensor. Has the same type as "x". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator ReduceStd. +*/ +REG_OP(ReduceStd) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y1, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y2, TensorType({DT_FLOAT, DT_FLOAT16})) + .ATTR(dim, ListInt, {}) + .ATTR(unbiased, Bool, true) + .ATTR(keepdim, Bool, false) + .OP_END_FACTORY_REG(ReduceStd) + +/** +* @brief Calculates the standard deviation of Tensors. + +* @par Inputs: +* include: +* @li x: A Tensor. Must be one of the following types: float16, float32. \n +* @li mean: A Tensor. It's the mean of X. Must be one of the following types: float16, float32. \n + + +* @par Attributes: +* Three Attributes, including: +* @li dim: An optional listint, Defaults to "None". \n +* @li unbiased: An optional bool. Defaults to "True". +* If "True", Use Bessel Correction. +* If "False", Do not use Bessel Correction. \n +* @li keepdim: An optional bool. Defaults to "False". +* If "True", Keep the original tensor dimension. +* If "False", Do not keep the original tensor dimension. \n + +* @par Outputs: +* @li y: A Tensor. It's the std of X. Has the same type as "x". + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator ReduceStdWithMean. +*/ +REG_OP(ReduceStdWithMean) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(mean, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .ATTR(dim, ListInt, {}) + .ATTR(unbiased, Bool, true) + .ATTR(keepdim, Bool, false) + .OP_END_FACTORY_REG(ReduceStdWithMean) } //namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_REDUCE_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/resource_variable_ops.h b/third_party/fwkacllib/inc/ops/resource_variable_ops.h index 1b60d42a..74ac83f8 100644 --- a/third_party/fwkacllib/inc/ops/resource_variable_ops.h +++ b/third_party/fwkacllib/inc/ops/resource_variable_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/rnn.h b/third_party/fwkacllib/inc/ops/rnn.h index 84723872..80546860 100644 --- a/third_party/fwkacllib/inc/ops/rnn.h +++ b/third_party/fwkacllib/inc/ops/rnn.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -33,6 +33,7 @@ namespace ge { *@li c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li w:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_Z. *@li b:A 1D Tensor. Must be one of the following types: float16. The format must be ND . \n +*@li mask:A 1D Tensor. Must be one of the following types: uint8. *@par Attributes: *@li keep_prob:An integer identifying the keep prob in the op. Default to 1. @@ -42,7 +43,6 @@ namespace ge { *@par Outputs: *seven outputs: -*@li mask:A 1D Tensor. Must be one of the following types: uint8. *@li ct:A 4D Tensor. Must be one of the following types: float16, float32. *@li ht:A 4D Tensor. Must be one of the following types: float16. *@li it:A 4D Tensor. Must be one of the following types: float16, float32. @@ -187,16 +187,16 @@ REG_OP(DynamicRNNGrad) *@brief: DynamicRNN calculation. *@par Inputs: *ten inputs: -*@li x:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li w:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. -*@li b:A 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. -*@li seq_length:A 1D Tensor. Must be one of the following types: int32. The format must be ND. -*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li init_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li wci:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. -*@li wcf:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. -*@li wco:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. -*@li mask:A 1D Tensor. Must be one of the following types: uint8. The format must be ND . \n +*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li w:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. +*@li seq_length:A optional Tensor. Only Support float16 in FRACTAL_NZ and int32 in ND. +*@li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li wcf:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li wco:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li mask:A 1D optional Tensor. Must be one of the following types: uint8. The format must be ND . \n *@par Attributes: *@li cell_type:An string identifying the cell type in the op. Default to "LSTM". Only LSTM is currently supported. @@ -209,6 +209,7 @@ REG_OP(DynamicRNNGrad) *@li time_major:An bool identifying the time major in the op. Default to true. *@li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported. *@li forget_bias:An float identifying the forget bias in the op. Default to 0. +*@li gate_order:An string identifying the type of gate order in the op. Support "ijfo" and "ifjo". Default to "ijfo". *@li is_training:An bool identifying is training in the op. Default to true . \n *@par Outputs: @@ -221,12 +222,14 @@ REG_OP(DynamicRNNGrad) *@li f:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li o:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@par Third-party framework compatibility: +* Compatible with the TF operator LSTM. */ REG_OP(DynamicRNN) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(w, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(b, TensorType({DT_FLOAT16, DT_FLOAT})) - .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32})) + .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32, DT_FLOAT16})) .OPTIONAL_INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) .OPTIONAL_INPUT(init_c, TensorType({DT_FLOAT16, DT_FLOAT})) .OPTIONAL_INPUT(wci, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -251,9 +254,237 @@ REG_OP(DynamicRNN) .ATTR(time_major, Bool, true) .ATTR(activation, String, "tanh") .ATTR(forget_bias, Float, 0.0) + .ATTR(gate_order, String, "ijfo") .ATTR(is_training, Bool, true) .OP_END_FACTORY_REG(DynamicRNN) +/** +*@brief: DynamicRNNV2 calculation. +*@par Inputs: +*ten inputs: +*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li weight_input:A required 4D Tensor. Must be one of the following types: float16, float32. +*The format must be FRACTAL_Z. +*@li weight_hidden:A required 4D Tensor. Must be one of the following types: float16, float32. +*The format must be FRACTAL_Z. +*@li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. +*@li seq_length:A optional 1D Tensor. Must be one of the following types: int32. The format must be ND. +*@li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li wcf:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li wco:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li mask:A 1D optional Tensor. Must be one of the following types: uint8. The format must be ND . \n + +*@par Attributes: +*@li cell_type:An string identifying the cell type in the op. Default to "LSTM". Only LSTM is currently supported. +*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". +*Only UNIDIRECTIONAL is currently supported. +*@li cell_depth:An integer identifying the cell depth in the op. Default to 1. +*@li use_peephole:An bool identifying if use peephole in the op. Default to false. +*@li keep_prob:An float identifying the keep prob in the op. Default to 1. +*@li cell_clip:An float identifying the cell clip in the op. Default to -1. +*@li num_proj:An integer identifying the num projection in the op. Default to 0. +*@li time_major:An bool identifying the time major in the op. Default to true. +*@li activation:An string identifying the type of activation function in the op. Default to "tanh". +*Only tanh is currently supported. +*@li recurrent_activation:An string identifying the type of activation function in the op. Default to "sigmoid". +*Supprot "sigmoid" and "hard_sigmoid". In general, set "hard_sigmoid" for TF Keras LSTM. +*@li forget_bias:An float identifying the forget bias in the op. Default to 0. +*@li gate_order:An string identifying the type of gate order in the op. Support "ijfo" and "ifco". Default to "ijfo". +*Set "ijfo" for TF operator LSTM, Set "ifco" for TF Keras LSTM. +*@li stateful: An bool identifying the type of stateful in the op. Default to fasle.Only false is currently supported. +*@li merge_mode: An string identifying the type of merge_modein the op. Default to "concat". +*Only "concat" is currently supported +*@li is_training:An bool identifying is training in the op. Default to true . \n + +*@par Outputs: +*eight outputs: +*@li y:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li output_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*Return the last output_h. +*@li output_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*Return the last output_c. +*@li i:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li j:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li f:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li o:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@par Third-party framework compatibility: +* Compatible with the TF operator LSTM or TF keras operator LSTM. +*/ + +REG_OP(DynamicRNNV2) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(weight_input, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(weight_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(b, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32})) + .OPTIONAL_INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(init_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wci, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wcf, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wco, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(mask, TensorType({DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(i, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(j, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(f, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(o, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(tanhc, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(cell_type, String, "LSTM") + .ATTR(direction, String, "UNIDIRECTIONAL") + .ATTR(cell_depth, Int, 1) + .ATTR(use_peephole, Bool, false) + .ATTR(keep_prob, Float, 1.0) + .ATTR(cell_clip, Float, -1.0) + .ATTR(num_proj, Int, 0) + .ATTR(time_major, Bool, true) + .ATTR(activation, String, "tanh") + .ATTR(recurrent_activation, String, "sigmoid") + .ATTR(forget_bias, Float, 0.0) + .ATTR(gate_order, String, "ijfo") + .ATTR(stateful, Bool, false) + .ATTR(merge_mode, String, "concat") + .ATTR(is_training, Bool, true) + .OP_END_FACTORY_REG(DynamicRNNV2) + +/** +*@brief: DynamicRNNV3 calculation. +*@par Inputs: +*ten inputs: +*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li w:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. +*@li seq_length:A optional 1D Tensor. Must be one of the following types: int32. The format must be ND. +*@li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li wcf:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li wco:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li mask:A 1D optional Tensor. Must be one of the following types: uint8. The format must be ND . \n +*@li real_mask:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li project:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. + +*@par Attributes: +*@li cell_type:An string identifying the cell type in the op. Default to "LSTM". Only LSTM is currently supported. +*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. +*@li cell_depth:An integer identifying the cell depth in the op. Default to 1. +*@li use_peephole:An bool identifying if use peephole in the op. Default to false. +*@li keep_prob:An float identifying the keep prob in the op. Default to 1. +*@li cell_clip:An float identifying the cell clip in the op. Default to -1. +*@li num_proj:An integer identifying the num projection in the op. Default to 0. +*@li time_major:An bool identifying the time major in the op. Default to true. +*@li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported. +*@li forget_bias:An float identifying the forget bias in the op. Default to 0. +*@li is_training:An bool identifying is training in the op. Default to true . \n + +*@par Outputs: +*eight outputs: +*@li y:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li output_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li output_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li i:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li j:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li f:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li o:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@par Third-party framework compatibility: +* Compatible with the TF operator LSTM. +*/ +REG_OP(DynamicRNNV3) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(w, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(b, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32})) + .OPTIONAL_INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(init_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wci, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wcf, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wco, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(mask, TensorType({DT_UINT8})) + .OPTIONAL_INPUT(real_mask, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(project, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(i, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(j, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(f, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(o, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(tanhc, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(cell_type, String, "LSTM") + .ATTR(direction, String, "UNIDIRECTIONAL") + .ATTR(cell_depth, Int, 1) + .ATTR(use_peephole, Bool, false) + .ATTR(keep_prob, Float, 1.0) + .ATTR(cell_clip, Float, -1.0) + .ATTR(num_proj, Int, 0) + .ATTR(time_major, Bool, true) + .ATTR(activation, String, "tanh") + .ATTR(forget_bias, Float, 0.0) + .ATTR(is_training, Bool, true) + .OP_END_FACTORY_REG(DynamicRNNV3) + +/** +*@brief: DynamicLSTMV2 calculation. +*@par Inputs: +*ten inputs: +*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li w:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. +*@li cont:A required 2D Tensor. Must be one of the following types: float16, float32. The format must be ND. +*@li w_xc_x_static:A optional 2D Tensor. Must be one of the following types: float16, float32. The format must be ND. +*@li h0:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li c0:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li wci:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li wcf:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li wco:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li mask:A optional 1D Tensor. Must be one of the following types: uint8. The format must be ND . + +*@par Attributes: +*@li num_output:An integer identifying the num projection in the op. Default to 0. +*@li expose_hidden:An bool identifying the expose_hidden in the op. Default to flase. +*@li need_output_last:An bool identifying the time major in the op. Default to true. +*@li forget_bias:An float identifying the forget bias in the op. Default to 0. + +*@par Outputs: +*eight outputs: +*@li y:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li output_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li output_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li last_output_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li last_output_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@par Third-party framework compatibility: +* Compatible with the Caffe operator LSTM. +*@par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(DynamicLSTMV2) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(w, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(b, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(cont, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(w_xc_x_static, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(h0, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(c0, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wci, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wcf, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wco, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(mask, TensorType({DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(last_output_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(last_output_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(num_output, Int, 0) + .ATTR(expose_hidden, Bool, false) + .ATTR(need_output_last, Bool, false) + .ATTR(forget_bias, Float, 0.0) + .OP_END_FACTORY_REG(DynamicLSTMV2) + /** *@brief: LSTMInputGrad calculation. *@par Inputs: @@ -297,6 +528,60 @@ REG_OP(LSTMInputGrad) .OP_END_FACTORY_REG(LSTMInputGrad) + +/** +*@brief: Dynamic LSTM Cell grad calculation.Calculate the gradient of gates and cell state. +*@par Inputs: +*twelve inputs: +*@li init_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dc:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li i:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li j:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li f:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li o:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li mask:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li t_state:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ . \n + +*@par Attributes: +*@li forget_bias:An integer identifying the forget bias in the op. Default to 1. +*@li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported . \n +*@li direction:An string that marks the calculation sequence of the operator. Default to "Forward". +*@li gate_order:An string mark the order of output 4 gate. Default to "ijfo". + +*@par Outputs: +*two outputs: +*@li dgate:A 4D Tensor. Must be one of the following types: float16. +*@li dct_1:A 4D Tensor. Must be one of the following types: float16, float32. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(DynamicLSTMGradCell) + .INPUT(init_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(c, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(dy, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(dh, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(dc, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(i, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(j, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(f, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(o, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(tanhct, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(mask, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(t_state, TensorType({DT_INT32, DT_INT32})) + .OUTPUT(dgate, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dct_1, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(forget_bias, Float, 1) + .ATTR(activation, String, "") + .ATTR(direction, String, "Forward") + .ATTR(gate_order, String, "ijfo") + .OP_END_FACTORY_REG(DynamicLSTMGradCell) + + /** *@brief: Basic LSTM Cell backward calculation.Calculate the gradient of input and hidden state. *@par Inputs: @@ -475,9 +760,9 @@ REG_OP(BasicRNNCell) .OP_END_FACTORY_REG(BasicRNNCell) /** -*@brief: DynamicGRU calculation. +*@brief DynamicGRU calculation. *@par Inputs: -*seven inputs: \n +*seven inputs: *@li x:Must be one of the following types: float16. The format must be FRACTAL_NZ. *@li w:Must be one of the following types: float16. The format must be FRACTAL_Z. *@li b:Must be one of the following types: float16, float32. The format must be ND. @@ -497,7 +782,7 @@ REG_OP(BasicRNNCell) *@li is_training:An bool identifying is training in the op. Default to true. *@par Outputs: -*five outputs: \n +*five outputs: *@li y:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li output_h:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li r:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. @@ -531,9 +816,9 @@ REG_OP(DynamicGRU) .OP_END_FACTORY_REG(DynamicGRU) /** -*@brief: DynamicGRUV2 calculation. +*@brief DynamicGRUV2 calculation. *@par Inputs: -*seven inputs: \n +*seven inputs: *@li x:Must be one of the following types: float16. The format must be FRACTAL_NZ. *@li weight_input:Must be one of the following types: float16. The format must be FRACTAL_Z. *@li weight_hidden:Must be one of the following types: float16. The format must be FRACTAL_Z. @@ -555,16 +840,13 @@ REG_OP(DynamicGRU) *@li is_training:An bool identifying is training in the op. Default to true. *@par Outputs: -*six outputs: \n +*six outputs: *@li y:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li output_h:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li update:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li reset:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li new:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li hidden_new:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. - -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(DynamicGRUV2) .INPUT(x, TensorType({DT_FLOAT16})) @@ -592,6 +874,68 @@ REG_OP(DynamicGRUV2) .ATTR(is_training, Bool, true) .OP_END_FACTORY_REG(DynamicGRUV2) + +/** +*@brief DynamicGRUV2Hidden calculation. +*@par Inputs: +*five inputs: +*@li x_weight_input:Must be one of the following types: float32. The format must be FRACTAL_NZ. +*@li weight_hidden:Must be one of the following types: float16. The format must be FRACTAL_Z. +*@li bias_hidden:Must be one of the following types: float16, float32. The format must be ND. +*@li seq_length:Must be one of the following types: int32. The format must be ND. +*@li init_h:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. + +*@par Attributes: +*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". +Only UNIDIRECTIONAL is currently supported. +*@li cell_depth:An integer identifying the cell depth in the op. Default to 1. +*@li keep_prob:An float identifying the keep prob in the op. Default to 1. +*@li cell_clip:An float identifying the cell clip in the op. Default to -1. +*@li num_proj:An integer identifying the num projection in the op. Default to 0. +*@li time_major:An bool identifying the time major in the op. Default to true. +*@li activation:An string identifying the type of activation function in the op. Default to "tanh". +Only tanh is currently supported. +*@li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. +*@li reset_after:An bool identifying whether to apply reset gate after matrix multiplication. Default to true. +*@li is_training:An bool identifying is training in the op. Default to true. + +*@par Outputs: +*six outputs: +*@li y:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li output_h:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li update:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li reset:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li new:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li hidden_new:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(DynamicGRUV2Hidden) + .INPUT(x_weight_input, TensorType({DT_FLOAT32})) + .INPUT(weight_hidden, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(bias_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32})) + .OPTIONAL_INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(update, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(reset, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(new, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(hidden_new, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(direction, String, "UNIDIRECTIONAL") + .ATTR(cell_depth, Int, 1) + .ATTR(keep_prob, Float, 1.0) + .ATTR(cell_clip, Float, -1.0) + .ATTR(num_proj, Int, 0) + .ATTR(time_major, Bool, true) + .ATTR(activation, String, "tanh") + .ATTR(gate_order, String, "zrh") + .ATTR(reset_after, Bool, true) + .ATTR(is_training, Bool, true) + .OP_END_FACTORY_REG(DynamicGRUV2Hidden) + + /** *@brief: DynamicGRUV2Grad calculation. *@par Inputs: @@ -618,7 +962,6 @@ REG_OP(DynamicGRUV2) *@li cell_clip:An float identifying the cell clip in the op. Default to -1. *@li num_proj:An integer identifying the num projection in the op. Default to 0. *@li time_major:An bool identifying the time major in the op. Default to true. -*@li bias_type:An string identifying the type of bias_type function in the op. Default to "double_bias". *@li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. *@li reset_after:An bool identifying whether to apply reset gate after matrix multiplication. Default to true. @@ -630,6 +973,9 @@ REG_OP(DynamicGRUV2) *@li db_hidden:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li dx:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(DynamicGRUV2Grad) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -658,7 +1004,6 @@ REG_OP(DynamicGRUV2Grad) .ATTR(cell_clip, Float, -1.0) .ATTR(num_proj, Int, 0) .ATTR(time_major, Bool, true) - .ATTR(bias_type, String, "double_bias") .ATTR(gate_order, String, "zrh") .ATTR(reset_after, Bool, true) .OP_END_FACTORY_REG(DynamicGRUV2Grad) @@ -667,7 +1012,7 @@ REG_OP(DynamicGRUV2Grad) *@brief: GRUV2HiddenGrad calculation. *@par Inputs: *nine inputs: \n -*@li weight_hidden:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dh_pre_t:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li dy:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. @@ -678,6 +1023,7 @@ REG_OP(DynamicGRUV2Grad) *@li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@par Attributes: +*@li t_state:An Int identifying the current t state. Default to [0, 4]. *@li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. *@par Outputs: @@ -685,10 +1031,12 @@ REG_OP(DynamicGRUV2Grad) *@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li dgate_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li dnt_x:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ -REG_OP(GRUV2HiddenGrad) - .INPUT(weight_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) +REG_OP(GRUV2HiddenGradCell) + .INPUT(dh_pre_t, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(h, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(dy, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(dh, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -699,8 +1047,197 @@ REG_OP(GRUV2HiddenGrad) .OUTPUT(dh_prev, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(dgate_h, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(dnt_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(t_state, Int, 0) .ATTR(gate_order, String, "zrh") - .OP_END_FACTORY_REG(GRUV2HiddenGrad) + .OP_END_FACTORY_REG(GRUV2HiddenGradCell) + +/** +* @brief Calculates the reversed outputs of the function "embedding". \n + +* @par Inputs: +* Two inputs, including: +* @li grad: A mutable Tensor of word grad. Must be one of the following types: +* float32. +* @li indices: A mutable word index Tensor of the int32 type.\n + +* @par Attributes: +* @li num_weights: An int attr which use to judge how many words in dict. \n + +* @li padding_idx: An int attr judge which word to fill zeros. Defaults to "-1". \n + +* @li scale_grad_by_freq: An optional bool. Defaults to "False". +* If "True", "grad_weight" will be scale by word_frequency. +* If "False", "grad_weight" will not be scale by word_frequency. \n + +* @par Outputs: +* @li grad_weight: A mutable output Tensor of new word grad has the same type as "grads". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator EmbeddingDenseGrad. +*/ +REG_OP(EmbeddingDenseGrad) + .INPUT(grad, TensorType({ DT_FLOAT32 })) /* "First operand." */ + .INPUT(indices, TensorType({ DT_INT32 })) /* "Second operand." */ + .OUTPUT(y, TensorType({ DT_FLOAT32 })) /* "Result, has same element type as two inputs" */ + .REQUIRED_ATTR(num_weights, Int) + .ATTR(padding_idx, Int, -1) + .ATTR(scale_grad_by_freq, Bool, false) + .OP_END_FACTORY_REG(EmbeddingDenseGrad) + +/** +*@brief CommonLSTM calculation. +*@par Inputs: +*eight inputs: \n +*@li x:Each time step is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li w:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li r:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li b:An optional input. Each direction is a 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. +*@li sequence_lens:An optional input. A 1D Tensor.Must be one of the following types: int32. The format must be ND. +*@li initial_h:An optional input. Each direction is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li initial_c:An optional input. Each direction is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li p:An optional input. Each direction is a 1D Tensor.Must be one of the following types: float16, float32. The format must be ND. + +*@par Attributes: +*@li activation_alpha:Optional scaling values used by some activation functions. Empty is currently supported. +*@li activation_beta:Optional scaling values used by some activation functions. Empty is currently supported. +*@li activations:The list of activation functions. Empty is currently supported. +*@li clip:An float identifying the cell clip in the op. Default to -1. +*@li direction:Specify if the RNN is forward, reverse, or bidirectional. Must be one of forward(default), reverse, or bidirectional. +*@li hidden_size:Number of neurons in the hidden layer. Reserved. +*@li input_forget:Couple the input and forget gates if 1. Reserved. + +*@par Outputs: +*three outputs: \n +*@li y:First dimension is time step, second dimension is direction, others is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li y_h:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li y_c:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*/ + +REG_OP(CommonLSTM) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(w, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(r, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(b, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(sequence_lens, TensorType({DT_INT32})) + .OPTIONAL_INPUT(initial_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(initial_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(p, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(activation_alpha, ListFloat, {}) + .ATTR(activation_beta, ListFloat, {}) + .ATTR(activations, ListString, {}) + .ATTR(clip, Float, -1.0) + .ATTR(direction, String, "forward") + .REQUIRED_ATTR(hidden_size, Int) + .ATTR(input_forget, Int, 0) + .OP_END_FACTORY_REG(CommonLSTM) + +/** + * @brief Calculate the mask. According to hidden_size and num_step, convert seq_length to mask. + * + * @par Inputs: + * @li seq_length: A 1D Tensor. Must be one of the following types: int32. Record the current length of each batch. [batch_size]. + * @li b: A 1D Tensor. Must be one of the following types: fp16/fp32. Record the hidden_size. [4 * hidden_size]. + * @li x: A 3D Tensor. Must be one of the following types: fp16/fp32. Record the num_step/batch_size/input_size. [num_step, batch_size, input_size]. + * + * @par Outputs: + * seq_mask: A 3D Tensor. Must be one of the following types: fp16/fp32. with the shape of [num_step, batch_size, hidden_size]. And has the same type as "b" \n + * + * @par Restrictions: + * Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. + */ +REG_OP(RnnGenMaskV2) + .INPUT(seq_length, TensorType({DT_INT32})) + .INPUT(b, TensorType({{DT_FLOAT16, DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(seq_mask, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(RnnGenMaskV2) + +/** +* @brief Common GRU calculation. + +* @par Inputs: +* Eight inputs, including: +* @li x: The input sequences packed (and pontentially padded) into on 3D Tesnor(float16). The format must be FRACTAL_NZ +* @li w: The weight tensor for the gates is 3D Tensor(float16). The format must be FRACTAL_Z +* @li r: The recurrence weight tesnor is 3D Tensor(float16). The format must be FRACTAL_Z +* @li b: The bias tensor for the gates. The format must be ND +* @li sequence_lens: Optional tensor specifying lengths of sequences(int32). The format must be ND +* @li init_h: Optional initial value of the hidden(float16,float32). The format must be FRACTAL_NZ + +* @par Attributes: +* @li activation_alpha: Optional scaling values used by some activation functions. \n +* @li activation_beta: Optional scaling values used by some activation functions. \n +* @li activations: A list of 2 (or 4 if bidirectional) activation functions for update, reset, and hidden gates. \n +* @li clip: Cell clip threshold. \n +* @li direction: Specify if the RNN is forward, reverse, or bidirectional. \n +* @li hidden_size: Number of neurons in the hidden layer. \n +* @li linear_before_reset: When computing the output of the hidden gate, apply the linear transformation before multiplying by the output of the reset gate. \n + +* @par Outputs: +* @li y: A Tensor that concats all the intermediate output values of the hidden(float16,float32). The format must be FRACTAL_NZ +* @li y_h: The last output value of the hidden(float16,float32). The format must be FRACTAL_NZ +*/ +REG_OP(CommonGRU) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(w, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(r, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(b, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(sequence_lens, TensorType({DT_INT32})) + .OPTIONAL_INPUT(initial_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(activation_alpha, ListFloat, {}) + .ATTR(activation_beta , ListFloat, {}) + .ATTR(activations , ListString, {}) + .ATTR(clip, Float, -1.0) + .ATTR(direction, String, "forward") + .REQUIRED_ATTR(hidden_size, Int) + .ATTR(linear_before_reset , Int, 0) + .OP_END_FACTORY_REG(CommonGRU) +/** +* @brief Calculates the reversed outputs of the function "embedding". \n + +* @par Inputs: +* Four inputs, including: +* @li weight: A mutable Tensor of word grad. Must be one of the following types: +* float32. +* @li indices: A mutable word index Tensor of the int32 type.\n +* @li offsets: A mutable word index Tensor of the int32 type.\n +* @li per_sample_weights: to indicate all weights should be taken to be 1. +* If specified, per_sample_weights must have exactly the same shape as input +* and is treated as having the same offsets, if those are not None. +* Only supported for mode='sum'..\n + +* @par Attributes: +* @li mode: An string attr which use "sum"``, ``"mean"`` or ``"max"``. Specifies the way to reduce the bag.. \n + +* @li scale_grad_by_freq: An optional bool. Defaults to "False". +* If "True", "grad_weight" will be scale by word_frequency. +* If "False", "grad_weight" will not be scale by word_frequency. \n +* @li sparse: if True, gradient w.r.t.attr weight matrix will be a sparse tensor. \n +* @li include_last_offset: if True, attr offsets has one additional element, where the last element +* is equivalent to the size of indices. This matches the CSR format.. \n + +* @par Outputs: +* @li grad_weight: A mutable output Tensor of new word grad has the same type as "grads". \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator EmbeddingBag. +*/ +REG_OP(EmbeddingBag) + .INPUT(weight, TensorType({ DT_FLOAT32 })) + .INPUT(indices, TensorType({ DT_INT32 })) + .OPTIONAL_INPUT(offsets, TensorType({DT_INT32})) + .OPTIONAL_INPUT(per_sample_weights, TensorType({DT_FLOAT32})) + .OUTPUT(y, TensorType({ DT_FLOAT32 })) + .ATTR(mode, String, "mean") + .ATTR(scale_grad_by_freq, Bool, false) + .ATTR(sparse, Bool, false) + .ATTR(include_last_offset, Bool, false) + .OP_END_FACTORY_REG(EmbeddingBag) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_RNN_H_ diff --git a/third_party/fwkacllib/inc/ops/rpn_ops.h b/third_party/fwkacllib/inc/ops/rpn_ops.h index b7649a44..089af326 100644 --- a/third_party/fwkacllib/inc/ops/rpn_ops.h +++ b/third_party/fwkacllib/inc/ops/rpn_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/save_ops.h b/third_party/fwkacllib/inc/ops/save_ops.h index 0ce473b7..5ce6c2e0 100644 --- a/third_party/fwkacllib/inc/ops/save_ops.h +++ b/third_party/fwkacllib/inc/ops/save_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/sdca_ops.h b/third_party/fwkacllib/inc/ops/sdca_ops.h index cbd9839d..34c6a268 100644 --- a/third_party/fwkacllib/inc/ops/sdca_ops.h +++ b/third_party/fwkacllib/inc/ops/sdca_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/selection_ops.h b/third_party/fwkacllib/inc/ops/selection_ops.h index 2c99e82e..1c26e033 100644 --- a/third_party/fwkacllib/inc/ops/selection_ops.h +++ b/third_party/fwkacllib/inc/ops/selection_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -239,6 +239,30 @@ REG_OP(GatherV2D) .REQUIRED_ATTR(axis, Int) .OP_END_FACTORY_REG(GatherV2D) +/** +*@Gathers values along an axis specified by dim . \n + +*@par Inputs: +*@li x: A Tensor. Must be one of the following types: float16, float32, int32, int64. +*@li index: A Tensor. Must be one of the following types: int64 . \n + +*@par Attributes: +* dim: the axis along which to index . \n + +*@par Outputs: +* y: A Tensor. Has the same type as "x" . \n + +*@par Third-party framework compatibility +*Compatible with the PyTorch operator Gather. +*/ + +REG_OP(GatherElements) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT64})) + .INPUT(index, TensorType({DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT64})) + .ATTR(dim, Int, 0) + .OP_END_FACTORY_REG(GatherElements) + /** *@brief Extracts a strided slice of a tensor. Roughly speaking, this op extracts a slice of size (end-begin)/stride from the given input tensor. @@ -275,8 +299,6 @@ REG_OP(GatherV2D) *@par Outputs: *y: A Tensor. Has the same type as "x" . \n -*@attention Constraints: - *@par Third-party framework compatibility * Compatible with the TensorFlow operator StridedSlice. */ @@ -327,8 +349,6 @@ REG_OP(StridedSlice) *@par Outputs: *y: A Tensor. Has the same type as "x" . \n -*@attention Constraints: - *@par Third-party framework compatibility * Compatible with the TensorFlow operator StridedSlice. @@ -385,8 +405,6 @@ REG_OP(StridedSliceD) *@par Outputs: *output: A Tensor. Has the same type as "dy" . \n -*@attention Constraints: - *@par Third-party framework compatibility * Compatible with the TensorFlow operator StridedSliceGradD. @@ -444,8 +462,6 @@ REG_OP(StridedSliceGradD) *@par Outputs: *output: A Tensor has the same type as "dy" . \n -*@attention Constraints: - *@par Third-party framework compatibility * Compatible with the TensorFlow operator StridedSliceGrad. */ @@ -486,6 +502,38 @@ REG_OP(UnsortedSegmentSum) .OUTPUT(y, TensorType::NumberType()) .OP_END_FACTORY_REG(UnsortedSegmentSum) +/** +*@brief Creates a one-dimensional tensor of size steps whose values are evenly spaced from start to +* end, inclusive, on a logarithmic scale with base base. \n + +*@par Inputs: +*One inputs, including: +* @li assist: A tensor. Must be one of the following types: +* float16, float32. \n + +* @par Attributes: +* @li start: An required float. Used to select the start. \n +* @li end: An required float. Used to select the end. \n +* @li steps: An optional int.Defaults to 100. \n +* @li base: An optional float.Defaults to 10.0. \n +* @li dtype: An optional int.Defaults to 1. \n + +*@par Outputs: +*y: A Tensor with the same type and shape of input_x's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator logspaced. \n +*/ +REG_OP(LogSpaceD) + .INPUT(assist, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .REQUIRED_ATTR (start, Float) + .REQUIRED_ATTR (end, Float) + .ATTR(steps, Int, 100) + .ATTR(base, Float, 10.0) + .ATTR(dtype, Int, 1) + .OP_END_FACTORY_REG(LogSpaceD) + /** *@brief Computes the sum along segments of a tensor . \n @@ -796,6 +844,34 @@ REG_OP(SliceD) .REQUIRED_ATTR(size, ListInt) .OP_END_FACTORY_REG(SliceD) +/** +*@brief Extracts a slice from a tensor. +* This operation extracts a slice of size "size" from a tensor "x" +* starting at the location specified by "begin" . \n + +*@par Inputs: +*@li x: A Tensor. Must be one of the following types: +* float16, float32, double, int64, int32, uint8, uint16, uint32, uint64, int8, +* int16, complex64, complex128, qint8, quint8, qint16, quint16, qint32 . \n + +*@par Inputs: +*@li offsets: The starting location for the slice. + +*@par Attributes: +*@li size: The tensor shape . \n + +*@par Outputs: +*y: A Tensor. Has the same type as "x". The slice extracted from the tensor. +*@par Restrictions: +*Warning: THIS FUNCTION IS DEPRECATED. Please use Slice instead. +*/ +REG_OP(SliceDV2) + .INPUT(x, TensorType::BasicType()) + .INPUT(offsets, TensorType::IndexNumberType()) + .OUTPUT(y, TensorType::BasicType()) + .REQUIRED_ATTR(size, ListInt) + .OP_END_FACTORY_REG(SliceDV2) + /** * @brief Finds values and indices of the "k" largest elements for the last * dimension . \n @@ -829,8 +905,8 @@ REG_OP(SliceD) * @li sorted = true * @li It's unstable sorted indices on the platform of Ascend310 -* @par Third-party framework compatibility -* @li Compatible with the TensorFlow operator TopK. +* @par Restrictions: +* Warning: THIS FUNCTION IS DEPRECATED. Please use TopKV2 instead. */ REG_OP(TopKD) .INPUT(x, TensorType::RealNumberType()) @@ -855,6 +931,44 @@ REG_OP(TopKD) * Number of top elements to look for along the last dimension (along each row * for matrices) . \n +* @par Attributes: +* @li sorted: An optional bool. Defaults to true. +* If true, the resulting "k" elements will be sorted by the values in descending +* order. +* @li dim: An optional int. Defaults to -1. For reserved use. +* @li largest: An optional bool. Defaults to true. For reserved use. \n + +* @par Outputs: +* @li values: A Tensor, specifying the sorted data. Has the same type as +* "input". +* @li indices: A Tensor of type int32, specifying the indices of sorted data . \n + +* @see TopK() +* @par Third-party framework compatibility +* @li Compatible with the TensorFlow operator TopKV2. +*/ +REG_OP(TopKV2) + .INPUT(x, TensorType::RealNumberType()) + .INPUT(k, TensorType({DT_INT32})) + .OUTPUT(values, TensorType::RealNumberType()) + .OUTPUT(indices, TensorType({DT_INT32})) + .ATTR(sorted, Bool, true) + .ATTR(dim, Int, -1) + .ATTR(largest, Bool, true) + .OP_END_FACTORY_REG(TopKV2) + +/** +* @brief Finds values and indices of the "k" largest elements for the last +* dimension . \n + +* @par Inputs: +* Two inputs, including: +* @li x: A 1D or higher tensor of type BasicType, with the last dimension +* at least "k". +* @li k: A 0D Tensor of type int32. +* Number of top elements to look for along the last dimension (along each row +* for matrices) . \n + * @par Attributes: * @li sorted: An optional bool. Defaults to true. * If true, the resulting "k" elements will be sorted by the values in descending @@ -876,15 +990,17 @@ REG_OP(TopK) .OUTPUT(values, TensorType::RealNumberType()) .OUTPUT(indices, TensorType({DT_INT32})) .ATTR(sorted, Bool, true) + .ATTR(largest, Bool, true) + .ATTR(dim, Int, -1) .OP_END_FACTORY_REG(TopK) /** *@brief Creates a new tensor by applying sparse "updates" to individual values or slices within a tensor (initially zero for numeric, empty for string) of the given "shape" according to "indices" . \n *@par Inputs: *Inputs including: -* @li indices: A required index tensor. Must be one of the following types: float32, float16, int32, int8, uint8. -* @li x: A required slice tensor. Must be one of the following types: float32, float16, int32, int8, uint8. -* @li shape: A required list of int32, specifying the output shape. +* @li indices: A required index tensor. Must be one of the following types: int32 or int64. +* @li x: A required slice tensor. Must be one of the following types: float32, float16, int32, int8, uint8... +* @li shape: A required list of int32 or int64, specifying the output shape. *@par Outputs: *y:A output Tensor with same datatype as "updates" . \n @@ -895,7 +1011,7 @@ REG_OP(TopK) * Compatible with the TensorFlow operator ScatterNd. */ REG_OP(ScatterNd) - .INPUT(indices, TensorType::BasicType()) + .INPUT(indices, TensorType::IndexNumberType()) .INPUT(x, TensorType::BasicType()) .INPUT(shape, TensorType::IndexNumberType()) .OUTPUT(y, TensorType::BasicType()) @@ -908,11 +1024,11 @@ REG_OP(ScatterNd) *@par Inputs: *Inputs including: * @li indices: A required index tensor. Must be one of the following types: - * float, float16, int32, int16. format:ND. + * int32 or int64. format:ND. * @li x: A required slice tensor. Must be one of the following types: - * float, float16, int32, int16. format:ND. + * float16, float, int32, int8, uint8. format:ND. *@par Attributes: -* @li shape: A required list of int32, specifying the output shape. +* @li shape: A required list of int32 or int64, specifying the output shape. *@par Outputs: *y: A Tensor. Has the same type as "x". format:ND . \n @@ -927,8 +1043,8 @@ REG_OP(ScatterNd) */ REG_OP(ScatterNdD) .INPUT(indices, TensorType::IndexNumberType()) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT16})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT16})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) .REQUIRED_ATTR(shape, ListInt) .OP_END_FACTORY_REG(ScatterNdD) @@ -1752,6 +1868,33 @@ REG_OP(Crop) .REQUIRED_ATTR(offsets, ListInt) .OP_END_FACTORY_REG(Crop) +/** +*@brief Returns a namedtuple (values, indices) where values is the cumulative +* the cumulative minimum of elements of input in the dimension dim. +* And indices is the index location of each maximum value found in the dimension dim. \n + +*@par Inputs: +*One inputs, including: +* @li x: A tensor . Must be one of the following types: +* float16, float32, int32, uint32, int8, uint8. \n + +*@par Attributes: +* @li axis: Axis along which to cummin. \n + +*@par Outputs: +* y: A Tensor with the same type and shape of x's. \n +* indices: A Tensor with the int32 type and the same shape of x's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator Cummin. \n +*/ +REG_OP(Cummin) + .INPUT(x, TensorType::BasicType()) + .OUTPUT(y, TensorType::BasicType()) + .OUTPUT(indices, TensorType::BasicType()) + .REQUIRED_ATTR(axis, Int) + .OP_END_FACTORY_REG(Cummin) + /** *@brief Extends the input with copies of data along a specified dimension. For example: *(1) If x = [[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]]], with shape (2, 3, 2); @@ -1921,6 +2064,249 @@ REG_OP(CumulativeLogsumexpD) .ATTR(exclusive, Bool, false) .ATTR(reverse, Bool, false) .OP_END_FACTORY_REG(CumulativeLogsumexpD) + +/** +* @brief Add updates to var according to axis and indices. + +* @par Inputs: +* Three inputs, including: +* @li var: A Tensor. Must be one of the following types: +* float16, float32, int16, int32, int8, uint8. +* @li indices: A Tensor of the indices, type should be int32. +* @li updates: A Tensor of the same type as "var". \n + +* @par Attributes: +* @li axis: An required int to specify the axis to perform indices add. \n + +* @par Outputs: +* @li var: A Tensor. Same as input "var". + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator index_add_. +*/ +REG_OP(InplaceIndexAdd) + .INPUT(var, TensorType({DT_INT16, DT_INT32, DT_INT8, + DT_UINT8, DT_FLOAT32, DT_FLOAT16})) + .INPUT(indices, TensorType({DT_INT32})) + .INPUT(updates, TensorType({DT_INT16, DT_INT32, DT_INT8, + DT_UINT8, DT_FLOAT32, DT_FLOAT16})) + .OUTPUT(var, TensorType({DT_INT16, DT_INT32, DT_INT8, + DT_UINT8, DT_FLOAT32, DT_FLOAT16})) + .REQUIRED_ATTR(axis, Int) + .OP_END_FACTORY_REG(InplaceIndexAdd) + +/** +* @brief Replace the value of X with value according to mask. +* @par Inputs: +* three inputs, including: +* @li x: A Tensor of dtype is float16 or float32 or int64 or int32 or int8. +* @li mask: A Tensor of dtype bool. +* @li value: A Tensor of dtype float16 or float32 or int64 or int32 or int8. + +* @par Outputs: +* @li y: A tensor. Must be one of the following dtypes: +* float16, float32, int64, int32, int8. +*/ +REG_OP(MaskedFill) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32, DT_INT64})) + .INPUT(mask, TensorType({DT_BOOL})) + .INPUT(value, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32, DT_INT64})) + .OP_END_FACTORY_REG(MaskedFill) + +/** +* @brief Choose the value of X with value according to mask. + +* @par Inputs: +* two inputs, including: +* @li x: A Tensor of dtype is float16 or float32. +* @li mask: A Tensor of dtype is bool. \n + +* @par Outputs: +* @li y: A tensor with the same type as x. \n + +* @par Third-party framework compatibility +* Compatible with the Numpy operator select. +* Replaces the pytorch operator masked_select in some scenarios.\n +*/ +REG_OP(MaskedSelectV2) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(mask, TensorType({DT_BOOL})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(MaskedSelectV2) + +/** +* @brief Slice a tensor at its last dim, e.x. a[..., begin:end:stride]. \n + +* @par Inputs: +* One inputs, including: +* @li x: A Tensor. Must be one of the following types: float16, float32, int16, int32. + +* @par Attributes: +* @li start: An attribute of type Int, start index of last dim. \n +* @li end: An attribute of type Int, end index of last dim. \n +* @li stride: An attribute of type Int, stride of slice. \n + +* @par Outputs: +* @li y: A Tensor. Has the same type as "x". \n + +* @par Third-party framework compatibility +* No compatibility +*/ +REG_OP(SliceLastDim) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT8, DT_INT16, DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT8, DT_INT16, DT_INT32, DT_INT64})) + .REQUIRED_ATTR(start, Int) + .REQUIRED_ATTR(end, Int) + .ATTR(stride, Int, 1) + .OP_END_FACTORY_REG(SliceLastDim) + +/** +* @brief Extracts a strided slice of a tensor. Roughly speaking, this op \n +* extracts a slice of size (end-begin)/stride from the given input tensor. \n +* Starting at the location specified by begin the slice continues by \n +* adding stride to the index until all dimensions are not less than end. \n +* +* @par Inputs: +* Four inputs, including: +* @li x: A Tensor. Must be one of the following types: float32, float64, int32, uint8, int16, int8, \n +* complex64, int64, qint8, quint8, qint32, qint16, quint16, uint16, \n +* complex128, float16, uint32, uint64, complex64, complex128. \n +* @li begin: A Tensor of type int32 or int64, for the index of the first value to select. +* +* @li end: A Tensor of type int32 or int64, for the index of the last value to select. +* +* @li axes: A Tensor of type int32 or int64, indicate axis to be select. +* +* @li strides: A Tensor of type int32 or int64, for the increment. +* +* @par Attributes: +* @li begin_mask: A Tensor of type int32. \n +* A bitmask where a bit "i" being "1" means to ignore the begin \n +* value and instead use the largest interval possible. +* @li end_mask: A Tensor of type int32. \n +* Analogous to "begin_mask". +* @li ellipsis_mask: A Tensor of type int32. \n +* A bitmask where bit "i" being "1" means the "i"th position \n +* is actually an ellipsis. +* @li new_axis_mask: A Tensor of type int32. \n +* A bitmask where bit "i" being "1" means the "i"th \n +* specification creates a new shape 1 dimension. +* @li shrink_axis_mask: A Tensor of type int32. \n +* A bitmask where bit "i" implies that the "i"th \n +* specification should shrink the dimensionality. +* +* @par Outputs: +* y: A Tensor. Has the same type as "x". +* +* @attention Constraints: +* +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator StridedSliceV2. +*/ +REG_OP(StridedSliceV2) + .INPUT(x, TensorType::BasicType()) + .INPUT(begin, TensorType::IndexNumberType()) + .INPUT(end, TensorType::IndexNumberType()) + .OPTIONAL_INPUT(axes, TensorType::IndexNumberType()) + .OPTIONAL_INPUT(strides, TensorType::IndexNumberType()) + .ATTR(begin_mask, Int, 0) + .ATTR(end_mask, Int, 0) + .ATTR(ellipsis_mask, Int, 0) + .ATTR(new_axis_mask, Int, 0) + .ATTR(shrink_axis_mask, Int, 0) + .OUTPUT(y, TensorType::BasicType()) + .OP_END_FACTORY_REG(StridedSliceV2) + +/** +*@brief Fills the elements of the input tensor with value val by selecting the indices in the order given in index. \n + +*@par Inputs: +*Three inputs, including: +* @li x: A tensor. Must be one of the following types: +* float16, float32, int32. \n +*@li assist1: A tensor. Must be one of the following types: +* float16, float32, int32. \n +*@li assist2: A tensor. Must be one of the following types: +* float16, float32, int32. \n + +* @par Attributes: +* @li dim: A required int. Used to select the dimension of this tensor. \n + +*@par Outputs: +*y: A Tensor with the same type and shape of input_x's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator IndexFill. \n +*/ +REG_OP(IndexFillD) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .INPUT(assist1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .INPUT(assist2, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .REQUIRED_ATTR(dim, Int) + .OP_END_FACTORY_REG(IndexFillD) + +/** +* @brief For each row r of this and for each column c, do (*this)(r, c) += src(j, c), \n +* where j ranges from indexes[r].first through indexes[r].second - 1. \n +* In general indexes must be >= 0 and < src.NumRows(); \n +* but to represent an empty range you may use the pair (-1, -1) or any pair of numbers (i, j) such that i >= j. \n + +* @par Inputs: +* Three inputs, including: +* @li x: A Tensor. Must be one of the following types: +* float16, float32. +* @li indices: A Tensor of the indices, type should be int32. +* @li src: A Tensor of the same type as "x". \n + +* @par Outputs: +* @li x: A Tensor. Same as input "x". + +* @par Third-party framework compatibility +* Compatible with the kaldi operator AddRowRanges. +*/ +REG_OP(AddRowRanges) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(src, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(indices, TensorType({DT_INT32})) + .OUTPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .OP_END_FACTORY_REG(AddRowRanges) + +/** +*@brief masked fill tensor along with one axis by range. +* boxes. It is a customized masked fill range operator . \n + +*@par Inputs: +* Four inputs, including: +*@li x: input tensor. A ND Tensor of float32/float16/int32/int8 with shapes +* 1-D (D,), 2-D(N, D), 3-D(N, C, D) +*@li start: masked fill start pos. A 3D Tensor of int32 with +* shape (num, N). "num" indicates the number of loop masked fill, and the value N +* indicates the batch of ND Tensor, if input x shape is 1-D, N = 1. \n +*@li end: masked fill end pos. A 3D Tensor of int32 with +* shape (num, N). "num" indicates the number of loop masked fill, and the value N +* indicates the batch of ND Tensor. \n +*@li value: masked fill value. A 2D Tensor of float32/float16/int32/int8 with +* shape (num,). "num" indicates the number of loop masked fill + +*@par Attributes: +*@li axis: axis with masked fill of int32. Defaults to -1. + +*@par Outputs: +*y: A ND Tensor of float32/float16/int32/int8 with shapes 1-D (D,), 2-D(N, D), 3-D(N, C, D) + +* @par Restrictions: +* Warning: input shape's length must not be bigger than 1024 * 1024 * 1024. +*/ +REG_OP(MaskedFillRange) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32})) + .INPUT(start, TensorType({DT_INT32})) + .INPUT(end, TensorType({DT_INT32})) + .INPUT(value, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32})) + .REQUIRED_ATTR(axis, Int) + .OP_END_FACTORY_REG(MaskedFillRange) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_SELECTION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/set_ops.h b/third_party/fwkacllib/inc/ops/set_ops.h index 1d02fa15..04e04f1b 100644 --- a/third_party/fwkacllib/inc/ops/set_ops.h +++ b/third_party/fwkacllib/inc/ops/set_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/sparse_ops.h b/third_party/fwkacllib/inc/ops/sparse_ops.h index d7512790..a1fc9ee6 100644 --- a/third_party/fwkacllib/inc/ops/sparse_ops.h +++ b/third_party/fwkacllib/inc/ops/sparse_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -383,11 +383,11 @@ REG_OP(SparseFillEmptyRowsGrad) REG_OP(SparseTensorDenseMatMul) .INPUT(x1_indices, TensorType({DT_INT32, DT_INT64})) .INPUT(x1_values, TensorType({DT_FLOAT, DT_DOUBLE, DT_INT32, \ - DT_COMPLEXT64, DT_COMPLEX128, DT_FLOAT16})) + DT_COMPLEXT64, DT_COMPLEX128, DT_FLOAT16, DT_INT64})) .INPUT(x1_shape, TensorType({DT_INT64})) - .INPUT(x2, TensorType({DT_FLOAT, DT_DOUBLE, DT_INT32, DT_COMPLEXT64, \ + .INPUT(x2, TensorType({DT_FLOAT, DT_DOUBLE, DT_INT64, DT_INT32, DT_COMPLEXT64, \ DT_COMPLEX128, DT_FLOAT16})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_INT32, DT_COMPLEXT64, \ + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_INT64, DT_INT32, DT_COMPLEXT64, \ DT_COMPLEX128, DT_FLOAT16})) .ATTR(adjoint_a, Bool, false) .ATTR(adjoint_b, Bool, false) diff --git a/third_party/fwkacllib/inc/ops/spectral_ops.h b/third_party/fwkacllib/inc/ops/spectral_ops.h index 64fa7814..34ccb398 100644 --- a/third_party/fwkacllib/inc/ops/spectral_ops.h +++ b/third_party/fwkacllib/inc/ops/spectral_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -26,6 +26,24 @@ namespace ge { +/** +*@brief Computes the inverse 1-dimensional discrete Fourier transform over the +inner-most dimension of `x`. \n + +*@par Inputs: +*@li x: A Tensor. Must be the following types: complex64, complex128. \n + +*@par Outputs: +*@li y: A complex tensor of the same rank as `x`. \n + +*@par Third-party framework compatibility +* Compatible with TensorFlow IFFT operator. +*/ +REG_OP(IFFT) + .INPUT(x, TensorType({DT_COMPLEX64,DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_COMPLEX64,DT_COMPLEX128})) + .OP_END_FACTORY_REG(IFFT) + /** *@brief Real-valued fast Fourier transform . \n @@ -47,6 +65,84 @@ REG_OP(RFFT) .OUTPUT(y, TensorType({DT_COMPLEX64})) .OP_END_FACTORY_REG(RFFT) +/** +*@brief Inverse real-valued fast Fourier transform. \n + +*@par Inputs: +*@li x: A complex64 tensor. +*@li fft_length: An int32 tensor of shape [1]. The FFT length. \n + +*@par Outputs: +*@li y: A float32 tensor of the same rank as `input`. The inner-most + dimension of `input` is replaced with the `fft_length` samples of its inverse + 1D Fourier transform. \n + +*@par Third-party framework compatibility +* Compatible with TensorFlow IRFFT operator. +*/ +REG_OP(IRFFT) + .INPUT(x, TensorType({DT_COMPLEX64})) + .INPUT(fft_length, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT})) + .OP_END_FACTORY_REG(IRFFT) + + +/** +*@brief 2D fast Fourier transform. \n + +*@par Inputs: +*@li x: A complex64 tensor. + +*@par Outputs: +*@li y: A complex64 tensor of the same shape as `input`. The inner-most 2 + dimensions of `input` are replaced with their 2D Fourier transform. \n + +*@par Third-party framework compatibility +* Compatible with TensorFlow FFT2D operator. +*/ +REG_OP(FFT2D) + .INPUT(x, TensorType({DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_COMPLEX64, DT_COMPLEX128})) + .OP_END_FACTORY_REG(FFT2D) + +/** +*@brief Calculate the one-dimensional discrete Fourier transform on the +innermost dimension of the input. \n + +*@par Inputs: +*@li x: A Tensor. Must be the following types: complex64, complex128. \n + +*@par Outputs: +*@li y: A complex tensor with the same shape as input. The innermost dimension +of the input is replaced by its 1-dimensional Fourier transform. \n + +*@par Third-party framework compatibility +* Compatible with TensorFlow FFT operator. +*/ +REG_OP(FFT) + .INPUT(x, TensorType({DT_COMPLEX64,DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_COMPLEX64,DT_COMPLEX128})) + .OP_END_FACTORY_REG(FFT) + +/** +*@brief Calculate the inverse 1-dimensional discrete Fourier transform on the +innermost dimension of the input. \n + +*@par Inputs: +*@li x: A Tensor. Must be the following types: complex64, complex128. \n + +*@par Outputs: +*@li y: A complex tensor with the same shape as input. The innermost dimension +of the input is replaced by its inverse two-dimensional Fourier transform. \n + +*@par Third-party framework compatibility +* Compatible with TensorFlow IFFT2D operator. +*/ +REG_OP(IFFT2D) + .INPUT(x, TensorType({DT_COMPLEX64,DT_COMPLEX128})) + .OUTPUT(y, TensorType({DT_COMPLEX64,DT_COMPLEX128})) + .OP_END_FACTORY_REG(IFFT2D) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_SPECTRAL_OPS_H_ \ No newline at end of file diff --git a/third_party/fwkacllib/inc/ops/split_combination_ops.h b/third_party/fwkacllib/inc/ops/split_combination_ops.h index efe4715d..fe25a46f 100644 --- a/third_party/fwkacllib/inc/ops/split_combination_ops.h +++ b/third_party/fwkacllib/inc/ops/split_combination_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -62,8 +62,8 @@ REG_OP(Split) *Must be one of the following types: float16, float32, int32, int8, int16, int64, uint8, uint16, uint32, uint64 *@par Attributes: -*@li split_dim: A required int8, int16, int32, or int64. Specifies the dimension along which to split. No default value. -*@li num_split: A required int8, int16, int32, or int64. Specifies the number of output tensors. No default value . \n +*@li split_dim: A required int32. Specifies the dimension along which to split. No default value. +*@li num_split: A required int32. Specifies the number of output tensors. No default value . \n *@par Outputs: *y:Dynamic output. A list of output tensors. Has the same type and format as "x" . \n @@ -94,12 +94,12 @@ REG_OP(SplitD) *@par Inputs: * Three inputs, including: *@li x: An ND Tensor. -*Must be one of the following types: -*@li size_splits: A list of int8, int16, int32, or int64. Specifies a list containing the sizes of each output tensor along the split dimension. -*@li split_dim: An int8, int16, int32, or int64. Specifies the dimension along which to split . \n +*Must be one of the types:float16, float32, double, int64, int32, uint8, uint16, uint32, uint64, int8, int16, complex64, complex128, qint8, quint8, qint16, quint16, qint32. +*@li size_splits: Must be one of the types:int32, int64. Specifies a list containing the sizes of each output tensor along the split dimension. +*@li split_dim: Must be the following type:int32. Specifies the dimension along which to split . \n *@par Attributes: -*num_split: A required int8, int16, int32, or int64. Specifies the number of output tensors. No default value . \n +*num_split: A required int32. Specifies the number of output tensors. No default value . \n *@par Outputs: *y: Dynamic output.A list of output tensors. Has the same type and format as "x" . \n @@ -129,9 +129,9 @@ REG_OP(SplitV) *Must be one of the following types: float16, float32, int32, int8, int16, int64, uint8, uint16, uint32, uint64 *@par Attributes: -*@li size_splits: A required list of int8, int16, int32, or int64. Specifies a list containing the sizes of each output tensor along the split dimension. -*@li split_dim: A required int8, int16, int32, or int64. Specifies the dimension along which to split. No default value. -*@li num_split: A required int8, int16, int32, or int64. Specifies the number of output tensors. No default value . \n +*@li size_splits: A required list of int32. Specifies a list containing the sizes of each output tensor along the split dimension. +*@li split_dim: A required int32. Specifies the dimension along which to split. No default value. +*@li num_split: A required int32. Specifies the number of output tensors. No default value . \n *@par Outputs: *y: Dynamic output.A list of output tensors. Has the same type and format as "x" . \n @@ -317,15 +317,15 @@ REG_OP(Concat) * int64, uint8, uint16, uint32, uint64, float16, float32, bool . It's a dynamic input. \n *@par Attributes: -*@li axis: A optional int, defaultvalue is 0. +*@li axis: A optional int, default value is 0. * Dimension along which to pack. The range is [-(R+1), R+1). *@li N: A required int. Number of tensors . \n *@par Outputs: *y: A Tensor. Has the same type as "x". + *@par Third-party framework compatibility -*Compatible with the TensorFlow operator Pack. -It's a dynamic output. +* Compatible with the TensorFlow operator Pack. */ REG_OP(Pack) .DYNAMIC_INPUT(x, TensorType::BasicType()) diff --git a/third_party/fwkacllib/inc/ops/state_ops.h b/third_party/fwkacllib/inc/ops/state_ops.h index db1f5353..3c8e32b6 100644 --- a/third_party/fwkacllib/inc/ops/state_ops.h +++ b/third_party/fwkacllib/inc/ops/state_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/stateful_random_ops.h b/third_party/fwkacllib/inc/ops/stateful_random_ops.h index 366112d6..c2f65c6a 100644 --- a/third_party/fwkacllib/inc/ops/stateful_random_ops.h +++ b/third_party/fwkacllib/inc/ops/stateful_random_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/stateless_random_ops.h b/third_party/fwkacllib/inc/ops/stateless_random_ops.h index dad3c379..ff9daaa3 100644 --- a/third_party/fwkacllib/inc/ops/stateless_random_ops.h +++ b/third_party/fwkacllib/inc/ops/stateless_random_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/string_ops.h b/third_party/fwkacllib/inc/ops/string_ops.h index 4a88bc79..f9cc2549 100644 --- a/third_party/fwkacllib/inc/ops/string_ops.h +++ b/third_party/fwkacllib/inc/ops/string_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -25,6 +25,235 @@ #include "graph/operator_reg.h" namespace ge { +/** +*@brief Creates ngrams from ragged string data . \n + +*@par Inputs: +include: +*@li data:1-D.The values tensor of the ragged string tensor to make ngrams out of. +*@li data_splits:The splits tensor of the ragged string tensor to make ngrams out of . \n + +*@par Attributes: +* separator:The string to append between elements of the token. Use "" for no separator. +* ngram_widths:The sizes of the ngrams to create. +* left_pad:The string to use to pad the left side of the ngram sequence. Only used if pad_width != 0. +* right_pad:The string to use to pad the right side of the ngram sequence. Only used if pad_width != 0. +* pad_width:The number of padding elements to add to each side of each sequence. +* preserve_short_sequences: Preserve short sequences. \n + +*@par Outputs: +*@li ngrams:The values tensor of the output ngrams ragged tensor. +*@li ngrams_splits:The splits tensor of the output ngrams ragged tensor. \n + +*@see StringNGrams() + +*@par Third-party framework compatibility +*compatible with StringNGrams op of tensorflow + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(StringNGrams) + .INPUT(data, TensorType({DT_STRING})) + .INPUT(data_splits, TensorType({DT_INT32, DT_INT64})) + .OUTPUT(ngrams, TensorType({DT_STRING})) + .OUTPUT(ngrams_splits, TensorType({DT_INT32, DT_INT64})) + .REQUIRED_ATTR(separator, String) + .ATTR(ngram_widths, ListInt, {}) + .REQUIRED_ATTR(left_pad, String) + .REQUIRED_ATTR(right_pad, String) + .REQUIRED_ATTR(pad_width, Int) + .REQUIRED_ATTR(preserve_short_sequences, Bool) + .OP_END_FACTORY_REG(StringNGrams) + +/** +*@brief Decodes each string in `input` into a sequence of Unicode code points . \n + +*@par Inputs: +include: +*@li input:The text to be decoded. Can have any shape. Note that the output is flattened +to a vector of char values. \n + +*@par Attributes: +* input_encoding:Text encoding of the input strings. This is any of the encodings supported +by ICU ucnv algorithmic converters. Examples: `"UTF-16", "US ASCII", "UTF-8"`. +* errors:Error handling policy when there is invalid formatting found in the input. +The value of 'strict' will cause the operation to produce a InvalidArgument +error on any invalid input formatting. A value of 'replace' (the default) will +cause the operation to replace any invalid formatting in the input with the +`replacement_char` codepoint. A value of 'ignore' will cause the operation to +skip any invalid formatting in the input and produce no corresponding output +character. +* replacement_char:The replacement character codepoint to be used in place of any invalid +formatting in the input when `errors='replace'`. Any valid unicode codepoint may +be used. The default value is the default unicode replacement character is +0xFFFD or U+65533. +* replace_control_characters:Whether to replace the C0 control characters (00-1F) with the +`replacement_char`. Default is false. \n + +*@par Outputs: +*@li row_splits:A 1D tensor containing the row splits. +*@li char_values:A 1D tensor containing the decoded codepoints. +*@li char_to_byte_starts:A 1D int32 Tensor containing the byte index in the input string where each +character in `char_values` starts. \n + +*@see UnicodeDecodeWithOffsets() + +*@par Third-party framework compatibility +*compatible with UnicodeDecodeWithOffsets op of tensorflow + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(UnicodeDecodeWithOffsets) + .INPUT(input, TensorType({DT_STRING})) + .OUTPUT(row_splits, TensorType({DT_INT64})) + .OUTPUT(char_values, TensorType({DT_INT32})) + .OUTPUT(char_to_byte_starts, TensorType({DT_INT64})) + .REQUIRED_ATTR(input_encoding, String) + .ATTR(errors, String, "replace") + .ATTR(replacement_char, Int, 65533) + .ATTR(replace_control_characters, Bool, false) + .ATTR(Tsplits, Type, DT_INT64) + .OP_END_FACTORY_REG(UnicodeDecodeWithOffsets) + +/** +*@brief Decodes each string in `input` into a sequence of Unicode code points. \n + +*@par Inputs: +include: +*@li input:The text to be decoded. Can have any shape. Note that the output is flattened +to a vector of char values. \n + +*@par Attributes: +* input_encoding:Text encoding of the input strings. This is any of the encodings supported +by ICU ucnv algorithmic converters. Examples: `"UTF-16", "US ASCII", "UTF-8"`. +* errors:Error handling policy when there is invalid formatting found in the input. +The value of 'strict' will cause the operation to produce a InvalidArgument +error on any invalid input formatting. A value of 'replace' (the default) will +cause the operation to replace any invalid formatting in the input with the +`replacement_char` codepoint. A value of 'ignore' will cause the operation to +skip any invalid formatting in the input and produce no corresponding output +character. +* replacement_char:The replacement character codepoint to be used in place of any invalid +formatting in the input when `errors='replace'`. Any valid unicode codepoint may +be used. The default value is the default unicode replacement character is +0xFFFD or U+65533. +* replace_control_characters:Whether to replace the C0 control characters (00-1F) with the +`replacement_char`. Default is false. \n + +*@par Outputs: +*@li row_splits:A 1D tensor containing the row splits. +*@li char_values:A 1D tensor containing the decoded codepoints. \n + +*@see UnicodeDecode() + +*@par Third-party framework compatibility +*compatible with UnicodeDecode op of tensorflow + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(UnicodeDecode) + .INPUT(input, TensorType({DT_STRING})) + .OUTPUT(row_splits, TensorType({DT_INT64})) + .OUTPUT(char_values, TensorType({DT_INT32})) + .REQUIRED_ATTR(input_encoding, String) + .ATTR(errors, String, "replace") + .ATTR(replacement_char, Int, 65533) + .ATTR(replace_control_characters, Bool, false) + .ATTR(Tsplits, Type, DT_INT64) + .OP_END_FACTORY_REG(UnicodeDecode) + +/** +*@brief Transcode the input text from a source encoding to a destination encoding. \n + +*@par Inputs: +include: +*@li input:The text to be processed. Can have any shape. \n + +*@par Attributes: +* input_encoding:Text encoding of the input strings. This is any of the encodings supported +by ICU ucnv algorithmic converters. Examples: `"UTF-16", "US ASCII", "UTF-8"`. +* output_encoding:The unicode encoding to use in the output. Must be one of `"UTF-8", "UTF-16-BE", "UTF-32-BE"`. +Multi-byte encodings will be big-endian. +* errors:Error handling policy when there is invalid formatting found in the input. +The value of 'strict' will cause the operation to produce a InvalidArgument +error on any invalid input formatting. A value of 'replace' (the default) will +cause the operation to replace any invalid formatting in the input with the +`replacement_char` codepoint. A value of 'ignore' will cause the operation to +skip any invalid formatting in the input and produce no corresponding output +character. +* replacement_char:The replacement character codepoint to be used in place of any invalid +formatting in the input when `errors='replace'`. Any valid unicode codepoint may +be used. The default value is the default unicode replacement character is +0xFFFD or U+65533. +* replace_control_characters:Whether to replace the C0 control characters (00-1F) with the +`replacement_char`. Default is false. \n + +*@par Outputs: +*@li output:A string tensor containing unicode text encoded using `output_encoding`. \n + +*@see UnicodeTranscode() + +*@par Third-party framework compatibility +*compatible with UnicodeTranscode op of tensorflow + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(UnicodeTranscode) + .INPUT(input, TensorType({DT_STRING})) + .OUTPUT(output, TensorType({DT_STRING})) + .REQUIRED_ATTR(input_encoding, String) + .ATTR(output_encoding, String, "UTF-8") + .ATTR(errors, String, "replace") + .ATTR(replacement_char, Int, 65533) + .ATTR(replace_control_characters, Bool, false) + .OP_END_FACTORY_REG(UnicodeTranscode) + +/** +*@brief Encode a tensor of ints into unicode strings. \n + +*@par Inputs: +include: +*@li input_values:A 1D tensor containing the unicode codepoints that should be encoded. +*@li input_splits:A 1D tensor specifying how the unicode codepoints should be split into strings. \n + +*@par Attributes: +* output_encoding:The unicode encoding to use in the output. Must be one of `"UTF-8", "UTF-16-BE", "UTF-32-BE"`. +Multi-byte encodings will be big-endian. +* errors:Error handling policy when there is invalid formatting found in the input. +The value of 'strict' will cause the operation to produce a InvalidArgument +error on any invalid input formatting. A value of 'replace' (the default) will +cause the operation to replace any invalid formatting in the input with the +`replacement_char` codepoint. A value of 'ignore' will cause the operation to +skip any invalid formatting in the input and produce no corresponding output +character. +* replacement_char:The replacement character codepoint to be used in place of any invalid +formatting in the input when `errors='replace'`. Any valid unicode codepoint may +be used. The default value is the default unicode replacement character is +0xFFFD or U+65533. \n + +*@par Outputs: +*@li output:The 1-D Tensor of strings encoded from the provided unicode codepoints. \n + +*@see UnicodeEncode() + +*@par Third-party framework compatibility +*compatible with UnicodeEncode op of tensorflow + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(UnicodeEncode) + .INPUT(input_values, TensorType({DT_INT32})) + .INPUT(input_splits, TensorType({DT_INT32, DT_INT64})) + .OUTPUT(output, TensorType({DT_STRING})) + .ATTR(errors, String, "replace") + .ATTR(output_encoding, String, "UTF-8") + .ATTR(replacement_char, Int, 65533) + .OP_END_FACTORY_REG(UnicodeEncode) /** *@brief Split elements of input based on delimiter into a SparseTensor . \n @@ -61,6 +290,116 @@ REG_OP(StringSplit) .ATTR(skip_empty, Bool, true) .OP_END_FACTORY_REG(StringSplit) +/** +*@brief Replaces the match of pattern in input with rewrite. \n + +*@par Inputs: +include: +*@li input:A Tensor of type string. The text to be processed. \n + +*@par Attributes: +*@li pattern:A string. The regular expression to match the input. +*@li rewrite:A string. The rewrite to be applied to the matched expression. +*@li replace_global:An optional bool. Defaults to True. If True, the replacement is global, +otherwise the replacement is done only on the first match. + +*@par output: +*@li output::A Tensor of type string. +*/ +REG_OP(StaticRegexReplace) + .INPUT(input, TensorType({DT_STRING})) + .OUTPUT(output, TensorType({DT_STRING})) + .ATTR(pattern, String, "") + .ATTR(rewrite, String, "") + .ATTR(replace_global, Bool, true) + .OP_END_FACTORY_REG(StaticRegexReplace) + +/** +*@brief The input is a string tensor of any shape. The pattern is the +*regular expression to be matched with every element of the input tensor. +*The boolean values (True or False) of the output tensor indicate +*if the input matches the regex pattern provided. + +*@par Inputs: +include: +*@li input:A Tensor of type string. The text to be processed. \n + +*@par Attributes: +*@li pattern:A string. The regular expression to match the input. + +*@par output: +*@li output::A bool tensor with the same shape as `input`. +*/ +REG_OP(StaticRegexFullMatch) + .INPUT(input, TensorType({DT_STRING})) + .OUTPUT(output, TensorType({DT_BOOL})) + .ATTR(pattern, String, "") + .OP_END_FACTORY_REG(StaticRegexFullMatch) + +/** +*@brief A Tensor of type string. The input to be joined. \n + +*@par Inputs: +include: +*@li input:A Tensor of type string. The text to be processed. +*@li segment_ids:A Tensor. Must be one of the following types: int32, int64. +*A tensor whose shape is a prefix of data.shape. Negative segment ids are not supported. +*@li num_segments:A Tensor. Must be one of the following types: int32, int64. A scalar. + +*@par Attributes: +*@li separator:An optional string. Defaults to "". The separator to use when joining. + +*@par output: +*@li output::A Tensor of type string.. +*/ +REG_OP(UnsortedSegmentJoin) + .INPUT(input, TensorType({DT_STRING})) + .INPUT(segment_ids, TensorType({DT_INT32,DT_INT64})) + .INPUT(num_segments, TensorType({DT_INT32,DT_INT64})) + .OUTPUT(output, TensorType({DT_STRING})) + .ATTR(separator, String, "") + .OP_END_FACTORY_REG(UnsortedSegmentJoin) + +/** +*@brief Inputs to TensorFlow operations are outputs of another TensorFlow operation. +*This method is used to obtain a symbolic handle that represents the computation of the input. + +*@par Inputs: +include: +*@li input:A Tensor of type string. The text to be processed. + +*@par Attributes: +*@li encoding:An optional string. Defaults to "". + +*@par output: +*@li output::A Tensor of type string.. +*/ +REG_OP(StringLower) + .INPUT(input, TensorType({DT_STRING})) + .OUTPUT(output, TensorType({DT_STRING})) + .ATTR(encoding, String, "") + .OP_END_FACTORY_REG(StringLower) + +/** +*@brief Inputs to TensorFlow operations are outputs of another TensorFlow operation. +*This method is used to obtain a symbolic handle that represents the computation of the input. + +*@par Inputs: +include: +*@li input:A Tensor of type string. The text to be processed. + +*@par Attributes: +*@li encoding:An optional string. Defaults to "". + +*@par output: +*@li output::A Tensor of type string.. +*/ +REG_OP(StringUpper) + .INPUT(input, TensorType({DT_STRING})) + .OUTPUT(output, TensorType({DT_STRING})) + .ATTR(encoding, String, "") + .OP_END_FACTORY_REG(StringUpper) + /** *@brief Split elements of source based on sep into a SparseTensor . \n @@ -488,7 +827,7 @@ include: */ REG_OP(AsString) .INPUT(x, TensorType({DT_INT8, DT_INT16, DT_INT32, DT_INT64, DT_FLOAT, \ - DT_DOUBLE, DT_BOOL})) + DT_DOUBLE, DT_BOOL, DT_COMPLEX64, DT_COMPLEX128})) .OUTPUT(y, TensorType({DT_STRING})) .ATTR(precision, Int, -1) .ATTR(scientific, Bool, false) @@ -557,6 +896,45 @@ REG_OP(DecodeBase64) .INPUT(x, TensorType({DT_STRING})) .OUTPUT(y, TensorType({DT_STRING})) .OP_END_FACTORY_REG(DecodeBase64) + +/** +*@brief StringNormalization performs string operations for basic cleaning . \n + +*@par Inputs: +*@li input: only accepts [C] or [1, C] UTF-8 strings tensor . \n + +*@par Outputs: +*@li output: UTF-8 strings tensor after cleaning . \n + +*@par Attributes: +*@li stopwords : list of strings (default is empty). +*List of stop words. If not set, no word would be removed from input strings +tensor. + +*@li is_case_sensitive : bool (default is false). +*Boolean. Whether the identification of stop words in input strings tensor is +case-sensitive. Default is false. + +*@li case_change_action : string (default is "NONE"). +*string enum that cases output to be lowercased/uppercases/unchanged. Valid +values are "LOWER", "UPPER", "NONE". Default is "NONE". + +*@li local : string (default is "en_US"). +*Environment dependent string that denotes the locale according to which output +strings needs to be upper/lowercased.Default en_US or platform specific equivalent +as decided by the implementation . \n + +*@attention Constraints: +*@li input can be either a 1-D or 2-D tensor, the shape of 2-D tensor must be [1, C]. +*/ +REG_OP(StringNormalizer) + .INPUT(input, TensorType({DT_STRING})) + .OUTPUT(output, TensorType({DT_STRING})) + .ATTR(stopwords, ListString, {}) + .ATTR(is_case_sensitive, Bool, false) + .ATTR(case_change_action, String, "NONE") + .ATTR(local, String, "en_US") + .OP_END_FACTORY_REG(StringNormalizer) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_STRING_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/swap_co_ops.h b/third_party/fwkacllib/inc/ops/swap_co_ops.h index a1bf4f8b..6e8eaac3 100644 --- a/third_party/fwkacllib/inc/ops/swap_co_ops.h +++ b/third_party/fwkacllib/inc/ops/swap_co_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/target_crop_and_resize.h b/third_party/fwkacllib/inc/ops/target_crop_and_resize.h index 9c61f2c9..9bef1d7b 100644 --- a/third_party/fwkacllib/inc/ops/target_crop_and_resize.h +++ b/third_party/fwkacllib/inc/ops/target_crop_and_resize.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/transformation_ops.h b/third_party/fwkacllib/inc/ops/transformation_ops.h index 64e18fc7..4a46e35f 100644 --- a/third_party/fwkacllib/inc/ops/transformation_ops.h +++ b/third_party/fwkacllib/inc/ops/transformation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -130,28 +130,27 @@ REG_OP(Transpose) .OP_END_FACTORY_REG(Transpose) /** -*@brief Doing format_transfer for various data format only -support "NHWC/NCHW" to "NC1HWC0" and "NC1HWC0" to "NHWC/NCHW" -"NCHW" to "FRACTAL_Zn" or "FRACTAL_Zn" to "NCHW". -"HWCN" to "FRACTAL_Zn" or "FRACTAL_Zn" to "HWCN" . \n +*@brief Do format transfer for various data format. +* In general, the framework will insert it atomatically . \n *@par Inputs: -*src: A Tensor dtype of all types . \n +*src: A Tensor. For all branches can be types: float16, float32, int32, int8, bool. +* For branches without padding also can be types: int16, int64, uint8, uint16, uint32, uint64 . \n *@par Attributes: -*@li src_format: A string source data format, can be "NHWC", "NCHW", "FRACTAL_Zn" etc. -*@li dst_format: A string target data format, can be "NC1HWC0", "NCHW", "FRACTAL_Zn" etc. -*@li group: A required int32, default value is 1. \n +*@li src_format: A string source data format, can be "NHWC", "NCHW", "FRACTAL_Z" etc. +*@li dst_format: A string target data format, can be "NC1HWC0", "NCHW", "FRACTAL_Z" etc. +*@li group: A optional int32, default value is 1. \n *@par Outputs: -*dst: A Tensor dtype of all types. +*dst: A Tensor. Has the same type as "src". */ REG_OP(TransData) .INPUT(src, TensorType::BasicType()) .OUTPUT(dst, TensorType::BasicType()) .REQUIRED_ATTR(src_format, String) .REQUIRED_ATTR(dst_format, String) - .ATTR(group, Int, 1) + .ATTR(groups, Int, 1) .OP_END_FACTORY_REG(TransData) /** @@ -174,21 +173,27 @@ REG_OP(Permute) .OP_END_FACTORY_REG(Permute) /** -*@brief Flattens the inputs. Reserves axis 0 and flattens the input tensors -* along axis 1 . \n +*@brief Flattens the inputs tensor into a 2D matrix. If input tensor has shape (d_0, d_1,..., d_n), +* then the output will have shape (d_0 X d_1 ... d_(axis-1), d_axis X d_(axis + 1)...X d_n)\n *@par Inputs: -*One input: -*x: A multi-dimensional Tensor. Must be one of the following types: -* int8, uint8, int16, uint16, int32, uint32, int64,uint64, float16, float32 . \n +* One input: +* x: A multi-dimensional Tensor. Must be one of the following types: +* int8, uint8, int16, uint16, int32, uint32, int64,uint64, float16, float32. *@par Outputs: -*y: A 2D flattened Tensor (Reserves axis 0 and flattens the input tensors -* along axis 1). Must be one of the following data types: int8, uint8, int16, -* uint16, int32, uint32, int64,uint64, float16, float32 . \n +* y: A 2D flattened Tensor with the contents of the input tensor, with input dimensions up to axis flattened +* to the outer dimension of the output and remaining input dimensions flattened into the inner dimension of the output. +* Must be one of the following data types: int8, uint8, int16, uint16, int32, uint32, int64,uint64, float16, float32 . + +*@par Attributes: +* axis: A optional int32, default value is 1. Indicate up to which input dimensions (exclusive) should be flattened +* to the outer dimension of the output. The value for axis must be in the range [-r, r], where r is the rank of +* the input tensor. Negative value means counting dimensions from the back. When axis = 0, the shape of +* the output tensor is (1, (d_0 X d_1 ... d_n), where the shape of the input tensor is (d_0, d_1, ... d_n). *@par Third-party framework compatibility -* Compatible with TensorFlow operator Flatten. +* Compatible with TensorFlow / ONNX operator Flatten. */ REG_OP(Flatten) .INPUT(x, TensorType({DT_INT8, DT_INT16, DT_INT32, DT_INT64, @@ -197,6 +202,7 @@ REG_OP(Flatten) .OUTPUT(y, TensorType({DT_INT8, DT_INT16, DT_INT32, DT_INT64, DT_UINT8, DT_UINT16, DT_UINT32, DT_UINT64, DT_FLOAT, DT_FLOAT16})) + .ATTR(axis, Int, 1) .OP_END_FACTORY_REG(Flatten) /** @@ -357,7 +363,7 @@ REG_OP(DepthToSpace) *@brief Permutes data into spatial data blocks and then prunes them . \n *@par Inputs: -*@li x: A 4D Tensor with format NHWC. +*@li x: A 4D Tensor with format. Must set the format, supported format list ["NCHW, NHWC"] *@li crops: A 1D list or tuple of int32 or int64 . \n *Must be one of the following types: float16, float32 @@ -418,12 +424,8 @@ REG_OP(BatchToSpace) * Warning: THIS FUNCTION IS DEPRECATED. Please use BatchToSpace instead. */ REG_OP(BatchToSpaceD) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT64, DT_INT32, DT_UINT8, - DT_UINT16, DT_UINT32, DT_UINT64, DT_INT8, DT_INT16, DT_COMPLEX64, - DT_COMPLEX128, DT_QINT8, DT_QUINT8, DT_QINT16, DT_QUINT16, DT_QINT32})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT64, DT_INT32, DT_UINT8, - DT_UINT16, DT_UINT32, DT_UINT64, DT_INT8, DT_INT16, DT_COMPLEX64, - DT_COMPLEX128, DT_QINT8, DT_QUINT8, DT_QINT16, DT_QUINT16, DT_QINT32})) + .INPUT(x, TensorType::BasicType()) + .OUTPUT(y, TensorType::BasicType()) .REQUIRED_ATTR(block_size, Int) .REQUIRED_ATTR(crops, ListInt) .OP_END_FACTORY_REG(BatchToSpaceD) @@ -434,9 +436,10 @@ REG_OP(BatchToSpaceD) *@par Inputs: * Two inputs, including: -*@li x: An NHWC Tensor. Must be one of the following types: +*@li x: An 4D Tensor. Must be one of the following types: * float16, float32, double, int64, int32, uint8, uint16, uint32, uint64, int8, * int16, complex64, complex128, qint8, quint8, qint16, quint16, qint32. +* Must set the format, supported format list ["NCHW, NHWC"] *@li paddings: A 2D tensor of type int, specifying the input . \n *@par Attributes: @@ -518,7 +521,8 @@ REG_OP(Unpack) * @par Inputs: * x: A 4D Tensor with shape [batch, in_rows, in_cols, depth], Must be one of the * following types:float32, double, int32, uint8, int16, int8, int64, uint16, -* float16, uint32, uint64 +* float16, uint32, uint64. The inputs must have data_format with one of follows: +* NHWC, NCHW. * @par Attributes: * @li ksizes: A required list or tuple. The size of the sliding window for each @@ -533,7 +537,6 @@ REG_OP(Unpack) * This is equivalent to rate in dilated (a.k.a. Atrous) convolutions. * @li padding: A required string. The type of padding algorithm to use, support "SAME" or "VALID". \n -* @li data_format: A required string. The format of input, only supported NHWC. \n * @par Outputs: * y: A 4D Tensor with shape [batch, out_rows, out_cols, ksize_rows * @@ -554,7 +557,6 @@ REG_OP(ExtractImagePatches) .REQUIRED_ATTR(strides, ListInt) .REQUIRED_ATTR(rates, ListInt) .REQUIRED_ATTR(padding, String) - .ATTR(data_format, String, "NHWC") .OP_END_FACTORY_REG(ExtractImagePatches) /** @@ -563,6 +565,7 @@ REG_OP(ExtractImagePatches) * @par Inputs: * x: A 5D Tensor with shape [batch, in_planes, in_rows, in_cols, depth] . \n +* The inputs must have data_format with one of follows: NDHWC, NCDHW. \n * @par Attributes: * @li ksizes: A required list or tuple. The size of the sliding window for each @@ -571,7 +574,6 @@ REG_OP(ExtractImagePatches) * patches are in "x". Must be: [1, stride_planes, stride_rows, stride_cols, 1]. * @li padding: A required string. The type of padding algorithm to use , * support "SAME" or "VALID" . \n -* @li data_format: An optional string. The format of input, only supported NDHWC. \n * @par Outputs: * Output: A 5D Tensor with shape [batch, out_planes, out_rows, out_cols, ksize_planes * @@ -590,7 +592,6 @@ REG_OP(ExtractVolumePatches) .REQUIRED_ATTR(ksizes, ListInt) .REQUIRED_ATTR(strides, ListInt) .REQUIRED_ATTR(padding, String) - .ATTR(data_format, String, "NDHWC") .OP_END_FACTORY_REG(ExtractVolumePatches) /** @@ -717,6 +718,210 @@ REG_OP(CompressFcOp) .OUTPUT(compress_index, TensorType({DT_INT8})) .REQUIRED_ATTR(compress_parameters, ListInt) .OP_END_FACTORY_REG(CompressFcOp) + +/** +*@brief Performs Col2im for each batch entry. \n + +*@par Inputs: +*@li input_x: The Col Tensor. 5-D, shape: `(n, c1, kernel_h*kernel_w, ho*wo, c0)`. +where ho/wo is do = (output_d + 2*padding_d - dilation_d*(kernel_d - 1) - 1)//stride_d + 1 \n + +*@par Outputs: +*@li output_y: The img Tensor. 5-D, shape: `(n, c1, output_h, output_w, c0)`. \n + +*@par Attributes: +*@li kernel_shape: ListInt, value: `(kernel_h, kernel_w)`, the shape of kernel in convolution. +*@li dilation: ListInt, value: `(dilation_h, dilation_w)`, the dilation in convolution. +*@li padding: ListInt, value: `(padding_h, padding_w)`, the dilation in convolution. +*@li stride: ListInt, value: `(stride_h, stride_w)`, the dilation in convolution. \n + +*@par Third-party framework compatibility +* Compatible with Pytorch col2im/im2col_backward operator. +*/ +REG_OP(Col2im) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(output_size, TensorType({DT_INT32, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .REQUIRED_ATTR(kernel_size, ListInt) + .REQUIRED_ATTR(dilation, ListInt) + .REQUIRED_ATTR(padding, ListInt) + .REQUIRED_ATTR(stride, ListInt) + .OP_END_FACTORY_REG(Col2im) + +/** +* @brief Performs Im2col for each batch entry. \n + +* @par Inputs: +* x: A 4D Tensor with shape [batch, in_rows, in_cols, depth], Must be one of the +* following types:float32, int8, float16. The inputs must have data_format with +* one of follows:NHWC, NCHW. + +* @par Attributes: +* @li ksizes: A required list or tuple. The size of the sliding window for each +* dimension of images. +* @li strides: A optional list or tuple. How far the centers of two consecutive +* patches are in the images. Defaults to "{1}". +* @li dilations: A optional list or tuple. Defaults to "{1}". +* This is the input stride, specifying how far two consecutive patch +* samples are in the input. Equivalent to extracting patches +* with patch_sizes_eff = patch_sizes + (patch_sizes - 1) * +* (dilations - 1), followed by subsampling them spatially by a factor of dilations. +* This is equivalent to rate in dilated (a.k.a. Atrous) convolutions. +* @li padding_mode: A optional String. The type of padding algorithm to use, +* support "SAME", "VALID", "CALCULATED". Among the three modes, only the "CALCULATED" +* means to use the pads below. Defaults to "CALCULATED". +* @li pads: A optional list or tuple. The pad distance. Defaults to "{0}". \n + +* @par Outputs: +* y: A 4D Tensor with shape [batch, out_rows, out_cols, ksize_rows * +* ksize_cols * depth] containing image patches with size ksize_rows x ksize_cols +* x depth vectorized in the "depth" dimension. Note "out_rows" and "out_cols" +* are the dimensions of the output patches . \n + +* @attention Constraints: +* "ksizes", "strides", "dilations" and "pads" are lists of integers . \n + +* @par Third-party framework compatibility +* Compatible with Pytorch Im2col operator. +*/ +REG_OP(Im2col) + .INPUT(x, TensorType::RealNumberType()) + .OUTPUT(y, TensorType::RealNumberType()) + .REQUIRED_ATTR(ksizes, ListInt) + .ATTR(strides, ListInt, {1}) + .ATTR(dilations, ListInt, {1}) + .ATTR(padding_mode, String, "CALCULATED") + .ATTR(pads, ListInt, {0}) + .OP_END_FACTORY_REG(Im2col) + +/** +*@brief Generates a 2D or 3D flow field (sampling grid), given a batch of affine +matrices theta. \n + +*@par Inputs: +*Input theta must be float16 or float, output_size must be int32 type.Inputs +include: +*@li theta: input batch of affine matrices with shape (N,2,3) for 2D or (N,3,4) +for 3D +*@li output_size: the target output image size. (N×C×H×W for 2D or N×C×D×H×W for +3D) Example: torch.Size((32, 3, 24, 24)) . \n + + +*@par Attributes: +*align_corners: if True, consider -1 and 1 to refer to the centers of the corner +pixels rather than the image corners.Refer to grid_sample() for a more complete +description. A grid generated by affine_grid() should be passed to grid_sample() +with the same setting for this option. Default: False \n + +*@par Outputs: +*@li y: A 2-D integer tensor of shape [M] representing the +selected indices from the boxes tensor, where M <= max_output_size. \n + +*@attention Constraints: +*Input theta must be float16 or float, output_size must be int32 type . \n + +*@par Third-party framework compatibility +*Compatible with Pytorch affine_grid operator. +*/ + +REG_OP(AffineGrid) + .INPUT(theta, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(output_size, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(align_corners, Bool, false) + .OP_END_FACTORY_REG(AffineGrid) + +/** +*@brief Make memory of a view be contiguous. \n + +*@par Inputs: +*Four inputs, including: +*@li x: The input tensor. +*@li size: The shape of output tensor. +*@li stride: The stride of output tensor. +*@li storage_offset: The offset in the underlying storage of the output tensor. \n + +*@par Outputs: +*y: A Tensor. Has the same type as "x" . \n + +*@par Third-party framework compatibility +*Compatible with the pytorch operator as_strided. +*/ +REG_OP(AsStrided) + .INPUT(x, TensorType::BasicType()) + .INPUT(size, TensorType::IndexNumberType()) + .INPUT(stride, TensorType::IndexNumberType()) + .INPUT(storage_offset, TensorType::IndexNumberType()) + .OUTPUT(y, TensorType::BasicType()) + .OP_END_FACTORY_REG(AsStrided) + +/** +*@brief This transform extracts n-grams from the input sequence and save them as a +vector. \n + +*@par Inputs: +*@li input: can be either a 1-D or 2-D tensor for n-gram extraction, It is ether string UTF-8 or int32/int64 . \n + +*@par Attributes: +*@li max_gram_length : int (required) +*Maximum n-gram length. If this value is 3, 3-grams will be used to generate the output . +*@li max_skip_count : int (required) +*Maximum number of items (integers/strings) to be skipped when constructing an n-gram from X. +If max_skip_count=1, min_gram_length=2, max_gram_length=3, this operator may generate 2-grams +with skip_count=0 and skip_count=1, and 3-grams with skip_count=0 and skip_count=1. +*@li min_gram_length : int (required) +*Minimum n-gram length. If this value is 2 and max_gram_length is 3, output may contain counts of +2-grams and 3-grams. +*@li mode : string (required) +*The weighting criteria. It can be one of "TF" (term frequency), "IDF" (inverse document frequency), +and "TFIDF" (the combination of TF and IDF). +*@li ngram_counts : list of ints (required) +*The starting indexes of 1-grams, 2-grams, and so on in pool. It is useful when determining the boundary +between two consecutive collections of n-grams. For example, if ngram_counts is [0, 17, 36], +the first index (zero-based) of 1-gram/2-gram/3-gram in pool are 0/17/36. This format is essentially identical +to CSR (or CSC) sparse matrix format, and we choose to use this due to its popularity. +*@li ngram_indexes : list of ints (required) +*list of int64s (type: AttributeProto::INTS). This list is parallel to the specified 'pool_*' attribute. The i-th element +in ngram_indexes indicate the coordinate of the i-th n-gram in the output tensor. +*@li pool_int64s : list of ints +*List of int64 n-grams learned from the training set. Either this or pool_strings attributes must be present but not both. +It's an 1-D tensor starting with the collections of all 1-grams and ending with the collections of n-grams. The i-th element +in pool stores the n-gram that should be mapped to coordinate ngram_indexes[i] in the output vector. +*@li pool_strings : list of strings +*List of strings n-grams learned from the training set. Either this or pool_int64s attributes must be present but not both. +It's an 1-D tensor starting with the collections of all 1-grams and ending with the collections of n-grams. The i-th element +in pool stores the n-gram that should be mapped to coordinate ngram_indexes[i] in the output vector. +*@li weights : list of floats +*list of floats. This attribute stores the weight of each n-gram in pool. The i-th element in weights is the weight of +the i-th n-gram in pool. Its length equals to the size of ngram_indexes. By default, weights is an all-one tensor.This attribute +is used when mode is "IDF" or "TFIDF" to scale the associated word counts. \n + +*@par Outputs: +*@li output: tensor(float) +*For 1-D input, output is the n-gram representation of that input. For 2-D input, the output is also a 2-D tensor +whose i-th row is the n-gram representation of the i-th input row. More specifically, if input shape is [C], the corresponding +output shape would be [max(ngram_indexes) + 1]. If input shape is [N, C], this operator produces a [N, max(ngram_indexes) + 1]-tensor. \n + +*@attention Constraints: +*@li input can be either a 1-D or 2-D tensor, shape is [C] or [N, C]. +*@li max(ngram_indexes) + 1 == len(weights), len(y) == len(weights). +*@li ngram_counts and pool(pool_int64s or pool_strings) must match. +*@li either pool_strings or pool_int64s attributes must be present but not both. +*/ + +REG_OP(TfidVectorizer) + .INPUT(input, TensorType({DT_INT32, DT_INT64, DT_STRING})) + .OUTPUT(output, TensorType({DT_FLOAT})) + .REQUIRED_ATTR(max_gram_length, Int) + .REQUIRED_ATTR(max_skip_count, Int) + .REQUIRED_ATTR(min_gram_length, Int) + .REQUIRED_ATTR(mode, String) + .REQUIRED_ATTR(ngram_counts, ListInt) + .REQUIRED_ATTR(ngram_indexes, ListInt) + .ATTR(pool_int64s, ListInt, {}) + .ATTR(pool_strings, ListString, {}) + .ATTR(weights, ListFloat, {}) + .OP_END_FACTORY_REG(TfidVectorizer) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_TRANSFORMATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/warp_perspective_ops.h b/third_party/fwkacllib/inc/ops/warp_perspective_ops.h index e19cbd7c..8ef69d8b 100644 --- a/third_party/fwkacllib/inc/ops/warp_perspective_ops.h +++ b/third_party/fwkacllib/inc/ops/warp_perspective_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/runtime/event.h b/third_party/fwkacllib/inc/runtime/event.h index 57948c47..01f63705 100644 --- a/third_party/fwkacllib/inc/runtime/event.h +++ b/third_party/fwkacllib/inc/runtime/event.h @@ -41,6 +41,11 @@ typedef enum rtEventWaitStatus { #define RT_EVENT_DDSYNC 0x04U #define RT_EVENT_TIME_LINE 0x08U +#define RT_EVENT_DDSYNC_NS 0x01U +#define RT_EVENT_STREAM_MARK 0x02U +#define RT_EVENT_DDSYNC 0x04U +#define RT_EVENT_TIME_LINE 0x08U + /** * @ingroup dvrt_event * @brief create event instance diff --git a/third_party/fwkacllib/inc/runtime/rt.h b/third_party/fwkacllib/inc/runtime/rt.h index aa394eea..10f884f2 100644 --- a/third_party/fwkacllib/inc/runtime/rt.h +++ b/third_party/fwkacllib/inc/runtime/rt.h @@ -27,6 +27,7 @@ #include "mem.h" #include "rt_model.h" #include "stream.h" +#include "rt_stars.h" #include "rt_ffts.h" #endif // __CCE_RUNTIME_RT_H__ diff --git a/third_party/fwkacllib/inc/runtime/rt_stars.h b/third_party/fwkacllib/inc/runtime/rt_stars.h new file mode 100644 index 00000000..188656b1 --- /dev/null +++ b/third_party/fwkacllib/inc/runtime/rt_stars.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + * Description: + */ + +#ifndef __CCE_RUNTIME_STARS_H +#define __CCE_RUNTIME_STARS_H + +#include "base.h" + +#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +extern "C" { +#endif + +/** + * @ingroup rt_stars + * @brief launch stars task. + * used for send star sqe directly. + * @param [in] taskSqe stars task sqe + * @param [in] sqeLen stars task sqe length + * @param [in] stream associated stream + * @return RT_ERROR_NONE for ok, others failed + */ +RTS_API rtError_t rtStarsTaskLaunch(const void *taskSqe, uint32_t sqeLen, rtStream_t stream); + +/** + * @ingroup rt_stars + * @brief create cdq instance. + * @param [in] batchNum batch number + * @param [in] batchSize batch size + * @param [in] queName cdq name + * @return RT_ERROR_NONE for ok, ACL_ERROR_RT_NO_CDQ_RESOURCE for no cdq resources + */ +RTS_API rtError_t rtCdqCreate(uint32_t batchNum, uint32_t batchSize, const char *queName); + +/** + * @ingroup rt_stars + * @brief destroy cdq instance. + * @param [in] queName cdq name + * @return RT_ERROR_NONE for ok, others failed + */ +RTS_API rtError_t rtCdqDestroy(const char *queName); + +/** + * @ingroup rt_stars + * @brief get free batch in the queue. + * @param [in] queName cdq name + * @param [in] timeout batch size + * @param [out] batchId batch index + * @return RT_ERROR_NONE for ok, ACL_ERROR_RT_WAIT_TIMEOUT for timeout + */ +RTS_API rtError_t rtCdqAllocBatch(const char *queName, int32_t timeout, uint32_t *batchId); + +/** + * @ingroup rt_stars + * @brief launch a write_cdqm task on the stream. + * When the task is executed, the data information will be inserted into the cdqe index position of the queue. + * @param [in] queName cdq name + * @param [in] cdqeIndex cdqe index + * @param [in] data cdqe infomation + * @param [in] dataSize data size + * @param [in] stream launch task on the stream + * @return RT_ERROR_NONE for ok, others failed + */ +RTS_API rtError_t rtCdqEnQueue(const char *queName, uint32_t cdqeIndex, void *data, uint32_t dataSize, + rtStream_t stream); + +/** + * @ingroup rt_stars + * @brief launch a write_cdqm task on the stream. + * When the task is executed, the data information will be inserted into the cdqe index position of the queue. + * @param [in] queName cdq name + * @param [in] cdqeIndex cdqe index + * @param [in] data cdqe infomation + * @param [in] dataSize data size + * @param [in] stream launch task on the stream + * @return RT_ERROR_NONE for ok, others failed + */ +RTS_API rtError_t rtCdqEnQueuePtrMode(const char *queName, uint32_t cdqeIndex, const void *prtAddr, + rtStream_t stream); + +#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +} +#endif +#endif // __CCE_RUNTIME_STARS_H diff --git a/third_party/fwkacllib/inc/tdt/tsd_client.h b/third_party/fwkacllib/inc/tdt/tsd_client.h index 665c8b82..36fc500e 100644 --- a/third_party/fwkacllib/inc/tdt/tsd_client.h +++ b/third_party/fwkacllib/inc/tdt/tsd_client.h @@ -107,88 +107,6 @@ TDT_LIB_EXPORT TDT_StatusT UpdateProfilingMode(const uint32_t logicDeviceId, con */ TDT_LIB_EXPORT TDT_StatusT TsdSetMsprofReporterCallback(MsprofReporterCallback callback); -/** -* @ingroup CreateCmdParameterObj -* @brief creat tsdclient func parameter obj. -* -* @par Function -* creat tsdclient func parameter obj. -* -* @param type [IN] type tdt::TsdCmdType, tsd func type. -* @param cmdParameterObj [IN] type void *, func parameter obj. -* @retval TDT_OK Success -* @retval TDT_INTERFACE_NOT_SUPPORT -* -* @par Dependency -* @li libtsdclient.so: Library to which the interface belongs. -* @li data_common.h: Header file where tdt::TsdCmdType and tdt::InputItem defined. -* @li status.h: Header file where 'TDT_StatusT' defined -*/ -TDT_StatusT CreateCmdParameterObj(tdt::TsdCmdType type, void **cmdParameterObj); - -/** -* @ingroup SetCmdParameterObjAttribute -* @brief set cmdParameterObj input value. -* -* @par Function -* set cmdParameterObj input value. -* -* @param type [IN] type tdt::TsdCmdType, tsd func type. -* @param cmdParameterObj [IN] type void *, func parameter obj. -* @param itemType [IN] type tdt::InputItem, func input type. -* @param valuePtr [IN] type const void *, input value. -* @param valueLength [IN] type int, input value length. -* @retval TDT_OK Success -* @retval TDT_INTERFACE_NOT_SUPPORT -* -* @par Dependency -* @li libtsdclient.so: Library to which the interface belongs. -* @li data_common.h: Header file where tdt::TsdCmdType and tdt::InputItem defined. -* @li status.h: Header file where 'TDT_StatusT' defined -*/ -TDT_StatusT SetCmdParameterObjAttribute(tdt::TsdCmdType type, void *cmdParameterObj, tdt::InputItem itemType, const void *valuePtr, int valueLength); - -/** -* @ingroup GetCmdParameterObjAttribute -* @brief set cmdParameterObj input value. -* -* @par Function -* set cmdParameterObj input value. -* -* @param type [IN] type tdt::TsdCmdType, tsd func type. -* @param cmdParameterObj [IN] type void *, func parameter obj. -* @param itemType [IN] type tdt::InputItem, func input type. -* @param valuePtr [IN] type const void *, input value. -* @param valueLength [IN] type int, input value length. -* @retval TDT_OK Success -* @retval TDT_INTERFACE_NOT_SUPPORT -* -* @par Dependency -* @li libtsdclient.so: Library to which the interface belongs. -* @li data_common.h: Header file where tdt::TsdCmdType and tdt::InputItem defined. -* @li status.h: Header file where 'TDT_StatusT' defined -*/ -TDT_StatusT GetCmdParameterObjAttribute(tdt::TsdCmdType type, void *cmdParameterObj, tdt::InputItem itemType, void *valuePtr, int &valueLength); - -/** -* @ingroup TsdClientCmd -* @brief creat tsdclient func parameter obj. -* -* @par Function -* creat tsdclient func parameter obj. -* -* @param type [IN] type tdt::TsdCmdType, tsd func type. -* @param cmdParameterObj [IN] type void *, func parameter obj. -* @retval TDT_OK Success -* @retval TDT_INTERFACE_NOT_SUPPORT -* -* @par Dependency -* @li libtsdclient.so: Library to which the interface belongs. -* @li data_common.h: Header file where tdt::TsdCmdType and tdt::InputItem defined. -* @li status.h: Header file where 'TDT_StatusT' defined -*/ -TDT_StatusT TsdClientCmd(tdt::TsdCmdType cmd, void *cmdParameterObj); - #ifdef __cplusplus } #endif // __cplusplus diff --git a/third_party/fwkacllib/inc/toolchain/adx_datadump_server.h b/third_party/fwkacllib/inc/toolchain/adx_datadump_server.h index a1c39a51..67adecd9 100644 --- a/third_party/fwkacllib/inc/toolchain/adx_datadump_server.h +++ b/third_party/fwkacllib/inc/toolchain/adx_datadump_server.h @@ -1,12 +1,18 @@ /** -* @file adx_datadump_server.h -* -* Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -*/ + * Copyright 2019-2020 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. + */ #ifndef ADX_DATADUMP_SERVER_H #define ADX_DATADUMP_SERVER_H diff --git a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h index c8715041..07b32149 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h +++ b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h @@ -14,151 +14,99 @@ * limitations under the License. */ -#ifndef MSPROF_ENGINE_PROF_ACL_API_H_ -#define MSPROF_ENGINE_PROF_ACL_API_H_ - -#define MSVP_MAX_DEV_NUM 64 -#define MSVP_PROF_API __attribute__((visibility("default"))) +#ifndef MSPROFILER_API_PROF_ACL_API_H_ +#define MSPROFILER_API_PROF_ACL_API_H_ // DataTypeConfig -#define PROF_ACL_API 0x0001 -#define PROF_TASK_TIME 0x0002 -#define PROF_AICORE_METRICS 0x0004 -#define PROF_AICPU_TRACE 0x0008 -#define PROF_MODEL_EXECUTE 0x0010 -#define PROF_RUNTIME_API 0x0020 -#define PROF_RUNTIME_TRACE 0x0040 -#define PROF_SCHEDULE_TIMELINE 0x0080 -#define PROF_SCHEDULE_TRACE 0x0100 -#define PROF_AIVECTORCORE_METRICS 0x0200 -#define PROF_SUBTASK_TIME 0x0400 - -#define PROF_TRAINING_TRACE 0x0800 -#define PROF_HCCL_TRACE 0x1000 -#define PROF_DATA_PROCESS 0x2000 -#define PROF_TASK_TRACE 0x3842 +#define PROF_ACL_API 0x00000001 +#define PROF_TASK_TIME 0x00000002 +#define PROF_AICORE_METRICS 0x00000004 +#define PROF_AICPU_TRACE 0x00000008 +#define PROF_MODEL_EXECUTE 0x00000010 +#define PROF_RUNTIME_API 0x00000020 +#define PROF_RUNTIME_TRACE 0x00000040 +#define PROF_SCHEDULE_TIMELINE 0x00000080 +#define PROF_SCHEDULE_TRACE 0x00000100 +#define PROF_AIVECTORCORE_METRICS 0x00000200 +#define PROF_SUBTASK_TIME 0x00000400 + +#define PROF_TRAINING_TRACE 0x00000800 +#define PROF_HCCL_TRACE 0x00001000 + +#define PROF_TASK_TRACE 0x00001852 + +// system profilinig switch +#define PROF_CPU 0x00010000 +#define PROF_HARDWARE_MEMORY 0x00020000 +#define PROF_IO 0x00040000 +#define PROF_INTER_CONNECTION 0x00080000 +#define PROF_DVPP 0x00100000 +#define PROF_SYS_AICORE_SAMPLE 0x00200000 +#define PROF_AIVECTORCORE_SAMPLE 0x00400000 #define PROF_MODEL_LOAD 0x8000000000000000 // DataTypeConfig MASK -#define PROF_ACL_API_MASK 0x0001 -#define PROF_TASK_TIME_MASK 0x0002 -#define PROF_AICORE_METRICS_MASK 0x0004 -#define PROF_AICPU_TRACE_MASK 0x0008 -#define PROF_MODEL_EXECUTE_MASK 0x0010 -#define PROF_RUNTIME_API_MASK 0x0020 -#define PROF_RUNTIME_TRACE_MASK 0x0040 -#define PROF_SCHEDULE_TIMELINE_MASK 0x0080 -#define PROF_SCHEDULE_TRACE_MASK 0x0100 -#define PROF_AIVECTORCORE_METRICS_MASK 0x0200 -#define PROF_SUBTASK_TIME_MASK 0x0400 - -#define PROF_TRAINING_TRACE_MASK 0x0800 -#define PROF_HCCL_TRACE_MASK 0x1000 -#define PROF_DATA_PROCESS_MASK 0x2000 +#define PROF_ACL_API_MASK 0x00000001 +#define PROF_TASK_TIME_MASK 0x00000002 +#define PROF_AICORE_METRICS_MASK 0x00000004 +#define PROF_AICPU_TRACE_MASK 0x00000008 +#define PROF_MODEL_EXECUTE_MASK 0x00000010 +#define PROF_RUNTIME_API_MASK 0x00000020 +#define PROF_RUNTIME_TRACE_MASK 0x00000040 +#define PROF_SCHEDULE_TIMELINE_MASK 0x00000080 +#define PROF_SCHEDULE_TRACE_MASK 0x00000100 +#define PROF_AIVECTORCORE_METRICS_MASK 0x00000200 +#define PROF_SUBTASK_TIME_MASK 0x00000400 + +#define PROF_TRAINING_TRACE_MASK 0x00000800 +#define PROF_HCCL_TRACE_MASK 0x00001000 + +// system profilinig mask +#define PROF_CPU_MASK 0x00010000 +#define PROF_HARDWARE_MEMORY_MASK 0x00020000 +#define PROF_IO_MASK 0x00040000 +#define PROF_INTER_CONNECTION_MASK 0x00080000 +#define PROF_DVPP_MASK 0x00100000 +#define PROF_SYS_AICORE_SAMPLE_MASK 0x00200000 +#define PROF_AIVECTORCORE_SAMPLE_MASK 0x00400000 #define PROF_MODEL_LOAD_MASK 0x8000000000000000 -#include -#include - -/** - * @name ProrErrorCode - * @brief error code enum of prof_acl_apis - */ -enum ProfErrorCode { - PROF_ERROR_NONE = 0, // ok - PROF_ERROR_PARAM_INVALID, // param invalid, for example nullptr - PROF_ERROR_REPEAT_INIT, // profiling has already been inited - PROF_ERROR_CONFIG_INVALID, // config invalid, for example invalid json string - PROF_ERROR_DIR_NO_ACCESS, // dir is not accessable - PROF_ERROR_FAILURE, // failed to init or start profiling - PROF_ERROR_NOT_INITED, // profiling has not been inited - PROF_ERROR_DEVICE_INVALID, // device id invalid - PROF_ERROR_UNSUPPORTED, // unsupported data type or ai core metrics - PROF_ERROR_REPEAT_START, // profiilng has already been started - PROF_ERROR_NOT_STARTED, // profiling has not been started -}; - -/** - * @brief transfer profiling config in acl.json to sample config - * @param aclCfg [IN] profiling json string from acl.json as {"switch":"on", "result_path":"/home",...} - * @param sampleCfg [OUT] json string for GE as {"startCfg":[{"deviceID":"all","jobID":"1234",...}]} - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfAclCfgToSampleCfg(const std::string &aclCfg, std::string &sampleCfg); +#ifndef OS_TYPE +#define OS_TYPE 0 +#endif // OS_TYPE -/** - * @name ProfInit - * @brief init profiling - * @param profInitCfg [IN] config of init profiling of json format - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfInit(const std::string &profInitCfg); - -/** - * @name ProfAicoreMetrics - * @brief aicore metrics enum - */ -enum ProfAicoreMetrics { - PROF_AICORE_ARITHMATIC_THROUGHPUT = 0, - PROF_AICORE_PIPELINE = 1, - PROF_AICORE_SYNCHRONIZATION = 2, - PROF_AICORE_MEMORY = 3, - PROF_AICORE_INTERNAL_MEMORY = 4, - PROF_AICORE_STALL = 5, - PROF_AICORE_EVENT = 255 -}; +#if (OS_TYPE != LINUX) +#define MSVP_PROF_API __declspec(dllexport) +#else +#define MSVP_PROF_API __attribute__((visibility("default"))) +#endif -/** - * @name ProfConfig - * @brief struct of ProfStart - */ -struct ProfConfig { - uint32_t devNums; // length of device id list - uint32_t devIdList[MSVP_MAX_DEV_NUM]; // physical device id list - ProfAicoreMetrics aicoreMetrics; // aicore metric - uint64_t dataTypeConfig; // data type to start profiling -}; +#include +namespace Msprofiler { +namespace Api { /** - * @name ProfStartProfiling - * @brief start profiling - * @param profStartCfg [IN] config to start profiling - * @return ProfErrorCode + * @name ProfGetOpExecutionTime + * @brief get op execution time of specific part of data + * @param data [IN] data read from pipe + * @param len [IN] data length + * @param index [IN] index of part(op) + * @return op execution time (us) */ -MSVP_PROF_API int32_t ProfStartProfiling(const ProfConfig *profStartCfg); +MSVP_PROF_API uint64_t ProfGetOpExecutionTime(const void *data, uint32_t len, uint32_t index); +} +} -/** - * @name ProfStopConfig - * @brief struct of ProfStop - */ -struct ProfStopConfig { - uint64_t padding; -}; +#ifdef __cplusplus +extern "C" { +#endif -/** - * @name ProfStopProfiling - * @brief stop profiling - * @param profStopCfg [IN] config to stop profiling - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfStopProfiling(const ProfConfig *profStopCfg); - -/** - * @name ProfFinalize - * @brief finalize profiling task - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfFinalize(); +MSVP_PROF_API uint64_t ProfGetOpExecutionTime(const void *data, uint32_t len, uint32_t index); -/** - * @name ProfGetDataTypeConfig - * @brief get dataTypeConfig started with of one device - * @param deviceId [IN] deviceId to get dataTypeConfig - * @param dataTypeConfig [OUT] result get - * @return ProfErrorCode - */ -MSVP_PROF_API int32_t ProfGetDataTypeConfig(uint32_t deviceId, uint64_t &dataTypeConfig); +#ifdef __cplusplus +} +#endif -#endif // MSPROF_ENGINE_PROF_ACL_API_H_ +#endif // MSPROFILER_API_PROF_ACL_API_H_ diff --git a/third_party/fwkacllib/inc/toolchain/prof_mgr_core.h b/third_party/fwkacllib/inc/toolchain/prof_mgr_core.h index 4f013eef..f8cb1b22 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_mgr_core.h +++ b/third_party/fwkacllib/inc/toolchain/prof_mgr_core.h @@ -16,7 +16,16 @@ #ifndef MSPROF_ENGINE_PROF_MGR_CORE_H_ #define MSPROF_ENGINE_PROF_MGR_CORE_H_ +#ifndef OS_TYPE +#define OS_TYPE 0 +#endif // OS_TYPE + +#if (OS_TYPE != LINUX) +#define MSVP_PROF_API __declspec(dllexport) +#else #define MSVP_PROF_API __attribute__((visibility("default"))) +#endif + #include #include diff --git a/third_party/fwkacllib/inc/toolchain/prof_reporter.h b/third_party/fwkacllib/inc/toolchain/prof_reporter.h index ff91351b..d5ed7569 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_reporter.h +++ b/third_party/fwkacllib/inc/toolchain/prof_reporter.h @@ -41,42 +41,44 @@ namespace Engine { * the Reporter class .used to send data to profiling */ class MSVP_PROF_API Reporter { - public: - virtual ~Reporter() {} +public: + virtual ~Reporter() {} - public: - /** - * @ingroup reporter - * @name : Report - * @brief : API of libmsprof, report data to libmsprof, it's a non-blocking function \n - The data will be firstly appended to cache, if the cache is full, data will be ignored - * @param data [IN] const ReporterData * the data send to libmsporf - * @retval PROFILING_SUCCESS 0 (success) - * @retval PROFILING_FAILED -1 (failed) - * - * @par depend: - * @li libmsprof - * @li prof_reporter.h - * @since c60 - * @see Flush - */ - virtual int Report(const ReporterData *data) = 0; +public: + /** + * @ingroup reporter + * @name : Report + * @brief : API of libmsprof, report data to libmsprof, it's a non-blocking function \n + The data will be firstly appended to cache, if the cache is full, data will be ignored + * @param data [IN] const ReporterData * the data send to libmsporf + * @retval PROFILING_SUCCESS 0 (success) + * @retval PROFILING_FAILED -1 (failed) + * + * @par depend: + * @li libmsprof + * @li prof_reporter.h + * @since c60 + * @see Flush + */ + virtual int Report(const ReporterData *data) = 0; - /** - * @ingroup reporter - * @name : Flush - * @brief : API of libmsprof, notify libmsprof send data over, it's a blocking function \n - The all datas of cache will be write to file or send to host - * @retval PROFILING_SUCCESS 0 (success) - * @retval PROFILING_FAILED -1 (failed) - * - * @par depend: - * @li libmsprof - * @li prof_reporter.h - * @since c60 - * @see ProfMgrStop - */ - virtual int Flush() = 0; + /** + * @ingroup reporter + * @name : Flush + * @brief : API of libmsprof, notify libmsprof send data over, it's a blocking function \n + The all datas of cache will be write to file or send to host + * @retval PROFILING_SUCCESS 0 (success) + * @retval PROFILING_FAILED -1 (failed) + * + * @par depend: + * @li libmsprof + * @li prof_reporter.h + * @since c60 + * @see ProfMgrStop + */ + virtual int Flush() = 0; + + virtual uint32_t GetReportDataMaxLen() = 0; }; } // namespace Engine diff --git a/third_party/prebuild/aarch64/libalog.so b/third_party/prebuild/aarch64/libalog.so index e041ad7e1e1f697da1328537689b7b300ae292dd..65aefa59a84fb99b46d0674ef6870f62e282ec82 100755 GIT binary patch literal 225280 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 hj>&aFGyD0*7NnS?mdCooY-H{Z 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�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%0D~|Ddte6~g1vA84#7D%0asw*-_rj7 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%0DWw{ce&mincQQE8)) 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 literal 888880 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 diff --git a/third_party/prebuild/aarch64/libmmpa.a b/third_party/prebuild/aarch64/libmmpa.a index d7c29e2b85f165c17eca9700d17cb7ec4e4235a5..7d042c4c1e13d2d63065d39ea6fe44d8b5ea2371 100755 GIT binary patch delta 13805 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 delta 14890 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 EAJC3FN&o-= diff --git a/third_party/prebuild/x86_64/libalog.so b/third_party/prebuild/x86_64/libalog.so index 051f85d9b9b5482169ebe578cce911ae560a3541..4c8a45a4fce43e3262fc1fc2aa162588cbbac055 100755 GIT binary patch literal 173984 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 literal 164208 zcmd44dq7oH`ZvB&DYDBU%QCC!Xjs}6EK5y`qiBc1I*R6{3m_Lo5eN?6YKjEP6H#QB zvD*yQbeU=09``fix`}5h) zde-e(&${dlUOORcVy}b*$Gdtv=Q>2un+=n$4?33i(mTgVcSbt<;paf-D3MK!J=y!F z_7IcKiyg-=Ld;`7gyw$cd2_$P!h3P!VFI1yqfP9kqcqcP)pT1mofqdCb&eM&Y4XtL z;etN6FMr+CH9o%V03+zdl;t%U>6qXD>6NU4Q#8Mx>K8iL2zs$8mE-J>n+FkQB20wH zafoXXp2Yp(2)E<@7K9H>a%Zl_)4}mdLY$0nx#IH?p9ua3ghOzjiBNV_N7bD({m~C@2!UWt`A!grZBfb#fdEDQKcs7C` zp$y?K;GRPmjeA}XAie|fG{i?B9EET%!hCRL2-o61{wf5wOUY8)AC1sk<*opqi~F$% zx8nX{#8)CrMc{Q6;zJSNhPVpxLWClODZpPN&PRy9@-^*pjlJia^d<;?J?{JI^FQK# zIYKJ%WQ3n^KM-*qLIJ{k2*n5u;4enVMtB_IesGnDk3x7GVFvI=h4(q z1Y8Q@?-8GgxE=9Y1YUE1|Bd(r#Frp`4Iv%(6A`;suBk z5$X|E@*%DR5mo@7g>Vo;2JlG4zeBhKVLrk#1n>GYZUzB=f%rcNVT8fJzel(n_q7Nw zA@J%8?pB0)+@FJxgK!tZV+a-CPewQoVKDH1h-(nyGZ6Y99FH&@fma2>Nw}Yja2>)*1iG{r5NdFL z1;YQW>!ANb#rywn(M*Jq7EZzarHTs>mmthi%;*n# zedOrejqs6b#`)e%j9^98J9;5L(#MkQmy&5x`W8FWE z`|A+qS)6zKsCR?-PV3&geIGXuA-sw3Cxm|@+=lQf!Yc^8o<+D4;Ux$8o#A6qj7P0tCmZNY)|k=Rcy^NFZHNO1 zM->ta#KITo{qcN=t4)5Q@4(MP$U<1ETqoiX@ac$eLVPYl1mU*`)d)U> zi3ssmBe*(*C#(k}fETLlv4}slp2gozhLQHeOy0%`7gwSR6!bEDvkuT_Ro^+704N{j zq7RqX595%KeC}V3f(a&aQVvr++5z-;ym}oK(#R4w&8?SfwS3PRjfO5UtTjkk_xS&=pu0f@~cNn}z+u=df7ggBnS}g6b z7wtT8kkQl3g%Yk4RAlpk)N{Bqz&}_RjwxP0U@~LA%`_5Rv~ga$AWuG(Mvdz-6FJ{Y zKPs@IImwjY`+8FKG<|KJX}39xr9BUHT3<4}*FHWe&)#}2SNrKu`|;-UFAq26Y*YjB z>|u(wL+bZN*L$k+H-{McTy7q4p*!RnDD8Qm)2Q|J#uC?t`>NL}wYOw05OI0=u0Gi4 zFQ*g51+{XGha=yYo>x>)ItLIgj!#~bd$8M6JiA(No{t?%kU2xbVDPQVf2jJK zS>P ze#YF}KR@rmZ=b7vquOuUxlR*t-O7G!yxkC7Q}H?y4NkuLeuIab$a!{v;gbuDo|8@F ze1d^V`8H0dxK2~~a;7q9JVSGgY<%=H zN$v)Nd7i*)R1f}enAo$Cv44K3`TExx7R@f#Gdd^Upit?vOzbmk!ht+@P@&Eu=M4zoyyGnn^5cAX?{5{l{YgM*ehuSBaORgQ#ZVIeu zpxS50}0wp!~|9W{!Tc1qO0RqJ>>LG!&t`?pmM z?KM+e=V;Ym{iYH0>VBL0^VZ%*5ZxzNvig(gNrs=G{G-bIbsg*RL%jB9hvM?uf1>tR zn;z`&e2>@dYCnEGG~-zkubX>lpH-S~$0^;*v#bX{d6U{<=s~0RW7U6wwnN)nhF@wT zXKoMqPL}l>=65alG?o8{*fac$ZV-oP!@Y`p#2&UALBGmB+{3t@sCsgB-h}zd^}Lo- zHkn{%s{X(AV9%{;Z@Fr3D7IYRYI&-EXK;oZ(EXCH3Rw})9a;XUmLG0Yu2l6W>7IX6 z{t#Ucr+#jTS;}AI`Mvdq@ciVj=ts_XPS#*~;OW1xhxXxg*v~o0d4dOu)^)nJPgL#s z2z}fnyd|i&A8I={r5M3#)Q49;9WNb?22a!W8KL&s6f*Lcn8(g{J**S{pn9rx-WjCw zU!#I}wAb~Zj=PYqXS{wd(|Y-}AJ5g4br4{`q(5bdvy|^UaNqh*SNku2(Fl6};esCQ z+^_58)cK~qUYWnsc4$<8dy?jRe-C;lpkC6yqfP(nvcNe321(wp{qFINJ1UfJS(J~u|9dp5aX54*77$`)_&Cf-K_T9_P7!B+UEiB^P1R>w11<= z7(G?`?1CQ3KV1D@uKK-&D&MMndZE$tweqK^eWt1(@aBsV+MdlcFWOqTH~ii(A#g`EB*xQcHM}CRnH7 z@PpcO>u#gx71h&A?K5=0;niB4rP>bF+74d7=Sjc7FYyHpuFFj_XO;GQ6Pb-|(u|c_b7!k6fYlmag-umv5!oTRC5j;nLT=&M4I{2btj2tvIWcZ`vi| z^6rXvxjNok^_*m;mUE-dn~hN;f4zyEFM9A}PvAM*zm+dXFq+6e4EO@2%i3`_3XjI z0Lt~G=Qj>8@}DVRtL;$!dqcR|&PmemDr80P_t3vA2HP`qhY|MH!_VuuF4v94!>a3e z9bZj44|@CkHqm2csJH#3-;f46#$!k#${ql*nXX|z&H`PSW zZf*bELrnv0Q2t$QpQa{5Jg)p;^*_098v@0Xt3>^S{{e$f)Ar=BW&4zC`<$)vmm(&g zdb=T}DSv7Y_H&$;zgfql*T37<&!-ld3@cPmY7h1nQ2R-K$p}8C@<~!J1y*#R&PN@S zjQ*KguRru)4`b9nBtL7E{Ghs8qH^-?3^x{`E!>%_7%p+F#|L8tgZb(_814 zkiOXcMfv@D@bj(Gzba%!{H#Xo`5;r#)AZSy>TeqlG5lG|&(!veYI}P9@~HZ&MqMv? z>!P=$f3g44{mT`qCq@0Oyj%cxtMZjHeic~JwLS1VwEa`p8Q~$C=5?K?(tl&hzsN++ zr9JfHAGAH2Pd0)RRL@Seb7zwwPC$F{dbNjsoTzpi`ohTlqWP|t{xzKabH2`Z)jEK@ zeBV>PJZ>MC-a|hQRr%C7JuTk4=w_2E_Yb@_E8jNI5H*H&CTlyC$L%W*QhNxgJz$w6 zS4917x;hM=XYtC=aU>sw05=PZ_mrMLjGG^C)_l`-{pPv9qts5C)xgKAo?~=eL_an} zy7Gs6`NMm#=S*!Md65ZOEHmW#7Ujgy z*z4K|wJ?dju8)wA{-H6;HK0+;ky#m)1>=!uYc23zE$n&1TDe! z>Sz3FCtiDItDU#T*?GIPGuAn}PX1c;M7;6n8scIt&`aVU_NuOPz1mwe?!4t1>6g9b zFX+GTc54$od&{p^{nhFxp;oRe^)u1?4bC-@^J))zj?s22*LL&zw?FE~{>r_>D1h6M z>v*;Q`1dk>blz#&Zsfdu$C=t+ZTjM6rTV>jQr`m|{|M8NZ)tmuk^a)mtZ1#;vtQTk zp5J&-^@lQzg6mYz-95DDcRH@yPBnrPG>-?xAEMuP7~%{q=XYApC|@|^`bzaT=s2w| zH^ffm_h|b!KVtNF{nFOM_&Qj}m%q)(e{Le@HqS4`ty|txf7@7LGW7Jw})sbq-sl(NIMg4P| zmeVW$Du}T>$sZd952~K|h{?;xnz;Amt6_NLtMiQh>s9`7ZMQZZ?{k$uu?PPg?SbE{ zeyQmcqkn?xd8mhV=`}ijn{`}x<;>ImDu3H3c*m%7u2w$uuHk1ZpQrOe@>E0Ir1@s= zr|t8cA$BUiOY7VEx*^oOoVnUQx!OK(7jiwQ@~JNye3|m?(!bcR6`Oo(wLDkhIosK< z{vXwp>s;}}3ascf;c;%Z%aAkm8U2}G@9n5u>)WLDy$0i!SG$(KxyTemo5>lZSv zKYI502A<3Ky2A*bt@1Z(JEvX|I^3an_W)~j64KRvs>N&B%{{Vl2~*F8Oq-?z2hlAkbg0rWSoBV?SKd;4bws>60@ z)^_mh>fs*xx3BhBRLgm~D$DOd{uZ@Qzs`?CRQ^tHTt9CJJ!W;z(RTL7t=lgWyTZPE zy^+^yIV;p(rN_;u>?OYu?e=q^`r%Y{B>&W>52;^@ZZ$-q^4VJ7)Lhf=x?FP(P(95% zjG#9zwkw~z+wikh&$&8|nqD--AmxW6_UpYJtZ|M-Ut7D>OBf3fPRjw=t%l6o3HH;VtN`X59(^3hg9{2ld_D<@~pg0j+_ z%5YvqI48%+DJm{4c5*VOPRc1LtSFpQTp2E`m^x{ENm*&()V$dxh3475pXB5(&ZC07 zlH#QhoRyZET~an@T4_mH{``f`)UvXYNmb#(#nVc&KnOm+Fg&56qO4+kSwW#w8LlWK zaI(tgWG|^iQs@{-6_mFWNOGt@JF_wyPYT21%SuZN^TUM&3z1^@nc0QmI6ga^7p|&A z#b%|A@DfcdxC8~2Bxz}xmB=)+v{-eBYGf?swdj#l-JKVuX|XIP7LXV|a!O%d!KAW+ zs**w|&MI73STeDqYyk>dR6NI21$7S<7dVKFTxMxeS*5d}a6x5ZIH!`Wkzc+9HxOVl z6t=2x+>$Kxh?7})5$aQsS8`F+g6wbwWy5794hkVTja#A`3!EJGZ2tV5{JHaUit>s} zShnFT+rCQ0)&W00Tv3uyn2)>Sd=#~KL19L5QIWKrKFuukp60V}bLJF=!w_Rp$K_QP z=SwLr%3FZ)W}*x*go#xpCDSX=yp_eF3l}aZE|%^W2G7q%Lgo|7pXZqc;l)K6c}u7i z9iCUh9HuyxrR5dHrQsqp4D_CvSt&ZuK$T@Bg$o^&q_C7$fF49|dbJ$4WJ2k}g|P;j zS{5iNF>NGTkcIXYI|_wB`m;iL6_thOmz2%UE0OwyF3e|HEQWBx!opJ1>RpK}T}V{S z?kOoObLDT^24bS~5K^oIkg)BD9bNn_gBizp^|pzc7>+p6gV`S}jmea8cnR5oM0U zy~41$q~XrOV6S8mGD|V`F_?|H3M*yIE}j!AE-wt`l@^o~R*3zdF@A1g{(MgrdY26- zJp*oPnHi023p}bUo>RD>JiG*E&ilOlaB&$M=ZxVPr4`|+b1P8OiDea1vGH^BO6L@6 z#k3%J9)>fjoIkxdJU62d_B|KLM@kVeqNEZdXc6Ixs(hNjq{=z4tWoAJP%#Gu38kHp zld~`{rv$?(C!9A&tc;x>v)Y(V#F&LK+k@iLd=#RL#;JXS`goqmEnT2s<4cUiN&y^ zG7RdX#TeFxGi~cYT_uKMS$UXM(FSMF)9s=$=pUKUncdU}iqOT(y0E}>+L;+BqqyWu zB&on)&0mUSX=jk1o>x)251NjvJ1tr=3TIcrhHNcHJ4Z}6eiW4(CYIp{$q*fU;U(Ua z5$LB2FYzQK(ZrIf%DK|vX_SWp41~iKXJ?hoVT>_jCb02&B_*@r2Bjti5TwU~yC^Iv z4i(3`-gcX)vB;rWjU1YXIiPI?!#>9gfh@a-Zf$Feurx6&g^nSqT@2BrwZ_8D$>BUm z|6e=@ZUuvU>iO`4&H~h^EMJ_0@d$Jg?CR{2!oqU73*_g+Af4h;@eN{kF_2eKkh6&1 zBF0oKPy%g-I++~lIxu?SZp4&%%Y2M4amuU0m7J^5CSBs5f9gg$b8_;f3N&ExM-$<` zOd@JGv!7RzJ@^Q6#tj(e3Utt_mNOl3MW+T~XKt5Gnnswh}kQeG(2WBy!; zO3jq&ynH@c#N_oGV{V6XI73Y$t#`j#U;h1g}7(wW!*4tiOGiI_}_jsdkIA73bK-=_ssz)BxljR=1?IpFh(_4B(QiaxIo%$k=J2&_ z4Lq?+(giOrDG*Iv43~%=C94OnC#>SK(_{P;XFMzmeJGt2m&KH_GL}b_O`2a&T#;FH zQCZlS=E6#|OvQkig5Hsyq-M_A9LX55g-#I$Dm+h)aoH6zRT!^4cR^W!Q&Cuog%ax~ zDhiwsI@+tJvxsXZBrY+jJ&KRX4E!0E)5lq+_OH6hqOtC7jL3 zWzqXlK&k8{rTOPqlvR~aExS03MFeH0VU!7nMckaia22L1MCFTklUbf`=4MQ;7cYX7 zcNSF6p}`xL&1LA4{JCX|N@;Te_PBYh4Jz%!1{=R`nTcFNqXmr$8K~?5(@)R=qX-pN zEGVw5TRNvabMAyO$1yODVv>p3gyCp*{k}hG|{aB9&CcRb%(X z)SR3}SX^bt7FTm}Dl8+3nX_g|dyh}gsk$&WjM&y0g$uEm&&-hZez2^PL~(v$W`4MX#t;BA`%m>oHGUcDliq?UKts)x~`nNfI1MNi}ABSesWY%ET$7P2sFw_ z$TO2XN?B5lAt!R!aMPsGvyAe^%P@U*K341)29+9H9R0MU&5~K8M1J!5L~p6<6vgf& z9U9fM$cdHk9hh(Ar&*yI`xcGkic#;`{K0gbs4%0In1~EVEEcV-2%>ylsq%@miCM`? zT63FS2vwE*A?1*PG^G$NS-~H|1!VA6nPpIRV0=koUMWyjWo&JPRm`}&ii%>mt(+Vj zI+T{>U~J^cP6R!`t!7zK0XCmxW#^ewA-XRpD=y{MBW4lvK*$rc#>J=rQgaQ?au_DB zVos$43NflZJ0GJX|Fp_7o$<@CjPVwyo{Kcw2F%VN9Au9&@L0esT{0>bVqqg94qQa2 zgbRoKg~pg2Jk7?O4sS@WLkM9pmu||9Z=w3G1XBvpOjsnSd&EOe#YAj&*fNzKfr^Dn z^1?-B6$@mF@pSV!lgFGr36mEy8edY(3BZh~DOIIxG!t<{f-nfY7Un3R_+PHZ2vbhhyxvD7-Gti&R`%6chl% zeo?kAR)&8})s(`j%EE4`Xbs&6@eQ#A$h%7^=Iw9~=EXi&6Gf+IV{wN?`kWlJ4Glo8 z-WGANU8K)1D5+e+sf&w2?5&+_jBqBAH5Z);7oxf^ft0L?P$(`P=^L>`HLEqQNJ@EX z1jjx%uM%3Q)GVQ71mO^eiF8&rPs~0_mZ6?-28J~TR8&dOUN z&Jfuaz*l<7MF_d5fhKRSV+k#D`qQ^e7-56`$Iy4$Z*KEXXX) z#y-r;PFo49q}AQ zytqh`GYwlUyBy1%Zl#obxf;KyY<$^*@(K(^6*k*#$tc4b6t_A)9?o~*9#gBP(}QL_-B%Go+ht^pIAK}&VC7Iy zf@Q;L!?}p42=g|Lw{!BbqKF}!73QCOGT~W#xFB}NB?q{i98S7R@iK>xb-m0-sd(hQ z)X9;l9b48yoJHs1!R*RP^MVKz)?G-MS5h_y$(-}EGRKY28GhRE(?-PZ&p;VH{><2& zyzonKy#IRPuL~teFpR<7?MeRazDv$4K_8UL zdz#p-lwD=$qowiW67c)?o~G_GC5)6OYhoksaZIzflvk7e;-1E*vT;}L`)18^J~PkF zPv*p0cTdxWz4~@(=UrEOc>20hblrJ5+WC3%3C{k|)AN5`8ZS1b^vd3q&ge_(RwwUi zSK983hwRwMb}^BZqI+(>v^K}ypQv_K8Jdz;wb9h&$&>(C&b_1DK0*k ze=%pe;==^@cJdUP^7M-7^ZvdfUW?1+zum-}_3tQpeA{iFfO+5T@s9pI5x>SBf9~z3 zMN;GV4CT|~_)O(Par|WEbL05w%9qFSmnmNz$In*YKd5{8=PI8b$CoM}isLJl&yC}k zC|@4OU#om|9AB$^V;sL+`KCDjHszb+_?5~>`P4Z6UFFl`_>Ywj#qnP&pBu-2uY7qN->H0c9G`fHvCqah{vhR> z;`n6co8$N+l#j;o$12|%$Dg2lTO5C?@*Q#fS;{-dcW?jE$|uM1=PB=x<1>^`jpHXN zpB~3gS3VTS&r&`&j=w_r@;E+E`RX`+uJVm>e5vwHar~9aH^=c+%17h)#mcwF@mDF| z7RTSGcG3~YU!(F)O853(rhIZ7f4%blI6k6$Y8-#7^67E>O65aw{Qb)3#_^9RUmnLl zu6%VI|D^Jbas1zuZ;IoeQNB5je_r`$9RGsyt#SOT%D2VwZz$gp$G@e#qu*J1^UDXy zd*5Gq{Dptfc_&W(3gy$|_zLAiar_O+=f?4OD_YC&%$c%KPK^tCUZTiS^S9>pKS3%Eq;K-53_i`#h+~PLoNOki%+%q zQ!Rd^#e3hr^KrVxr&;nri}$_}=i`vYpJ~a@u=o)cpKI}FS^Qj!A8qmF7C*+~7hC+f z7GG`g=UM!6i%+-sMvD(v{7Q=-XYoxIKi=XWwfG4Z-)!;TH|2c1+Tt@U`KZNTXz`mZ zKFi`;Eq;>4Z?*V~Exyg-Ll*B^{A7#ou=pt!zuV%oE#5h@%l@ZYe3Hdav-o6-pKkF3 zEPkfN`z?N!#SgW3{%r&AO0{_Jccu7jq{UzE2_sIo_$w?vXz@7~AF}vdi=Scfc^02* z@%a`%*WwE-zTDyqEq<}Z7g>C@#m}|)@ z+5gos5+{Hb|67Ysws`M%)%bXT#b0a5`z^lO;)h!NGK){O_!^5JY4LRypKkHjTYS*s zZ?O1~#YZfDhQ;4#@wpa%lf}=q_**Q#+~RMw_{A2#!s4qf-aE47Nw#our79Txvbi{EYW4_mx*RG0lfV)029|ER?$Tl}9aet^Y4Zt;GLf5PI2TKu0a zKGou%wD^%0@BJ#_5wZ$*C z_!f(=w)p2Pe!0c}!{Qq)eyzo?wD|QF-(>MGSp1_F|Dwe=Tl_|gUv2T5EIw-Sn=O8` z#lK|ntrq{X#c#FvS1i8G;$O9R*WzEZ_zsJI-Qss!e5=Jf1H0`14U12*_$?NnZ1Hbd z`~Zu8$Kw4K|E|RkwfLe>zV1 zpvCK-z!5%V@%kq;gr8yY`X_LN&$ajita8q^_`VijZt?o7$)abm#p|yc3tw&Vhgf=+ zTfF{iwa7PGy#8qc;a6IGKTA)O#e084mI)rUc>PmPqNmy7^-mE9zuMyUPu&Y2wRrv0 zQ^Iey_+zc|v|7A2FCrhb z_%usCWbwl-eul++f2*2`axMN$OMb4!pJnmo7C+MB7hC)&i?6nL{Zsc+{^b^bjwRn{ z@nbB0rNxi6_$G_jKV>BPAGLV?dvV^?Z1L$9zuMvh79X|vaTdSX;>TNjtHtwgV0hP7 zi=SxmZ5DsN#k&@-f8s(^by)m`mi%su&$4*u*e?6O$l{YM{$h(yw)n{wKfvOrSiIlj zvn_t8#ZR^PREwWx@gpt%5{pl__~{lOw0QlKEz&+Ai=S!9&#?Ge7N2YJ`lsAQ&s>Yw zKPe}Cxy4^$=~-;?ITl}S@wpbi+~W05)QJ8@i_f>@S6Y0b#Wz{J{%If4^Qgspe*=XN znk{~=rDwIp&$IZb#m~3+%@$u`@vRoWz~Z-Be5u8^S$vtryB1$=@f{X_rN!^Ic>R+$ z(hkmVy6oTn6YNPAAGY))TYQzp53u-!7Vo!s?{8=_H@wfMU%zQf}0w)ou^e~-mG`kr)ul;J*$PqO&mTYR#`H(C4ui@)FE{TBa# z#RqG?P72m14tZ#h6ReAd6Wwix;U#{}3rQQKIbuILN6fl=kkdKjGW_%%mySDPIVo>% z>%=u=3Nbaew+g<1xEFC$@Hpb$#La?76Zau*57`?;#9#u-35FQv0v~`;)98k1%E|+2(csh6Jj56#~u(v z-Y4d(-1auXTZj)OZWa6zaX;dy;Pu34T-0Ci8sfu=n*={a+@H8n@MFYB5LXL+fcQw_ za=~{K4BJqsNdFV361NH7LYzk2D)=Sh;lxqF>xs`GZWg?T_)Ov^!A}v7AZ`@=81Y%e)q)=& zKAX5)@ZH2CiE{<7ARa{=5_}`^XySCi%ZSe*P8GbAcnq;$a0T&L;$*?|h|eW<1kWZu zkGSJ!>3`yM;x@rkhy%o}f-fK*M;sMAj(9wAv*6Lh8N^M3hZ9dAZWMeH@kHWk!Gnp< zCoUH}kT^)3E4UwVCUHn`U*Zdh(*^e;zK}Ro@K3)3&LZ{;-bp-(I9c#l#1|1ef3`x7ahu>R#FL3z1;0c*g*YmBJ#jX1v*0zvQ;C}dKSex^xKZ$9#Fr3P3x0rj zI&rz+yNPEI=L%jyJd-#i_(tMc#OZ>U5noE2DtIaJWyF5L6~vblCkviOdlkP8R$XaVfDQ_!HtX z;*Qt zTrT)-;>E#hPAr1+?k$5R_y5MERR}rTQUP^p5v0rcn@o$Nf1#0|vBg1;iZnb;Bh3Gpq& z9lNCei5rRA1aBd}mAF;#OT;UPqk`8H-$vXlcn$IG#7%;qBEEyTQSf8LcM?|%et`IQ z#N~qTCSFOLD|iL*UBn^5Hxl1XoGy47@jb+;f|nBCOY9e1L3|%^vfz2dzbAGC&nEr@ zamNqR|HMtiZGxu|-%s2s_yXbwh@*nX5kE-WEO<2WABmd;4<~+zxKZ#)#19i!3m#1T z2ywaKfy9pz=L+se{3qg&;J(C<5vL38Mf^B%s^Fh)2Y!OsFL)>MpNW$Ne?|NkVn^^N z#7`1;d@ub^+)Ugicnk4giCYD~MEn$SRPcJ@zY#YJUPJseag*Sui2qL9DEKkrRm9bT zA0U2)xLokv#H)#O1+O4(Ar1+?k$4Spy5MER&l0B!UP}BNv0rcn@jr-@1 z{0Z^v#2q`O|A||P+XQbReuKDG@Jqy7h@*nn6TeB^EO-s^Tf|L*pCW#nxKZ$9#P1MS z3x0t3UE*@VcN1?V&K10Z_&wr~;2VkGCr%f3`xj;x@rkh(9K76?_5lC&W>~}cp$M$oGZ8=aXWEHa9`rDh|>l4BHl)vD)^@rz+V&l1@9!@PMj?GE8=g6 z9l@Uv?;!5zkp3s`AZ`=9h4@?IR>3b3?<9^2UQhfTakJnx#NQJ)34V(B2jWJ-j}h-8 zt`__N@sGsig6}5YO`I!u1@V7~LxOK4{)sqU@G|0`iBknHCH{rjFSvsESK?&B^N9Bl zJA!8ucM^B(kp3rj5`fzTPa)>3#r9Ug7ZCR%jtU+}+?%*r@Mz*b#7%;S6Z6$!d!yi! zi22H}y;|^KV!kSDFBd$JIEgq{a6e+c8f*^^A4MDzd?WEd;&j2wh>s>t6}*&~uL|4! zf-8vmim*Ld@I2z*5Icfr6Z4f|d&hR^e_}szo8T$LgNR!NUqC#VI4XD?@$tmXf=3gl z5H|@PPRv(=?Tvy@B0hn*TJT_Ez8Y*V7d()7C~>afe#Cqg*d7wxmzb{r+tUU2B0iZo zRq#)Zz^4%V1@9z2l{i`OSH!0gJAywUKApJZYw3UDRN^+lTZq$$TLr&FJe)Wxcs=nM z#La@&5T8lhB={-f5yXvxA0s}CxLWW7#Ag$i3%;9pByq0b6~v>6LxOK49!;DcOJCI3 zIfQx`vppEIor@X+mjtE-rcTSod0=v|;p&t=n=(@RV6Zy{!TLT!hT_X;}_!&+msH zDE}6mX0=a3590nE?Cc|(+$T{bIS6eS5yptiitG#pBJF9>2@$ttE|an)+`Eu)#;o=n zB!&9hjQU#0w{Vy9Jc|sKl~iA7WXg=pa*XmoB-*mb63c>Epyrj%_6@jk|AG}((P_Tp zY9Zms`D(WN5_Vmv;t9d}5z}wM>1_Sjwwn<}cDjDdqIJ>8hN^R(M-w}4D^j~Ze}x~H zV5jQ7f#te;HRkM1i9509p-3e0Gu*jHLgl5A#J8{#-r&BECPUr-2IB}swxUMgVzNeq z&BL5`X=Y?y%X6r;)~fwJ9D&&dbi`2NZNsw}_ciFQi~8zl-eOJeP20#sHu&l|WR1}r z)7@wyTYYsuFad351L_+@eckb5ZoWEtF7)v2PYrU?wzS|c12}8>!>vKR!C(C+$Zl#k z+0tu*n+tAjI$P*8crccS?gkIegA)FOKKShw)y{E>&MQJ=pv^}k^8=ar!!S8hY7R`a z(S6BcRC{2*Etf!nXH>t%5n21Grq`DknWdDOOc}L|nUH~sS?2Mld_1e`am~w}?%CAx zB@6KiP<9z?5i1W4cnfNf4*x-;HE~k-PwsErBjED*h05-hQ(Yd*3Hj$X12t zcS*X>P;92D#ovtBWh!=oCDur>;YRExBUZ>vFS2AxD07IB;j9V6x>Z$8wZtY+j5T&2 z$0DoC!Wz*_?JEX3(}E3&A0rNq+8vC19zF`MD(2k;h*uQ{U*6f)mEiIX^d?;x>HoxZ z4I>^9HN*BGeQ@2L-oZ#maGiTzFkxfxjXmK3P?)9)528YE494rL9y=3yoT}40bXh7rHKy$BKpXQO~aZ$ru&jMm78 z)i5uo?t`kNOI6-I2ObW?^Kh6ntY8`z-l)r+h%huUUels2OOZru%k9LlPm5l zwNHKG@1dTBH9o7RGhyM$DCiSL(GV0g5ZT=lWEtT{psjr-6vgBtW3T9zzCQ7_8wWW* zwytxJlb)mW*O`L^1Wks#8dSq%j#sqSF7j3VETC}ygbYN=UP$bGOpq#b*5sd5zpj-Y7I#_?$ zTE9nabeDe7*_jdfDH!=CQjIIz9$61P z>%L0`z&0DsW_RlwXbd@hjqPa6-@bNc~DgmyzT`yoHyMEa?p`Z03*2n z@374b!Mx7Pb0kRq ztMR=3Dip$9D1E{4C2N=KzD`B~y7gQV2sriyn0|thFR^OTJ_|-ZU3(BpfR4jRJR18# z(;$)e-E|llaQZJ+C39KwCMMEaOdXtm>JtYoH)9HwT93Un>a+oM3q;%rk&jz8do>Cn z$NA6_xb$+)RVae=H`TrMsZs8$;}}EMfBvc~>$L}ha|7M-&({2(#iRPfhi>rlAJG?$ ziDI0CVzhAEj}o99(xS|N8&*LxuV6Q^31Z#kt2-1GL07S**j1jtc^Ub@@c#H2TN&?! z8~T5Y!vj=s9xFIiypGY{!b1||5J3((ff?KGq32bLVHFP*chhIlnUTbu*AH^q|AX#o zw4Q&9$+%{B!lJ3Z+oQf!(MVz|rKX@iVK4Rl*8=Hc>`By3sugYF!H_zVDJa_nl+8^- z0Rl4vv)X@$9Ms>|_g~hP{&eXZ7~IEjmpn=l4NRZN^qaA6!h(+G=AHrrDYE=0SHtL? z!UoJiTaz&UC8A@U=Z5bD-}Q=2!}5O!aHKMqXGYB>0Qm(7l%&O+y65RDj) z%4Bm1z%v7F3O5l|K;C{C4(tbH!ubrDoF&TBRwWzj6OVv4iM8ew3^cT4YWqC1 z7^r0(1Z73G7vLaioB)W&OpA*_Gqu& zc(md5;D>PHVkWz!-7=7-Yrd=bdO)ylOC&4hpbTvB`uJ*ZLdrno*I?wkVC3xyX}h+i z6*c;5`SntL;#`!4E9nx`YV{dxFDW^wqAzeIWAnramdSaWW!1 zGBD#rK6DR&1Lxe9hw(q54$fxDW0+XNr5Gty`*TOoJ3KjaPYElhWH)$A#Fo74SFiZ6Bf=V->mnY;i;Ba63P4dtCg{Cvf=@lny=g z0d8UITM^Zt`VRTSQ`~--s-d_KOk&PQxIH{&LgYVz)di?~ORm=kQ)C{z1;@LXsOrNh zr@&N3to_V!7+1p?Wz%P$jWTXZ{1u9Mp-SoP$D%wF(mLCZL5wxc%2@wRofe3EpB;?+ z49g2yQ(i_&FfAI?#t&jgmPB1{3H&-&Ey21ENT!pNg$jT8`6Ja=dpe4nwhQxQi3-;v+aQ-SABAvx3V)2`kBm?T^rAH~0H(Tq z&^;V2SifS!Tj8c)hXxz^_1~mrni`EWbTnc;bWV${jrWJ26XSP3g|*F?wQZ!%5ALTJ z@=)*`6*Tn!6$kQ2{1^CGjAd;4Tef>$hW>a2X@e+6FgATw%|l^A*1QQFEk?%=*gm(k zGqvvbijjI-)XR6i$v4B~TW8XgcIEr6mG9|HdA++5edevNF&90B3}hy1=Hf825#3z3 zD||TD5X>4icD{Sq%&9135?5bc`vLAZmKz1hZW$F|3*`$&HeqGz?!d^bjaH49l5a{J zd98Yx^UdaCE8b$Dk+{kTtY+m}PDEzNBU!hdml*YZsXh|j_K4_7ukBoXSh{a*XXM*AJ8Qn&zu|mYg(hL& z0Zkhkzmr`;SN(!@o#B%?9DHlfb1!Z~Y1W<-NvwdZI~gW}Q;&H}7uyf)EBzUf4s1UX zI^Nig*5zlMBNEo(p-50&u{U5Wrclm0M-`?T$XZB)#n-YB`E^}HNTFzHlO|A&&+={D*=1skNadbj7i#dn6!TY zhi{oRo01_nHhj*c`m?hlKe|UsnZ5}|))N&2;jrXwxHFvOu1Ut`& zAfpmYWG{O9ml!JVA3*gOQKO?be)x$yAEo9*DJFrF@iW;R!hQ>}JA>SEuX5GBq z0D3!AnJwTx4BLXI@YN218am}*Ll}m}75ExCEh<$1#rev6p4{SKC$NS>?gV)bPgBMk zB?nQrBsZ7+M;LjLW_F1C5eY9-K1nkCCgsKD)@}FIVOI(_IW=WK>|~UOT)&X5d12_K zmv`Bt`!XF}L;n)IVZ>PbH&%`q3_5?e+>eps9)+?=X3t7%pd^2Ery<8}_i-MpH|b9? z=@*#vE%zXyw+MI-qgj%+7ej&iC0N)SSWCboKDHI=;rPcHMW5o;CkpaCr>sac6Q1!7 zOIHJQwGW0G_b?;=v=N^s`Qm`WZF#&)Tyk}1GR-%8kmmW1)LV3oU#>^sqIO|ZqX*H~ zeZ3exV)b=x%3Kg|%TXkU_d3!2opGikP2LA+oy*~(ygGjlgW$Bs0fW+V;BY4GPrsYjXTTP0%*uGuw^{RU)<`rz)Mxz_uDzvxT z2vum?G?VUbtOo*eM%HpI(`XBSfKF<^2i9lSh3)f^(%SE3yB9zUx-J`i2CugNrEu>V za1vwBT8ug5K9mydQO_gOPB#bLdnp!W&&UML*2Vb4_7L?bp!qcPe+bJa)Zs5Ei>xc& zYvDhH?pfur2p1?Rog2egrG~}`yk&fSK#3}$G)-<-;+0R^N&^kqTj+i^S`U< z)0`k5bzAKr`<2M+^bLW?TbLapzhZlG-Pbcv$8J6%2m(IhYFJ~iZhIiI(O1it^mQNj zYO&cxr_`o2BhJFWNXFsJO5CsIkJtbjzC}*tVh^$+JKW!Z!%6WCRfC+&hTkU19P1Wi zNr0wa&TkInO-5Gao97P(aC7jae(bN14(7j!v#yND#~5ZfFmzvRHEDi;*aXfH*GXc` zGHF{(+T%s*k`i|`1|4xxi3yf+e){Z=o!MVn_7#RE)r^T?`-7rBcbi$GK+3?>ma`y=MCee@5?@3Tb4tW^>ssc{hR0#kS{|osKjr=bJ_bcwj8@?) zorgtFV`+l2)geE+w}4kDbVVNW*mkeC4!#ZbX-`0ZyDjLV*m{h%o@#YuM#@ln!^B@I z(TH$!@=`L1lddd$cq6l{>54rV5Ez~Vxt?0}qKi;6h z_1}Zpr$%7c-qs62M(10vsMMqc5aKTxx0Kk@dyJEOQy_T9ezfYv}w=a^u9{|}a6KwZz* zRXDY*{WoG{iKRSjw}N;+Y|7bcRf^Pav{0y z^FEmg|K4_FSNrftH*3^3UoF1~!Ib1a3&qGYtNy~Itoq)=HU?K_MZU%QFVShZgs*CU zeqEM!RU1*FWcNO}S@h-+A4+fTz_Y+~^yg_Cy=shjwl(H@Gtj1<^Lh)WJ7ZQxJyyo3 z#>kAwR?EcUk=bawQ4eXfi%~XrII_x!bRyeR-2GmY24t)F-D28MtOdV?x6~HQ!_2i; z^JPrQ!oD`0ZJ3JUY8$pcgBeN2E1F<6c?jX96#G0Me&dT^!j54Z-J8)kvaaQ#YC_rv z@+&PeKS?>?WI1nq%M=Iu>q3+TUC820!0WEa`(A0FdorFMi30Mx;Sp5FE68b55L0h{ z_27<%K2vYMd&sLsH-d4DFCYHNGjHC`HT7^eXDwnxioyp zn9IY%gOMZke6Mt|9yz0kbLnwh_-uffby6tOgJyEkKfu{wF zPUIVl^H3(lk&T`G?+wfPN#0E0U2N=|jE0Gw)noSW8*YVdw8OQeVYR$_4Slw}+Ho&K zH)DiWHM`3&U7%4f1%YbayH48a2dqs|=N7ts&lP22rsrE*sp+)r$PaRsm*ifF&Z z!5DO^`pfOZMG8`e!nFL-8W2mtvWZg{PBn0}I3|Tz^ z6caecvngF{4)@iafx==n!b(`K8ciFBO4IJdQoH4P%LKoLp>12`tvB9;50ds9h#TZr zJC4rnRrC(>n}N6af2tUSX{+`s&{)9r_(B!+iF={S*Qt^94tnFm-dT8&+ODJZV^jz$ zmwxm4sZ#-5e*H*yEXtIHX?+0S8ux>MY#z~+F3X406tq&3`^-OiGQK@CvdMRIf7Hl5 zL5k_C`#n-%GnIh_CW`5}uOTa$54euRLSe=br^9i^I)29qSJfx(k3~~MsPnp?UfUm4 zyZ(BlLCy7T+gGTs`){lSV5F-y8^4a${BEtZ=4CL{xvfaXQ`iAC*>^GJz+|~5a_>aH z;SDX#^SNk~fV!&z@a5OVSY`1jXn^|=614vTx#D{O)WfPI&uzOZ zc>pW9n~Q`^?i*0Xc^V}+O}1tI_eWj3SF#nA^p<^p#bR>i73~AzGXGZw5ozz)BqHy7 zM)4U&t?bv@2f_QoIYknSuf*%l=jhVkl_9;h7gn;;uiOtGkEse>D;t-wC{?f_E9LOO zYFLA_2HoPUr2#}XVf}l!gZ>u(fO;=q0$$7wo0?L}@dpR$Y&01J>iR$+(8AP385r^D z?p-jVOtdPF4A-wM0q-8U(TF|?u*RhS0_#P0hw$Nr^@)Ek*G9i+11)P81iKo2B_6sp zST>*sV-< z31cbsqq`m0nErU&wSVBXW= z#OPYRNh-^dq*!_;vm}$*|IK>0GRm(FrUUzxVa*zJ*C|K@J>`)_nA_I3XFc;bd{8 z*P_7jQ&HS}jr8&Y@w%^FbYX3jb3r<1nqU?>Ae4o>8R5}9a?AA%%fgOm*zGCRkn|0^ zH>FYHKc+NE{Dkb+eZ!tki3&FJku{&0tzz8=;pDY+QgAD;%Nn!l=(z3RrIi>-zs_>JR^It*`!P`X3!C^_QvszplSY{a@FAm#IId(*NQ5 zADp%e#=iwy6D)0h)3fo*esgd8XX^j9@^wE*<-frcORZh&(f^tL=V;~lhwDQV{I}!Z zr2cQ4U>QEa;rPddXZ1f`9`gM>o#2~Tg14bybb|j^{of(jhNJdxn6>S(`!E0&gNx{W z`aenCz4kn7`(Jy%+V7+Q(PlOiv~TH^nL|KIMb#eBU(1ys{TEzB?7$5kaIyOIKMLsslx;M~J zB#kvtoiEmti4{7#uzk(0ptAq0sp93LfvBp!)PYJN4 z$gkOv?-rdL>3<(YCZv5<^K+j?vul3s4CDJESpJdE^MIpGEL``0fe3c&BUYi1D6$Vl zZux=*<#HP9&W&&sf#;-3Pn&%VP63V`1Lf|8@aLW`Bz^0z(k2f<5j$_2rR2IUCCg&{ z(LNu&W0k-C`jax* z5BVBo zd#PP@8V`T)J3jb*0dwr|10pz)qabb+oq}QoH=#tR^?LVa4D9af3w|GTbb540pEX?b zr~6iIs&Nx)b|?DAub1~d@|}`(J_h;KaOckA{z%kIHZwI}_Li@TdLa$nX9jl0-OkhW zLj-uzy3WPd@MEhb4dXh;cKRG=QQ39>;lEY7Xih_)zGLO?@{ES136Y-zkyr78GBdI( zD}wWFQ~)p5@mWQ9LfV$B$bYgT_&pTt$Nr9O*+&_XcKI~&8~5h5vgwa(2+z)poR;pdJ4_ zKNEDXMRA$Y{!i1I!r7S9Z;xL0^Tit+=bCqXtMJP&?!6Q-hdKc%?K(YMa9fIzBYuU? z^YNcxu<|SMZ4c6d#0ck�a!R=nO|`dgHFMl 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
;!u4`Tw-{HQ;epW!i5iC8SIl2P{|t zaez_^lrsGx1TC2VpEhlWCjFrll4)l0Lnp~NGf7iqA<`P_XK@2!x1X}RQL)xfb`5K{ z_FHj{fZe*HM#YLN>&6wjU1fJ8)>;uW-~F6(pLgE(oteU3yVvzy*Z28eZSFbu`<&;T z^PF>@^PKa(nV?kn`{dA`x2JRH?HEX5%Yl7~%ys<+pae54PCwLc+h%^7$@2`-v0pWI zkOz)XrCuw4Qw^jY`{FzFah1u8N~GdRoWbfkh(bP*lG^9>lU=Bzi=1*D-T37(-AYp} z$>Mn`l^geXf4rv;2UTL0vu0rZ-;^D-eN}hlIWy|v@4pl-*B&Y8aWnohsTf{(Fje#n zx}2SQw|hpNEvbIfKKJ|3Xa8-yJiD9uq@I&HZO{67=be({b6*)}`pZk?w|+gp$YR=; z`+az26P4ez*0zT`aB%f|k@0QH6{YrX>)mT!s(08;@9#uRjcNT`f~Eqt5p8#6`o+9z zVDc5s!FH;Ro&+hOZa5LgamX9YU-AF=wL>*`q=#MhaaNDzIM$2&f(rdELw-KGM0Zho z9aX1|_|>GdbPV;WlPy`Pxd7V+_MH6kt&u$YnsJpL*w)c()i{<9>ML#rwngOe zdu~LsTst_RuY03)-Z^Cp#x_OtzR~*b(VOQE%s6uNm$&L>NVy{$)~7&R^WW8CHN8yz zikI_Wwt%Y~haH@84%<}N6iz=N#zTngTIc@DeJ=$#`roVnzr_ND^sA$$H>&*`#NvT4`v&9c)pfJCw zpVDuJpXq2>?kVT}eXkI{4Xj(fmm{v@Pj{e*_rBg_oTQ(};%HVG$yC6$k939em*@qP_bhw9w+E#Bbux>r}uu@;WkXQXTw1PcO)OxSt z8&x&elXMm0n9z&mzk$4pR8$tqYkz>Duhe^k2!!0Gft1giH{PwFSFddemu`D&$Qhj* z?aYr!9#g*-r5dE)!DO`V>Nh(clKQK`>L^Df9rbbTH9TTQ&a_XNTQOGuhGZoSruqx;p(@em(M{ zW#bh*4?vX`yZv@QF#8-cb`YzrRJ#o1dVC^GiMQCaC_J9LLl;%lhS=rzSS{x>kp_Jiq0cPez3f zvGiJ)HxEreVqfYprqlSjacAVE!QLfEO~AtaYWm9Q)n!;e{$G!Oq_Ow03@_U&1?fzAT%MgFVp4I;B4?q84fj?N_|33@Ny0qlo zTjyBTb@=x7{a{KbF>a1SteY$kgW*#7t6{YXDIlbr@uehcz* zk?%V**<--zN$5M@vclhmKHwCv8yNiFOm-L;0geI3fhXnu_h+&d0o3OQkONk}Fq3@& z7y(WT51juN$N|H^=^sH4aPr5v4@}|@qtC}*WEca6fzv-l`(cO5e}+EbB=8_G__LYp zB(VKoVXq4z4;&NxIe5We%w(;%0$+h1!GD{{whR9IOmmsxVI3G9-3=94W^#!*7dL}y#v`)hgz%X!H zcwpJZ=)d2<-oT09qCbISuc1C~gS~zSI|AE*5nvM74V(b(0ft_O9f08(ls6x87QQ^VJOT{}N4;%u9@D=&{fm6UEg7Z;7{6(cOz8inDApY9Ue&9545*WlE zk~k?m(0V881Dp?R2Zn(Yz;0mZov4T02Oa?q11EuFz>~mA{DG2S2s|(hoWLK{i2z6O zCxG@#8h^X!BybFW$ti^IBde4@Zv~tLCV}B=AP1ZP9s^F}Po|v#w&QQag|5W?>tR1& zrTk$?;3)8<@c7%Bp{u|HD}WJT1lSJj22O-gZ{hJb6Q+REz={P(uYf&(?Z6~33ETsm z0v-W|Zh}0}Du@27(J#OxFnlw{0k9o-5I72)08Rj308Rs^ffoLBeAz^=SfYZP+VDL874;Thc0wchaz+s?uE%XAzKAjscGW$AMG83E&yvG%$EQ($&xhoCZdKRt@w4gTP^61h^kKUW<0gdeH!V zf{myjaIy*W;0CmN74ic|f!)C5YUBf2%_tW*2@EcQzBRBba1uByxEAdfK7w`wgSVrc z8&PlIB4Bs}>;)XZ1LXpPTVQ8kCD00k2Zn&wooELz0*nC1fZf1p;4rXqE9wIr1&#x! zfX9I0yHG#iFz^g;5*S>H{<<6G1Czi?-~@0pFxZCi0Bi^D0geO5fL1%k126)d1P(`0 zpJm9u4dnwzfn&hw4%`Pu;;8>}_9A6WTb)E}5k zp`JIPJ_D!+aCi{;fRjUzFGss}!VbW3;4p9sxF48&ALM|ez$swpkD%vf=mjnU4&RS< z0;e8;USRnBs4s97I1Q|P5ca5meRpI00>d9byMg0-Fivj)ei&)s^j^pVhaW;a-Ua)7 z1o?m=;AUV1I0PI9jsmBFoNbpg#1339H*l{J~ z_hB3WEB^#?z|elw1K19n1cpBjeYZmH6Q~Dp3b+~A{ut~7jQknw0kr-c_P7n@eG>Cl z@YARtFa$gZ3xoCbdcbOiF7fz=`} zAGUy4OJXC_Yk;B< zjcV}UAE;;wR5k`08v~KefpEs1to6uO`+aNN5-1p#j1~D)&hru5UoYi127(`v@*fgA z@0IdL#Ll})TeU{ptegD4+CW8hpt32@*c6CV1vXa&+EEc-O`&oUQ2jc}kv+th-?%?( z0}CFbeZ%<%zb)dZ|&|MWs)&+(d1H-c#1AAsw1x9CW2t-g2E*U?G63oG; z5figK_HV83-=y#Jfgy~BS?iIv4teVW`|*DaI+B|LL+fy7vj`-8Yu&x9^vk?>4*Dma znaRQht9jOi8MXi)Ujly;{O5&N^K*3|7Ov$7O&8 z;P-%s>$j|WncrIiWszr;KrMdO;{HM0Zx?1mAn0sYBrv~0jmElXjy{JGv}^WA$zEU6 zGlBVyN5Ma*oB*;l-K+e*7a)LnXbVEU^w)h--Zy5l0Q*{iPmhAw3_dNa>aW}3G3)(X z@N=#1E|p*Y`0%(Vzu574@CSvr+g+>M9r9rs&aVjs(e4I6l=5?pzbUY2T_C(!&FMzl zHg$eW?6RQLvbwPc{vpRL{a&4Imt4Oz2S!VLF9-IQL;_^bPmT~9gD?<`%6fx3J}>nJUnPb;yPuYE z^ohXGT1>8un05`AcFmwZ8W>s)s!h$erh@an)}Pk-TA1&4j5OmhCrAGj8c!HT ze%}LugMQ2}e{J9h{!jSVg6uCihN}D}YiB{a1=3qoE@c0bhbU<6RV=3Mh%l?s@2j#CrZ`pJR^*>TesM$QlJYX(Uns!u1wUDUe;oX=0{m0p zCp^6L&-37qfd9|-&)m7#)BNPW)<5D0TA}CQKh0zxkwz;&fsXYdHWmL(3yB@>gIs8e z{##^m3I8bg3h-AbM*nCAJOMre{%ZF+R4D$I1q0n*AVAQ=QN`P@LthwYrwe5uwMm@W zBypx1kF^qKs_`iCjPyfz-W|_I&#k5*$*D#Lb{sqn?w}0{dwbo~EVCwyM=~~!Koj>7`K`4j4t5m}ls`hu}F=7wt*R5|s z{P{04*?$uv*RK+MV?k%XvcEDA*$eshlQY@BK1;nzZp5Z?5nPa6g9iV5^O$ZA10OY% zM@g;JIGG*9e8n??3lyV&$T+zS{5W{&dvl2&UjhCI_={y8=KP}Cr~3ZV_JxgN8i_EK zlWaF1wIf~$bgKKY4R((t%SkG@vJ0n*Ahp!_}mJ< z49`xUb@yYg-1ULUvXZ}$j&zo+W>NzAA4UHCc&2g(_HB;%sKJi6bLR{Qg)S+19-0aS z)OCK}BY}gLtP6}^au*Qs;w6Z0RC*iJy1uh7gg-eolRYf$$c@uGFiz`q4=VqISdU}2 z&fgiBkBuN`X>Tp^m*E-C%aUKk1K4kj$a%r8*}koIzts5C_Gj)o_4wP3{6~=g(~{r! zU?7NiQ~cax;3KE;Oig&K%W|qz>tBtZb^g`dILdf=7INK?yO?roaIYDkUj&~7A9VLW zCQr@}L_O02(eBfMMX0(xzeK67=i;}*|NUkr`*uy)d@cA2@F5Ss6?~&GJ1C3BACJ{kP(N2+!cI4yMj#6GW!zTeGcXNt|!roi~zlDR(5JXI_43glmT5&RdPEvokC z;$RgYt_n=ddY>~4cEmjy&cZ7cmd>FiQeV2MY zPx)4n&CO?6bP%16j>Noe@Z&gFe-tT8^3BBria_61AzbJm~*hsy z=vlz==sB;Q<-l=3_r} zPBwdo=tHx2`Q-em$-m*5K-ry=#IfOG+*%2_QONDFZ2f2q!ZUMSx_j|=%2DWD!Tx%xgP@}=4AHc^1Fy32v?Q%C{>GFk!3a<`mwTX_AN4Ais$DMww-^K9|!UkjViQ9nC}}h-GYRU|DbpH zysVC=@!W&$T@wgxHFFQgl_(RJ>VL?OLEiLZ&OQi`c~sYkQzAL4yGz9mdR=-J`O5rw zhNV@hpECbm1aB4KPk}#!a-8x~{@hDoZ}4}}A9}`fS;>W%N6rC_JYxS^ ze?aoL6v&V9A`cB@O|3BxZ0d28<_>DbdTL#t2Pax_K{h)m`jAIXjd9E&DHZpw!2SKW zzfg##Krn)tD0XWGKkneyl8=EuR)D_`{8Rz{QSfKLJNre(=M&(k!Dpr1+ zqV(M0Gy$gMdkOiD;GLUHfqdBX(LXo&vESwAD*sBzUiJ?Bz`HrGFkjxdmeb?E^7IQA z2q||f@{c3`OU&<_Pql$|-=dDRRNvl1Ydy*#QJ`eeWkjJuUU&6lve!M`rvqP94;LAlC z<=(+|T?T#%yx0CKz@I6gry0C;G0VkzE%ldjW8llcEBy!zjGgZT9|o`VV}D}!N5MB5 z9{q0gJOREPys{7U$WBD`KMQ^cym!342tEm3m5b++8!3MZ{Qd&`+$(UN3f}2=ME?Tt zM+)#O!H=5`Dz^gSxt!v^de6NQ@f>*V>7f9Z=#e)) z_JCJ*#JrV$ih*AVejNPzSxCSiJJ0jg`6&XSU8O$k`eo&DtlK!MbTKu4Y}H(hSw>Zy z{W!`wI6s@cS~>>haNk$x+_xc+EcqIul#2Z4i`v18{Z2vOqL1Ny6(16`pB*o=WLZ}) zy9)jF$V~P@cl$i=A;?kly8Oo#I4k^QpmDXl3(;5=sFZRO&=ml*r*J`(6a*ICnwZv}^W#=fN>l(J|bG zhg))P4KeA@Q^>dI9d7?7er7Hz83O+Ue0Ie*VR_CcOC!b?&ns&ovJ&!>kl!WpD4**i zD$DbgRe`V^jXO^(5j0ooGjz$M_XWG5Xa3~{_G4k$#IRhBYbo~-ihFmC= z&F+x#0y#T=5BnHeo+bMH@-JX?64XhVy>%iws%uf{uOvt9af^UkSnY*xt#PD%<) zJT+nvf>{aZo5H)k8}M1TSI6V`(ckUG{m^w;*K;4q_c-_p@O_dG>%lHDCkLX8=Vx($ z5AN5={d;n8#f#u43h<}EpDDo4y$0*i_4#@hfbTBAuLM6DBocAYy?y7!!iW`CsQkHx8D zI^+L~QvQv2=T->sa|)crh-bmUOr1P!;^$g_z5Ur9w+pU?KZYI|i+bGRL4|zACG)

zH#sD5mihS<_)+lByY;AZ z;!KgV;Z1Ug{E%HK?jjMZLf_o$F#lF$vrTUQk(=+i=MM6!iSLUAI|lDyygCaf((CYk z$`)WfMD=-D0{VkDXS2VT`sVyoVf{(puM4W@`Xhbu6!cA0WV5I7S^Mu!_=S2uUd&SG zQ!nEF*e%)YJ#PEpO**`zWSc-cS{W~MuZMqnS2p`|xBTsauzHnKhKO?b*h=$rqdXeo zDWNu{*s&FQ_N>fiuVOo$`#wYp9BNnzo8`q&JQG&?aQjBJAN%e3h=(yY(HJBU8igZ% zX{D9H|3lEf`BuCWEkhl4EU+&Pmqg*+T?YmYeptt~JO@4q{+0su`H)>79S2LfuR}hB--+<}AyxlFw!99AWqvHi#w&u~ov0H1Ie&`& z$Md8IbOwysYS(i&A zfW8&@9gec*Y<8~{fJdFNKxm!v0(f&0=j}UXagcJiLM{op`-}P0T>OOBNK3>mSLE+o zv|o7w`ksKkv31$(DQQRXbLvk7Dq7T`G;}5PWVH8Q4Su|NAa23I;5gmItdawE7gJq; z!Mo>DOjV$^vxvMX>Uut+&x6Ijk0Rfh_1Wx) z@L9$OmS;Q`kTIebePPx4>Qj(wZ^>qN3IRFnH6Ve_C6;sq2g0g(_Y&leKn};f_9f%+ zb?_75u}tuMw#9y6A@lXJrHFTMA7-~N$+rUhN$}f*#d!%r3G5d-Rf$snR@|>>wa-rx zuj1WR#H;e$qKW&8m5{p+a-)!IbkA2gas3B-`nexIb(_^j>hTovk8QyIUh-os$rjP< z8>Id(;{NzXce|y2r@$WpKZ4ILoYn93t8(Ru7-me|@v|47Yy9`H`;@wQ zw$|U_UP#6MTXFE;erGm&tCX`%uRpc;m;t{B{I|XR9`=3D(eH9_Vn2aQ*`ITM=qcz4 z-j&Vn7Cm?)&G#_u(tvY)d0%b4e#cDe@e<^Q?sl&iG7eq`KMZ~lpY=G8a%|FnyP?0kJ)8X;>(PSp zoBY^cqm%j53=5KnLOwu$?u@VS2KPlJHzW25*$-aTqX4n{E66voEjOOs`6hgL z6Z{zZeG*MLhM^1s&N8P*ZH(tZ&x)I1&lsK;N_}|=-wZwp{v1OBQKS_E-wpm3!mDvF zJ_;uc_-O{eXV@#h^%(Mn;@o#g-alM_u)rTI@COV0CoB+pw6O5hN8P-*cDed4&}h;J zncuB6H25UA^&L-qCK6?+=M7c^eSe2~Ec}#DoV!a#3ISzRV@#U(x zNY_V}Cb{;!L!+z@a-FNe!mBvy3adk%96x=#=FRz1B@3EEc~hQ2($?>?*?#$K`e}yg zO6tSuwYqQGJ<6#f)9l~U_vt$q6BiQ8iS@*d#7^QMafG;! zcz}4Ac$9dYc!GGESb87JCoUwG6YGf^iJinj;s|jc@c{8K@hI^)@dWWSvGk8vK5-$j zoLEoXNbDpI5=V&phzE#=iARaYi6@AsiKX|meBwf4IkBF&k=RKbB#sdG5f2a#6OR&) z6HgFN6H6ap`NW09a$-GkBe9b>NE{*VBOV|gCLSdoC!QdlCYBDfeBwf4IkBF&k=RKb zB#sdG5f2a#6OR&)6HgFN6HDK3sq13mLSi|wp16_NNgO1O5cd%e5DycN5|0y45Kj|J zA7uH&g~W1VJ#izklQ>8mA?_m{ARZ8mA?_m{ zARZPKg~W1VJ#izklQ>8mA?_m{ARZ+(_&s4iZO*`-lgKhlxjt z$B8G1r-`K>Wc!H=iRHw4;znX8agaDd+($e>JWM=FJWf18JWVX!!}5s>iRHw4;znX8 zagaDd+($e>JWM=FJWf18JWVWBhh4BgaUrpsSWnzY>?95nM~M4~2Z)D>M~TOYCy1ws zrT>HNCoUwG6YGf^iJinj;s|jc@c{8K@hI^)@dWWSvGl_%pSX}%POK+xBz6)9i6g{) z!~?{`#G}OH#1q8R#L~SipSX}%POK+xBz6)9i6g{)!~?{`#G}OH#1q8R#L|aYK5-$j zoLEoXNbDpI5=V&phzE#=iARaYi6@AsiKQQ5`NW09a$-GkBe9b>NE{*VBWi8`5B`)d zD#KO6|FeLIt<@#`ZI23*yK0#hR{l3J?ZapJe>>Ag-zKJKG37|Ns*t+^hHbunZB6miyz!5!3Hu`dX&{l=i-k>HB&AdZr&_dNI=@ zOy9uthnQZ%^utWw$n<`u!%TmY>7`76mg!|of1YVMmJoYuc z_oV;Alm40~{R2<>B~SWQPkPoD-1VF1NnhhhS9#K{o^+=t{XS26#FK8Qsd-muQN!8| z*M@FhvV2L{au6$)R4lnEv@E>zrf~VP<)KA&1BrNQT}w#uH!Q1=F?zPE1S^a=&vMF@ zV5KqVSZ=<=GUr`xezs-Kh1~o(mN`#y^QCys>tyuj5}bCK^DXDy606KI=X!2_jy1*e zAUA)WHC7<5D6#z3L_vP8WzGrRdd|0w@chut2dw0G+~Y#-msoGXckveDgZ8FSbHe39f$WPa3d5T-&AC#V2)`vG5z!xevLizS$+SS{FiSlnnybrepvArS)(5LQSy5|{AZ|Vu1C+8$p=0Bx2dO+dSsoJ>&N&n z^(phn|A*o)vL@Is!$`|D3-*(CwR-9!-QLv;y@VOZd2l^7}n{9wYylhkug%n1}y5_(J_V30}&Lc%CbKkNl{If0?}Z zImGY4iyh23M^at#og%ZW{Q0#Myp-#G&T*@f&!4AT!56B(eCJys{(VZ%Mb^~KSE_oL zar;5?FOWCmb6*iXpDMy1QhMfDA&#pc8$3}&{(Io1y+IjxxQtop4MfkZ0sFmI3 z>H;NRlItq)h3s%c5&qpp_{JjqrXqYCywt~9rt72LNke^x$+xSQi12G;w9lV{mvORa z&6TR&#{Pdveu0PoTk09E)e6)*jL3O{{B)h>)w_w{{ZJ_S!yY}CkYDWKuO}b!@GHSf zyOMWl{SsHp6(>KrUGwVQ3h>3|*Dj_1E!MDl=|QQme-!GkharzIZOvQP9#?wu*Ow<1 zpTAE14du;zG=&}mFYOxTdMf(?xsDd$f2j22uXq0j{zB-PI#1g{Vp_R=OMd(@omSt` ziH~oAfXGkWsO8l=IwdDedpH{ z_(TysU!eS0N|*Z!%1;BdGA*8Nx#;Q?o(Go5j}TOzVaPf-UM>ni^xAf z`QX!9uhBnBe)4~6{?qKo&wvl2-@Wtti6Z(ZsAr;AEBKsNXB{UWS*Q6b>i<{rm7ePd=;pM_7n_*Rr&? z-7_BkhJ5luU9Oxv$@LAxU#j_UXxjP_`7yT3jN5-vJcS(aJIYtG+&R2gh7VGoARXJo z&mnE+53pS?ksp0j6PwBZ(#U^O6LM}N*Bl%mDtj`}xL&KXE+;?r7ELVC;?{NK z!-zWM`hZX0xQ%@KKk4*g4OTsPJ@QEqwkdfxC#k_A{D-JN@-AJj`rRDJf0}%V>*fZk zJW@o@^F?_1`#FWyqu*11@Nc!^Ur~P$177SFIjD(qXtxFA+n>?A`VLWitWZ2NJ79eg zzLR=FU(>>Y7zZEpnUsQt>;6O zpC(`V8BM6~q{hcNaEyiQd8Ok0)-=Z_+^o88DI&ko$TKe8M)^MS!LMk7?!X!;qUSHc z7m7okrk)AUy7_(bk(Ii=r&;a^^6g`qSWf;mqlfl1^Q9CA?gj0jc)u0q!mhr954x6; zAD+;PIlZj+7@qTSA!>aL_Wkg z*6^PoAN(6FXzc%2K;)}N&z+j*Hp%*~;#rsjUZ(u?Vt0LhQ$*e$;C%eF zR$}%k?<7CNk-zh47Y4}gHu=*Pf_$Ys`t5AJr zz&oCR{^6xs^pp30RxK9 zKNo!;^-pj-tMBwgzDv;XLhbrv%8xD3{WXkznp__zKP?AwxYTzm06%BsBU*l=x{KdG zQ9Kh4_y@`lbKSXu_f8d&pP_uj6GzR#`Y-kmu^(@vo{Py>{*@-m$;)?|7HV$`<&$66 zg2q2=Dsanz6w&iF@Tz~`rTdp*f%P5oA@;lB|FMXkR~3&q zlL3@z?<_bjvCk;|+pVn6<>aUSUK2IsZzMl{JNuCi^j0JPc`az{vr6&I?0_icCoa=^ z26!)BM1F+w?eu$tl>a#S%DC3^3i&UR57Q4UAwL0L>^aQ+LKS)W`*>mp^~YVn89)3l z&Q3AS8_cy<$jNRvQL+5j7&w1zzUeB+tpsI<;pZqgToTQ!aQ#^$n@Ng0Saq5YD zObeTM_^*wAZY&N^*E8hDzOMvW_x`Df zyzgRN?(`b1-#iz1yW$;+`EfDjgYw`H*RM5LHAUn%6yYDBp3u`;f$`g;dB76t+gukYRuV$Vh@|BnC`m66w!o3d`(erW2k6*9l z>!{~R^48yJVxdptSBmI4LHWoDE%&-sXT4fPz7#J^$v7Y81Ty7bNd`ARyBKPUe+@)qN|aq^So z$2{xfPmCVMZ)V^3ALPe5z-y@IHS!Zb)kG!vAQmjKXJo!^D3=o}1U`uMqJq!SC~jR% z`EgF%5#G2}@kT0#t>9(d2{GQgowwrD6JdNlNdCbhdOlx-m*0C+^&iy=K1x0E`)|Te zZ`JMEN&aU=^!$eM)<0`OOj~vJ!m%LK%)8FNMD*uhS12Cwe6uds$lP2+el_KTTwio9 zoRgCu<39af7PW)?B*)c4^6w`f;y5w(e8|Xq#`$N+Pcu$7ar@KcBPX@ub*#{HiqCKF zPbfd(IdAzz5qbIY2V)bbwzpndm|w1V%y;@pbcecbBR}y;oo?4)Z7QN?2j!Ero9W*V zkZ=E(R$$_j$H2?@_db_7Ncl0w31;8%W%5&e@S?sG2r6G7AG%2!@_E|x7m8=49q@Z2 z&$u1aR$cOkztlKy(hA;BJ(nupp@1L5l%Kjm3mQMUhWzw@XhHSe?D%*m`H9=K{LiU> z2l?ToCSE1~2>J2PYCWc39#=do;eanuJ~XAtmwE3f`3X|0v!8m?1e^5JuJxn_PV*ee@*M5IjlDF zlSeeal=ZnEywtya;gyOp@xVSMPay}4Q%{ohG0z{5k)IChdUCp2|44p{^)&ULCLjE% zR{m*I1_rQgMv*L}?9Ntlc@1>rx#ah1^pZ6D$e}wYm zoEN5De@Z_216`*2n>6_NdGe7TYJQt8#`+TZV5=tfvZ_Z7|CAX;@fJVw!p4Q|Yytf&A z$RTGw%6A+~ea6^c^&LpKxrh8X_XRYQ^(pexZ`Tzx{_uCRhez=JI zpHY6?v(A2@i2Ta>W z_A{E;M*b`0$G)x!G+$lc1RvsOC%jDgsa3jMGiQHGev*2w*0-&)tF+yMp7YZAcd1Cv-I$f-A)O z@1Xp!r#|l|Kl-v({GHSyOz-bkkUJL2hdTcW>fNr%qM)XKKxbKs0#O^0YT40~>F8Ej zLGDPQPLWhkUuNw}hiysZ2UE z(AkL&jKx#&E+~zs+A_Uu9f|(Fc-m@fi}llbZLv&$D%}GYzdB+oN4lq1OKXL`|X}l}q$@L=(|O zPc*$`xe|<}2AL&=LDSPK;;~fEAj}+1_QEY;tiS+m{lXw-OMncQTg9@I1%Td#Y#HX$x%Y5DqiZ~tI?4SXaQbrxR1@4}3bpCD zS5JaYx2!R_bYujcTQ#YwLp-<){7qmSIti^$xYj(aGX7;Co2dQuo8GO1(G1>bEdgM!hY9C%U8_SORWHof##jfcg6^({XM~a(44^J$m~}f~V`aIPct$T^s+uCMOeLx6olP+do&v^b zOG{I=$`)7}J*(V=R?*#Cn}H!y_~))sZE8^0U-~DB1v8%MPkJmX{f=UlKSO&ls<$k? z35Cg8R2%QWr=AY1Wbs%u6SdO)9oxNK0}16?ax)uU;p`ddmRj_jl!WHW+NBCYskHOD zM2y2_=}k@P7F9@n42xAyY|ug@AQ?%hdDSa@Dq}!*kf=4~*T!WjsToM6;OC@FZ5*Xc zq6n)u-IeMXbXy3SA&Rw1?AMXpsSUk8o=ji}*Ty@e1Bp!aPAR4pGpDwvvy&!Y6V0ek zsM@+@CYtI>OGUM{YY>oRSbS9rZe|9OR#bI?yL65i-Ib;tdXyj~Cc$VhifR(^Xde`% z;@(C`)uS>-(tSx;wmRiwCIwH>?->x%M`9XLtp>Lm=1>_;BthkBw;VQ>wXsJPClxq-AU zt!#{mCy|>7$US2yRVyKCIuX&ebqqx%R=}XS*W=z$%|zVe3VX$wxLafN>h4<`-yxP# z(~|z!cC%8b)zjCX>FM0rmg;TW5k<(BQ?|ky=u7nUZO<_@R$oW2$7i%{xkaXh_PN^W z!aU1sy5k+&Q6J^TuqcSkrk+gq>WxZLO&_z~+|%FVXJtO$ZmmRGhJeBpo0~vZQ@T14?b|L(qL@KPUQM+k z8dD3DSxs_N%<%A-sPu9*^rERghpn9D*oCU5sivm8docptO|Z*bA0J4^WhVzO4Rg7r z#7G;GSZU&rS0)`q3uKa5_3)kCFJdK9B~kyd2U9sZ%`8-hFi8w;vUlsXT*a+j*;$e zI7($Lu)HCPgB@CWx*|Qvc%zCrQ#}YC;1alAD$i&84do3GsAn+8bq8b3!AfX$f-qP| zCgCnn?W&x%t=_2zn5<$LWKwxc!aD>TXoPZj#>l9wcwA$ZUfE=~!Q;WXy9+^vB2|J% z?$fKS7!4s6bSm?s+=OZ!EVx`sl|uVsUVqruX74d|xScC_`I2Qa+8t|)jF_$h15)`1 z@nPC%h+1-65_?$7eFu%Poo7qEM?yta#nt|NJvL1$)uHEAu6nW(s5Yy(M8>0CRBqZj z3T#U2eu0hZhU7p5ZIfBHu2c4K7%3IXHW7)Gu!wg@)BP#W+(VCYmaj*M6ivsi&h*Yc z&j@sMuI(!gr>3?x(mELpssXF8?6gMH+Yu=2K+NA_$NUg5E<^>Yj6GGO6Y+Rb#nL9g zMoT2L#hk!=6cIf;dA_ln1DKHwmANwm(IBJ2yO~;fX4+?5GAskTC+o!IIU{bWeveq;tQb zCpK<7y_F2AzJ7NNaClRoURVHQ`O#C0igCs8YL7p)w8=O^i9N(Wic{AGbCpG{F(a`z#PZPA z(Y?K`Guq?uyDKbpK!s}dsy&|C$|Tg%?Y4_OMjabiX^@&HQgs|iNJymJBUiDyzCjgQ zFIUk5`bhDZFD+plX&~mpu#p(tajMxPd{{^O@Chq36|16gf7HYBwRkX>YQ zM_z!5Jjk7!ZQ44$o@FA2bKF$_PIr5eRgFaC=Pq9PwoW+=a!aDVDj*TVI0BMRIBB<_ zS)9z0-P4B{vqwjDZb{ClgzQ2*+ftc3$_{9_i5}E;&Tf=a--CW|>x6~keV(1Bbf6lo z+WliXqPa4Oawb!E)X@-V`a9_c^qkuhqaa@R-97DG3;p<=3` zJrV3F>}5d)63%+^7B=*Y@#Jy{QmgyUs*1(1IZ|=E+YqQuOwBTJHl7Ya8`k&qsokX2 zTOb0m%My!3v6%E^cFOqE6;SIW+#Kc=njm`wcLTK`vbv55a`B6-;?iKflQGMntzOfn zeQK(S55V+TzD#wvUX?IB)TGiboEw)xt6o-9=xXh+?ZJ8|+3iV|I}|Y5mAU_$mE3H)-1fi$32db!1=mc5iS#VyL@ONMcF5kR zKhe|SnW%_Yh8Gwg%D? zOt_n^Ods#9#?yix9O;;hQdF)s+!2VZ>N)swIbPMC99i^;LtzY>)EX<&?)AhGs6bYY z?U)>-csAAA;5ZI%s!c1;>D`#adUQRjLq2rra7F=k+v4cRB`# z)Lk4!uKr?-Whh0pR&Ebkon1H)aMxV#Q|;hT6|Co|Yr=8qloGJ;r+Kcd!d}#0717#{ z5K?!aI_Oawd$km~H~x-+tNe@cDAJP>k4U|>n};J#$a*HBGB#2xOpvLHtLntjjx;MC z!)<+>uGb*c0S8*G4X~XIRk2}zXDsS*0?NK(d+`#ES>S$f(E?}BBUt@#K$%}$R#SRy zG&7KjCeXtzc#J94SMAx*2i4o{PJ>0YtJ0HRc`7vp^-MK$L@mLwLScoRxTZb5W)B|a z6A-j_7Kn7EM%=Z)u4+H3ENIEv44);#(~=+3(=AE(NqxQ}p+s$b+W?RAFb(gu9~`La zqjc@X-H^PLFBjI zLI*k|phvT@CSb-~=ShWh=%Tx;Dc022 z(kt(3EWJr)jW`FMZR1sioA5fq>W%s|9E!D>U5C&vho)SmEr;k7P304}wze)j`qv8> zp6sFnHegHNkm?^u%6VU^M?4TbmD{Rfap<#J5Z5W$*8X)F>>or5Di~HOH;-hUoFpsH zYN;t_PNvQ_;ne;{d^UJg}Hg97C_T$73~(N3 z&rYxq>c?4d)LIhn=4&3^F(@%9omIc@p>vqeC?VS0(}6mv?1*8kCGr*sI*RWc{TBeQ zm8L&RGa+f{q<|X z$vuQCBQgAc-+{N{UB4OWVA9QRFr)Ba7kC;6*I2$%UjR)gm66N!Gj8fTYp@<+jm zO-k`!F7v&u2F?4&`mQd^d=`}Vke&I>_q!ULkU|}oc@NoO7w$Rpo9}@&7;@y5kEZ>G zPU3?zzxn+tgRi_~BsH3H4Lj(`Z@yR7;2a}J6k9v5`;d_GP5+tipSAH$r*wY(cYE@i z@2NGo)l&g)`Hy(=oA0wVc<83Hm;V@U2k@W6-2UF%@e6f}%s4SxjQtHB#0`0;*W@?f zk9&;yz4kWw3?4#W8G9zb`5xUDn7^HdHTO+Eqjx*++uzF@()laR#9;mq(ZDnKAi7NX=J$Fk7wY_H78*&7A$QU`hP0F)_V6aZ_!s9T zvT`|*CekhR3b^h-f KL87U*q5lu&?{icD diff --git a/third_party/prebuild/x86_64/liberror_manager.so b/third_party/prebuild/x86_64/liberror_manager.so index cd9ad8bcbde41fabcc1ff2895b3428afcd04ecc7..d97e6ef1d987e5ac05f425392759f23c7a6ccb45 100755 GIT binary patch literal 1168920 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

xa;f#`qcZ6y`IE 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

qngPQM*a*kRx`3 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

uV`%lyUaY9ppW{L0rd|>UFx8LIJ`6N!1 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

2T;+9wVD{D;mxIQ(LYZR5uo5vDZB4Dt| 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�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

*>JS|bHmP4SG5(!fx%_mpsKhg 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≦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ⅇmUZxf@@B({dMX!YR2EFThE;124o0xg9UU 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

KC>mZWF_sowM$DIw+1+Lx;X5D4(tY;UGMedhQ_` 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 H^z;88J0#7R diff --git a/third_party/prebuild/x86_64/libmmpa.a b/third_party/prebuild/x86_64/libmmpa.a index bec195ad066b02a4966ccf47860634e9c7200bcc..13ca68db5f5ff60d6d735e48b9dd82cfc60e4f72 100755 GIT binary patch delta 14566 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%0A@Esh^w|ze|oz1i_ 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 Ook?=X*FxTz&i@bbUq`+G From 0e43f8c1d52e60fba16aad837f90ec3ad08fcffc Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Thu, 29 Jul 2021 09:50:53 +0800 Subject: [PATCH 33/59] update headers --- inc/external/acl/acl.h | 4 +- inc/external/acl/acl_base.h | 2 + inc/external/acl/acl_mdl.h | 16 +- inc/external/acl/acl_op.h | 28 + inc/external/acl/acl_op_compiler.h | 6 +- inc/external/acl/acl_prof.h | 37 + inc/external/acl/acl_rt.h | 18 + inc/external/acl/ops/acl_dvpp.h | 109 ++- inc/external/ge/ge_ir_build.h | 28 +- inc/external/hccl/hccl.h | 27 + inc/framework/executor/ge_executor.h | 138 ++-- inc/framework/ge_runtime/task_info.h | 253 +++++-- third_party/fwkacllib/inc/ops/array_ops.h | 68 +- .../fwkacllib/inc/ops/control_flow_ops.h | 2 +- third_party/fwkacllib/inc/ops/ctc_ops.h | 8 +- third_party/fwkacllib/inc/ops/data_flow_ops.h | 41 +- .../inc/ops/elewise_calculation_ops.h | 166 +++-- .../fwkacllib/inc/ops/functional_ops.h | 3 - third_party/fwkacllib/inc/ops/image_ops.h | 311 +++++++- third_party/fwkacllib/inc/ops/linalg_ops.h | 17 +- third_party/fwkacllib/inc/ops/list_ops.h | 64 +- third_party/fwkacllib/inc/ops/lookup_ops.h | 4 +- third_party/fwkacllib/inc/ops/math_ops.h | 135 ++-- .../inc/ops/matrix_calculation_ops.h | 232 ++++-- .../fwkacllib/inc/ops/nn_calculation_ops.h | 699 +++++++++--------- third_party/fwkacllib/inc/ops/nn_detect_ops.h | 153 ++-- third_party/fwkacllib/inc/ops/nn_norm_ops.h | 175 ++--- third_party/fwkacllib/inc/ops/nn_ops.h | 28 +- .../fwkacllib/inc/ops/nn_pooling_ops.h | 97 ++- .../fwkacllib/inc/ops/nn_training_ops.h | 11 +- .../fwkacllib/inc/ops/nonlinear_fuc_ops.h | 85 ++- third_party/fwkacllib/inc/ops/pad_ops.h | 22 +- third_party/fwkacllib/inc/ops/parsing_ops.h | 135 ++-- third_party/fwkacllib/inc/ops/quantize_ops.h | 10 +- .../fwkacllib/inc/ops/ragged_array_ops.h | 9 +- .../fwkacllib/inc/ops/ragged_conversion_ops.h | 3 +- .../fwkacllib/inc/ops/ragged_math_ops.h | 6 +- third_party/fwkacllib/inc/ops/random_ops.h | 143 +++- third_party/fwkacllib/inc/ops/reduce_ops.h | 107 ++- .../fwkacllib/inc/ops/resource_variable_ops.h | 28 +- third_party/fwkacllib/inc/ops/rnn.h | 18 +- third_party/fwkacllib/inc/ops/rpn_ops.h | 6 +- third_party/fwkacllib/inc/ops/sdca_ops.h | 14 +- third_party/fwkacllib/inc/ops/selection_ops.h | 163 ++-- third_party/fwkacllib/inc/ops/sparse_ops.h | 43 +- third_party/fwkacllib/inc/ops/spectral_ops.h | 20 +- .../fwkacllib/inc/ops/split_combination_ops.h | 9 +- third_party/fwkacllib/inc/ops/state_ops.h | 2 +- .../fwkacllib/inc/ops/stateful_random_ops.h | 31 +- third_party/fwkacllib/inc/ops/string_ops.h | 50 +- .../fwkacllib/inc/ops/transformation_ops.h | 17 +- third_party/fwkacllib/inc/runtime/base.h | 4 +- third_party/fwkacllib/inc/runtime/config.h | 15 +- third_party/fwkacllib/inc/runtime/context.h | 4 +- third_party/fwkacllib/inc/runtime/dev.h | 22 +- .../fwkacllib/inc/runtime/dvfsprofile.h | 4 +- third_party/fwkacllib/inc/runtime/event.h | 14 +- third_party/fwkacllib/inc/runtime/kernel.h | 4 +- third_party/fwkacllib/inc/runtime/mem.h | 4 +- third_party/fwkacllib/inc/runtime/rt_ffts.h | 73 +- third_party/fwkacllib/inc/runtime/rt_model.h | 4 +- third_party/fwkacllib/inc/runtime/rt_stars.h | 8 +- third_party/fwkacllib/inc/runtime/stream.h | 4 +- .../fwkacllib/inc/toolchain/prof_acl_api.h | 32 + .../fwkacllib/inc/toolchain/prof_callback.h | 12 + 65 files changed, 2582 insertions(+), 1423 deletions(-) mode change 100755 => 100644 third_party/fwkacllib/inc/runtime/rt_ffts.h diff --git a/inc/external/acl/acl.h b/inc/external/acl/acl.h index 8d261201..a5194472 100644 --- a/inc/external/acl/acl.h +++ b/inc/external/acl/acl.h @@ -25,9 +25,9 @@ extern "C" { #endif -// Current version is 1.0.0 +// Current version is 1.1.0 #define ACL_MAJOR_VERSION 1 -#define ACL_MINOR_VERSION 0 +#define ACL_MINOR_VERSION 1 #define ACL_PATCH_VERSION 0 /** diff --git a/inc/external/acl/acl_base.h b/inc/external/acl/acl_base.h index 64d4bd81..90da8b8f 100644 --- a/inc/external/acl/acl_base.h +++ b/inc/external/acl/acl_base.h @@ -150,6 +150,8 @@ typedef enum { ACL_DOUBLE = 11, ACL_BOOL = 12, ACL_STRING = 13, + ACL_COMPLEX64 = 16, + ACL_COMPLEX128 = 17 } aclDataType; typedef enum { diff --git a/inc/external/acl/acl_mdl.h b/inc/external/acl/acl_mdl.h index 2bf85e29..522dbd38 100644 --- a/inc/external/acl/acl_mdl.h +++ b/inc/external/acl/acl_mdl.h @@ -295,11 +295,23 @@ ACL_FUNC_VISIBILITY aclError aclmdlAddDatasetBuffer(aclmdlDataset *dataset, aclD ACL_FUNC_VISIBILITY aclError aclmdlSetDatasetTensorDesc(aclmdlDataset *dataset, aclTensorDesc *tensorDesc, size_t index); +/** + * @ingroup AscendCL + * @brief Get aclTensorDesc from aclmdlDataset + * + * @param dataset [IN] aclmdlDataset pointer; + * @param index [IN] index of tensorDesc + * + * @retval Get address of aclTensorDesc when executed successfully. + * @retval Failure return NULL + */ +ACL_FUNC_VISIBILITY aclTensorDesc *aclmdlGetDatasetTensorDesc(const aclmdlDataset *dataset, size_t index); + /** * @ingroup AscendCL * @brief Get the number of aclDataBuffer in aclmdlDataset * - * @param dataset [IN] aclmdlDataset poiter + * @param dataset [IN] aclmdlDataset pointer * * @retval the number of aclDataBuffer */ @@ -309,7 +321,7 @@ ACL_FUNC_VISIBILITY size_t aclmdlGetDatasetNumBuffers(const aclmdlDataset *datas * @ingroup AscendCL * @brief Get the aclDataBuffer in aclmdlDataset by index * - * @param dataset [IN] aclmdlDataset poiter + * @param dataset [IN] aclmdlDataset pointer * @param index [IN] the index of aclDataBuffer * * @retval Get successfully, return the address of aclDataBuffer diff --git a/inc/external/acl/acl_op.h b/inc/external/acl/acl_op.h index d2e59bfb..f340b6bc 100644 --- a/inc/external/acl/acl_op.h +++ b/inc/external/acl/acl_op.h @@ -135,6 +135,34 @@ ACL_FUNC_VISIBILITY aclError aclopSetAttrFloat(aclopAttr *attr, const char *attr */ ACL_FUNC_VISIBILITY aclError aclopSetAttrString(aclopAttr *attr, const char *attrName, const char *attrValue); +/** + * @ingroup AscendCL + * @brief set an attribute. the type of the attribute is aclDataType + * + * @param attr [OUT] pointer to the instance of aclopAttr + * @param attrName [IN] attribute name + * @param attrValue [IN] attribute value + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopSetAttrDataType(aclopAttr *attr, const char *attrName, aclDataType attrValue); + +/** + * @ingroup AscendCL + * @brief set an attribute. the type of the attribute is list of aclDataType + * + * @param attr [OUT] pointer to the instance of aclopAttr + * @param attrName [IN] attribute name + * @param numValues [IN] number of values. false if attrValue is 0, true otherwise. + * @param values [IN] pointer to values + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopSetAttrListDataType(aclopAttr *attr, const char *attrName, int numValues, + const aclDataType values[]); + /** * @ingroup AscendCL * @brief set an attribute. the type of the attribute is list of bools diff --git a/inc/external/acl/acl_op_compiler.h b/inc/external/acl/acl_op_compiler.h index d9d1b3da..b64b2bad 100644 --- a/inc/external/acl/acl_op_compiler.h +++ b/inc/external/acl/acl_op_compiler.h @@ -86,9 +86,9 @@ ACL_FUNC_VISIBILITY aclError aclopCompile(const char *opType, int numInputs, con * @retval OtherValues Failure */ ACL_FUNC_VISIBILITY aclError aclopCompileAndExecute( - const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], const aclDataBuffer *const inputs[], - int numOutputs, const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], const aclopAttr *attr, - aclopEngineType engineType, aclopCompileType compileFlag, const char *opPath, aclrtStream stream); + const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], const aclDataBuffer *const inputs[], + int numOutputs, const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], const aclopAttr *attr, + aclopEngineType engineType, aclopCompileType compileFlag, const char *opPath, aclrtStream stream); /** * @ingroup AscendCL diff --git a/inc/external/acl/acl_prof.h b/inc/external/acl/acl_prof.h index 3784d8c6..a93374b0 100644 --- a/inc/external/acl/acl_prof.h +++ b/inc/external/acl/acl_prof.h @@ -40,13 +40,20 @@ typedef enum { ACL_AICORE_MEMORY_BANDWIDTH = 2, ACL_AICORE_L0B_AND_WIDTH = 3, ACL_AICORE_RESOURCE_CONFLICT_RATIO = 4, + ACL_AICORE_MEMORY_UB = 5, ACL_AICORE_NONE = 0xFF } aclprofAicoreMetrics; +typedef enum { + ACL_STEP_START = 0, // step start + ACL_STEP_END = 1 // step end +} aclprofStepTag; + typedef struct aclprofConfig aclprofConfig; typedef struct aclprofStopConfig aclprofStopConfig; typedef struct aclprofAicoreEvents aclprofAicoreEvents; typedef struct aclprofSubscribeConfig aclprofSubscribeConfig; +typedef struct aclprofStepInfo aclprofStepInfo; /** * @ingroup AscendCL @@ -322,6 +329,36 @@ ACL_FUNC_VISIBILITY uint64_t aclprofGetOpDuration(const void *opInfo, size_t opI */ ACL_FUNC_VISIBILITY size_t aclprofGetModelId(const void *opInfo, size_t opInfoLen, uint32_t index); +/** + * @ingroup AscendCL + * @brief + * + * @param stepInfo [IN] pointer to stepInfo data + * @param aclprofstepTag [IN] start or end flag + * @param stream [IN] steam info + * + * @retval 0 for failed + */ +ACL_FUNC_VISIBILITY aclError aclprofGetStepTimestamp(aclprofStepInfo *stepInfo, aclprofStepTag tag, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief create pointer to aclprofStepInfo data + * + * + * @retval aclprofStepInfo pointer + */ +ACL_FUNC_VISIBILITY aclprofStepInfo *aclprofCreateStepInfo(); + +/** + * @ingroup AscendCL + * @brief destroy aclprofStepInfo pointer + * + * + * @retval void + */ +ACL_FUNC_VISIBILITY void aclprofDestroyStepInfo(aclprofStepInfo *stepinfo); + #ifdef __cplusplus } #endif diff --git a/inc/external/acl/acl_rt.h b/inc/external/acl/acl_rt.h index 5ee70724..50dbc34d 100644 --- a/inc/external/acl/acl_rt.h +++ b/inc/external/acl/acl_rt.h @@ -44,6 +44,12 @@ typedef enum aclrtEventStatus { ACL_EVENT_STATUS_RESERVED = 2, } aclrtEventStatus; +typedef enum aclrtEventWaitStatus { + ACL_EVENT_WAIT_STATUS_COMPLETE = 0, + ACL_EVENT_WAIT_STATUS_NOT_READY = 1, + ACL_EVENT_WAIT_STATUS_RESERVED = 0xffff, +} aclrtEventWaitStatus; + typedef enum aclrtCallbackBlockType { ACL_CALLBACK_NO_BLOCK, ACL_CALLBACK_BLOCK, @@ -499,6 +505,18 @@ ACL_FUNC_VISIBILITY aclError aclrtResetEvent(aclrtEvent event, aclrtStream strea */ ACL_FUNC_VISIBILITY aclError aclrtQueryEvent(aclrtEvent event, aclrtEventStatus *status); +/** + * @ingroup AscendCL + * @brief Queries an event's wait-status + * + * @param event [IN] event to query + * @param status [OUT] event wait-status + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtQueryEventWaitStatus(aclrtEvent event, aclrtEventWaitStatus *status); + /** * @ingroup AscendCL * @brief Block Host Running, wait event to be complete diff --git a/inc/external/acl/ops/acl_dvpp.h b/inc/external/acl/ops/acl_dvpp.h index dcaa3936..5418ebd3 100644 --- a/inc/external/acl/ops/acl_dvpp.h +++ b/inc/external/acl/ops/acl_dvpp.h @@ -158,6 +158,20 @@ enum acldvppJpegFormat { ACL_JPEG_CSS_UNKNOWN = 1000 }; +enum acldvppChannelDescParamType { ACL_DVPP_CSC_MATRIX_UINT32 = 0 }; + +enum aclvdecChannelDescParamType { ACL_VDEC_CSC_MATRIX_UINT32 = 0 }; + +// Csc Matrix can be used both for acldvppChannelDescParamType and aclvdecChannelDescParamType +enum acldvppCscMatrix { + ACL_DVPP_CSC_MATRIX_BT601_WIDE = 0, + ACL_DVPP_CSC_MATRIX_BT601_NARROW, + ACL_DVPP_CSC_MATRIX_BT709_WIDE, + ACL_DVPP_CSC_MATRIX_BT709_NARROW, + ACL_DVPP_CSC_MATRIX_BT2020_WIDE, + ACL_DVPP_CSC_MATRIX_BT2020_NARROW +}; + /** * @ingroup AscendCL * @brief alloc device memory for dvpp. @@ -1910,9 +1924,9 @@ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropAndPasteAsync(acldvppChannelDesc * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizePasteAsync( - acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], acldvppRoiConfig *pasteAreas[], - acldvppResizeConfig *resizeConfig, aclrtStream stream); + acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], acldvppRoiConfig *pasteAreas[], + acldvppResizeConfig *resizeConfig, aclrtStream stream); /** * @ingroup AscendCL @@ -2557,10 +2571,93 @@ ACL_FUNC_VISIBILITY aclError acldvppClearHist(acldvppHist *hist); * @see acldvppCreateChannel | acldvppCreateBatchPicDesc | acldvppCreateRoiConfig | acldvppCreateResizeConfig */ ACL_FUNC_VISIBILITY aclError acldvppVpcBatchCropResizeMakeBorderAsync( - acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, uint32_t size, - acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], acldvppBorderConfig *borderCfgs[], - acldvppResizeConfig *resizeConfig, aclrtStream stream); + acldvppChannelDesc *channelDesc, acldvppBatchPicDesc *srcBatchPicDescs, uint32_t *roiNums, uint32_t size, + acldvppBatchPicDesc *dstBatchPicDescs, acldvppRoiConfig *cropAreas[], acldvppBorderConfig *borderCfgs[], + acldvppResizeConfig *resizeConfig, aclrtStream stream); +/** + * @ingroup AscendCL + * @brief set param for dvpp channel desc + * + * @par Function + * set attribution in dvpp channelDesc for specified type + * + * @param channelDesc [OUT] the channel destruction + * @param paramType [IN] specified param type + * @param length [IN] mem length of param + * @param param [IN] pointer to param + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppGetChannelDescParam | acldvppCreateChannelDesc | acldvppDestroyChannelDesc + */ +ACL_FUNC_VISIBILITY aclError acldvppSetChannelDescParam(acldvppChannelDesc *channelDesc, + acldvppChannelDescParamType paramType, size_t length, + const void *param); + +/** + * @ingroup AscendCL + * @brief get param of dvpp channel desc + * + * @par Function + * get attribution value in dvpp channelDesc for specified type + * + * @param channelDesc [IN] the channel destruction + * @param paramType [IN] specified param type + * @param length [IN] mem length allocated for output param + * @param paramRetSize [OUT] mem length of output param + * @param param [OUT] pointer to output param + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acldvppSetChannelDescParam | acldvppCreateChannelDesc | acldvppDestroyChannelDesc + */ +ACL_FUNC_VISIBILITY aclError acldvppGetChannelDescParam(const acldvppChannelDesc *channelDesc, + acldvppChannelDescParamType paramType, size_t length, + size_t *paramRetSize, void *param); +/** + * @ingroup AscendCL + * @brief set param for vdec channel desc + * + * @par Function + * set attribution in channelDesc for specified type + * + * @param channelDesc [OUT] the vdec channel destruction + * @param paramType [IN] specified param type + * @param length [IN] mem length of param + * @param param [IN] pointer to param + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclvdecGetChannelDescParam | aclvdecCreateChannelDesc | aclvdecDestroyChannelDesc + */ +ACL_FUNC_VISIBILITY aclError aclvdecSetChannelDescParam(aclvdecChannelDesc *channelDesc, + aclvdecChannelDescParamType paramType, size_t length, + const void *param); +/** + * @ingroup AscendCL + * @brief get param of vdec channel desc + * + * @par Function + * get attribution value in channelDesc for specified type + * + * @param channelDesc [IN] the vdec channel destruction + * @param paramType [IN] specified param type + * @param length [IN] mem length allocated for output param + * @param paramRetSize [OUT] mem length of output param + * @param param [OUT] pointer to output param + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclvdecSetChannelDescParam | aclvdecCreateChannelDesc | aclvdecDestroyChannelDesc + */ +ACL_FUNC_VISIBILITY aclError aclvdecGetChannelDescParam(const aclvdecChannelDesc *channelDesc, + aclvdecChannelDescParamType paramType, size_t length, + size_t *paramRetSize, void *param); #ifdef __cplusplus } #endif diff --git a/inc/external/ge/ge_ir_build.h b/inc/external/ge/ge_ir_build.h index 04e059a1..729685a9 100644 --- a/inc/external/ge/ge_ir_build.h +++ b/inc/external/ge/ge_ir_build.h @@ -1,18 +1,18 @@ /** -* Copyright 2020 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. -*/ + * Copyright 2019-2020 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. + */ #ifndef INC_EXTERNAL_GE_IR_BUILD_H_ #define INC_EXTERNAL_GE_IR_BUILD_H_ diff --git a/inc/external/hccl/hccl.h b/inc/external/hccl/hccl.h index 8261adc4..c24b5374 100644 --- a/inc/external/hccl/hccl.h +++ b/inc/external/hccl/hccl.h @@ -144,6 +144,33 @@ extern HcclResult HcclGetRankId(HcclComm comm, uint32_t *rank); */ extern HcclResult HcclBarrier(HcclComm comm, aclrtStream stream); +/** + * @brief AllGather operator. + * + * @param sendBuff A pointer identifying the input data address of the operator. + * @param count An integer(u64) identifying the number of the send data. + * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. + * @param destRank An integer identifying the destination rank. + * @param comm A pointer identifying the communication resource based on. + * @param stream A pointer identifying the stream information. + * @return HcclResult + */ +extern HcclResult HcclSend(void *sendBuf, uint64_t count, HcclDataType dataType, uint32_t destRank, HcclComm comm, + aclrtStream stream); +/** + * @brief AllGather operator. + * + * @param recvBuff A pointer identifying the output data address of the operator. + * @param count An integer(u64) identifying the number of the receive data. + * @param dataType The data type of the operator, must be one of the following types: int8, int32, float16, float32. + * @param srcRank An integer identifying the source rank. + * @param comm A pointer identifying the communication resource based on. + * @param stream A pointer identifying the stream information. + * @return HcclResult + */ +extern HcclResult HcclRecv(void *recvBuf, uint64_t count, HcclDataType dataType, uint32_t srcRank, HcclComm comm, + aclrtStream stream); + /** * @brief Destroy HCCL comm * diff --git a/inc/framework/executor/ge_executor.h b/inc/framework/executor/ge_executor.h index fcca561c..ce7c82ac 100644 --- a/inc/framework/executor/ge_executor.h +++ b/inc/framework/executor/ge_executor.h @@ -50,14 +50,30 @@ class GE_FUNC_VISIBILITY GeExecutor { public: GeExecutor(); ~GeExecutor() = default; - ge::Status Initialize(); - ge::Status Finalize(); - ge::Status UnloadModel(uint32_t modelId); + Status Initialize(); + Status Finalize(); + + /// + /// @ingroup ge + /// @brief Initialize global execute environment. + /// @param [in] options: environment variables. + /// @return init result + /// + static Status Initialize(const std::map &options); + + /// + /// @ingroup ge + /// @brief Finalize global execute environment. + /// @return execute result + /// + static Status FinalizeEx(); + + Status UnloadModel(uint32_t modelId); // Get input and output descriptor - ge::Status GetModelDescInfo(uint32_t model_id, std::vector &input_desc, - std::vector &output_desc, bool new_model_desc = false); + Status GetModelDescInfo(uint32_t model_id, std::vector &input_desc, std::vector &output_desc, + bool new_model_desc = false); /// /// @ingroup ge @@ -68,7 +84,7 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [in] batch_size: batch size entered by user in dynamic multi-batch scenario /// @return execute result /// - ge::Status SetDynamicBatchSize(uint32_t model_id, void *dynamic_input_addr, uint64_t length, uint64_t batch_size); + Status SetDynamicBatchSize(uint32_t model_id, void *dynamic_input_addr, uint64_t length, uint64_t batch_size); /// /// @ingroup ge @@ -80,8 +96,8 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [in] image_width: image width entered by user in dynamic multi-resolution scenario /// @return execute result /// - ge::Status SetDynamicImageSize(uint32_t model_id, void *dynamic_input_addr, uint64_t length, uint64_t image_height, - uint64_t image_width); + Status SetDynamicImageSize(uint32_t model_id, void *dynamic_input_addr, uint64_t length, uint64_t image_height, + uint64_t image_width); /// /// @ingroup ge @@ -93,8 +109,8 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [in] dynamic_dims: array of dynamic dimensions /// @return execute result /// - ge::Status SetDynamicDims(uint32_t model_id, void *dynamic_input_addr, uint64_t length, - const std::vector &dynamic_dims); + Status SetDynamicDims(uint32_t model_id, void *dynamic_input_addr, uint64_t length, + const std::vector &dynamic_dims); /// /// @ingroup ge @@ -104,8 +120,8 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [out] cur_dynamic_dims: current dynamic dims /// @return execute result /// - ge::Status GetCurDynamicDims(uint32_t model_id, const std::vector &dynamic_dims, - std::vector &cur_dynamic_dims); + Status GetCurDynamicDims(uint32_t model_id, const std::vector &dynamic_dims, + std::vector &cur_dynamic_dims); /// /// @ingroup ge @@ -115,8 +131,7 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [out] dynamic_type /// @return execute result /// - ge::Status GetDynamicBatchInfo(uint32_t model_id, std::vector> &batch_info, - int32_t &dynamic_type); + Status GetDynamicBatchInfo(uint32_t model_id, std::vector> &batch_info, int32_t &dynamic_type); /// /// @ingroup ge @@ -125,7 +140,7 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [out] batch_info /// @return execute result /// - ge::Status GetCombinedDynamicDims(uint32_t model_id, std::vector> &batch_info); + Status GetCombinedDynamicDims(uint32_t model_id, std::vector> &batch_info); /// /// @ingroup ge @@ -134,9 +149,9 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [out] user_designate_shape_order /// @return execute result /// - ge::Status GetUserDesignateShapeOrder(uint32_t model_id, std::vector &user_designate_shape_order); + Status GetUserDesignateShapeOrder(uint32_t model_id, std::vector &user_designate_shape_order); - ge::Status GetCurShape(const uint32_t model_id, std::vector &batch_info, int32_t &dynamic_type); + Status GetCurShape(const uint32_t model_id, std::vector &batch_info, int32_t &dynamic_type); /// /// @ingroup ge @@ -148,22 +163,22 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [in] aippParms: kAippDynamicPara by user in dynamic aipp /// @return execute result /// - ge::Status SetDynamicAippData(uint32_t model_id, void *dynamic_input_addr, uint64_t length, - const std::vector &aippBatchPara, - const kAippDynamicPara &aippParms); + Status SetDynamicAippData(uint32_t model_id, void *dynamic_input_addr, uint64_t length, + const std::vector &aipp_batch_para, + const kAippDynamicPara &aippParms); - ge::Status GetAIPPInfo(uint32_t model_id, uint32_t index, AippConfigInfo &aipp_info); + Status GetAIPPInfo(uint32_t model_id, uint32_t index, AippConfigInfo &aipp_info); - ge::Status GetOpAttr(uint32_t model_id, const std::string &op_name, const std::string &attr_name, - std::string &attr_value); + Status GetOpAttr(uint32_t model_id, const std::string &op_name, const std::string &attr_name, + std::string &attr_value); - ge::Status GetModelAttr(uint32_t model_id, std::vector &dynamic_output_shape_info); + Status GetModelAttr(uint32_t model_id, std::vector &dynamic_output_shape_info); - ge::Status GetAippType(uint32_t model_id, uint32_t index, InputAippType &type, size_t &aipp_index); + Status GetAippType(uint32_t model_id, uint32_t index, InputAippType &type, size_t &aipp_index); - ge::Status CommandHandle(const ge::Command &command); + Status CommandHandle(const Command &command); - ge::Status SetDump(const DumpConfig &dump_config); + Status SetDump(const DumpConfig &dump_config); /// /// @ingroup ge @@ -173,7 +188,7 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @return SUCCESS /// @return FAILED /// - ge::Status GetMaxUsedMemory(uint32_t model_id, uint32_t &max_size); + Status GetMaxUsedMemory(uint32_t model_id, uint32_t &max_size); /// /// @ingroup ge @@ -182,7 +197,7 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [out] ModelData &model_data: Offline model memory data /// @return SUCCESS handle successfully / others handle failed /// - ge::Status LoadDataFromFile(const std::string &path, ge::ModelData &model_data); + Status LoadDataFromFile(const std::string &path, ModelData &model_data); /// /// @ingroup ge @@ -195,8 +210,8 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [out] uint32_t &model_id: Corresponding identification after model loading /// @return SUCCESS handle successfully / others handle failed /// - ge::Status LoadModelFromData(uint32_t &model_id, const ge::ModelData &model_data, void *dev_ptr, size_t mem_size, - void *weight_ptr, size_t weight_size); + Status LoadModelFromData(uint32_t &model_id, const ModelData &model_data, void *dev_ptr, size_t mem_size, + void *weight_ptr, size_t weight_size); /// /// @ingroup ge @@ -207,9 +222,8 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [in] output_queue_ids: input queue ids create from user. /// @return: 0 for success / others for fail /// - ge::Status LoadModelWithQ(uint32_t &model_id, const ge::ModelData &model_data, - const std::vector &input_queue_ids, - const std::vector &output_queue_ids); + Status LoadModelWithQ(uint32_t &model_id, const ModelData &model_data, const std::vector &input_queue_ids, + const std::vector &output_queue_ids); /// /// @ingroup ge @@ -221,8 +235,8 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [out] domi::OutputData *output_data: Model output data /// @return SUCCESS handle successfully / others handle failed /// - ge::Status ExecModel(uint32_t model_id, void *stream, const ge::RunModelData &input_data, - ge::RunModelData &output_data, bool async_mode = false); + Status ExecModel(uint32_t model_id, void *stream, const RunModelData &input_data, RunModelData &output_data, + bool async_mode = false); /// /// @ingroup ge @@ -236,9 +250,9 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [out] std::vector &output_desc: description of model output data /// @return SUCCESS handle successfully / others handle failed /// - ge::Status ExecModel(uint32_t model_id, void *stream, const ge::RunModelData &run_input_data, - const std::vector &input_desc, ge::RunModelData &run_output_data, - std::vector &output_desc, bool async_mode = false); + Status ExecModel(uint32_t model_id, void *stream, const RunModelData &run_input_data, + const std::vector &input_desc, RunModelData &run_output_data, + std::vector &output_desc, bool async_mode = false); /// /// @ingroup ge @@ -248,7 +262,7 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [out] size_t &weight_size Weight memory space size /// @return SUCCESS handle successfully / others handle failed /// - ge::Status GetMemAndWeightSize(const std::string &path, size_t &mem_size, size_t &weight_size); + Status GetMemAndWeightSize(const std::string &path, size_t &mem_size, size_t &weight_size); /// /// @ingroup ge @@ -259,39 +273,39 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [out] size_t &weight_size Weight memory space size /// @return SUCCESS handle successfully / others handle failed /// - ge::Status GetMemAndWeightSize(const void *model_data, size_t model_size, size_t &mem_size, size_t &weight_size); + Status GetMemAndWeightSize(const void *model_data, size_t model_size, size_t &mem_size, size_t &weight_size); - static ge::Status LoadSingleOp(const std::string &modelName, const ge::ModelData &modelData, void *stream, - SingleOp **single_op); + static Status LoadSingleOp(const std::string &modelName, const ModelData &modelData, void *stream, + SingleOp **single_op); - static ge::Status LoadSingleOpV2(const std::string &modelName, const ge::ModelData &modelData, void *stream, - SingleOp **single_op, const uint64_t model_id); + static Status LoadSingleOpV2(const std::string &modelName, const ModelData &modelData, void *stream, + SingleOp **single_op, const uint64_t model_id); - static ge::Status ExecuteAsync(SingleOp *executor, const std::vector &inputs, - std::vector &outputs); + static Status ExecuteAsync(SingleOp *executor, const std::vector &inputs, + std::vector &outputs); - static ge::Status LoadDynamicSingleOp(const std::string &model_name, const ge::ModelData &modelData, void *stream, - DynamicSingleOp **single_op); + static Status LoadDynamicSingleOp(const std::string &model_name, const ModelData &modelData, void *stream, + DynamicSingleOp **single_op); - static ge::Status LoadDynamicSingleOpV2(const std::string &model_name, const ge::ModelData &modelData, void *stream, - DynamicSingleOp **single_op, const uint64_t model_id); + static Status LoadDynamicSingleOpV2(const std::string &model_name, const ModelData &modelData, void *stream, + DynamicSingleOp **single_op, const uint64_t model_id); - static ge::Status ExecuteAsync(DynamicSingleOp *executor, const std::vector &input_desc, - const std::vector &inputs, std::vector &output_desc, - std::vector &outputs); + static Status ExecuteAsync(DynamicSingleOp *executor, const std::vector &input_desc, + const std::vector &inputs, std::vector &output_desc, + std::vector &outputs); - static ge::Status ReleaseSingleOpResource(void *stream); + static Status ReleaseSingleOpResource(void *stream); - static ge::Status GetDeviceIdByModelId(uint32_t model_id, uint32_t &device_id); + static Status GetDeviceIdByModelId(uint32_t model_id, uint32_t &device_id); - ge::Status GetBatchInfoSize(uint32_t model_id, size_t &shape_count); - ge::Status GetOrigInputInfo(uint32_t model_id, uint32_t index, OriginInputInfo &orig_input_info); - ge::Status GetAllAippInputOutputDims(uint32_t model_id, uint32_t index, std::vector &input_dims, - std::vector &output_dims); - ge::Status GetOpDescInfo(uint32_t device_id, uint32_t stream_id, uint32_t task_id, OpDescInfo &op_desc_info); + Status GetBatchInfoSize(uint32_t model_id, size_t &shape_count); + Status GetOrigInputInfo(uint32_t model_id, uint32_t index, OriginInputInfo &orig_input_info); + Status GetAllAippInputOutputDims(uint32_t model_id, uint32_t index, std::vector &input_dims, + std::vector &output_dims); + Status GetOpDescInfo(uint32_t device_id, uint32_t stream_id, uint32_t task_id, OpDescInfo &op_desc_info); private: - static bool isInit_; + static std::atomic_bool is_inited_; }; } // namespace ge diff --git a/inc/framework/ge_runtime/task_info.h b/inc/framework/ge_runtime/task_info.h index 4530bff7..abc4783d 100644 --- a/inc/framework/ge_runtime/task_info.h +++ b/inc/framework/ge_runtime/task_info.h @@ -50,10 +50,18 @@ enum TaskInfoType { class TaskInfo { public: virtual ~TaskInfo() {} - uint32_t stream_id() const { return stream_id_; } - TaskInfoType type() const { return type_; } - std::string op_name() const { return op_name_; } - bool dump_flag() const { return dump_flag_; } + uint32_t stream_id() const { + return stream_id_; + } + TaskInfoType type() const { + return type_; + } + std::string op_name() const { + return op_name_; + } + bool dump_flag() const { + return dump_flag_; + } protected: TaskInfo(const std::string &op_name, uint32_t stream_id, TaskInfoType type, bool dump_flag) @@ -84,15 +92,33 @@ class CceTaskInfo : public TaskInfo { is_flowtable_(is_flowtable) {} ~CceTaskInfo() override {} - cce::ccOpContext cc_context() const { return ctx_; } - std::string stub_func() const { return stub_func_; } - uint32_t block_dim() const { return block_dim_; } - const std::vector &args() const { return args_; } - uint32_t args_size() const { return args_size_; } - const std::vector &sm_desc() const { return sm_desc_; } - const std::vector &flow_table() const { return flow_table_; } - const std::vector &args_offset() const { return args_offset_; } - bool is_flowtable() const { return is_flowtable_; } + cce::ccOpContext cc_context() const { + return ctx_; + } + std::string stub_func() const { + return stub_func_; + } + uint32_t block_dim() const { + return block_dim_; + } + const std::vector &args() const { + return args_; + } + uint32_t args_size() const { + return args_size_; + } + const std::vector &sm_desc() const { + return sm_desc_; + } + const std::vector &flow_table() const { + return flow_table_; + } + const std::vector &args_offset() const { + return args_offset_; + } + bool is_flowtable() const { + return is_flowtable_; + } private: cce::ccOpContext ctx_; @@ -126,17 +152,39 @@ class TbeTaskInfo : public TaskInfo { workspace_addrs_(workspace_addrs) {} ~TbeTaskInfo() override {} - const std::string &stub_func() const { return stub_func_; } - uint32_t block_dim() const { return block_dim_; } - const std::vector &args() const { return args_; } - uint32_t args_size() const { return args_size_; } - const std::vector &sm_desc() const { return sm_desc_; } - void *binary() const { return binary_; } - uint32_t binary_size() const { return binary_size_; } - const std::vector &meta_data() const { return meta_data_; } - const std::vector &input_data_addrs() const { return input_data_addrs_; } - const std::vector &output_data_addrs() const { return output_data_addrs_; } - const std::vector &workspace_addrs() const { return workspace_addrs_; } + const std::string &stub_func() const { + return stub_func_; + } + uint32_t block_dim() const { + return block_dim_; + } + const std::vector &args() const { + return args_; + } + uint32_t args_size() const { + return args_size_; + } + const std::vector &sm_desc() const { + return sm_desc_; + } + void *binary() const { + return binary_; + } + uint32_t binary_size() const { + return binary_size_; + } + const std::vector &meta_data() const { + return meta_data_; + } + const std::vector &input_data_addrs() const { + return input_data_addrs_; + } + const std::vector &output_data_addrs() const { + return output_data_addrs_; + } + const std::vector &workspace_addrs() const { + return workspace_addrs_; + } void SetBinary(void *binary, uint32_t binary_size) { binary_ = binary; @@ -171,12 +219,24 @@ class AicpuTaskInfo : public TaskInfo { output_data_addrs_(output_data_addrs) {} ~AicpuTaskInfo() override {} - const std::string &so_name() const { return so_name_; } - const std::string &kernel_name() const { return kernel_name_; } - const std::string &node_def() const { return node_def_; } - const std::vector &input_data_addrs() const { return input_data_addrs_; } - const std::vector &output_data_addrs() const { return output_data_addrs_; } - const std::string &ext_info() const { return ext_info_; } + const std::string &so_name() const { + return so_name_; + } + const std::string &kernel_name() const { + return kernel_name_; + } + const std::string &node_def() const { + return node_def_; + } + const std::vector &input_data_addrs() const { + return input_data_addrs_; + } + const std::vector &output_data_addrs() const { + return output_data_addrs_; + } + const std::string &ext_info() const { + return ext_info_; + } private: std::string so_name_; @@ -192,7 +252,9 @@ class LabelSetTaskInfo : public TaskInfo { LabelSetTaskInfo(const std::string &op_name, uint32_t stream_id, uint32_t label_id) : TaskInfo(op_name, stream_id, TaskInfoType::LABEL_SET, false), label_id_(label_id) {} ~LabelSetTaskInfo() override {} - uint32_t label_id() const { return label_id_; } + uint32_t label_id() const { + return label_id_; + } private: uint32_t label_id_; @@ -203,7 +265,9 @@ class LabelGotoTaskInfo : public TaskInfo { LabelGotoTaskInfo(const std::string &op_name, uint32_t stream_id, uint32_t label_id) : TaskInfo(op_name, stream_id, TaskInfoType::LABEL_GOTO, false), label_id_(label_id) {} ~LabelGotoTaskInfo() override {} - uint32_t label_id() const { return label_id_; } + uint32_t label_id() const { + return label_id_; + } private: uint32_t label_id_; @@ -218,9 +282,15 @@ class LabelSwitchTaskInfo : public TaskInfo { label_list_(label_list), cond_(cond) {} ~LabelSwitchTaskInfo() override {} - uint32_t label_size() const { return label_size_; } - const std::vector &label_list() const { return label_list_; } - void *cond() const { return cond_; } + uint32_t label_size() const { + return label_size_; + } + const std::vector &label_list() const { + return label_list_; + } + void *cond() const { + return cond_; + } private: uint32_t label_size_; @@ -230,7 +300,9 @@ class LabelSwitchTaskInfo : public TaskInfo { class EventTaskInfo : public TaskInfo { public: - uint32_t event_id() const { return event_id_; } + uint32_t event_id() const { + return event_id_; + } protected: EventTaskInfo(const std::string &op_name, uint32_t stream_id, TaskInfoType type, uint32_t event_id) @@ -271,14 +343,13 @@ class FusionEndTaskInfo : public TaskInfo { class HcclTaskInfo : public TaskInfo { public: HcclTaskInfo(const std::string &op_name, uint32_t stream_id, const std::string hccl_type, void *input_data_addr, - void *output_data_addr, void *workspace_addr, int64_t workspace_size, int64_t hccl_stream_num, + void *output_data_addr, int64_t workspace_size, int64_t hccl_stream_num, const std::vector &private_def, void *ops_kernel_store, int32_t count, int64_t root_id, int64_t op_type, int64_t data_type, const std::string &group, bool dump_flag) : TaskInfo(op_name, stream_id, TaskInfoType::HCCL, dump_flag), hccl_type_(hccl_type), input_data_addr_(input_data_addr), output_data_addr_(output_data_addr), - workspace_addr_(workspace_addr), workspace_size_(workspace_size), hccl_stream_num_(hccl_stream_num), private_def_(private_def), @@ -290,25 +361,47 @@ class HcclTaskInfo : public TaskInfo { group_(group) {} ~HcclTaskInfo() override {} - const std::string &hccl_type() const { return hccl_type_; } - void *input_data_addr() const { return input_data_addr_; } - void *output_data_addr() const { return output_data_addr_; } - void *workspace_addr() const { return workspace_addr_; } - int64_t workspace_size() const { return workspace_size_; } - int64_t hccl_stream_num() const { return hccl_stream_num_; } - const std::vector &private_def() const { return private_def_; } - void *ops_kernel_store() const { return ops_kernel_store_; } - int32_t count() const { return count_; } - int64_t root_id() const { return root_id_; } - int64_t op_type() const { return op_type_; } - int64_t data_type() const { return data_type_; } - const std::string &group() const { return group_; } + const std::string &hccl_type() const { + return hccl_type_; + } + void *input_data_addr() const { + return input_data_addr_; + } + void *output_data_addr() const { + return output_data_addr_; + } + int64_t workspace_size() const { + return workspace_size_; + } + int64_t hccl_stream_num() const { + return hccl_stream_num_; + } + const std::vector &private_def() const { + return private_def_; + } + void *ops_kernel_store() const { + return ops_kernel_store_; + } + int32_t count() const { + return count_; + } + int64_t root_id() const { + return root_id_; + } + int64_t op_type() const { + return op_type_; + } + int64_t data_type() const { + return data_type_; + } + const std::string &group() const { + return group_; + } private: std::string hccl_type_; void *input_data_addr_; void *output_data_addr_; - void *workspace_addr_; int64_t workspace_size_; int64_t hccl_stream_num_; std::vector private_def_; @@ -329,9 +422,15 @@ class ProfilerTraceTaskInfo : public TaskInfo { flat_(flat) {} ~ProfilerTraceTaskInfo() override {} - uint64_t log_id() const { return log_id_; } - bool notify() const { return notify_; } - uint32_t flat() const { return flat_; } + uint64_t log_id() const { + return log_id_; + } + bool notify() const { + return notify_; + } + uint32_t flat() const { + return flat_; + } private: uint64_t log_id_; @@ -351,11 +450,21 @@ class MemcpyAsyncTaskInfo : public TaskInfo { kind_(kind) {} ~MemcpyAsyncTaskInfo() override {} - void *dst() const { return dst_; } - uint64_t dst_max() const { return dst_max_; } - void *src() const { return src_; } - uint64_t count() const { return count_; } - uint32_t kind() const { return kind_; } + void *dst() const { + return dst_; + } + uint64_t dst_max() const { + return dst_max_; + } + void *src() const { + return src_; + } + uint64_t count() const { + return count_; + } + uint32_t kind() const { + return kind_; + } private: void *dst_; @@ -377,11 +486,21 @@ class StreamSwitchTaskInfo : public TaskInfo { data_type_(data_type) {} ~StreamSwitchTaskInfo() override {} - int64_t true_stream_id() const { return true_stream_id_; } - void *input_addr() const { return input_addr_; } - void *value_addr() const { return value_addr_; } - int64_t cond() const { return cond_; } - int64_t data_type() const { return data_type_; } + int64_t true_stream_id() const { + return true_stream_id_; + } + void *input_addr() const { + return input_addr_; + } + void *value_addr() const { + return value_addr_; + } + int64_t cond() const { + return cond_; + } + int64_t data_type() const { + return data_type_; + } private: int64_t true_stream_id_; @@ -397,7 +516,9 @@ class StreamActiveTaskInfo : public TaskInfo { : TaskInfo(op_name, stream_id, TaskInfoType::STREAM_ACTIVE, false), active_stream_id_(active_stream_id) {} ~StreamActiveTaskInfo() override {} - uint32_t active_stream_id() const { return active_stream_id_; } + uint32_t active_stream_id() const { + return active_stream_id_; + } private: uint32_t active_stream_id_; diff --git a/third_party/fwkacllib/inc/ops/array_ops.h b/third_party/fwkacllib/inc/ops/array_ops.h index fd35b546..450c893e 100644 --- a/third_party/fwkacllib/inc/ops/array_ops.h +++ b/third_party/fwkacllib/inc/ops/array_ops.h @@ -35,7 +35,7 @@ namespace ge { * @li values:A `Tensor`. Must have the same type as `sorted_x`. \n *@par Attributes: -*@li out_type:An optional `DType` from: `int32, int64`. +*out_type:An optional `DType` from: `int32, int64`. Defaults to `int32`. \n *@par Outputs: @@ -504,7 +504,7 @@ REG_OP(Constant) *x: A tensor. \n *@par Outputs: -*y: A tensor. \n +*y: A copy of input tensor. \n *@par Third-party framework compatibility *Compatible with the TensorFlow operator Snapshot. @@ -684,7 +684,9 @@ REG_OP(ExpandDims) *@par Inputs: *@li x: Original tensor. -*@li axis: List of ints. \n + +*@par Attributes: +*@li axes: List of ints indicating the dimensions to be inserted. \n *@par Outputs: *y: Reshape tensor with same data as input. \n @@ -755,10 +757,10 @@ REG_OP(Squeeze) *@brief Returns an integer representing the rank of input tensor. The rank of a tensor is the number of indices required to uniquely select each element of the tensor, that is, the dimension size of the tensor. \n *@par Inputs: -*x: A tensor. \n +*x: A Tensor of type float32, float16, int8, int16, uint16, uint8, int32, int64, uint32, uint64, bool, double. \n *@par Outputs: -*y: A tensor. The rank of input tensor. \n +*y: A tensor. The rank of input tensor. Type is int32. \n *@par Third-party framework compatibility *Compatible with the TensorFlow operator Rank. @@ -848,7 +850,6 @@ REG_OP(PlaceHolder) *x: A tensor. \n *@par Attributes: -*@li dtype: data type of tensor. *@li shape: tensor shape. \n *@par Outputs: @@ -867,13 +868,13 @@ REG_OP(PlaceholderWithDefault) *@brief Reads and returns the value of the input variable tensor. \n *@par Inputs: -*x: A tensor. \n +*x: A tensor must have numeric type. \n *@par Attributes: *dtype: An optional int32 or int64. The output data type. Defaults to int32. \n *@par Outputs: -*y: A tensor. \n +*y: A tensor must have numeric type. \n *@par Third-party framework compatibility *Compatible with the TensorFlow operator ReadVariableOp. @@ -1134,10 +1135,10 @@ This is an M-length vector. This is an R-length vector *@par Attributes: -*@li normalize: boolean (if true, edit distances are normalized by length of truth). \n +*normalize: boolean (if true, edit distances are normalized by length of truth). \n *@par Outputs: -*@li output: A dense float tensor with rank R - 1. \n +*output: A dense float tensor with rank R - 1. \n *@par Third-party framework compatibility * Compatible with TensorFlow EditDistance operator. @@ -1154,18 +1155,17 @@ REG_OP(EditDistance) .OP_END_FACTORY_REG(EditDistance) /** -* @brief sort_v2. +* @brief sort the input tensor without returning the value of index. * @par Inputs: -* @li x: An ND tensor of type float16. +* x: An ND tensor of type float16. * @par Attributes: - * @li axis: An optional int. The dimension to sort along. This value defaults to -1. * @li descending: An optional bool. Controls the sorting order (ascending or descending). This value defaults to False. * @par Outputs: -* @li y: An ND tensor of type float16. +* y: An ND tensor of type float16. * @attention Constraints: * @li Axis should select the last dim. @@ -1206,7 +1206,7 @@ REG_OP(Expand) *@Returns a tensor containing the indices of all non-zero elements of input. \n *@par Inputs: -*@li x: A Tensor. Must be one of the following types: float16, float32, int32, int64. +*x: A Tensor. Must be one of the following types: float16, float32, int32, int64. *@par Attributes: * transpose: the output tensor will be transposed if true. \n @@ -1230,15 +1230,15 @@ REG_OP(NonZero) * @par Inputs: * One inputs, including: -* @li x: A Tensor. Must be one of the following types: +* x: A Tensor. Must be one of the following types: * float16, float32, int32, int8 ,uint8. \n * @par Attributes: -* @li shape: A required listInt to specify the shape that the input tensor expanded to. \n +* shape: A required listInt to specify the shape that the input tensor expanded to. \n * @par Outputs: -* @li y: A Tensor. Has the same type as "x", and the shape specified by input and attr shape \n +* y: A Tensor. Has the same type as "x", and the shape specified by input and attr shape \n * @par Third-party framework compatibility * Compatible with the ONNX operator Expand. @@ -1249,6 +1249,38 @@ REG_OP(ExpandD) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) .REQUIRED_ATTR(shape, ListInt) .OP_END_FACTORY_REG(ExpandD) + +/** +*@brief Finds unique elements in a 1D tensor. \n + +*@par Inputs: +*x: 1D tensor. Must be one of the following types: +* float16, float32, double, int64, int32, int16, uint16, int8 ,uint8. \n + +*@par Attributes: +*@li return_inverse: Whether to also return the indices for where elements in the original +* input ended up in the returned unique list. +*@li return_inverse: Whether to also return the counts for each unique element. + +*@par Outputs: +*@li y1: The output list of unique scalar elements. Has the same type as "x". +*@li y2: Representing the indices for where elements in the original input map to in the output. +*@li y3: Representing the number of occurrences for each unique value or tensor. \n + +* @par Third-party framework compatibility +* Compatible with the troch operator _unique2. +*/ + +REG_OP(UniqueWithCountsAndSorting) + .INPUT(x, TensorType({ DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, \ + DT_INT32, DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE })) + .OUTPUT(y1, TensorType({ DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, \ + DT_INT32, DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE })) + .OUTPUT(y2, TensorType({ DT_INT32, DT_INT64 })) + .OUTPUT(y3, TensorType({ DT_INT32, DT_INT64 })) + .ATTR(return_inverse, Bool, false) + .ATTR(return_counts, Bool, false) + .OP_END_FACTORY_REG(UniqueWithCountsAndSorting) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_ARRAY_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/control_flow_ops.h b/third_party/fwkacllib/inc/ops/control_flow_ops.h index e5bd3534..cd993599 100644 --- a/third_party/fwkacllib/inc/ops/control_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/control_flow_ops.h @@ -96,7 +96,7 @@ REG_OP(RefMerge) * Otherwise, the data is forwarded to "output_false" . \n *@par Inputs: - *@li data: The tensor to be forwarded. \n + *@li data: The tensor to be forwarded. * Must be one of the following types: float16, float32, float64, * int8, int16, int32, int64, uint8, uint16, uint32, uint64, bool. *@li pred: A boolean scalar. The output port that will receive data . \n diff --git a/third_party/fwkacllib/inc/ops/ctc_ops.h b/third_party/fwkacllib/inc/ops/ctc_ops.h index e907b828..bbc610ff 100644 --- a/third_party/fwkacllib/inc/ops/ctc_ops.h +++ b/third_party/fwkacllib/inc/ops/ctc_ops.h @@ -74,7 +74,7 @@ REG_OP(CTCLoss) *@li sequence_length: A vector containing sequence lengths, size `(batch_size)`. \n *@par Attributes: -*@li merge_repeated: If True, merge repeated classes in output. \n +* merge_repeated: If True, merge repeated classes in output. \n *@par Outputs: *@li decoded_indices: Indices matrix, size `(total_decoded_outputs x 2)`, @@ -108,6 +108,8 @@ REG_OP(CTCGreedyDecoder) *@par Attributes: *@li merge_repeated: If True, merge repeated classes in output. \n +*@li beam_width:A scalar >= 0 (beam search beam width). +*@li top_paths:A scalar >= 0, <= beam_width (controls output size). *@par Outputs: *@li decoded_indices: A list (length: top_paths) of indices matrices. Matrix j, @@ -162,7 +164,7 @@ REG_OP(CTCBeamSearchDecoder) * Compatible with Pytorch CTCLoss operator. *@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*The length of Label should in [4, 1000]. */ REG_OP(CTCLossV2) .INPUT(log_probs, TensorType({DT_FLOAT, DT_DOUBLE})) @@ -203,7 +205,7 @@ REG_OP(CTCLossV2) * Compatible with Pytorch CTCLoss operator. *@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*The limit of Label’s length is 1K. */ REG_OP(CTCLossV2Grad) .INPUT(grad_out, TensorType({DT_FLOAT, DT_DOUBLE})) diff --git a/third_party/fwkacllib/inc/ops/data_flow_ops.h b/third_party/fwkacllib/inc/ops/data_flow_ops.h index 6021f4e3..32454d27 100644 --- a/third_party/fwkacllib/inc/ops/data_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/data_flow_ops.h @@ -1201,6 +1201,8 @@ REG_OP(TensorArraySize) *@brief A queue implementation that dequeues elements in a random order. \n *@par Attributes: +*@li component_types:A list of fully-defined Tensortype objects with +the same length as shapes, or None. *@li shapes: (Optional.) A list of fully-defined TensorShape objects with the same length as dtypes, or None. *@li capacity: An integer. The upper bound on the number of elements that may @@ -1281,6 +1283,7 @@ The length of this attr must be either 0 or the same as the length of elements are not constrained, and only one element may be dequeued at a time. *@li container: An optional string. Defaults to "". If non-empty, this queue is placed in the given container. Otherwise, a default container is used. +*@li capacity:An integer. The upper bound on the number of elements that may be stored in this queue. *@li shared_name: An optional string. Defaults to "". If non-empty, this queue will be shared under the given name across multiple sessions. \n @@ -1435,7 +1438,7 @@ REG_OP(OrderedMapClear) *@par Inputs: *Including: -* @li resource: A Tensor of type DT_RESOURCE. +* resource: A Tensor of type DT_RESOURCE. *@par Outputs: *handle: A Tensor of type DT_STRING ref. \n @@ -1526,7 +1529,7 @@ REG_OP(OrderedMapPeek) *@par Inputs: *Including: -* @li indices: A Tensor of type DT_INT32. \n +* indices: A Tensor of type DT_INT32. \n *@par Attributes: *@li capacity: An optional int that is >= 0. Defaults to "0". @@ -2331,6 +2334,40 @@ REG_OP(CacheAllIndexToLocal) .REQUIRED_ATTR(dtype, Type) .OP_END_FACTORY_REG(CacheAllIndexToLocal) +/** +*@brief LRUCacheV2, aicore LRUCache. +*@par Inputs: +*index_list: exchange index list +*data: host data +*cache: gm cache +*tag: cache's tag +*is_last_call: if is last call write all cache to data +*@par Outputs: +*data: output data +*cache: gm cache +*tag: cache's tag +*index_offset_list: index_offset_list +*not_in_cache_index_list: output not in cache's index_list +*not_in_cache_number: scalar +*@par Attributes: +*pre_route_count: types of all outputs +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(LRUCacheV2) + .INPUT(index_list, TensorType::BasicType()) + .INPUT(data, TensorType::BasicType()) + .INPUT(cache, TensorType::BasicType()) + .INPUT(tag, TensorType::BasicType()) + .INPUT(is_last_call, TensorType::BasicType()) + .OUTPUT(data, TensorType::BasicType()) + .OUTPUT(cache, TensorType::BasicType()) + .OUTPUT(tag, TensorType::BasicType()) + .OUTPUT(index_offset_list, TensorType::BasicType()) + .OUTPUT(not_in_cache_index_list, TensorType::BasicType()) + .OUTPUT(not_in_cache_number, TensorType::BasicType()) + .REQUIRED_ATTR(pre_route_count, Int) + .OP_END_FACTORY_REG(LRUCacheV2) + /** *@brief DynamicGetNext, dynamic get next data *@par Inputs: diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index f61e2939..b4299026 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -624,9 +624,9 @@ REG_OP(Log1p) *@attention Constraints: *@li x2: The input data does not support 0 -*@li When NUM exceeds 2048 , the accuracy of operator cannot guarantee the +*@li When NUM exceeds 2048 , the accuracy of operator cannot guarantee the *requirement of double thousandths in the mini form -*@li Due to different architectures, the calculation results of this operator +*@li Due to different architectures, the calculation results of this operator *on NPU and CPU may be inconsistent *@li If shape is expressed as (D1,D2... ,Dn), then D1*D2... *DN<=1000000,n<=8 @@ -2066,9 +2066,9 @@ REG_OP(FloorDiv) *@attention Constraints: *@li x2: The input data does not support 0 -*@li When NUM exceeds 2048 , the accuracy of operator cannot guarantee the +*@li When NUM exceeds 2048 , the accuracy of operator cannot guarantee the *requirement of double thousandths in the mini form -*@li Due to different architectures, the calculation results of this operator +*@li Due to different architectures, the calculation results of this operator *on NPU and CPU may be inconsistent *@li If shape is expressed as (D1,D2... ,Dn), then D1*D2... *DN<=1000000,n<=8 @@ -2200,9 +2200,9 @@ REG_OP(Tan) *@attention Constraints: *@li x2: The input data does not support 0 -*@li When NUM exceeds 2048 , the accuracy of operator cannot guarantee the +*@li When NUM exceeds 2048 , the accuracy of operator cannot guarantee the *requirement of double thousandths in the mini form -*@li Due to different architectures, the calculation results of this operator +*@li Due to different architectures, the calculation results of this operator *on NPU and CPU may be inconsistent *@li If shape is expressed as (D1,D2... ,Dn), then D1*D2... *DN<=1000000,n<=8 @@ -2467,11 +2467,11 @@ REG_OP(Eltwise) *@par Inputs: *One inputs, including: - * @li input_x: A tensor. Must be one of the following types: + * input_x: A tensor. Must be one of the following types: * float16, float32. \n *@par Outputs: - *y: A Tensor with the same type and shape of input_x's. \n + *output_y: A Tensor with the same type and shape of input_x's. \n *@par Third-party framework compatibility *Compatible with the Pytorch operator Erfinv. \n @@ -3154,13 +3154,13 @@ REG_OP(FusedMulAddNL2loss) *@brief Tests whether the input exceeds a threshold. \n *@par Inputs: -*@li x: A Tensor with any format. Must be one of the following types: float16, float32. \n +* x: A Tensor with any format. Must be one of the following types: float16, float32. \n *@par Attributes: -*@li threshold: A required float32. Defaults to "0.0". "x" is compared with "threshold", outputs "1" for inputs above threshold; "0" otherwise. \n +* threshold: A required float32. Defaults to "0.0". "x" is compared with "threshold", outputs "1" for inputs above threshold; "0" otherwise. \n *@par Outputs: -*@li y: A Tensor with any format. Has the same type as the input. Must be one of the following types: float16, float32. +* y: A Tensor with any format. Has the same type as the input. Must be one of the following types: float16, float32. *@par Third-party framework compatibility * Compatible with the Caffe operator Threshold. */ @@ -3175,7 +3175,7 @@ REG_OP(FusedMulAddNL2loss) *@brief Returns the index number corresponding to the maximum value entered. \n *@par Inputs: -*@li x: A tensor. Must be one of the following types: float16, float32. \n +*x: A tensor. Must be one of the following types: float16, float32. \n *@par Attributes: *@li axis: An optional int. Specify the axis to be cut at the input tensor. If this parameter is not provided, find the topk for each batch. Defaults to 10000 @@ -3203,12 +3203,11 @@ REG_OP(ArgMaxWithK) *@brief Multiply tensor with scale. \n *@par Inputs: -*Five inputs, including: -* @li x1: A Tensor. Must be one of the following types:int32,int16, float16, float32. -* @li x2: A scale. Must be float. \n +*One input, including: +*x: A Tensor. Must be one of the following types:int32,int16, float16, float32. *@par Outputs: -*@li y: A Tensor. Has the same type and shape as "x1". \n +*y: A Tensor. Has the same type and shape as "x1". \n *@par Third-party framework compatibility: * Compatible with the Pytorch operator muls. @@ -3223,12 +3222,11 @@ REG_OP(Muls) *@brief Fill tensor with scale. \n *@par Inputs: -*Five inputs, including: -* @li x1: A Tensor. Must be one of the following types:int32,int16, float16, float32. -* @li x2: A scale. Must be float. \n +*One input, including: +*x1: A Tensor. Must be one of the following types:int32,int16, float16, float32. *@par Outputs: -*@li y: A Tensor. Has the same type and shape as "x1". \n +*y: A Tensor. Has the same type and shape as "x1". \n *@par Third-party framework compatibility: * Compatible with the Pytorch operator fills. @@ -3378,7 +3376,7 @@ REG_OP(TensorMove) *@par Inputs: *One inputs, including: -* @li x: A Tensor. Must be one of the following types: float16, float32, int8, uint8, int16, uint16, int32, uint32, int64, uint64. \n +*x: A Tensor. Must be one of the following types: float16, float32, int8, uint8, int16, uint16, int32, uint32, int64, uint64. \n *@par Outputs: *output_x: A Tensor. Has the same type as "x". \n @@ -3397,7 +3395,7 @@ REG_OP(TensorRedirect) * multiply the result by the scalar value and add it to tensor x1 * @par Inputs: -* Three inputs, including: +* Four inputs, including: * @li input_data: A mutable input Tensor. Must be one of the following types: * float16, float32. * @li x1: A mutable input Tensor of the same type as x1. @@ -3406,7 +3404,7 @@ REG_OP(TensorRedirect) * float16, float32, int32. \n * @par Outputs: -* @li y: A mutable Tensor. Has the same type as "x1". \n +* y: A mutable Tensor. Has the same type as "x1". \n * @par Third-party framework compatibility * Compatible with the Pytorch operator Addcdiv. @@ -3420,12 +3418,12 @@ REG_OP(Addcdiv) .OP_END_FACTORY_REG(Addcdiv) /** -* @brief Performs the element-wise multiplication of tensor x2 by tensor x3, -* multiply the result by the scalar value and add it to tensor input_data +* @brief Performs the element-wise multiplication of tensor x2 by tensor x3, +* multiply the result by the scalar value and add it to tensor input_data * @par Inputs: -* Three inputs, including: +* Four inputs, including: * @li input_data: A mutable input Tensor. Must be one of the following types: * float16, float32, int8, int32, uint8. * @li x1: A mutable input Tensor of the same type as x1. @@ -3433,7 +3431,7 @@ REG_OP(Addcdiv) * @li value: A tensor which includes only one element of the same type as x1. \n * @par Outputs: -* @li y: A mutable output Tensor. Has the same type as "x1". \n +* y: A mutable output Tensor. Has the same type as "x1". \n * @par Third-party framework compatibility * Compatible with the Pytorch operator Addcmul. @@ -3455,7 +3453,7 @@ REG_OP(Addcmul) * @li alpha: A scalar tensor of type float16, float32. \n * @par Outputs: -* @li y: An ND tensor tensor with the same shape and type as "x1". \n +* y: An ND tensor tensor with the same shape and type as "x1". \n * @par Third-party framework compatibility * Compatible with the Pytorch operator Axpy. @@ -3467,25 +3465,6 @@ REG_OP(AxpyV2) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) .OP_END_FACTORY_REG(AxpyV2) -/** -* @brief Computes the result of x1 - x2. - -* @par Inputs: -* @li x1: An ND tensor of type float16, float, int32. -* @li x2: An ND tensor of type float16, float, int32. \n - -* @par Outputs: -* @li y: An ND tensor tensor with the same type as "x1". \n - -* @par Third-party framework compatibility -* Compatible with the Pytorch operator Sub. -*/ -REG_OP(PtSub) - .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) - .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) - .OP_END_FACTORY_REG(PtSub) - /** * @brief Add the partial values of two tensors in format NC1HWC0. @@ -3502,7 +3481,7 @@ REG_OP(PtSub) * the difference between C1 and offset in "x1" and "x2". \n * @par Outputs: -* @li y: A Tensor of the same type as "x1", and the same shape as "x1", +* y: A Tensor of the same type as "x1", and the same shape as "x1", * except for the C1 value. Record the result after adding. \n */ REG_OP(StrideAdd) @@ -3523,7 +3502,7 @@ REG_OP(StrideAdd) * @li input_y: A Tensor. the second tensor. \n * @par Outputs: -* @li output_z: A Tensor. Bool type, compare result of the two inputs. \n +*output_z: A Tensor. Bool type, compare result of the two inputs. \n * @par Third-party framework compatibility * Compatible with the Pytorch equal operator. \n @@ -3535,21 +3514,21 @@ REG_OP(TensorEqual) .OP_END_FACTORY_REG(TensorEqual) /** - * @brief Element-wise min of each of the input tensors (with Numpy-style broadcasting support). - * All inputs and outputs must have the same data type. This operator supports multidirectional + * @brief Element-wise min of each of the input tensors (with Numpy-style broadcasting support). + * All inputs and outputs must have the same data type. This operator supports multidirectional * (i.e., Numpy-style) broadcasting - * - * @par inputs + * + * @par Inputs: * one input including: - * @li x: dynamic input A Tensor. Must be one of the following types: float32, float16, double, int32, int64 - * - * @par output + * x: dynamic input A Tensor. Must be one of the following types: float32, float16, double, int32, int64 + * + * @par Outputs: * one output including: - * @li y:A Tensor of the same type as x - * + * y:A Tensor of the same type as x + * */ REG_OP(MaxN) - .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_FLOAT64, DT_INT32, DT_INT64})) + .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_FLOAT64, DT_INT32, DT_INT64})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_FLOAT64, DT_INT32, DT_INT64})) .OP_END_FACTORY_REG(MaxN) @@ -3634,16 +3613,16 @@ REG_OP(DataCompare) *which Hardmax will be performed.The output tensor has the same shape and contains the Hardmax values of the *corresponding input. * -*@par inputs +*@par Inputs: *one input including: -*@li x: input A Tensor.Must be one of the following types:float32,float16 +*x: input A Tensor.Must be one of the following types:float32,float16 * *@par Attributes: -*@li axis:A required int attribute that decides which dimension will be used to cal the hard_max +*axis:A required int attribute that decides which dimension will be used to cal the hard_max * -*@par output: +*@par Outputs: *one output including: -*@li y:A Tensor of the same type as x +*y:A Tensor of the same type as x * */ REG_OP(HardMax) @@ -3661,7 +3640,7 @@ REG_OP(HardMax) * @li input_y: A Tensor. the second tensor must be 1d. \n * @par Outputs: -* @li output: A Tensor. Result of the two inputs, must be 1d. \n +* output: A Tensor. Result of the two inputs, must be 1d. \n * @par Third-party framework compatibility * Compatible with the Pytorch dot operator. \n @@ -3671,7 +3650,7 @@ REG_OP(Dot) .INPUT(input_y, TensorType({DT_FLOAT, DT_FLOAT16, DT_UINT8, DT_INT8, DT_INT32})) .OUTPUT(output, TensorType({DT_FLOAT, DT_FLOAT16, DT_UINT8, DT_INT8, DT_INT32})) .OP_END_FACTORY_REG(Dot) - + /** *@brief Returns a new tensor with boolean elements representing \n *if each element of input is “close” to the corresponding element of other \n @@ -3719,7 +3698,7 @@ REG_OP(IsClose) * *@attention Constraints: *@li indices: only support int32,and shape same to "updates" -*@li The value range of "dimension" is [-dims, dims - 1]. "dims" is the dimension length of "x". +*@li The value range of "dimension" is [-dims, dims - 1]. "dims" is the dimension length of "x". *@li y:A Tensor, the type and shape is same to "var" \n *@par Third-party framework compatibility @@ -3754,7 +3733,7 @@ REG_OP(ArgMaxGrad) *@attention Constraints: *@li indices: only support int32,and shape same to "updates" -*@li The value range of "dimension" is [-dims, dims - 1]. "dims" is the dimension length of "x". +*@li The value range of "dimension" is [-dims, dims - 1]. "dims" is the dimension length of "x". *@li y:A Tensor, the type and shape is same to "var" \n *@par Third-party framework compatibility @@ -3805,15 +3784,15 @@ REG_OP(AddMatMatElements) *@par Inputs: *Two inputs, including: -* @li input_x1: A tensor. Must be the following types: -* float32. \n +* @li input_x1: A tensor. Must be the following types: float32. +* @li input_x2: A tensor. Must of the following types: float32. \n -*@par Inputs: -*@li input_x2: A tensor. Must of the following types: -* float32. \n +* @par Attributes: +* @li dim:The type is Int and the default value is 1. +* @li eps:The type is Float and the default value is 1e-8. \n *@par Outputs: -*@li output_y: A Tensor with the same type of input_x's. \n +* output_y: A Tensor with the same type of input_x's. \n *@par Third-party framework compatibility *Compatible with the Pytorch operator CosineSimilarity. \n @@ -3826,6 +3805,45 @@ REG_OP(CosineSimilarity) .ATTR(eps, Float, 1e-8) .OP_END_FACTORY_REG(CosineSimilarity) +/** +*@brief count adam result. \n + +*@par Inputs: +*eleven inputs, including: +* @li var: A Tensor. Support float16/float32.\n +* @li m: A Tensor. Datatype and shape are same as exp_avg.\n +* @li v: A Tensor. Datatype and shape are same as exp_avg.\n +* @li lr: A Tensor. Datatype is same as exp_avg. Shape (1, ).\n +* @li beta1: A Tensor. Datatype is same as exp_avg. Shape (1, ).\n +* @li beta2: A Tensor. Datatype is same as exp_avg. Shape (1, ).\n +* @li epsilon: A Tensor. Datatype is same as exp_avg. Shape (1, ).\n +* @li grad: A Tensor. Datatype and shape are same as exp_avg.\n +* @li max_grad_norm: A Tensor. Datatype is same as exp_avg. Shape (1, ).\n +* @li global_grad_norm: A Tensor. Datatype is same as exp_avg. Shape (1, ).\n +* @li weight_decay: A Tensor. Datatype is same as exp_avg. Shape (1, ).\n + +*@par Outputs: +*three inputs, including: +* @li var: A Tensor. Datatype and shape are same as exp_avg.\n +* @li m: A Tensor. Datatype and shape are same as exp_avg.\n +* @li v: A Tensor. Datatype and shape are same as exp_avg.\n +*/ +REG_OP(ApplyAdamV2) + .INPUT(var, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(m, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(v, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(lr, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(beta1, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(beta2, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(epsilon, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(grad, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(max_grad_norm, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(global_grad_norm, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .INPUT(weight_decay, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .OUTPUT(var, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .OUTPUT(m, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .OUTPUT(v, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .OP_END_FACTORY_REG(ApplyAdamV2) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_ELEWISE_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/functional_ops.h b/third_party/fwkacllib/inc/ops/functional_ops.h index b09ac058..7cfe39c4 100644 --- a/third_party/fwkacllib/inc/ops/functional_ops.h +++ b/third_party/fwkacllib/inc/ops/functional_ops.h @@ -163,9 +163,6 @@ REG_OP(Case) * if it is not a scalar, non-empty means True and empty means False. *@li body: A subgraph takes 'input' and returns a another list of tensors . \n - *@par Attributes: - *parallel_iterations: An optional int, default as 10 . \n - *@par Outputs: *output: The output tensors returned by "body". Has the same type as "input" . \n diff --git a/third_party/fwkacllib/inc/ops/image_ops.h b/third_party/fwkacllib/inc/ops/image_ops.h index 6909345a..2327e76e 100644 --- a/third_party/fwkacllib/inc/ops/image_ops.h +++ b/third_party/fwkacllib/inc/ops/image_ops.h @@ -28,7 +28,7 @@ namespace ge { *@brief Decode the frame(s) of a GIF-encoded image to a uint8 tensor . \n *@par Inputs: -*@li contents:A Tensor of type string. 0-D. The GIF-encoded image. \n +*contents:A Tensor of type string. 0-D. The GIF-encoded image. \n *@par Outputs: *image:A Tensor of type uint8. \n @@ -128,8 +128,8 @@ crops from the input image tensor and resizes them using bilinear sampling or nearest neighbor sampling to a common output size specified by crop_size . \n *@par Inputs: -*Input images must be a 4-D tensor. Inputs include: -*@li images:A Tensor. Must be one of the following types:uint8, uint16, int8, +*Input x must be a 4-D tensor. Inputs include: +*@li x:A Tensor. Must be one of the following types:uint8, uint16, int8, int16, int32, int64, float16, float, double. A 4-D tensor of shape [batch, image_height, image_width, depth]. The format must be NHWC. *@li boxes: A Tensor of type float. A 2-D tensor of shape [num_boxes, 4]. @@ -266,8 +266,9 @@ depth] containing the original image size. Both image_height and image_width need to be positive . \n *@par Attributes: -method: A string specifying the interpolation method. Only 'bilinear' is -supported for now . \n +*@li method: A string specifying the interpolation method. Only 'bilinear' is +supported for now . +*@li T: output of type \n *@par Outputs: *y:A 4-D tensor of shape [batch, image_height, image_width, depth]. The format @@ -585,9 +586,11 @@ REG_OP(ResizeNearestNeighborV2GradD) channels], The image tensor that was resized . \n *@par Attributes: -*align_corners: An optional bool. Defaults to False. If true, the centers of +*@li align_corners: An optional bool. Defaults to False. If true, the centers of the 4 corner pixels of the input and grad tensors are aligned. Defaults to -false . \n +false . +*@li half_pixel_centers: indicates if the offset coordinates are normalized. Defaults +to false . \n *@par Outputs: *y: A Tensor. Has the same type as original_image . \n @@ -617,9 +620,10 @@ REG_OP(ResizeBilinearV2Grad) size for the images . \n *@par Attributes: -*align_corners: If true, the centers of the 4 corner pixels of the input and +* @li align_corners: If true, the centers of the 4 corner pixels of the input and output tensors are aligned, preserving the values at the corner pixels. -Defaults to false . \n +Defaults to false . +* @li half_pixel_centers: An optional bool. Defaults to False . \n *@par Outputs: *y: 4-D with shape [batch, new_height, new_width, channels] . \n @@ -684,6 +688,9 @@ be non-negative. In the case of 0, the cropped area does not need to overlap any of the bounding boxes supplied . *@li aspect_ratio_range: The cropped area of the image must have an aspect ratio = width / height within this range. +*@li area_range: An optional list of `floats`. Defaults to `[0.05, 1]`. The +cropped area of the image must contain a fraction of the supplied image +within this range. *@li max_attempts: Number of attempts at generating a cropped region of the image of the specified constraints. After max_attempts failures, return the entire image. @@ -740,6 +747,9 @@ generator is seeded by the given seed. Otherwise, it is seeded by a random seed. *@li seed2: A second seed to avoid seed collision. *@li aspect_ratio_range: The cropped area of the image must have an aspect ratio = width / height within this range. +*@li area_range: An optional list of `floats`. Defaults to `[0.05, 1]`. The +cropped area of the image must contain a fraction of the supplied image +within this range. *@li max_attempts: Number of attempts at generating a cropped region of the image of the specified constraints. After max_attempts failures, return the entire image. @@ -787,9 +797,10 @@ REG_OP(SampleDistortedBoundingBoxExt2) The new size for the images . \n *@par Attributes: -*align_corners: If true, the centers of the 4 corner pixels of the input and +*@li align_corners: If true, the centers of the 4 corner pixels of the input and output tensors are aligned, preserving the values at the corner pixels. Defaults to false . \n +*@li half_pixel_centers: An optional bool. Defaults to False . \n *@par Outputs: *y: 4-D with shape [batch, new_height, new_width, channels] . \n @@ -999,10 +1010,6 @@ deciding whether boxes overlap too. *@li score_threshold: A 0-D float tensor representing the threshold for deciding when to remove boxes based on score . \n -*@par Attributes: -*pad_to_max_output_size: If true, the output selected_indices is padded -to be of length max_output_size. Defaults to false . \n - *@par Outputs: *selected_indices: A 1-D integer tensor of shape [M] representing the selected indices from the boxes tensor, where M <= max_output_size . \n @@ -1094,8 +1101,8 @@ REG_OP(EncodePng) *contents: 0-D. PNG-decoded image . *@par Attributes: -*channels: graph channels \n -*dtype: type of image +*@li channels: graph channels \n +*@li dtype: type of image *@par Outputs: *image: is a 3-D uint8 or uint16 Tensor of shape [height, width, channels] @@ -1116,10 +1123,10 @@ REG_OP(DecodePng) *@brief Bmp-decode an image. \n *@par Inputs: -*@li contents: A Tensor of type string. 0-D. The BMP-encoded image. \n +*contents: A Tensor of type string. 0-D. The BMP-encoded image. \n *@par Attributes: -*@li channels: Decode the desired number of color channels of the image. \n +*channels: Decode the desired number of color channels of the image. \n *@par Outputs: *image: A Tensor dtype of uint8. @@ -1253,6 +1260,7 @@ REG_OP(KeepRatioResizeBilinear) No default value. *@li align_corners: An optional bool. If "true", the centers of the corner pixels of the input and output tensors are aligned. Defaults to "false" . \n +*@li half_pixel_centers: An optional bool. Defaults to False . \n *@par Outputs: *y: A Tensor with the same type and format as input "images" . \n @@ -1381,6 +1389,7 @@ REG_OP(NonMaxSuppressionV5) *@li scale: A `Tensor` of type `float32`. *@li translation: A `Tensor` of type `float32` . \n +*@par Attributes: *@li kernel_type: type is string, default lanczos3 *@li antialias: type is bool, default true \n @@ -1411,6 +1420,7 @@ REG_OP(ScaleAndTranslate) *@li scale: A `Tensor` of type `float32`. *@li translation: A `Tensor` of type `float32` . \n +*@par Attributes: *@li kernel_type: type is string, default lanczos3 *@li antialias: type is bool, default true @@ -1460,9 +1470,10 @@ if they fall beyond [0, 1]. If false, do not do clipping and output the box coordinates as it is. If not specified, defaults to true . \n *@par Outputs: -*nmsed_boxes:type is float -*nmsed_scores:type is float -*nmsed_classes:type is float \n +*@li nmsed_boxes:type is float +*@li nmsed_scores:type is float +*@li nmsed_classes:type is float +*@li valid_detections:type is INT32 \n *@par Third-party framework compatibility * Compatible with tensorflow CombinedNonMaxSuppression operator. @@ -1508,6 +1519,9 @@ REG_OP(IMGWarp) *@par Outputs: *map_img: A Tensor after resize. \n + +*@par Restrictions: +*Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(Remap) .INPUT(img, TensorType({DT_UINT8, DT_FLOAT16, DT_FLOAT32})) @@ -1524,7 +1538,7 @@ and 4 mean input[(h_top, w_left), (h_top, w_right), (h_bottom, w_left), (h_bott *@li warp_index: the resize offset A 4-D float tensor of shape `[n, 2, h, w]`, 2 means (x, y) for resize point. *@par Outputs: -*remap_img: A Tensor after ResizeBilinear, A 4-D tensor of shape `[n, c, h, w]`. \n +*warp_img: A Tensor after ResizeBilinear, A 4-D tensor of shape `[n, c, h, w]`. \n */ REG_OP(IMGWarpResize) .INPUT(img, TensorType({DT_FLOAT32})) @@ -1558,6 +1572,39 @@ REG_OP(SpatialTransformerD) .ATTR(use_default_theta, ListBool, {}) .OP_END_FACTORY_REG(SpatialTransformerD) +/** +*@brief Function spatial transformer . \n + +*@par Inputs: +*@li x: A Tensor dtype of float16, float32, double, uint8, int8, uint16, int16, int32, uint32, uint64, int64. +*@li theta: A Tensor dtype of float16, float32, double, uint8, int8, uint16, int16, int32, uint32, uint64, int64, + auxiliary coefficients . \n + +*@par Attributes: +*@li output_size: A tuple output size. +*@li default_theta: A tuple default theta +*@li use_default_theta: List use default theta + +*@par Outputs: +*y: A Tensor dtype of float16, float32, double, uint8, int8, uint16, int16, int32, uint32, uint64, int64, + should be same shape and type as x. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(SpatialTransformer) + .INPUT(x, TensorType({DT_FLOAT,DT_FLOAT16,DT_DOUBLE,DT_UINT8,DT_INT8,DT_UINT16, + DT_INT16,DT_INT32,DT_UINT32,DT_UINT64,DT_INT64})) + .OPTIONAL_INPUT(theta, TensorType({DT_FLOAT,DT_FLOAT16,DT_DOUBLE,DT_UINT8,DT_INT8, + DT_UINT16,DT_INT16,DT_INT32,DT_UINT32,DT_UINT64,DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT,DT_FLOAT16,DT_DOUBLE,DT_UINT8,DT_INT8,DT_UINT16, + DT_INT16,DT_INT32,DT_UINT32,DT_UINT64,DT_INT64})) + .ATTR(output_size, ListInt, {-1, -1}) + .ATTR(default_theta, ListFloat, {}) + .ATTR(align_corners, Bool, false) + .ATTR(use_default_theta, ListInt, {}) + .OP_END_FACTORY_REG(SpatialTransformer) + /** * @brief Resize the input tensor. \n currently, only support resize image tensor using nearest neighbor and linear interpolation. @@ -1623,7 +1670,7 @@ REG_OP(Resize) *@brief Function parse image from string to int. \n *@par Inputs: -*@li contents: A Tensor of type string. 0-D. The JPEG-encoded image. \n +* contents: A Tensor of type string. 0-D. The JPEG-encoded image. \n *@par Attributes: *@li channels: An optional int. Defaults to 0. Number of color channels for the decoded image. @@ -1668,7 +1715,7 @@ REG_OP(DenseImageWarp) *@par Inputs: *One inputs, including: -* @li x: A tensor. Must be one of the following types: +* x: A tensor. Must be one of the following types: * float16, float32. \n *@par Attributes: @@ -1713,7 +1760,7 @@ REG_OP(ResizeD) *@par Inputs: *One inputs, including: -* @li grads: A tensor. Must be one of the following types: +* grads: A tensor. Must be one of the following types: * float16, float32. \n *@par Attributes: @@ -1762,8 +1809,8 @@ REG_OP(ResizeGradD) *@li flow: 4-D Tensor with shape `[batch, height, width, 2]`. \n *@par Outputs: -*grad_image: Returns 4-D with the same shape and dtype as `image`. -*grad_flow: Returns 4-D with the same shape and dtype as `flow`. \n +*@li grad_image: Returns 4-D with the same shape and dtype as `image`. +*@li grad_flow: Returns 4-D with the same shape and dtype as `flow`. \n */ REG_OP(DenseImageWarpGrad) .INPUT(grad, TensorType({DT_FLOAT, DT_FLOAT16})) @@ -1817,12 +1864,12 @@ REG_OP(GridSampler2D) *@li assist: Assist matrix, a 4-D tensor of type float16. *@par Attributes: -*@li align_corners: An optional bool. If "true", the centers of the corner +*align_corners: An optional bool. If "true", the centers of the corner pixels of the input and output tensors are aligned. Defaults to "false" . *@par Outputs: -*diff: Returns 4-D Tensor with the same shape and dtype as `grid`. -*position: Returns 4-D Tensor with the same shape as `grid`. +*@li diff: Returns 4-D Tensor with the same shape and dtype as `grid`. +*@li position: Returns 4-D Tensor with the same shape as `grid`. */ REG_OP(GridUnnormal) .INPUT(grid, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -1840,10 +1887,13 @@ REG_OP(GridUnnormal) *@li position: 4-D Tensor with shape `[batch, output_height, output_width, 2]`. *@par Attributes: -*@li padding_mode: An optional string specifying the pad method. Only 'zeros' is supported for now . +*padding_mode: An optional string specifying the pad method. Only 'zeros' is supported for now . *@par Outputs: *y: Returns 4-D Tensor with the same dtype as `x`. + +*@par Restrictions: +*Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(ImageUnfold) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -1936,5 +1986,204 @@ REG_OP(GridSampler3DGrad) .ATTR(align_corners, Bool, false) .OP_END_FACTORY_REG(GridSampler3DGrad) +/** +*@brief Upsample the 3-D data with the nearest neighbor ​interpolation algorithm. \n + +*@par Inputs: +*One inputs, including: +*x: A 5-D input tensor [N, C, D, H, W]. Must be one of the following types: +* float16, float32, float64. \n + +*@par Attributes: +*@li output_size: An optional listInt. Defaults to none. + contain 3 elements: output_depth, output_height, output_width. The number of elements of 'output_size' + should be the same as the rank of input 'x'. Only one of 'scales' and 'output_size' can be specified. \n +*@li scales: An optional listFloat. Defaults to none. + The scale array along each dimension, contain 3 elements: scale_depth, scale_height, scale_width. + The number of elements of 'scales' should be the same as the rank of input 'x'. One of 'scales' and + 'output_size' MUST be specified and it is an error if both are specified. \n + +*@par Outputs: +*y: A 5-D tensor. Has the same type as input x, shape depends on x and output_size/scales. \n + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. \n +*/ + +REG_OP(UpsampleNearest3d) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .ATTR(output_size, ListInt, {}) + .ATTR(scales, ListFloat, {}) + .OP_END_FACTORY_REG(UpsampleNearest3d) + +/** +*@brief Upsample the 3-D data with the trilinear ​interpolation algorithm. \n + +*@par Inputs: +*One inputs, including: +*x: A 5-D input tensor [N, C, D, H, W]. Must be one of the following types: +* float16, float32, float64. \n + +*@par Attributes: +*@li output_size: An optional listInt. Defaults to none. + contain 3 elements: output_depth, output_height, output_width. The number of elements of 'output_size' should + be the same as the rank of input 'x'. Only one of 'scales' and 'output_size' can be specified. \n +*@li scales: An optional listFloat. Defaults to none. + The scale array along each dimension, contain 3 elements: scale_depth, scale_height, scale_width. + The number of elements of 'scales' should be the same as the rank of input 'x'. + One of 'scales' and 'output_size' MUST be specified and it is an error if both are specified. \n +*@li align_corners: An optional bool. Defaults to false. + If true, the input and output tensors are aligned by the center points of their corner pixels, preserving the + values at the corner pixels. If false, the input and output tensors are aligned by the corner points of their + corner pixels, and the interpolation use edge value padding for out of boundary values. \n + +*@par Outputs: +*y: A 5-D tensor. Has the same type as input x, shape depends on x and output_size/scales. \n + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. \n +*/ + +REG_OP(UpsampleTrilinear3d) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .ATTR(output_size, ListInt, {}) + .ATTR(scales, ListFloat, {}) + .ATTR(align_corners, Bool, false) + .OP_END_FACTORY_REG(UpsampleTrilinear3d) + +/** +*@brief Upsample the 3-D gradient data with the nearest neighbor ​interpolation algorithm. \n + +*@par Inputs: +*One inputs, including: +*grad_output: A 5-D input tensor [N, C, D, H, W]. Must be one of the following types: +* float16, float32, float64. \n + +*@par Attributes: +*@li input_size: An required listInt. + contain 5 elements: [min_batch, channels, depth, height, width]. Must: + input_size[0] == grad_output_tensor_size[0] + input_size[1] == grad_output_tensor_size[1]. \n +*@li output_size: An optional listInt. Defaults to none. + contain 3 elements: depth, height, width. The number of elements of 'output_size' should + be the same as the rank of input 'grad_output'. Only one of 'scales' and 'output_size' can be specified. Must: + grad_output_tensor_size[2] == floor(input_size[2] * scales[0]) == output_size[0] + grad_output_tensor_size[3] == floor(input_size[3] * scales[1]) == output_size[1] + grad_output_tensor_size[4] == floor(input_size[4] * scales[2]) == output_size[2]. \n +*@li scales: An optional listFloat. Defaults to none. + The scale array along each dimension, contain 3 elements: scale_depth, scale_height, scale_width. + The number of elements of 'scales' should be the same as the rank of input 'grad_output'. + One of 'scales' and 'output_size' MUST be specified and it is an error if both are specified. \n + +*@par Outputs: +*y: A 5-D tensor. Has the same type as input grad_output, shape depends on Attributes:input_size. \n + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ + +REG_OP(UpsampleNearest3dGrad) + .INPUT(grad_output, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .REQUIRED_ATTR(input_size, ListInt) + .ATTR(output_size, ListInt, {}) + .ATTR(scales, ListFloat, {}) + .OP_END_FACTORY_REG(UpsampleNearest3dGrad) + +/** +*@brief Upsample the 3-D gradient data trilinear ​interpolation algorithm. \n + +*@par Inputs: +*One inputs, including: +*grad_output: A 5-D input tensor [N, C, D, H, W]. Must be one of the following types: +* float16, float32, float64. \n + +*@par Attributes: +*@li input_size: An required listInt. + contain 5 elements: [min_batch, channels, depth, height, width]. Must: + input_size[0] == grad_output_tensor_size[0] + input_size[1] == grad_output_tensor_size[1]. \n +*@li output_size: An optional listInt. Defaults to none. + contain 3 elements: depth, height, width. The number of elements of 'output_size' should + be the same as the rank of input 'grad_output'. Only one of 'scales' and 'output_size' can be specified. Must: + grad_output_tensor_size[2] == floor(input_size[2] * scales[0]) == output_size[0] + grad_output_tensor_size[3] == floor(input_size[3] * scales[1]) == output_size[1] + grad_output_tensor_size[4] == floor(input_size[4] * scales[2]) == output_size[2]. \n +*@li scales: An optional listFloat. Defaults to none. + The scale array along each dimension, contain 3 elements: scale_depth, scale_height, scale_width. + The number of elements of 'scales' should be the same as the rank of input 'grad_output'. + One of 'scales' and 'output_size' MUST be specified and it is an error if both are specified. \n + +*@par Outputs: +*y: A Tensor with shape depends on intput_size and output_size/scales. Must be one of the following + types: float16, float32, float64. \n + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ + +REG_OP(UpsampleTrilinear3dGrad) + .INPUT(grad_output, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .REQUIRED_ATTR(input_size, ListInt) + .ATTR(output_size, ListInt, {}) + .ATTR(scales, ListFloat, {}) + .ATTR(align_corners, Bool, false) + .OP_END_FACTORY_REG(UpsampleTrilinear3dGrad) + + +/** +*@brief Upsample the 1-D data with the nearest neighbor ​interpolation algorithm. \n + +*@par Inputs: +*x: A 1-D input tensor [N, C, W]. Must be one of the following types: +* float16, float32, float64. \n + +*@par Attributes: +*@li output_size: An required listInt contains output_width. +*@li scales: An optional listFloat contains scale_width. Defaults to be zero. \n + +*@par Outputs: +*y: A 3-D tensor. Has the same type as input x, shape depends on x and output_size/scales. \n + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. \n +*/ + +REG_OP(UpsampleNearest1d) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .REQUIRED_ATTR(output_size, ListInt) + .ATTR(scales, ListFloat, {}) + .OP_END_FACTORY_REG(UpsampleNearest1d) + +/** +*@brief Upsample the 1-D gradient data with the nearest neighbor ​interpolation algorithm. \n + +*@par Inputs: +*grad_output: A 3-D input tensor [N, C, W]. Must be one of the following types: +* float16, float32, float64. \n + +*@par Attributes: +*@li output_size: An required listInt contains output_width. +*@li scales: An optional listFloat contains scale_width. Defaults to be zero. +*@li input_size: An required listInt contains output_width. \n + +*@par Outputs: +*y: A 3-D tensor. Has the same type as input grad_output, shape depends on Attributes:input_size. \n + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. \n +*/ + +REG_OP(UpsampleNearest1dGrad) + .INPUT(grad_output, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .REQUIRED_ATTR(input_size, ListInt) + .REQUIRED_ATTR(output_size, ListInt) + .ATTR(scales, ListFloat, {}) + .OP_END_FACTORY_REG(UpsampleNearest1dGrad) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_IMAGE_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/linalg_ops.h b/third_party/fwkacllib/inc/ops/linalg_ops.h index 69c77bf6..f6cc8694 100644 --- a/third_party/fwkacllib/inc/ops/linalg_ops.h +++ b/third_party/fwkacllib/inc/ops/linalg_ops.h @@ -347,6 +347,9 @@ REG_OP(SelfAdjointEig) .OP_END_FACTORY_REG(SelfAdjointEig) /** +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. + *@brief Computes the sign and the log of the absolute value of the determinant of one or more square matrices . \n @@ -382,9 +385,10 @@ REG_OP(Slogdet) *x:Tensor of shape [..., M, N]. Let P be the minimum of M and N . \n *@par Attributes: -*compute_uv:If True then left and right singular vectors will be computed and +*@li compute_uv:If True then left and right singular vectors will be computed and returned in u and v, respectively. Otherwise, only the singular values will -be computed, which can be significantly faster . \n +be computed, which can be significantly faster . +*@li full_matrices:the param effect u,v. \n *@par Outputs: *@li sigma:Singular values. Shape is [..., P]. The values are sorted in @@ -427,6 +431,9 @@ denotes the lower triangular factor `L` with unit diagonal. *@li p: upper triangular part denotes the upper triangular factor `U`.Permutation of the rows encoded as a list of indices in `0..M-1`. Shape is `[..., M]` . \n +*@par Attributes: +*output_idx_type: An optional DType from: int32, int64. + *@par Third-party framework compatibility * Compatible with TensorFlow Lu operator. */ @@ -467,6 +474,12 @@ left-hand side . \n *@par Outputs: y: Tensor of shape `[..., M, K]` containing the solutions \n +*@par Attributes: +*partial_pivoting: Whether to perform partial pivoting. `True` by default. +Partial pivoting makes the procedure more stable, but slower. Partial +pivoting is unnecessary in some cases, including diagonally dominant and +symmetric positive definite matrices + *@par Third-party framework compatibility * Compatible with TensorFlow TridiagonalSolve operator. */ diff --git a/third_party/fwkacllib/inc/ops/list_ops.h b/third_party/fwkacllib/inc/ops/list_ops.h index a1b622e9..0aa94e73 100644 --- a/third_party/fwkacllib/inc/ops/list_ops.h +++ b/third_party/fwkacllib/inc/ops/list_ops.h @@ -35,10 +35,10 @@ namespace ge { *@li max_num_elements: The maximum number of elements. \n *@par Attributes: -*@li element_dtype: The type of elements in the list. \n +*element_dtype: The type of elements in the list. \n *@par Outputs: -*@li handle: An empty tensor list . \n +*handle: An empty tensor list . \n *@par Third-party framework compatibility. *Compatible with tensorflow EmptyTensorList operator. @@ -59,10 +59,10 @@ and the other elements of the given list in `input_handle`. \n *@li tensor: The tensor to put on the list. \n *@par Attributes: -*@li element_dtype: The type of elements in the list. \n +*element_dtype: The type of elements in the list. \n *@par Outputs: -*@li output_handle:A list with the elements of old list followed by tensor. \n +*output_handle:A list with the elements of old list followed by tensor. \n *@par Third-party framework compatibility. *Compatible with tensorflow TensorListPushBack operator. @@ -86,7 +86,7 @@ list with all but that element. \n *@li element_shape: A shape compatible with that of elements in the list. \n *@par Attributes: -*@li element_dtype: The type of elements in the list. \n +*element_dtype: The type of elements in the list. \n *@par Outputs: *@li output_handle:A list with the elements of the old list followed by tensor. @@ -110,10 +110,10 @@ REG_OP(TensorListPopBack) *@brief The number of tensors in the input tensor list. \n *@par Inputs: -*@li input_handle: The input list. \n +*input_handle: The input list. \n *@par Outputs: -*@li length:The number of tensors in the list. \n +*length:The number of tensors in the list. \n *@par Third-party framework compatibility. *Compatible with tensorflow TensorListLength operator. @@ -127,13 +127,13 @@ REG_OP(TensorListLength) *@brief The shape of elements in the input tensor list. \n *@par Inputs: -*@li input_handle: The input list. \n +*input_handle: The input list. \n *@par Attributes: -*@li shape_type: The type of shape in the list. \n +*shape_type: The type of shape in the list. \n *@par Outputs: -*@li element_shape:A shape compatible with that of elements in the list. \n +*element_shape:A shape compatible with that of elements in the list. \n *@par Third-party framework compatibility. *Compatible with tensorflow TensorListElementShape operator. @@ -156,7 +156,7 @@ REG_OP(TensorListElementShape) *@li shape_type: The type of shape in the list. \n *@par Outputs: -*@li handle: An output tensor list . \n +*handle: An output tensor list . \n *@par Third-party framework compatibility. *Compatible with tensorflow TensorListReserve operator. @@ -178,10 +178,10 @@ REG_OP(TensorListReserve) *@li element_shape: A shape compatible with that of elements in the list. \n *@par Attributes: -*@li element_dtype: The type of elements in the list. \n +*element_dtype: The type of elements in the list. \n *@par Outputs: -*@li item: An output tensor value of index position . \n +*item: An output tensor value of index position . \n *@par Third-party framework compatibility. *Compatible with tensorflow TensorListGetItem operator. @@ -206,10 +206,10 @@ REG_OP(TensorListGetItem) *@li item: The element to be assigned to that position. \n *@par Attributes: -*@li element_dtype: The type of elements in the list. \n +*element_dtype: The type of elements in the list. \n *@par Outputs: -*@li output_handle: An output tensor list . \n +*output_handle: An output tensor list . \n *@par Third-party framework compatibility. *Compatible with tensorflow TensorListSetItem operator. @@ -233,10 +233,10 @@ REG_OP(TensorListSetItem) *@li tensor: The tensor push into tensor list. \n *@par Attributes: -*@li element_dtype: The type of elements in the list. \n +*element_dtype: The type of elements in the list. \n *@par Outputs: -*@li output_handles: The output tensor lists. \n +*output_handles: The output tensor lists. \n *@par Third-party framework compatibility. *Compatible with tensorflow TensorListPushBackBatch operator. @@ -263,7 +263,7 @@ REG_OP(TensorListPushBackBatch) *@li num_elements: The number of elements in the list. \n *@par Outputs: -*@li tensor: The tensor of list. \n +*tensor: The tensor of list. \n *@par Third-party framework compatibility. *Compatible with tensorflow TensorListStack operator. @@ -293,7 +293,7 @@ the leading dim of input_handle.element_shape or the element_shape input arg is not already set. \n *@par Attributes: -*@li element_dtype: The type of elements in the list. \n +*element_dtype: The type of elements in the list. \n *@par Outputs: *@li tensor: The concated result. @@ -324,10 +324,10 @@ REG_OP(TensorListConcatV2) *@li lengths: Vector of sizes of the 0th dimension of tensors in the list. \n *@par Attributes: -*@li element_dtype: The type of elements in the list. \n +*element_dtype: The type of elements in the list. \n *@par Outputs: -*@li output_handle: The list. \n +*output_handle: The list. \n *@par Third-party framework compatibility. *Compatible with tensorflow TensorListSplit operator. @@ -351,10 +351,10 @@ REG_OP(TensorListSplit) *@li element_shape: The shape of elements in the list. \n *@par Attributes: -*@li element_dtype: The type of elements in the list. \n +*element_dtype: The type of elements in the list. \n *@par Outputs: -*@li output_handle: An output tensor list . \n +*output_handle: An output tensor list . \n *@par Third-party framework compatibility. *Compatible with tensorflow TensorListFromTensor operator. @@ -377,7 +377,7 @@ REG_OP(TensorListFromTensor) *@li size: size of the output list. \n *@par Outputs: -*@li output_handle: The output tensor list. \n +*output_handle: The output tensor list. \n *@par Third-party framework compatibility. *Compatible with tensorflow TensorListResize operator. @@ -397,10 +397,10 @@ REG_OP(TensorListResize) *@li element_shape: The shape of elements in the list. \n *@par Attributes: -*@li element_dtype: The type of elements in the list. \n +*element_dtype: The type of elements in the list. \n *@par Outputs: -*@li values: The tensor. \n +*values: The tensor. \n *@par Third-party framework compatibility. *Compatible with tensorflow TensorListGather operator. @@ -429,10 +429,10 @@ the largest index in indices. If -1, the list is just large enough to include the largest index in indices. \n *@par Attributes: -*@li element_dtype: The type of elements in the list. \n +*element_dtype: The type of elements in the list. \n *@par Outputs: -*@li output_handle: The TensorList. \n +*output_handle: The TensorList. \n *@par Third-party framework compatibility. *Compatible with tensorflow TensorListScatterV2 operator. @@ -458,10 +458,10 @@ REG_OP(TensorListScatterV2) *@li indices: The indices used to index into the list. \n *@par Attributes: -*@li element_dtype: The type of elements in the list. \n +*element_dtype: The type of elements in the list. \n *@par Outputs: -*@li output_handle: The TensorList. \n +*output_handle: The TensorList. \n *@par Third-party framework compatibility. *Compatible with tensorflow TensorListScatterIntoExistingList operator. @@ -485,10 +485,10 @@ REG_OP(TensorListScatterIntoExistingList) *@li input_b: The input tensor list B. \n *@par Attributes: -*@li element_dtype: The type of elements in the list. \n +*element_dtype: The type of elements in the list. \n *@par Outputs: -*@li output: The output list. \n +*output: The output list. \n *@par Third-party framework compatibility. *Compatible with tensorflow TensorListConcatLists operator. diff --git a/third_party/fwkacllib/inc/ops/lookup_ops.h b/third_party/fwkacllib/inc/ops/lookup_ops.h index 5d928e5a..b1fc254f 100644 --- a/third_party/fwkacllib/inc/ops/lookup_ops.h +++ b/third_party/fwkacllib/inc/ops/lookup_ops.h @@ -77,8 +77,8 @@ REG_OP(LookupTableInsert) *handle: A Tensor of type resource. Handle to the table . \n *@par Attributes: -*@li Tkeys: A DType. -*@li Tvalues: A DType . \n +*@li Tkeys: A DType of keys. +*@li Tvalues: A DType of values. *@par Outputs: *@li keys: A Tensor of type Tkeys. diff --git a/third_party/fwkacllib/inc/ops/math_ops.h b/third_party/fwkacllib/inc/ops/math_ops.h index 319bcf70..6eb418d8 100644 --- a/third_party/fwkacllib/inc/ops/math_ops.h +++ b/third_party/fwkacllib/inc/ops/math_ops.h @@ -227,10 +227,10 @@ REG_OP(Bucketize) *@par Inputs: *One inputs, including: -* @li input_x: A tensor. Must be one of the following types: float16, float32, int8, uint8, int32. \n +*input_x: A tensor. Must be one of the following types: float16, float32, int8, uint8, int32. \n *@par Outputs: -*y: A tensor with the same type and shape of input_x \n +*output_y: A tensor with the same type and shape of input_x \n *@par Third-party framework compatibility *Compatible with the Pytorch operator Trunc. \n @@ -298,7 +298,7 @@ REG_OP(SparseSegmentMean) *@par Inputs: *The input grad must have be type float or double. Inputs include: -*@li grad: A Tensor. Must be one of the following types: float, double. +*@li x: A Tensor. Must be one of the following types: float, double. gradient propagated to the SparseSegmentMean op. *@li indices: A Tensor. Must be one of the following types: int32, int64. indices passed to the corresponding SparseSegmentMean op. @@ -365,6 +365,7 @@ REG_OP(InitData) component of an element of this dataset. *@li output_shapes: A nested structure of TensorShape objects corresponding to each component of an element of this dataset. +*@li output_num:output of nums. *@li channel_name: A string. Default "" . \n *@par Outputs: @@ -538,11 +539,11 @@ REG_OP(NextAfter) *@par Inputs: *One inputs, including: -* @li input_x: A tensor. Must be one of the following types: +* input_x: A tensor. Must be one of the following types: * float16, float32. \n *@par Attributes: -*@li p: An optional float.Defaults to 2. \n +*p: An optional float.Defaults to 2. \n *@par Outputs: *y: A Tensor with the same type and shape of input_x's. \n @@ -560,10 +561,10 @@ REG_OP(Pdist) *@brief Compute element-wise finiteness, return a boolean tensor. *@par Inputs: - *x:A Tensor. + *x:A Tensor of type float16, float32, double. *@par Outputs: - *y:A Tensor. Has the same shape as x. + *y:A Tensor. Returns which elements of x are finite *@par Third-party framework compatibility. *Compatible with tensorflow IsFinite operator. @@ -577,10 +578,10 @@ REG_OP(IsFinite) *@brief Compute element-wise infiniteness, return a boolean tensor. *@par Inputs: - *x:A Tensor. + *x:A Tensor of type float16, float32, double. *@par Outputs: - *y:A Tensor. Has the same shape as x. + *y:A Tensor. Has the same shape as x. Returns which elements of x are isinf. *@par Third-party framework compatibility. *Compatible with tensorflow IsInf operator. @@ -594,7 +595,11 @@ REG_OP(IsInf) *@brief Computes the complex absolute value of a tensor. *@par Inputs: - *x:A Tensor. + *x: x of complex numbers, this operation returns a tensor of type + float or double that is the absolute value of each element in x . + +* @par Attributes: +* Tout: representing the output of type. *@par Outputs: *y:A tensor of type `float` or `double` that is the absolute value of each element in `x`. @@ -612,10 +617,10 @@ REG_OP(ComplexAbs) *@brief Returns which elements of x are NaN. *@par Inputs: - *x:A Tensor. + *x:A Tensor of type float16, float32, double. *@par Outputs: - *y:A Tensor. Has the same shape as x. + *y:A Tensor. Has the same shape as x. Returns which elements of x are isnan *@par Third-party framework compatibility. *Compatible with tensorflow IsNan operator. @@ -629,7 +634,10 @@ REG_OP(IsNan) *@brief Returns the real part of a complex number. *@par Inputs: - *input:A Tensor. + *input:A Tensor. Must have numeric type. + + *@par Attributes: + *Tout: Type of outputs. \n *@par Outputs: *output:A Tensor. Has the same shape as input. @@ -670,7 +678,8 @@ REG_OP(Conj) *@li weight: A Tensor dtype of float32 . \n *@par Attributes: -*reduction: An optional attribute. Defaults to "mean" . \n +*@li reduction: An optional attribute. Defaults to "mean" . +*@li ignore_index:An optional attribute.Defaults to -100 . \n *@par Outputs: *@li y: A Tensor dtype of float32. @@ -700,7 +709,8 @@ REG_OP(NLLLoss) *@li total_weight:A Tensor dtype of float32 . \n *@par Attributes: -*reduction: An optional attribute. Defaults to "mean" . \n +*@li reduction: An optional attribute. Defaults to "mean" . +*@li ignore_index:An optional attribute.Defaults to -100 . \n *@par Outputs: *x_grad: A Tensor. Must be the following type: float32 . \n @@ -720,24 +730,24 @@ REG_OP(NLLLossGrad) .OP_END_FACTORY_REG(NLLLossGrad) /** -*@brief The ifmr . \n +*@brief IFMR(Input Feature Map Reconstruction). \n *@par Inputs: -*@li data:A Tensor of feature map -*@li data_min:A Tensor of min value of feature map. -*@li data_max:A Tensor of max value of feature map. -*@li cumsum:A Tensor of cumsum bin of data . \n +*@li data: A Tensor of feature map. +*@li data_min: A Tensor of min value of feature map. +*@li data_max: A Tensor of max value of feature map. +*@li cumsum: A Tensor of cumsum bin of data . \n *@par Attributes: -*min_percentile: min init percentile. -*max_percentile: max init percentile. -*search_range: search range. -*search_step: step size of searching. -*with_offset: whether using offset . \n +*@li min_percentile: min init percentile. +*@li max_percentile: max init percentile. +*@li search_range: search range. +*@li search_step: step size of searching. +*@li with_offset: whether using offset . \n *@par Outputs: -*scale: optimal scale. -*offset: optimal offset . \n +*@li scale: optimal scale. +*@li offset: optimal offset . \n *@par Third-party framework compatibility *Compatible with mindspore @@ -758,16 +768,16 @@ REG_OP(IFMR) .OP_END_FACTORY_REG(IFMR) /** -*@brief weights adaptive range quantization. \n +*@brief Weights Adaptive Range Quantization. \n *@par Inputs: -*@li w:A Tensor of weights. \n -*@li w_min:A Tensor of weights reduce_min. \n -*@li w_max:A Tensor of weights reduce_max. \n +*@li w: A Tensor of weights. \n +*@li w_min: A Tensor of weights reduce_min. \n +*@li w_max: A Tensor of weights reduce_max. \n *@par Attributes: -*num_bits: the bits num used for quantize. -*offset_flag: whether using offset. \n +*@li num_bits: the bits num used for quantize. +*@li offset_flag: whether using offset. \n *@par Outputs: *y: fake quantized weights. \n @@ -789,22 +799,22 @@ REG_OP(WtsARQ) .OP_END_FACTORY_REG(WtsARQ) /** -*@brief The acts_ulq. \n +*@brief Activations Universal Linear Quantization. \n *@par Inputs: -*@li x:A Tensor of feature map -*@li clamp _min:A Tensor of min clamp value of feature map. -*@li clamp _max:A Tensor of max clamp value of feature map. +*@li x: A Tensor of feature map. +*@li clamp _min: A Tensor of min clamp value of feature map. +*@li clamp _max: A Tensor of max clamp value of feature map. *@par Attributes: -*fixed_min: fix min to zero. -*num_bits: quant bits. \n +*@li fixed_min: fix min to zero. +*@li num_bits: quant bits. \n *@par Outputs: -*y: output fake quant feature map. -*clamp_min_mask: where x > clamp_min -*clamp_min_mask: where x < clamp_max -*x_clamped_loss: clamp loss. \n +*@li y: output fake quant feature map. +*@li clamp_min_mask: where x > clamp_min. +*@li clamp_min_mask: where x < clamp_max. +*@li x_clamped_loss: clamp loss. \n *@par Third-party framework compatibility *Compatible with mindspore @@ -826,12 +836,12 @@ REG_OP(ActsULQ) .OP_END_FACTORY_REG(ActsULQ) /** -*@brief The acts_ulq_input_grad. \n +*@brief The gradient of Activations Universal Linear Quantization. \n *@par Inputs: -*@li y_grad: A Tensor of gradient -*@li clamp_min_mask: A Tensor of boolean mask indicating whether an additional one is needed' -*@li clamp_max_mask: A Tensor of boolean mask indicating whether an additional one is needed' +*@li y_grad: A Tensor of gradient. +*@li clamp_min_mask: A Tensor of boolean mask indicating whether an additional one is needed'. +*@li clamp_max_mask: A Tensor of boolean mask indicating whether an additional one is needed'. *@par Outputs: *x_grapd: The gradient of inpust. \n @@ -851,10 +861,10 @@ REG_OP(ActsULQInputGrad) .OP_END_FACTORY_REG(ActsULQInputGrad) /** -*@brief The act_ulq_clamp_max_grad. \n +*@brief The gradient of Activations Universal Linear Quantization clamp max. \n *@par Inputs: -*@li y_grad: A Tensor of gradient +*@li y_grad: A Tensor of gradient. *@li clamp_max_mask: A Tensor of boolean mask indicating whether an additional one is needed. *@li x_clamped_loss: A Tensor of gradient. \n @@ -876,10 +886,10 @@ REG_OP(ActULQClampMaxGrad) .OP_END_FACTORY_REG(ActULQClampMaxGrad) /** -*@brief The act_ulq_clamp_min_grad. \n +*@brief The gradient of Activations Universal Linear Quantization clamp min. \n *@par Inputs: -*@li y_grad: A Tensor of gradient +*@li y_grad: A Tensor of gradient. *@li clamp_min_mask: A Tensor of boolean mask indicating whether an additional one is needed. *@li x_clamped_loss: A Tensor of gradient. \n @@ -904,7 +914,7 @@ REG_OP(ActULQClampMinGrad) * @brief Computes Lp norm. * @par Inputs: -* @li x: An ND tensor of type float16, float32. \n +* x: An ND tensor of type float16, float32. \n * * @par Attributes: * @li p: Int, "inf" or "-inf", default value is 2. @@ -913,7 +923,7 @@ REG_OP(ActULQClampMinGrad) * @li epsilon: Float, default is 1e-12. \n * @par Outputs: -* @li y: An ND tensor of type float16, float32. The shape of y is depending +* y: An ND tensor of type float16, float32. The shape of y is depending * on axes and keepdim. \n * @par Third-party framework compatibility @@ -932,11 +942,13 @@ REG_OP(LpNorm) * @brief get complex. * @par Inputs: -* @li real: An ND tensor of type float32. double -* @li imag: An ND tensor of type float32. double \n +* @li real: An ND tensor of type float32 double, representing the real part of a complex number. +* @li imag: An ND tensor of type float32 double, representing the imaginary part of a complex number. \n * +* @par Attributes: +* Tout: representing the output of type. * @par Outputs: -* @li out: An ND tensor of type complex64, complex128 \n +* out: An ND tensor of type complex64, complex128 \n */ REG_OP(Complex) .INPUT(real, TensorType({DT_FLOAT, DT_DOUBLE})) @@ -949,10 +961,13 @@ REG_OP(Complex) * @brief deal complex. * @par Inputs: -* @li input: An ND tensor of type complex64, complex128 \n -* +* input: An ND tensor of type complex64, complex128 \n + +* @par Attributes: +* Tout: representing the output of type. + * @par Outputs: -* @li output: An ND tensor of type float32. double \n +* output: An ND tensor of type float32. double \n */ REG_OP(Imag) .INPUT(input, TensorType({DT_COMPLEX64, DT_COMPLEX128})) @@ -988,7 +1003,7 @@ REG_OP(Angle) * float16, float32. \n *@par Attributes: -* @li reduction: Specifies the reduction to apply to the output: +* reduction: Specifies the reduction to apply to the output: * 'none' | 'mean' | 'sum'. Default: 'mean'. \n *@par Outputs: diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index b317be37..81c6a29e 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -61,21 +61,28 @@ REG_OP(MatMul) *@brief Multiplies matrix "a" by matrix "b", producing "a * b" . \n *@par Inputs: -*Two inputs, including: -* @li x1: A matrix Tensor. 2D. Must be one of the following types: float16, -* float32, int32. Has format [ND, NHWC, FRACTAL_NZ]. -* @li x2: A matrix Tensor. 2D. Must be one of the following types: float16, -* float32, int32. Has format [ND, NHWC, FRACTAL_NZ]. -* @li bias: A 1D Tensor. Must be one of the following types: float16, -* float32, int32. Has format [ND, NHWC] . \n +*Four inputs, including: +* @li x1: A matrix Tensor. 2D. Must be one of the following types: float32, + float16, int32, int8. Has format [ND, NHWC, FRACTAL_NZ]. +* @li x2: A matrix Tensor. 2D. Must be one of the following types: float32, + float16, int32, int8. Has format [ND, NHWC, FRACTAL_NZ]. +* @li bias: A 1D Tensor. Must be one of the following types: float32, + float16, int32. Has format [ND, NHWC]. +* @li offset_w: A Optional 1D Tensor for quantized inference. Type is int8. + Reserved. \n *@par Attributes: -*@li transpose_x1: A bool. If True, changes the shape of "x1" from [M, K] to [K, M]. -*@li transpose_x2: A bool. If True, changes the shape of "x2" from [M, K] to [K, M] . \n +* @li transpose_x1: A bool. If True, changes the shape of "x1" from [K, M] to + [M, K]. +* @li transpose_x2: A bool. If True, changes the shape of "x2" from [N, K] to +[K, N]. +* @li offset_x: An optional integer for quantized MatMulV2. +* The negative offset added to the input x1 for int8 type. Ensure offset_x + within the effective range of int8 [-128, 127]. Defaults to "0". \n *@par Outputs: -*y: The result matrix Tensor. 2D. Must be one of the following types: float16, -* float32, int32. Has format [ND, NHWC, FRACTAL_NZ] . \n +*y: The result matrix Tensor. 2D. Must be one of the following types: float32, + float16, int32. Has format [ND, NHWC, FRACTAL_NZ]. \n *@par Third-party framework compatibility * Compatible with the TensorFlow operator BatchMatmul. @@ -95,19 +102,27 @@ REG_OP(MatMulV2) *@brief Multiplies matrix "a" by matrix "b", producing "a * b" . \n *@par Inputs: -*Two inputs, including: +*Five inputs, including: * @li x1: A matrix Tensor. 2D. Must be one of the following types: int8. * @li x2: A matrix Tensor. 2D. Must be one of the following types: int8. * @li compress_index: A compress index matrix of type int8. -* @li bias: A 1D Tensor. Must be one of the following types: int32, float16. +* @li bias: An optional Tensor. 1D. Must be one of the following types: int32, + float16. +* @li offset_w: An optional matrix Tensor. 2D. Must be one of the following + types: int8. \n *@par Attributes: -*@li transpose_x1: A bool. If True, changes the shape of "x1" from [M, K] to [K, M]. -*@li transpose_x2: A bool. If True, changes the shape of "x2" from [M, K] to [K, M] . \n +*@li transpose_x1: A bool. If True, changes the shape of "x1" from [K, M] to + [M, K]. +*@li transpose_x2: A bool. If True, changes the shape of "x2" from [N, K] to + [K, N]. +*@li offset_x: An optional integer for quantized MatMulV2Compress. +*The negative offset added to the input x1 for int8 type. Ensure offset_x + within the effective range of int8 [-128, 127]. Defaults to "0". \n *@par Outputs: -*y: The result matrix Tensor. 2D. Must be one of the following types: float16, -* int32. \n +*y: The result matrix Tensor. 2D. Must be one of the following types: int32, +* float16. \n */ REG_OP(MatMulV2Compress) @@ -488,13 +503,13 @@ REG_OP(ScatterElements) *@par Inputs: * Three inputs, including: -*@li var: An ND Tensor . \n +*@li var: An ND Tensor . *Must be one of the following types: float16, float32, int32, int8, uint8 *@li indices: An ND Tensor of type int32 or int64 -*@li updates: An Tensor. format:NCHW, NHWC . \n +*@li updates: An Tensor. format:NCHW, NHWC . *Must be one of the following types: float16, float32, int32, int8, uint8 @@ -516,6 +531,61 @@ REG_OP(ScatterAdd) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterAdd) +/** +*@brief Use a scalar to modify the tensor. \n + +*@par Inputs: +*inputs, including: +*@li index: An ND Tensor . \n + +*Must be one of the following types: float16, float32, int32, int8, uint8 + +*@par Attributes: +* dim : the axis along which to index . +* value : the source element(s) to scatter . \n + +*@par Outputs: +*y: A Tensor. Has the same type and format as input "index" . \n + +*@par Third-party framework compatibility +* Compatible with the Pytorch operator ScatterScalar. +*/ +REG_OP(ScatterScalar) + .INPUT(index, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .REQUIRED_ATTR(dim, Int) + .REQUIRED_ATTR(value, Float) + .OP_END_FACTORY_REG(ScatterScalar) + +/** +*@brief Use a tensor to modify the tensor . \n + +*@par Inputs: +* Two inputs, including: +*@li index: An ND Tensor . \n + +*Must be one of the following types: float16, float32, int32, int8, uint8 + +*@li src: An ND Tensor . \n + +*Must be one of the following types: float16, float32, int32, int8, uint8 + +*@par Attributes: +* dim : the axis along which to index . \n + +*@par Outputs: +*y: A Tensor. Has the same type and format as input "index" . \n + +*@par Third-party framework compatibility +* Compatible with the Pytorch operator ScatterTensor. +*/ +REG_OP(ScatterTensor) + .INPUT(index, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(src, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .REQUIRED_ATTR(dim, Int) + .OP_END_FACTORY_REG(ScatterTensor) + /** *@brief Divides a variable reference by sparse updates . \n @@ -530,7 +600,7 @@ REG_OP(ScatterAdd) *Must be one of the following types: float16, float, int32, int8, uint8 *@par Attributes: -*@li use_locking: An optional bool. Defaults to "False". If "True", +*use_locking: An optional bool. Defaults to "False". If "True", * the operation will be protected by a lock . \n *@par Outputs: @@ -752,10 +822,12 @@ REG_OP(DiagPart) *@par Attributes: *@li num_output: Reserved. -*@li transpose: A bool, specifying weight whether to transpose, either "true" or "false". Defaults to "false". +*@li transpose: A bool, specifying weight whether to transpose input w, either "true" or "false". Defaults to "false". *@li axis: Optional. A int, 1 or 2, specifying which dimension the input "K" starts from. Defaults to 1. * The product of the subsequent dimensions starting form first dimension or the second dimension is "K". -*@li offset_x: Reserved . \n +*@li offset_x: An optional integer for quantized FullyConnection. +*The negative offset added to the input image for int8 type. Ensure offset_x within the +*effective range of int8 [-128, 127]. Defaults to "0". \n *@par Outputs: *y: The result tensor of type float16, int32, float32 . \n @@ -779,27 +851,34 @@ REG_OP(FullyConnection) .OP_END_FACTORY_REG(FullyConnection) /** -*@brief Also known as a "fully-connected-compress" layer, computes an inner product with a set of learned weights, and (optionally) adds biases . \n +*@brief Also known as a "fully-connected-compress" layer, computes an inner +product with a set of learned weights, and (optionally) adds biases . \n *@par Inputs: -* Four inputs, including: +* Five inputs, including: *@li x: A Tensor of type uint8, int8. -*@li w: A weight matrix of type int8, int8. -*@li w: A compress index matrix of type int8, int8. -*@li b: A Tensor of type float16, int32, int32. -*@li offset_w: A Tensor of type int8.i +*@li w: A weight matrix of type int8. +*@li compress_index: A compress index matrix of type int8. +*@li b: A Tensor of type int32. +*@li offset_w: A Tensor of type int8. *@par Attributes: -*@li num_output: Reserved. -*@li transpose: A bool, specifying whether to transpose, either "true" or "false". Defaults to "false". -*@li axis: Reserved. -*@li offset_x: Reserved . \n +*@li num_output: A int, specifying the number of outputs. +*@li transpose: A bool, specifying whether to transpose input w, either "true" + or "false". Defaults to "false". +*@li axis: Optional. A int, 1 or 2, specifying which dimension the input "K" +starts from. Defaults to "1". +* The product of the subsequent dimensions starting form first dimension or the +second dimension is "K". +*@li offset_x: An optional integer for quantized FullyConnectionCompress. +*The negative offset added to the input image for int8 type. Ensure offset_x +within the effective range of int8 [-128, 127]. Defaults to "0". \n *@par Outputs: -*y: The result tensor of type int32 . \n +*y: The result tensor of type int32. \n *@par Third-party framework compatibility -* Compatible with the Caffe operator InnerProduct . \n +* Compatible with the Caffe operator InnerProduct. \n *@par Quantization supported or not * Yes @@ -925,13 +1004,13 @@ REG_OP(ScatterMin) *@par Inputs: * Three inputs, including: -*@li var: An ND Tensor . \n +*@li var: An ND Tensor . *Must be one of the following types: float16, float, int32, int8, uint8 *@li indices: An NCHW, NHWC, or ND Tensor . \n *Must be one of the following types: int32 or int64 -*@li updates: An NCHW, NHWC, or ND Tensor . \n +*@li updates: An NCHW, NHWC, or ND Tensor . *Must be one of the following types: float16, float, int32, int8, uint8 @@ -958,13 +1037,13 @@ REG_OP(ScatterMax) *@par Inputs: * Three inputs, including: -*@li var: An ND Tensor . \n +*@li var: An ND Tensor . *Must be one of the following types: float16, float, int32, int8, uint8 *@li indices: An ND Tensor . \n *Must be one of the following types: int32 or int64 -*@li updates: An ND Tensor . \n +*@li updates: An ND Tensor . *Must be one of the following types: float16, float, int32, int8, uint8 @@ -1112,15 +1191,47 @@ REG_OP(IndexAdd) .ATTR(axis, Int, 0) .OP_END_FACTORY_REG(IndexAdd) +/** +* @brief According to the index number of indexes, replace the value +*corresponding to X1 with the value in x2. + +* @par Inputs: +* Three inputs, including: +* @li x1: A Tensor. Must be one of the following types: +* float16, float32, int32, int8, uint8. +* @li x2: A Tensor of the same type as "x1". +* @li indices: A Tensor of the indices, type should be int32. + +* @par Attributes: +* @li accumulate: Does it support self accumulation.Defaults to 0. + +* @par Outputs: +* @li y: A Tensor. Same as input "x1". + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator index_put. + +* @par Restrictions: +* Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(IndexPut) + .INPUT(x1, TensorType({DT_INT64, DT_INT32, DT_INT8, DT_UINT8, DT_FLOAT32, DT_FLOAT16})) + .INPUT(x2, TensorType({DT_INT64, DT_INT32, DT_INT8, DT_UINT8, DT_FLOAT32, DT_FLOAT16})) + .INPUT(indices, TensorType({DT_INT64, DT_INT32})) + .OUTPUT(y, TensorType({DT_INT64, DT_INT32, DT_INT8, DT_UINT8, DT_FLOAT32, DT_FLOAT16})) + .ATTR(accumulate, Int, 0) + .OP_END_FACTORY_REG(IndexPut) + /** *@brief: Returns the upper triangular part of a matrix (2-D tensor) or batch of matrices input \n *@par Inputs: -* Two inputs, including: -*@li x: A Tensor. Must be one of the following types: -* float16, float32, double, int32, uint8, int16, int8, complex64, int64, -* qint8, quint8, qint32, uint16, complex128, uint32, uint64. -*@li diagonal:(int, optional) – the diagonal to consider。\n +*x: A Tensor. Must be one of the following types: +*float16, float32, double, int32, uint8, int16, int8, complex64, int64, +*qint8, quint8, qint32, uint16, complex128, uint32, uint64. \n + +*@par Attributes: +*diagonal: An optional attribute indicates the diagonal to consider. \n *@par Outputs: *y: A Tensor. Has the same type as "x" . \n @@ -1138,11 +1249,12 @@ REG_OP(Triu) *@brief: Returns the upper triangular part of a matrix (2-D tensor) or batch of matrices input \n *@par Inputs: -* Two inputs, including: -*@li x: A Tensor. Must be one of the following types: -* float16, float32, double, int32, uint8, int16, int8, complex64, int64, -* qint8, quint8, qint32, uint16, complex128, uint32, uint64. -*@li diagonal:(int, optional) – the diagonal to consider。\n +*x: A Tensor. Must be one of the following types: +*float16, float32, double, int32, uint8, int16, int8, complex64, int64, +*qint8, quint8, qint32, uint16, complex128, uint32, uint64. \n + +*@par Attributes: +*diagonal: An optional attribute indicates the diagonal to consider. \n *@par Outputs: *y: A Tensor. Has the same type as "x" . \n @@ -1213,6 +1325,30 @@ REG_OP(Eye) .ATTR(dtype, Int, 0) .OP_END_FACTORY_REG(Eye) +/** +*@brief: Fill diagonal of at least 2 dimension tensors with value . \n + +*@par Inputs: +*x: A Tensor. Must be one of the following types: +* float32, int32, int64 . \n + +*@par Outputs: +*y: A Tensor. Has the same type as "x" . \n + +*@par Attributes: +*fill_value:The value to fill in +*wrap: An optional bool. Defaults to "False". If "True", Use recursive fill. \n + +*@par Third-party framework compatibility +* Compatible with the Pytorch operator FillDiagonal. +*/ +REG_OP(FillDiagonal) + .INPUT(x, TensorType({DT_FLOAT, DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_INT32, DT_INT64})) + .REQUIRED_ATTR(fill_value, Float) + .ATTR(wrap, Bool, false) + .OP_END_FACTORY_REG(FillDiagonal) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATRIX_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h index 98473c65..a55cebe2 100644 --- a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h @@ -195,7 +195,7 @@ REG_OP(DepthwiseConv2DBackpropInput) .INPUT(input_size, TensorType({DT_INT32, DT_INT64})) .INPUT(filter, TensorType({DT_FLOAT16})) .INPUT(out_backprop, TensorType({DT_FLOAT16})) - .OUTPUT(input_grad, TensorType({DT_FLOAT16})) + .OUTPUT(input_grad, TensorType({DT_FLOAT16, DT_FLOAT32})) .REQUIRED_ATTR(strides, ListInt) .ATTR(dilations, ListInt, {1, 1, 1, 1}) .REQUIRED_ATTR(pads, ListInt) @@ -255,7 +255,7 @@ REG_OP(DepthwiseConv2DBackpropInput) REG_OP(DepthwiseConv2DBackpropInputD) .INPUT(filter, TensorType({DT_FLOAT16})) .INPUT(out_backprop, TensorType({DT_FLOAT16})) - .OUTPUT(input_grad, TensorType({DT_FLOAT16})) + .OUTPUT(input_grad, TensorType({DT_FLOAT16, DT_FLOAT32})) .REQUIRED_ATTR(input_size, ListInt) .REQUIRED_ATTR(strides, ListInt) .ATTR(dilations, ListInt, {1, 1, 1, 1}) @@ -367,19 +367,19 @@ REG_OP(BiasAddGrad) * Gradients with respect to the output of the convolution. *\n *\n - * The following are the supported data types and data formats: -*@verbatim - | Tensor | out_bckprop | filter | y - ------------|-------------|---------|-------- - | Data Type | float16 | float16 | float16 - | |-------------|---------|-------- - | | float32 | float32 | float32 - | |-------------|---------|-------- - | | float64 | float64 | float64 - ------------|-------------|---------|-------- - | Format | NCHW | NCHW | NCHW - | | NHWC | HWCN | NHWC -@endverbatim + * The following are the supported data types and data formats:\n + *\n + | Tensor | out_bckprop | filter | y\n + ------------|-------------|---------|--------\n + | Data Type | float16 | float16 | float16\n + | |-------------|---------|--------\n + | | float32 | float32 | float32\n + | |-------------|---------|--------\n + | | float64 | float64 | float64\n + ------------|-------------|---------|--------\n + | Format | NCHW | NCHW | NCHW\n + | | NHWC | HWCN | NHWC\n + *\n * For float32 and float64 type, the actual calculation on the chip is based on * float16. *\n @@ -398,36 +398,37 @@ REG_OP(BiasAddGrad) * "NHWC". Specify the data format of the input and output data. *\n *\n - * The following value range restrictions must be met: -*@verbatim - | Name | Field | Scope - -------------------|----------|-------------- - | input_size | H | [1, 4096] - | | W | [1, 4096] - -------------------|----------|-------------- - | Filter | H | [1, 255] - | | W | [1, 255] - -------------------|----------|-------------- - | out_backprop | H*strideH| [1, 4096] - | | W*strideW| [1, 4096] - -------------------|----------|-------------- - | y(fmap) | H | [1, 4096] - | | W | [1, 4096] - -------------------|----------|-------------- - | Stride | H | [1, 63] - | | W | [1, 63] - -------------------|----------|-------------- - | Padding | Top | [0, 255] - | | Bottom | [0, 255] - | | Left | [0, 255] - | | Right | [0, 255] - -------------------|----------|-------------- - | Dilation | H | [1, 255] - | | W | [1, 255] + * The following value range restrictions must be met:\n + *\n + | Name | Field | Scope\n + -------------------|----------|--------------\n + | input_size | H | [1, 200000]\n + | | W | [1, 4096]\n + -------------------|----------|--------------\n + | Filter | H | [1, 255]\n + | | W | [1, 255]\n + -------------------|----------|--------------\n + | out_backprop | H*strideH| [1, 200000]\n + | | W*strideW| [1, 4096]\n + -------------------|----------|--------------\n + | y(fmap) | H | [1, 200000]\n + | | W | [1, 4096]\n + -------------------|----------|--------------\n + | Stride | H | [1, 63]\n + | | W | [1, 63]\n + -------------------|----------|--------------\n + | Padding | Top | [0, 255]\n + | | Bottom | [0, 255]\n + | | Left | [0, 255]\n + | | Right | [0, 255]\n + -------------------|----------|--------------\n + | Dilation | H | [1, 255]\n + | | W | [1, 255]\n + *\n -@endverbatim * In Ascend910, fmap or out_backprop's H and W not support 1 when * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 + * and filter_width > fmap_width * If filter_h = 1 and filter_w = 1, out_backprop_w * stride_h * stride_w < 4096 *\n * @@ -496,7 +497,7 @@ REG_OP(Conv2DBackpropInput) REG_OP(Conv2DBackpropInputD) .INPUT(filter, TensorType({DT_FLOAT16, DT_INT8})) .INPUT(out_backprop, TensorType({DT_FLOAT16, DT_INT8})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_INT32, DT_FLOAT32})) .REQUIRED_ATTR(input_size, ListInt) .REQUIRED_ATTR(strides, ListInt) .REQUIRED_ATTR(pads, ListInt) @@ -508,7 +509,7 @@ REG_OP(Conv2DBackpropInputD) /** *@brief Computes the Deconvolution with respect to the input. *@par Inputs: - * Three inputs: + * Two required inputs: * @li x: A Tensor of type float16 or int8. 4D with shape * [batch, out_channels, out_height, out_width]. Gradients with respect * to the output of the convolution. @@ -520,16 +521,16 @@ REG_OP(Conv2DBackpropInputD) * Type is int8. Reserved.\n *\n *\n - * The following are the supported data types and data formats: -*@verbatim - | Tensor | x | filter | bias | y - ------------|---------|---------|---------|-------- - | Data Type | float16 | float16 | float16 | float16 - | |---------|---------|---------|-------- - | | int8 | int8 | int32 | int32 - ------------|---------|---------|---------|-------- - | Format | NCHW | NCHW | ND | NCHW -@endverbatim + * The following are the supported data types and data formats:\n + *\n + | Tensor | x | filter | bias | y\n + ------------|---------|---------|---------|--------\n + | Data Type | float16 | float16 | float16 | float16\n + | |---------|---------|---------|--------\n + | | int8 | int8 | int32 | int32\n + ------------|---------|---------|---------|--------\n + | Format | NCHW | NCHW | ND | NCHW\n + *\n * For int8, a dequant or requant operator must be followed. *\n * @@ -550,35 +551,35 @@ REG_OP(Conv2DBackpropInputD) * within the effective range of int8 [-128, 127]. Defaults to "0". *\n *\n - * The following value range restrictions must be met: -*@verbatim - | Name | Field | Scope - -------------------|----------|-------------- - | x (out_backprop) | H*strideH| [1, 4096] - | | W*strideW| [1, 4096] - -------------------|----------|-------------- - | Filter | H | [1, 255] - | | W | [1, 255] - -------------------|----------|-------------- - | y (fmap) | H | [1, 4096] - | | W | [1, 4096] - -------------------|----------|-------------- - | Stride | H | [1, 63] - | | W | [1, 63] - -------------------|----------|-------------- - | Padding | Top | [0, 255] - | | Bottom | [0, 255] - | | Left | [0, 255] - | | Right | [0, 255] - -------------------|----------|-------------- - | Dilation | H | [1, 255] - | | W | [1, 255] - -------------------|----------|-------------- - | Offset_x | | [-128, 127] - -@endverbatim + * The following value range restrictions must be met:\n + *\n + | Name | Field | Scope\n + -------------------|----------|--------------\n + | x (out_backprop) | H*strideH| [1, 200000]\n + | | W*strideW| [1, 4096]\n + -------------------|----------|--------------\n + | Filter | H | [1, 255]\n + | | W | [1, 255]\n + -------------------|----------|--------------\n + | y (fmap) | H | [1, 200000]\n + | | W | [1, 4096]\n + -------------------|----------|--------------\n + | Stride | H | [1, 63]\n + | | W | [1, 63]\n + -------------------|----------|--------------\n + | Padding | Top | [0, 255]\n + | | Bottom | [0, 255]\n + | | Left | [0, 255]\n + | | Right | [0, 255]\n + -------------------|----------|--------------\n + | Dilation | H | [1, 255]\n + | | W | [1, 255]\n + -------------------|----------|--------------\n + | Offset_x | | [-128, 127]\n + *\n * In Ascend910, fmap or out_backprop's H and W not support 1 when * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 + * and filter_width > fmap_width * If filter_h = 1 and filter_w = 1, out_backprop_w * stride_h * stride_w < 4096 *\n * @@ -628,19 +629,19 @@ REG_OP(Deconvolution) * convolution. *\n *\n - * The following are the supported data types and data formats: -*@verbatim - | Tensor | x | out_backprop | y - ------------|---------|--------------|--------- - | Data Type | float16 | float16 | float16 - | |---------|--------------|--------- - | | float32 | float32 | float32 - | |---------|--------------|--------- - | | float64 | float64 | float64 - |-----------|---------|--------------|--------- - | Format | NCHW | NCHW | NCHW - | | NHWC | NHWC | HWCN -@endverbatim + * The following are the supported data types and data formats:\n + *\n + | Tensor | x | out_backprop | y\n + ------------|---------|--------------|---------\n + | Data Type | float16 | float16 | float16\n + | |---------|--------------|---------\n + | | float32 | float32 | float32\n + | |---------|--------------|---------\n + | | float64 | float64 | float64\n + |-----------|---------|--------------|---------\n + | Format | NCHW | NCHW | NCHW\n + | | NHWC | NHWC | HWCN\n + *\n * For float32 and float64 type of x and outbackprop, the actual calculation on the chip * is based on float16. *\n @@ -658,39 +659,34 @@ REG_OP(Deconvolution) * @li data_format: An optional string from: "NHWC", "NCHW". Defaults to * "NHWC". Specify the data format of the input and output data. *\n -*\n -* The following value range restrictions must be met: -*@verbatim - | Name | Field | Scope - -------------------|----------|-------------- - | x(fmap) | H | [1, 4096] - | | W | [1, 4096] - -------------------|----------|-------------- - | Filter Size | H | [1, 255] - | | W | [1, 255] - -------------------|----------|-------------- - | out_backprop | H | [1, 4096] - | | W | [1, 4096] - -------------------|----------|-------------- - | y | H | [1, 4096] - | | W | [1, 4096] - -------------------|----------|-------------- - | Stride | H | [1, 63] - | | W | [1, 63] - -------------------|----------|-------------- - | Padding | Top | [0, 255] - | | Bottom | [0, 255] - | | Left | [0, 255] - | | Right | [0, 255] - -------------------|----------|-------------- - | Dilation | H | [1, 255] - | | W | [1, 255] - -@endverbatim - * In Ascend910, out_backprop's H and W not support 1 when - * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 *\n - * + * The following value range restrictions must be met:\n + *\n + | Name | Field | Scope\n + -------------------|----------|--------------\n + | x(fmap) | H | [1, 200000]\n + | | W | [1, 4096]\n + -------------------|----------|--------------\n + | Filter Size | H | [1, 255]\n + | | W | [1, 255]\n + -------------------|----------|--------------\n + | out_backprop | H | [1, 200000]\n + | | W | [1, 4096]\n + -------------------|----------|--------------\n + | y | H | [1, 200000]\n + | | W | [1, 4096]\n + -------------------|----------|--------------\n + | Stride | H | [1, 63]\n + | | W | [1, 63]\n + -------------------|----------|--------------\n + | Padding | Top | [0, 255]\n + | | Bottom | [0, 255]\n + | | Left | [0, 255]\n + | | Right | [0, 255]\n + -------------------|----------|--------------\n + | Dilation | H | [1, 255]\n + | | W | [1, 255]\n + *\n *@par Outputs: * y: A Tensor. Has the same type as x, has the same format as filter_size. *\n @@ -780,16 +776,16 @@ REG_OP(Conv2DBackpropFilterD) *\n *\n * The following are the supported data types and data formats: -*@verbatim - | Tensor | x | filter | bias | y - ------------|---------|---------|---------|-------- - | Data Type | float16 | float16 | float16 | float16 - | | float32 | float32 | float32 | float32 - | | int8 | int8 | int32 | int32 - ------------|---------|---------|---------|-------- - | Format | NCHW | NCHW | ND | NCHW - | | NHWC | HWCN | | NHWC -@endverbatim +*\n +*\n +| Tensor | x | filter | bias | y |\n +| :-------: | :-----: | :-----: | :-----: | :-----: |\n +| Data Type | float16 | float16 | float16 | float16 |\n +| | float32 | float32 | float32 | float32 |\n +| | int8 | int8 | int32 | int32 |\n +| Format | NCHW | NCHW | ND | NCHW |\n +| | NHWC | HWCN | | NHWC |\n +*\n * For float32 type, the actual calculation on the chip is based on * float16. *\n @@ -813,35 +809,30 @@ REG_OP(Conv2DBackpropFilterD) *\n *\n * The following value range restrictions must be met: -*@verbatim - | Name | Field | Scope - -------------------|----------|-------------- - | Input Image Size | H | [1, 100000] - | | W | [1, 4096] - -------------------|----------|-------------- - | Filter Size | H | [1, 255] - | | W | [1, 255] - -------------------|----------|-------------- - | Stride | H | [1, 63] - | | W | [1, 63] - -------------------|----------|-------------- - | Padding | Top | [0, 255] - | | Bottom | [0, 255] - | | Left | [0, 255] - | | Right | [0, 255] - -------------------|----------|-------------- - | Dilation | H | [1, 255] - | | W | [1, 255] - -------------------|----------|-------------- - | Offset_x | | [-128, 127] - -@endverbatim +*\n +*\n +| Name | Field | Scope |\n +| :--------------: | :------: | :---------: |\n +| Input Image Size | H | [1, 100000] |\n +| | W | [1, 4096] |\n +| Filter Size | H | [1, 255] |\n +| | W | [1, 255] |\n +| Stride | H | [1, 63] |\n +| | W | [1, 63] |\n +| Padding | Top | [0, 255] |\n +| | Bottom | [0, 255] |\n +| | Left | [0, 255] |\n +| | Right | [0, 255] |\n +| Dilation | H | [1, 255] |\n +| | W | [1, 255] |\n +| Offset_x | - | [-128, 127] |\n +*\n * The W dimension of the input image supports cases exceeding 4096, but it may * cause compilation errors. *\n * *@par Outputs: -*@li y: A 4D Tensor of output feature map. Has the same type as "x". With the +* y: A 4D Tensor of output feature map. Has the same type as "x". With the * format "NHWC", the data is stored in the order of: [batch, out_height, * out_width, out_channels]. *\n @@ -956,16 +947,15 @@ REG_OP(Conv2DCompress) *\n *\n * The following are the supported data types and data formats: -*@verbatim - | Tensor | x | filter | offsets | bias | y - ------------|---------|---------|---------|----------|-------- - | Data Type | float16 | float16 | float16 | float16 | float16 - | |---------|---------|---------|----------|-------- - | | float32 | float32 | float32 | float32 | float32 - ------------|---------|---------|---------|----------|-------- - | Format | NCHW | NCHW | NCHW | ND | NCHW - | | NHWC | HWCN | NHWC | | NHWC -@endverbatim +*\n +*\n +| Tensor | x | filter | offsets | bias | y |\n +| :-------: | :-----: | :-----: | :-----: | :-----: | :-----: |\n +| Data Type | float16 | float16 | float16 | float16 | float16 |\n +| | float32 | float32 | float32 | float32 | float32 |\n +| Format | NCHW | NCHW | NCHW | ND | NCHW |\n +| | NHWC | HWCN | NCHW | | NHWC |\n +*\n * For float32 type, the actual convolution calculation part on the chip is * based on float16. *\n @@ -992,19 +982,18 @@ REG_OP(Conv2DCompress) *\n *\n * The following value range restrictions must be met: -*@verbatim - | Name | Field | Scope - --------------------|--------|---------------------------- - | Input Image Size | H | [1, 100000 / filter_height] - | | W | [1, 4096 / filter_width] - --------------------|--------|---------------------------- - | Filter Size | H | [1, 63] - | | W | [1, 63] -@endverbatim +*\n +*\n +| Name | Field | Scope |\n +| :--------------: | :------: | :-------------------------: |\n +| Input Image Size | H | [1, 100000 / filter_height] |\n +| | W | [1, 4096 / filter_width] |\n +| Filter Size | H | [1, 63] |\n +| | W | [1, 63] |\n *\n * *@par Outputs: -*@li y: A 4D Tensor of output feature map. Has the same type as "x". With the +* y: A 4D Tensor of output feature map. Has the same type as "x". With the * format "NHWC", the data is stored in the order of: [batch, out_height, * out_width, out_channels]. *\n @@ -1042,41 +1031,38 @@ REG_OP(DeformableConv2D) /** *@brief Computes a 3D convolution given 5D "x" and "filter" tensors. - *@par Inputs: + +*@par Inputs: * @li x: A 5D tensor. Must be one of the following types: float16, * (Currently does not support int8). The format of x is NCDHW or NDHWC. * @li filter: A 5D tensor of the same type as "x". * (Currently does not support int8). - * The format is NCDHW, NDHWC or DHWCN . \n - -*@par Optional input: - * @li bias: An optional 1D tensor of the same type as "x". - * @li offset_w: An optional 1D tensor for quantized deconvolution. Reserved . \n + * The format is NCDHW, NDHWC or DHWCN. + * @li bias: Optional. An 1D tensor of the same type as "x". + * @li offset_w: Optional. An 1D tensor for quantized deconvolution. Reserved. \n -*@par Required Attributes: - * @li strides: A list of 5 integers. Specifies the stride of the sliding window +*@par Attributes: + * @li strides: Required. A list of 5 integers. Specifies the stride of the sliding window * for each dimension of "x". * The N and C dimensions must be 1. Has the same format as "x". - * @li pads: A list of 6 integers. + * @li pads: Required. A list of 6 integers. * Supports only padding along the D, H and W dimensions in sequence of head, - * tail, top, bottom, left and right . \n - -*@par Attributes: - * @li groups: Number of blocked connections from input channels to output + * tail, top, bottom, left and right. + * @li dilations: Optional. A list of 5 integers. Specifies the dilation factor for each + * dimension of "x". + * @li groups: Optional. Number of blocked connections from input channels to output * channels. - * @li data_format: An optional string from: "NDHWC", "NCDHW". + * @li data_format: Optional. An string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. - * @li dilations: A list of 5 integers. Specifies the dilation factor for each - * dimension of "x". * The N, C and D dimensions must be 1. Has the same format as "x". - * @li offset_x: An optional int. Input offset, used for quantized inference. - * Defaults to 0. Reserved . \n + * @li offset_x: Optional. An int. Input offset, used for quantized inference. + * Defaults to 0. Reserved. \n *@par Outputs: - *y: A Tensor. Has the same type and data format as "x". \n + * y: A Tensor. Has the same type and data format as "x". \n *@attention Constraints: - *The image size after padding is greater than the filter size . \n + * The image size after padding is greater than the filter size. \n *@par Third-party framework compatibility * @li Compatible with the TensorFlow operator conv3d. @@ -1085,9 +1071,9 @@ REG_OP(DeformableConv2D) REG_OP(Conv3D) .INPUT(x, TensorType({DT_FLOAT16})) .INPUT(filter, TensorType({DT_FLOAT16})) - .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT16, DT_FLOAT32})) .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8})) - .OUTPUT(y, TensorType({DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT32})) .REQUIRED_ATTR(strides, ListInt) .REQUIRED_ATTR(pads, ListInt) .ATTR(dilations, ListInt, {1, 1, 1, 1, 1}) @@ -1099,8 +1085,8 @@ REG_OP(Conv3D) /** *@brief Computes the gradients of convolution 3d with respect to the input. + *@par Inputs: - * Three inputs: * @li input_size: A Tensor of type int32, int64. An integer vector representing * the shape of input, where input is a 5-D tensor * [batch, depth, height, width, channels] or @@ -1110,28 +1096,25 @@ REG_OP(Conv3D) * @li out_backprop: A Tensor. Must have the same type as filter. * 5-D with shape [batch, depth, out_height, out_width, out_channels] * or [batch, out_channels, depth, out_height, out_width]. Gradients with - * respect to the output of the convolution . \n + * respect to the output of the convolution. \n -*@par Required Attributes: - * @li strides: A list of 5 integers. Specifies the stride of the sliding window +*@par Attributes: + * @li strides: Required. A list of 5 integers. Specifies the stride of the sliding window * for each dimension of "out_backprop". * The N and C dimensions must be 1. Has the same format as "out_backprop". - * @li pads: A list of 6 integers. + * @li pads: Required. A list of 6 integers. * Supports only padding along the D, H and W dimensions in sequence of head, - * tail, top, bottom, left and right . \n - -*@par Attributes: - * Three attributes: - * @li groups: Number of blocked connections from input channels to output - * channels. - * @li data_format: An optional string from: "NDHWC", "NCDHW". - * Defaults to "NDHWC". Specify the data format of the input and output data. - * @li dilations: A tuple/list of 5 integers, The dilation factor for each + * tail, top, bottom, left and right. + * @li dilations: Optional. A tuple/list of 5 integers, The dilation factor for each * dimension of the input. * The N, C and D dimensions must be 1. Has the same format as "out_backprop". + * @li groups: Optional. Number of blocked connections from input channels to output + * channels. + * @li data_format: Optional. An string from: "NDHWC", "NCDHW". + * Defaults to "NDHWC". Specify the data format of the input and output data. \n *@par Outputs: - * y: A Tensor. Has the same type as filter,and has same format as "input_size" + * y: A Tensor. Has the same type as filter,and has same format as "input_size". \n *@par Third-party framework compatibility * Compatible with Tensorflow's conv3d_backprop_input @@ -1150,45 +1133,44 @@ REG_OP(Conv3DBackpropInput) /** *@brief Computes the gradients of convolution 3d with respect to the input. + *@par Inputs: - * Two inputs: * @li filter: A Tensor whose type is float16. The format of filter is NCDHW, * NDHWC or DHWCN. * @li out_backprop: A Tensor. Must have the same type as filter. The format is - * NDHWC or NCDHW. \n + * NDHWC or NCDHW. \n -*@par Required Attributes: - * @li strides: A list of 5 integers. Specifies the stride of the sliding window +*@par Attributes: + * @li input_size: Required. A tuple/list of type int32, int64. An integer vector + * representing the shape of input, where input is a 5-D tensor + * [batch, depth, height, width, channels] or + * [batch, channels, depth, height, width]. + * @li strides: Required. A list of 5 integers. Specifies the stride of the sliding window * for each dimension of "out_backprop". * The N and C dimensions must be 1. Has the same format as "out_backprop". - * @li pads: A list of 6 integers. Supports only padding along the D, H and W + * @li pads: Required. A list of 6 integers. Supports only padding along the D, H and W * dimensions in sequence of head, tail, top, bottom, left and right. - * @li input_size: A tuple/list of type int32, int64. An integer vector - * representing the shape of input, where input is a 5-D tensor - * [batch, depth, height, width, channels] or - * [batch, channels, depth, height, width] . \n - -*@par Attributes: - * Three attributes: - * @li groups: Number of blocked connections from input channels to output - * channels. - * @li data_format: An optional string from: "NDHWC", "NCDHW". - * Defaults to "NDHWC". Specify the data format of the input and output data. - * @li dilations: A tuple/list of 5 integers, The dilation factor for each + * @li dilations: Optional. A tuple/list of 5 integers, The dilation factor for each * dimension of input. * The N, C and D dimensions must be 1. Has the same format as "out_backprop". + * @li groups: Optional. Number of blocked connections from input channels to output + * channels. + * @li data_format: Optional. An string from: "NDHWC", "NCDHW". + * Defaults to "NDHWC". Specify the data format of the input and output data. \n + *@par Outputs: - * y: A Tensor. Has the same type and data format as "out_backprop". + * y: A Tensor. Has the same type and data format as "out_backprop". \n + *@par Third-party framework compatibility - * Compatible with Tensorflow's conv3d_backprop_input + * Compatible with Tensorflow's conv3d_backprop_input. \n *@par Restrictions: -* Warning: THIS FUNCTION IS DEPRECATED. Please use Conv3DBackpropInput instead. + * Warning: THIS FUNCTION IS DEPRECATED. Please use Conv3DBackpropInput instead. */ REG_OP(Conv3DBackpropInputD) .INPUT(filter, TensorType({DT_FLOAT16})) .INPUT(out_backprop, TensorType({DT_FLOAT16})) - .OUTPUT(y, TensorType({DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT32})) .REQUIRED_ATTR(input_size, ListInt) .REQUIRED_ATTR(strides, ListInt) .REQUIRED_ATTR(pads, ListInt) @@ -1242,8 +1224,8 @@ REG_OP(LSTM) /** *@brief Computes the gradients of convolution3D with respect to the filter + *@par Inputs: - * Three inputs: * @li x: A Tensor. Must be one of the following types: float16, float32. * Currently does not support double. * 5-D with shape [batch, in_depth, in_height, in_width, in_channels] @@ -1258,26 +1240,23 @@ REG_OP(LSTM) * or [batch, out_channels, out_depth, out_height, out_width]. * Gradients with respect to the output of the convolution. \n -*@par Required Attributes: - * @li strides: A tuple/list of 5 integers. Specifies the stride of the sliding +*@par Attributes: + * @li strides: Required. A tuple/list of 5 integers. Specifies the stride of the sliding * window for each dimension of "x". The N and C dimensions must be 1. * Has the same format as "x". - * @li pads: A tuple/list of 6 integers, [front, back, top, bottom, left, right] - * pads on feature map . \n - -*@par Attributes: - * Three attributes: - * @li dilations: A tuple/list of 5 integers, The dilation factor for each + * @li pads: Required. A tuple/list of 6 integers, [front, back, top, bottom, left, right] + * pads on feature map. + * @li dilations: Optional. A tuple/list of 5 integers, The dilation factor for each * dimension of input. * The N, C and D dimensions must be 1. Has the same format as "x". - * @li groups: Number of blocked connections from input channels to output + * @li groups: Optional. Number of blocked connections from input channels to output * channels. - * @li data_format: An optional string from: "NDHWC", "NCDHW". - * Defaults to "NDHWC". Specify the data format of the input and output data. + * @li data_format: Optional. An string from: "NDHWC", "NCDHW". + * Defaults to "NDHWC". Specify the data format of the input and output data. \n *@par Outputs: - * y: A Tensor that has the same type as "x" - * and the format is NDHWC, NCDHW or DHWCN. + * y: A Tensor that has the same type as "x" and the format is NDHWC, NCDHW or DHWCN. \n + *@par Third-party framework compatibility * Compatible with Tensorflow's conv3d_backprop_filter */ @@ -1295,8 +1274,8 @@ REG_OP(Conv3DBackpropFilter) /** *@brief Computes the gradients of convolution with respect to the filter. + *@par Inputs: - * Two inputs: * @li x: A Tensor of type float16. * 5-D with shape [batch, in_depth, in_height, in_width, in_channels] * or [batch, in_channels, in_depth, in_height, in_width]. @@ -1305,37 +1284,34 @@ REG_OP(Conv3DBackpropFilter) * or [batch, out_channels, out_depth, out_height, out_width]. * Gradients with respect to the output of the convolution. \n -*@par Required Attributes: - * @li filter_size: A tuple/list of type integers. An integer vector +*@par Attributes: + * @li filter_size: Required. A tuple/list of type integers. An integer vector * representing the tensor shape of filter, where filter is a 5-D tensor * [filter_depth, filter_height, filter_width, in_channels, out_channels], * [out_channels, filter_depth, filter_height, filter_width, in_channels] * or [out_channels, in_channels, filter_depth, filter_height, filter_width]. - * @li strides: A tuple/list of 5 integers. Specifies the stride of the sliding + * @li strides: Required. A tuple/list of 5 integers. Specifies the stride of the sliding * window for each dimension of "x". * The N and C dimensions must be 1. Has the same format as "x". - * @li pads: A tuple/list of 6 integers, [front, back, top, bottom, left, right] - * pads on feature map. \n - -*@par Attributes: - * Three attributes: - * @li dilations: A tuple/list of 5 integers, The dilation factor for each + * @li pads: Required. A tuple/list of 6 integers, [front, back, top, bottom, left, right] + * pads on feature map. + * @li dilations: Optional. A tuple/list of 5 integers, The dilation factor for each * dimension of input. * The N, C and D dimensions must be 1. Has the same format as "x". - * @li groups: Number of blocked connections from input channels to output + * @li groups: Optional. Number of blocked connections from input channels to output * channels. - * @li data_format: An optional string from: "NDHWC", "NCDHW". - * Defaults to "NDHWC". Specify the data format of the input and output data. + * @li data_format: Optional. An optional string from: "NDHWC", "NCDHW". + * Defaults to "NDHWC". Specify the data format of the input and output data. \n *@par Outputs: - * y: A Tensor of type float32 and the format is NDHWC, NCDHW or DHWCN. + * y: A Tensor of type float32 and the format is NDHWC, NCDHW or DHWCN. \n + *@par Third-party framework compatibility - * Compatible with Tensorflow's conv3d_backprop_filter + * Compatible with Tensorflow's conv3d_backprop_filter. \n + *@par Restrictions: -* Warning: THIS FUNCTION IS DEPRECATED. Please use Conv3DBackpropFilter instead. + * Warning: THIS FUNCTION IS DEPRECATED. Please use Conv3DBackpropFilter instead. */ - - REG_OP(Conv3DBackpropFilterD) .INPUT(x, TensorType({DT_FLOAT16})) .INPUT(out_backprop, TensorType({DT_FLOAT16})) @@ -1350,37 +1326,32 @@ REG_OP(Conv3DBackpropFilterD) /** *@brief Computes the transpose of convolution 3d with respect to the input. + *@par Inputs: - * Three inputs: * @li input_size: A Tensor of type int32. An integer vector representing the * shape of input. * @li x: A Tensor of type float16, currently does not support int8. The format * is NDHWC or NCDHW. * @li filter: A Tensor of type float16, currently does not support int8. * The format is NDHWC, NCDHW or DHWCN. + * @li bias: Optional. An optional 1D tensor of the same type as "x". Reserved. + * @li offset_w: Optional. An optional 1D tensor for quantized deconvolution. Reserved. \n -*@par Optional input: - * Two optional inputs - * @li bias: An optional 1D tensor of the same type as "x". Reserved. - * @li offset_w: An optional 1D tensor for quantized deconvolution. Reserved . \n - -*@par Required Attributes: - * @li strides: A tuple/list of 5 integers. Specifies the stride of the sliding +*@par Attributes: + * @li strides: Required. A tuple/list of 5 integers. Specifies the stride of the sliding * window for each dimension of "x". * The N and C dimensions must be 1. Has the same format as "x". - * @li pads: A tuple/list of 6 integers - -*@par Attributes: - * Five attributes: - * @li groups: Number of blocked connections from input channels to output - * channels. - * @li dilations: A tuple/list of 5 integers, + * @li pads: Required. A tuple/list of 6 integers. + * @li dilations: Optional. A tuple/list of 5 integers, * The dilation factor for each dimension of input. * The N, C and D dimensions must be 1. Has the same format as "x". - * @li data_format: An optional string from: "NDHWC", "NCDHW". + * @li groups: Optional. Number of blocked connections from input channels to output + * channels. + * @li data_format: Optional. An string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. - * @li output_padding: The size will be added in the output shape. - * @li offset_x: Input offset_x value. Reserved. + * @li output_padding: Optional. The size will be added in the output shape. + * @li offset_x: Optional. Input offset_x value. Reserved. \n + *@par Outputs: * y: A Tensor. Has the same type and format as "x". */ @@ -1388,9 +1359,9 @@ REG_OP(Conv3DTranspose) .INPUT(input_size, TensorType({DT_INT32, DT_INT64})) .INPUT(x, TensorType({DT_FLOAT16})) .INPUT(filter, TensorType({DT_FLOAT16})) - .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT16, DT_FLOAT32})) .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8})) - .OUTPUT(y, TensorType({DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT32})) .REQUIRED_ATTR(strides, ListInt) .REQUIRED_ATTR(pads, ListInt) .ATTR(dilations, ListInt, {1, 1, 1, 1, 1}) @@ -1402,46 +1373,44 @@ REG_OP(Conv3DTranspose) /** *@brief Computes the transpose of convolution 3d with respect to the input. + *@par Inputs: * @li x: A Tensor of type float16, currently does not support int8. * The format is NDHWC or NCDHW. * @li filter: A Tensor of type float16, currently does not support int8. * The format is NDHWC, NCDHW or DHWCN. + * @li bias: Optional. An 1D tensor of the same type as "x". Reserved. + * @li offset_w: Optional. An 1D tensor for quantized deconvolution. Reserved. \n -*@par Optional inputs: - * @li bias: An optional 1D tensor of the same type as "x". Reserved. - * @li offset_w: An optional 1D tensor for quantized deconvolution. Reserved . \n - -*@par Required Attributes: - * @li input_size: A tuple/list of type int32. - * An integer vector representing the shape of input - * @li strides: A tuple/list of 5 integers. +*@par Attributes: + * @li input_size: Required. A tuple/list of type int32. + * An integer vector representing the shape of input. + * @li strides: Required. A tuple/list of 5 integers. * Specifies the stride of the sliding window for each dimension of "x". * The N and C dimensions must be 1. Has the same format as "x". - * @li pads: A tuple/list of 6 integers . \n - -*@par Attributes: - * Five attributes: - * @li dilations: A tuple/list of 5 integers, The dilation factor for each + * @li pads: Required. A tuple/list of 6 integers. + * @li dilations: Optional. A tuple/list of 5 integers, The dilation factor for each * dimension of input. * The N, C and D dimensions must be 1. Has the same format as "x". - * @li groups: Number of blocked connections from input channels to output + * @li groups: Optional. Number of blocked connections from input channels to output * channels. - * @li data_format: An optional string from: "NDHWC", "NCDHW". + * @li data_format: Optional. An optional string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. - * @li output_padding: The size will be added in the output shape. - * @li offset_x: Input offset_x value. Reserved. + * @li output_padding: Optional. The size will be added in the output shape. + * @li offset_x: Optional. Input offset_x value. Reserved. \n + *@par Outputs: - * y: A Tensor. Has the same type and format as "x". + * y: A Tensor. Has the same type and format as "x". \n + *@par Restrictions: -* Warning: THIS FUNCTION IS DEPRECATED. Please use Conv3DTranspose instead. + * Warning: THIS FUNCTION IS DEPRECATED. Please use Conv3DTranspose instead. */ REG_OP(Conv3DTransposeD) .INPUT(x, TensorType({DT_FLOAT16})) .INPUT(filter, TensorType({DT_FLOAT16})) - .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT16, DT_FLOAT32})) .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8})) - .OUTPUT(y, TensorType({DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT32})) .REQUIRED_ATTR(input_size, ListInt) .REQUIRED_ATTR(strides, ListInt) .REQUIRED_ATTR(pads, ListInt) @@ -1469,17 +1438,17 @@ REG_OP(Conv3DTransposeD) * @li offset_w: An optional 1D tensor for quantized inference. Reserved. *\n *\n - * The following are the supported data types and data formats: -*@verbatim - | Tensor | x | filter | bias | y - ------------|---------|---------|---------|-------- - | Data Type | float16 | float16 | float16 | float16 - | |---------|---------|---------|-------- - | | int8 | int8 | int32 | int32 - ------------|---------|---------|---------|-------- - | Format | NCHW | NCHW | ND | NCHW - | | NHWC | HWCN | | NHWC -@endverbatim + * The following are the supported data types and data formats:\n + *\n + | Tensor | x | filter | bias | y\n + ------------|---------|---------|---------|--------\n + | Data Type | float16 | float16 | float16 | float16\n + | |---------|---------|---------|--------\n + | | int8 | int8 | int32 | int32\n + ------------|---------|---------|---------|--------\n + | Format | NCHW | NCHW | ND | NCHW\n + | | NHWC | HWCN | | NHWC\n + *\n * For int8, a dequant or requant operator must be followed. *\n * @@ -1504,38 +1473,38 @@ REG_OP(Conv3DTransposeD) * within the effective range of int8 [-128, 127]. Defaults to "0". *\n *\n - * The following value range restrictions must be met: -*@verbatim - | Name | Field | Scope - -------------------|----------|-------------- - | input_size | H | [1, 4096] - | | W | [1, 4096] - -------------------|----------|-------------- - | x (out_backprop) | H*strideH| [1, 4096] - | | W*strideW| [1, 4096] - -------------------|----------|-------------- - | filter | H | [1, 255] - | | W | [1, 255] - -------------------|----------|-------------- - | y (fmap) | H | [1, 4096] - | | W | [1, 4096] - -------------------|----------|-------------- - | Stride | H | [1, 63] - | | W | [1, 63] - -------------------|----------|-------------- - | Padding | Top | [0, 255] - | | Bottom | [0, 255] - | | Left | [0, 255] - | | Right | [0, 255] - -------------------|----------|-------------- - | Dilation | H | [1, 255] - | | W | [1, 255] - -------------------|----------|-------------- - | Offset_x | | [-128, 127] - -@endverbatim + * The following value range restrictions must be met:\n + *\n + | Name | Field | Scope\n + -------------------|----------|--------------\n + | input_size | H | [1, 200000]\n + | | W | [1, 4096]\n + -------------------|----------|--------------\n + | x (out_backprop) | H*strideH| [1, 200000]\n + | | W*strideW| [1, 4096]\n + -------------------|----------|--------------\n + | filter | H | [1, 255]\n + | | W | [1, 255]\n + -------------------|----------|--------------\n + | y (fmap) | H | [1, 200000]\n + | | W | [1, 4096]\n + -------------------|----------|--------------\n + | Stride | H | [1, 63]\n + | | W | [1, 63]\n + -------------------|----------|--------------\n + | Padding | Top | [0, 255]\n + | | Bottom | [0, 255]\n + | | Left | [0, 255]\n + | | Right | [0, 255]\n + -------------------|----------|--------------\n + | Dilation | H | [1, 255]\n + | | W | [1, 255]\n + -------------------|----------|--------------\n + | Offset_x | | [-128, 127]\n + *\n * In Ascend910, fmap or out_backprop's H and W not support 1 when * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 + * and filter_width > fmap_width * If filter_h = 1 and filter_w = 1, out_backprop_w * stride_h * stride_w < 4096 *\n * @@ -1557,9 +1526,9 @@ REG_OP(Conv2DTranspose) .INPUT(input_size, TensorType({DT_INT32, DT_INT64})) .INPUT(x, TensorType({DT_FLOAT16, DT_INT8})) .INPUT(filter, TensorType({DT_FLOAT16, DT_INT8})) - .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT16, DT_INT32})) + .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT16, DT_INT32, DT_FLOAT32})) .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_INT32, DT_FLOAT32})) .REQUIRED_ATTR(strides, ListInt) .REQUIRED_ATTR(pads, ListInt) .ATTR(dilations, ListInt, {1, 1, 1, 1}) @@ -1604,9 +1573,9 @@ REG_OP(Conv2DTranspose) REG_OP(Conv2DTransposeD) .INPUT(x, TensorType({DT_FLOAT16, DT_INT8})) .INPUT(filter, TensorType({DT_FLOAT16, DT_INT8})) - .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT16, DT_INT32})) + .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT16, DT_INT32, DT_FLOAT32})) .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_INT32, DT_FLOAT32})) .REQUIRED_ATTR(input_size, ListInt) .REQUIRED_ATTR(strides, ListInt) .REQUIRED_ATTR(pads, ListInt) @@ -1623,14 +1592,12 @@ REG_OP(Conv2DTransposeD) * Two inputs: * @li x: A Tensor of type float16,float32 * @li offsets: A Tensor of type float16,float32.Deformation offset parameter. -*@par Required Attributes: +*@par Attributes: * @li strides: A tuple/list of 4 integers.The stride of the sliding window for * height and width for H/W dimension. * @li pads: A tuple/list of 4 integers.Padding added to H/W dimension * of the input. * @li ksize: A tuple/list of 2 integers.kernel size. -*@par Attributes: - * Four attributes: * @li dilations: A tuple/list of 4 integers, The dilation factor for each dimension * of input. Defaults to [1, 1, 1, 1] * @li data_format: An optional string from: "NCHW", "NHWC". Defaults to "NCHW". Specify the data format of the input x. @@ -1659,22 +1626,20 @@ REG_OP(DeformableOffsets) * @li grad: A Tensor of type float16,float32. gradients with respect to DeformableOffsets output * @li x: A Tensor of type float16,float32. * @li offsets: A Tensor of type float16,float32.Deformation offset parameter. -*@par Required Attributes: +*@par Attributes: * @li strides: A tuple/list of 4 integers.The stride of the sliding window for * height and width for H/W dimension. * @li pads: A tuple/list of 4 integers.Padding added to H/W dimension * of the input. * @li ksize: A tuple/list of 2 integers.kernel size. -*@par Attributes: - * Three attributes: * @li dilations: A tuple/list of 4 integers, The dilation factor for each dimension * of input. Defaults to [1, 1, 1, 1] * @li data_format: An optional string from: "NCHW", "NHWC". Defaults to "NCHW". Specify the data format of the input x. * @li deformable_groups: Specify the c-axis grouping number of input x. * @li modulated: Specify version of DeformableConv2D, true means v2, false means v1. *@par Outputs: - * grad_x: A Tensor of type float16, float32. Gradients with respect to input_x - * grad_offsets: A Tensor of type float16, float32. Gradients with respect to input_offsets + * @li grad_x: A Tensor of type float16, float32. Gradients with respect to input_x + * @li grad_offsets: A Tensor of type float16, float32. Gradients with respect to input_offsets */ REG_OP(DeformableOffsetsGrad) .INPUT(grad, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -1695,11 +1660,9 @@ REG_OP(DeformableOffsetsGrad) *@brief Computes the deformed dilation output with the expected input *@par Inputs: * One inputs: - * @li x: A Tensor of type int8, float16, float32 -*@par Required Attributes: - * @li dilations: A tuple/list of integers. + * x: A Tensor of type int8, float16, float32 *@par Attributes: - * Two attributes: + * @li dilations: A tuple/list of integers. * @li padding_value: default value filling in blank * @li pads: A tuple/list of integers. *@par Outputs: diff --git a/third_party/fwkacllib/inc/ops/nn_detect_ops.h b/third_party/fwkacllib/inc/ops/nn_detect_ops.h index 5fa40ad6..bd14df77 100644 --- a/third_party/fwkacllib/inc/ops/nn_detect_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_detect_ops.h @@ -152,6 +152,42 @@ REG_OP(Iou) .ATTR(mode, String, "iou") .OP_END_FACTORY_REG(Iou) +/** +*@brief First calculate the minimum closure area of the two boxes, IoU, +* the proportion of the closed area that does not belong to the two boxes in the closure area, +* and finally subtract this proportion from IoU to get GIoU . \n + +*@par Inputs: +* Two inputs, including: +*@li bboxes: Bounding boxes, a 2D Tensor of type float16 or float32 with +* shape (N, 4). "N" indicates the number of bounding boxes, and the value +* "4" refers to [x1, y1, x2, y2] or [x, y, w, h]. +*@li gtboxes: Ground-truth boxes, a 2D Tensor of type float16 or float32 +* with shape (M, 4). "M" indicates the number of ground truth boxes, and +* the value "4" refers to [x1, y1, x2, y2] or [x, y, w, h] . \n + +*@par Attributes: +*@li trans: An optional bool, true for 'xywh', false for 'xyxy'. +*@li is_cross: An optional bool, control whether the output shape is [M, N] or [1, N] +*@li mode: Computation mode, a character string with the value range of [iou, iof] . \n + +*@par Outputs: +* overlap: A 2D Tensor of type float16 or float32 with shape [M, N] or [1, N], +* specifying the IoU or IoF ratio . \n + +*@attention Constraints: +* Only computation of float16 data is supported. To avoid overflow, the input +* length and width are scaled by 0.2 internally. +*/ +REG_OP(GIoU) + .INPUT(bboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(gtboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(overlap, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(trans, Bool, false) + .ATTR(is_cross, Bool, true) + .ATTR(mode, String, "iou") + .OP_END_FACTORY_REG(GIoU) + /** *@brief Performs the backpropagation of ROIAlign for training scenarios . \n @@ -417,7 +453,7 @@ REG_OP(PSROIPooling) *@brief Returns detection result . \n *@par Inputs: -* Four inputs, including: +* Five inputs, including: *@li rois: An NCHW tensor of type floa16 or float32, output from operator proposal_d at the preceding layer, used as the input of operator FSRDetectionOutput. *@li bbox_delta: An NCHWC0 tensor of type floa16 or float32, specifying the prediction offset, used to update the coordinates [x1, y1, x2, y2] of each ROI. *@li score: An NCHWC0 tensor of type floa16 or float32, specifying the probability of each class. Class 0 is the background class. @@ -459,7 +495,7 @@ REG_OP(FSRDetectionOutput) *@brief Returns detection result . \n *@par Inputs: -* Four inputs, including: +* Three inputs, including: *@li bbox_delta: An ND tensor of type floa16 or float32, specifying the box loc predictions, used as the input of operator SSDDetectionOutput. *@li score: An ND tensor of type floa16 or float32, specifying the box confidences data, used as the input of operator SSDDetectionOutput. *@li anchors: An ND tensor of type floa16 or float32, output from operator PriorBoxD, used as the input of operator SSDDetectionOutput. @@ -474,7 +510,6 @@ REG_OP(FSRDetectionOutput) *@li code_type: An optional int32, specify the code type. Defaults to 1(only supports 2). The corner is 1, center_size is 2, corner_size is 3 *@li keep_top_k: An optional int32, specify the topk value after nms. Defaults to -1 *@li confidence_threshold: An optional float32, specify the topk filter threshold. Only consider detections with confidence greater than the threshold -*@li kernel_name: An optional string, specifying the operator name. Defaults to "ssd_detection_output". *@par Outputs: *@li out_boxnum: A tensor of type int32, specifying the number of output boxes. *@li y: A tensor of type float16 or float32 with shape [batch,keep_top_k, 8], describing the information of each output box. @@ -989,26 +1024,26 @@ REG_OP(SPP) * feature map . \n *@attention Constraints: -*@li For the feature map input: -(1) If pooled_h = pooled_w = 2, the feature map size must not exceed 50. -(2) If pooled_h = pooled_w = 3, the feature map size must not exceed 60. -(3) If pooled_h = pooled_w = 4, the feature map size must not exceed 70. -(4) If pooled_h = pooled_w = 5, the feature map size must not exceed 70. -(5) If pooled_h = pooled_w = 6, the feature map size must not exceed 80. -(6) If pooled_h = pooled_w = 7, the feature map size must not exceed 80. -(7) If pooled_h = pooled_w = 8, the feature map size must not exceed 80. -(8) If pooled_h = pooled_w = 9, the feature map size must not exceed 70. -(9) If pooled_h = pooled_w = 10, the feature map size must not exceed 70. -(10) If pooled_h = pooled_w = 11, the feature map size must not exceed 70. -(11) If pooled_h = pooled_w = 12, the feature map size must not exceed 70. -(12) If pooled_h = pooled_w = 13, the feature map size must not exceed 70. -(13) If pooled_h = pooled_w = 14, the feature map size must not exceed 70. -(14) If pooled_h = pooled_w = 15, the feature map size must not exceed 70. -(15) If pooled_h = pooled_w = 16, the feature map size must not exceed 70. -(16) If pooled_h = pooled_w = 17, the feature map size must not exceed 50. -(17) If pooled_h = pooled_w = 18, the feature map size must not exceed 40. -(18) If pooled_h = pooled_w = 19, the feature map size must not exceed 40. -(19) If pooled_h = pooled_w = 20, the feature map size must not exceed 40. +* For the feature map input: +*@li If pooled_h = pooled_w = 2, the feature map size must not exceed 50. +*@li If pooled_h = pooled_w = 3, the feature map size must not exceed 60. +*@li If pooled_h = pooled_w = 4, the feature map size must not exceed 70. +*@li If pooled_h = pooled_w = 5, the feature map size must not exceed 70. +*@li If pooled_h = pooled_w = 6, the feature map size must not exceed 80. +*@li If pooled_h = pooled_w = 7, the feature map size must not exceed 80. +*@li If pooled_h = pooled_w = 8, the feature map size must not exceed 80. +*@li If pooled_h = pooled_w = 9, the feature map size must not exceed 70. +*@li If pooled_h = pooled_w = 10, the feature map size must not exceed 70. +*@li If pooled_h = pooled_w = 11, the feature map size must not exceed 70. +*@li If pooled_h = pooled_w = 12, the feature map size must not exceed 70. +*@li If pooled_h = pooled_w = 13, the feature map size must not exceed 70. +*@li If pooled_h = pooled_w = 14, the feature map size must not exceed 70. +*@li If pooled_h = pooled_w = 15, the feature map size must not exceed 70. +*@li If pooled_h = pooled_w = 16, the feature map size must not exceed 70. +*@li If pooled_h = pooled_w = 17, the feature map size must not exceed 50. +*@li If pooled_h = pooled_w = 18, the feature map size must not exceed 40. +*@li If pooled_h = pooled_w = 19, the feature map size must not exceed 40. +*@li If pooled_h = pooled_w = 20, the feature map size must not exceed 40. *@par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. */ @@ -1222,9 +1257,7 @@ REG_OP(RpnProposalsD) * @li box_filter: bool, mark of box_filter. Defaults to "true" * @li core_max_num: int, max number of core. Defaults to "8" *@par Outputs: -* @li sorted_rois: A Tensor. Must be float16. N-D with shape [N, 4]. -* @li sorted_scores: A Tensor. Must be float16. N-D with shape [N, 1]. -* @li sorted_classes: A Tensor. Must be float16. N-D with shape [N, 1]. +*sorted_box: A Tensor. Must be float16. N-D with shape [N, 1]. */ REG_OP(RpnProposalPostProcessing) .INPUT(sorted_proposal, TensorType({DT_FLOAT16})) @@ -1382,7 +1415,7 @@ REG_OP(BatchMultiClassNonMaxSuppression) * @li shape_hw: A 1D Tensor of type int32 . \n * @par Attributes: -* @li reversed_box: An optional bool, specifying the last two dims is "4,num" or +* reversed_box: An optional bool, specifying the last two dims is "4,num" or * "num,4", "true" for "4,num", "false" for "num,4". Defaults to "false" . \n * @par Outputs: @@ -1429,9 +1462,9 @@ REG_OP(NormalizeBBox) * @li anchors: A Tensor. Must be int32. * *@par Attributes: -* @li scales: optional, listfloat, . +* @li scales: optional, listfloat. * @li decode_clip: optional, float, threahold of decode process. -* @li reversed_boxes: optional, bool,. +* @li reversed_boxes: optional, bool. * *@par Outputs: * y: A Tensor. Must have the same type as box_predictions. @@ -1446,16 +1479,16 @@ REG_OP(DecodeBboxV2) .OP_END_FACTORY_REG(DecodeBboxV2) /** -*@brief Computes sort function. +*@brief sort the input tensor and return the value of index. * *@par Inputs: *Inputs include: -* x: A Tensor. Dtype support: flaot16, flaot, int16, int8, +* x: A Tensor. Dtype support: float16, float, int16, int8, uint8, int32, int64. -* + *@par Attributes: -* @li axis: optional, int. -* @li descending: optional,bool. +* @li axis: An optional attribute indicates the sorting axis. +* @li descending: An optional attribute indicates desending sort or not. * *@par Outputs: * @li y1: A Tensor. Must have the same type as x. @@ -1568,16 +1601,18 @@ deciding when to remove boxes based on score . \n the last dim representing (batch_id,class_id,index_id) . \n *@par Attributes: -*center_point_box:Integer indicate the format of the box data. +*@li center_point_box:Integer indicate the format of the box data. The default is 0. 0 - the box data is supplied as [y1, x1, y2, x2] where (y1, x1) and (y2, x2) are the coordinates of any diagonal pair of box corners and the coordinates can be provided as normalized (i.e., lying in the interval [0, 1]) or absolute.Mostly used for TF models. 1 - the box data is supplied as [x_center, y_center, width, height]. Mostly used for Pytorch models. \n +*@li max_boxes_size: An optional attribute integer representing the real maximum +*number of boxes to be selected by non max suppression . \n *@par Outputs: -*@li selected_indices: A 2-D integer tensor of shape [M] representing the +*selected_indices: A 2-D integer tensor of shape [M] representing the selected indices from the boxes tensor, where M <= max_output_size. \n *@attention Constraints: @@ -1603,7 +1638,7 @@ REG_OP(NonMaxSuppressionV7) *@brief Obtains the ROI feature matrix from the feature map list. It is a customized fused operator for mmdetection. \n *@par Inputs: -* Three inputs, including: +* Two inputs, including: *@li features: A 5HD Tensor list of type float32 or float16. *@li rois: ROI position. A 2D Tensor of float32 or float16 with shape (N, 5). "N" indicates the number of ROIs, * the value "5" indicates the indexes of images where the ROIs are located, "x0", "y0", "x1", and "y1". @@ -1760,7 +1795,7 @@ REG_OP(AnchorResponseFlags) * "N" indicates the number of ROIs. \n *@par Attributes: -*@li performance_mode: select performance mode, "high_precision" or "high_performance". +*performance_mode: select performance mode, "high_precision" or "high_performance". * select "high_precision" when input type is float32, the output tensor precision * will be smaller than 0.0001, select "high_performance" when input type is float32, * the ops will be best performance, but precision will be only smaller than 0.005. @@ -1795,12 +1830,12 @@ REG_OP(YoloBoxesEncode) *@li num_gts: A Tensor. Support int32. real k. shape (1, ) *@par Attributes: -*@li output_dim: float. IOU threshold for positive bboxes. -*@li group_size: float. minimum iou for a bbox to be considered as a positive bbox -*@li spatial_scale: bool. whether to assign all bboxes with the same highest overlap with some gt to that gt. +*@li pos_iou_thr: float. IOU threshold for positive bboxes. +*@li min_pos_iou: float. minimum iou for a bbox to be considered as a positive bbox +*@li gt_max_assign_all: bool. whether to assign all bboxes with the same highest overlap with some gt to that gt. *@par Outputs: -*@li assigned_gt_inds_pos: A Tensor. Support float16/float32. shape (n, ). +* assigned_gt_inds_pos: A Tensor. Support float16/float32. shape (n, ). */ REG_OP(GridAssignPositive) .INPUT(assigned_gt_inds, TensorType({ DT_FLOAT, DT_FLOAT16 })) @@ -1816,6 +1851,40 @@ REG_OP(GridAssignPositive) .REQUIRED_ATTR(min_pos_iou, Float) .REQUIRED_ATTR(gt_max_assign_all, Bool) .OP_END_FACTORY_REG(GridAssignPositive) + +/** +*@brief GIoUGrad . \n + +*@par Inputs: +*@li dy : data of grad increment, a 1D Tensor of type float16 or float32 with +* shape (N,). +*@li bboxes: Bounding boxes, a 2D Tensor of type float16 or float32 with +* shape (4, N). "N" indicates the number of bounding boxes, and the value +* "4" refers to [x1, y1, x2, y2] or [x, y, w, h]. +*@li gtboxes: Ground-truth boxes, a 2D Tensor of type float16 or float32 +* with shape (4, M). "M" indicates the number of ground truth boxes, and +* the value "4" refers to [x1, y1, x2, y2] or [x, y, w, h] . \n + +*@par Attributes: +*@li trans: An optional attr, true for 'xywh', false for 'xyxy', only support true now. +*@li is_cross: An optional attr, if false M equals N, only support false now. +*@li mode: An optional attr, a character string with the value range of ['iou', 'iof'], +* only support 'iou' now. \n + +*@par Outputs: +*@li dbboxes: A 2D Tensor of type float16 or float32 with shape [4, N]. +*@li dgtboxes: A 2D Tensor of type float16 or float32 with shape [4, M]. +*/ +REG_OP(GIoUGrad) + .INPUT(dy, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(bboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(gtboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dbboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dgtboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(trans, Bool, false) + .ATTR(is_cross, Bool, true) + .ATTR(mode, String, "iou") + .OP_END_FACTORY_REG(GIoUGrad) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_DETECT_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index b44c0780..9ce7abfd 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -54,15 +54,16 @@ REG_OP(LogSoftmaxGrad) *@par Inputs: *Two inputs, including: * @li features: A Tensor. Must be one of the following types: half, float32, double. -* A "batch_size * num_classes" matrix. +*A "batch_size * num_classes" matrix. * @li labels: A Tensor. Must be one of the following types: 'int32', 'int64'. -* batch_size vector with values in [0, num_classes). -* This is the label for the given minibatch entry. +*batch_size vector with values in [0, num_classes). +*This is the label for the given minibatch entry. \n *@par Outputs: -*loss: A Tensor for per example loss (a "batch_size" vector). Has the same type as "features". -*backprop: A Tensor for the backpropagated gradients (a batch_size * num_classes matrix). Has the same type as "features" . \n +*@li loss: A Tensor for per example loss (a "batch_size" vector). Has the same type as "features". +*@li backprop: A Tensor for the backpropagated gradients (a batch_size * num_classes matrix). +Has the same type as "features" . \n *@par Third-party framework compatibility *Compatible with the TensorFlow operator SparseSoftmaxCrossEntropyWithLogits. @@ -84,8 +85,8 @@ REG_OP(SparseSoftmaxCrossEntropyWithLogits) * @li labels: A Tensor of the same type as "features". A "batch_size * num_classes" matrix . \n *@par Outputs: -*loss: A Tensor for per example loss (a "batch_size" vector). Has the same type as "features". -*backprop: A Tensor for the backpropagated gradients (a batch_size * num_classes matrix). Has the same type as "features" . \n +* @li loss: A Tensor for per example loss (a "batch_size" vector). Has the same type as "features". +* @li backprop: A Tensor for the backpropagated gradients (a batch_size * num_classes matrix). Has the same type as "features" . \n *@par Third-party framework compatibility *Compatible with the TensorFlow operator SoftmaxCrossEntropyWithLogits. @@ -127,12 +128,13 @@ REG_OP(SoftmaxGrad) *@brief Computes the sigmoid cross entropy loss of "predict" and "target" . \n *@par Inputs: -* Two inputs, including: +* Three inputs, including: *@li predict: A multi-dimensional Tensor of type float16 or float32, specifying the predictive value. -*@li target: A multi-dimensional Tensor of type float16 or float32, specifying the target value . \n +*@li target: A multi-dimensional Tensor of type float16 or float32, specifying the target value . +*@li dout:A multi-dimensional Tensor of float16 or float32,specifying the gradient transferred from the upper layer. \n *@par Outputs: -*loss: Sigmoid cross entropy between the predictive value and target value. Has the same dimensions as "predict" . \n +*gradient: Sigmoid cross entropy between the predictive value and target value. Has the same dimensions as "predict" . \n *@par Third-party framework compatibility * Compatible with the scenario where "reduction" is set to "none"of PyTorch operator SigmoidCrossEntropyWithLogitsGrad. @@ -148,13 +150,12 @@ REG_OP(SigmoidCrossEntropyWithLogitsGrad) *@brief Performs the backpropagation of SigmoidCrossEntropyWithLogits for training scenarios . \n *@par Inputs: -* Three inputs, including: +* Two inputs, including: *@li predict: A multi-dimensional Tensor of type float16 or float32, specifying the predictive value. -*@li target: A multi-dimensional Tensor of type float16 or float32, specifying the target value. -*@li dout: A multi-dimensional Tensor of float16 or float32, specifying the gradient transferred from the upper layer . \n +*@li target: A multi-dimensional Tensor of type float16 or float32, specifying the target value. \n *@par Outputs: -*gradient: Return gradient. Has the same dimensions and type as "predict" . \n +*loss: Return loss. Has the same dimensions and type as "predict" . \n *@par Third-party framework compatibility * Compatible with the scenario where "reduction" is set to "none"of PyTorch operator SigmoidCrossEntropyWithLogits. @@ -572,7 +573,7 @@ REG_OP(LayerNorm) *@par Inputs: *One input, including: -* @li x: A Tensor. Must be one of the following types: float16, float32 . \n +* x: A Tensor. Must be one of the following types: float16, float32 . \n *@par Attributes: * @li p: Specify L_p norm, the type is float. @@ -581,7 +582,7 @@ REG_OP(LayerNorm) *@par Outputs: *One outputs, including: -* @li y: shape and dtype of output, should be same shape and type as input. +* y: shape and dtype of output, should be same shape and type as input. */ REG_OP(Renorm) .INPUT(x, TensorType::BasicType()) @@ -811,7 +812,7 @@ REG_OP(LayerNormBetaGammaBackpropV2) * shape of "keep_prob" should be (1,) or [1,]. * Has the same type as "x" . \n -*@par Output: +*@par Outputs: *y: A mutable Tensor. Has the same type as "x". */ REG_OP(DropOutDoMask) @@ -839,7 +840,7 @@ REG_OP(DropOutDoMask) * shape of "keep_prob" should be (1,) or [1,]. * Has the same type as "x" . \n -*@par Output: +*@par Outputs: *y: A mutable Tensor. Has the same type as "x". *@par Restrictions: *Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. @@ -1010,7 +1011,7 @@ REG_OP(LRNGrad) *@li grads: A Tensor. Has the same type as acts. *@par Attributes: - *@li blank_label: An optional attribute. Defaults to 0. + *blank_label: An optional attribute. Defaults to 0. *@par Third-party framework compatibility * Compatible with TensorFlow RNNTLoss operator. @@ -1198,13 +1199,11 @@ REG_OP(INInferV2D) * @li epsilon: An attribute of type Float. \n * @par Outputs: -*Three outputs, including: +* Three outputs, including: * @li y: A Tensor. Has the same type as "x". \n * @li mean: A Tensor. Has the same type as "x". \n * @li variance: A Tensor. Has the same type as "x". \n -* @par Third-party framework compatibility -* Can be used by onnx InstanceNormalization */ REG_OP(InstanceNorm) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -1218,24 +1217,22 @@ REG_OP(InstanceNorm) .OP_END_FACTORY_REG(InstanceNorm) /** -*@brief InstanceNormGrad operator interface implementation. +* @brief InstanceNormGrad operator interface implementation. -*@par Inputs: -*Five inputs, including: +* @par Inputs: +* Five inputs, including: * @li dy: A Tensor. Must be one of the following types: float16, float32. * @li x: A Tensor. Must be one of the following types: float16, float32. * @li variance: A Tensor. Must be one of the following types: float16, float32. * @li mean: A Tensor. Must be one of the following types: float16, float32. * @li gamma: A Tensor. Must be one of the following types: float16, float32 . \n -*@par Outputs: -*Three outputs, including: +* @par Outputs: +* Three outputs, including: * @li pd_x: A Tensor. Must be one of the following types: float16, float32. * @li pd_gamma: A Tensor. Must be one of the following types: float16, float32. * @li pd_beta: A Tensor. Must be one of the following types: float16, float32. -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(InstanceNormGrad) .INPUT(dy, TensorType({DT_FLOAT, DT_FLOAT16})) @@ -1248,58 +1245,6 @@ REG_OP(InstanceNormGrad) .OUTPUT(pd_beta, TensorType({DT_FLOAT, DT_FLOAT16})) .OP_END_FACTORY_REG(InstanceNormGrad) -/** -*@brief InstanceNormXBackprop operator interface implementation. - -*@par Inputs: -*Five inputs, including: -* @li dy: A Tensor. Must be one of the following types: float16, float32. -* @li x: A Tensor. Must be one of the following types: float16, float32. -* @li variance: A Tensor. Must be one of the following types: float16, float32. -* @li mean: A Tensor. Must be one of the following types: float16, float32. -* @li gamma: A Tensor. Must be one of the following types: float16, float32 . \n - -*@par Outputs: -*Two outputs, including: -* @li pd_x: A Tensor. Must be one of the following types: float16, float32. -* @li res_for_gamma: A Tensor. Must be one of the following types: float32. - -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. -*/ -REG_OP(InstanceNormXBackprop) - .INPUT(dy, TensorType({DT_FLOAT, DT_FLOAT16})) - .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) - .INPUT(variance, TensorType({DT_FLOAT, DT_FLOAT16})) - .INPUT(mean, TensorType({DT_FLOAT, DT_FLOAT16})) - .INPUT(gamma, TensorType({DT_FLOAT, DT_FLOAT16})) - .OUTPUT(pd_x, TensorType({DT_FLOAT, DT_FLOAT16})) - .OUTPUT(res_for_gamma, TensorType({DT_FLOAT})) - .OP_END_FACTORY_REG(InstanceNormXBackprop) - -/** -*@brief InstanceNormBetaGammaBackprop operator interface implementation. - -*@par Inputs: -*Two inputs, including: -* @li dy: A Tensor. Must be one of the following types: float16, float32. -* @li res_for_gamma: A Tensor. Must be one of the following types: float32.\n - -*@par Outputs: -*Two outputs, including: -* @li pd_gamma: A Tensor. Must be one of the following types: float16, float32. -* @li pd_beta: A Tensor. Must be one of the following types: float16, float32. - -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. -*/ -REG_OP(InstanceNormBetaGammaBackprop) - .INPUT(dy, TensorType({DT_FLOAT, DT_FLOAT16})) - .INPUT(res_for_gamma, TensorType({DT_FLOAT})) - .OUTPUT(pd_gamma, TensorType({DT_FLOAT, DT_FLOAT16})) - .OUTPUT(pd_beta, TensorType({DT_FLOAT, DT_FLOAT16})) - .OP_END_FACTORY_REG(InstanceNormBetaGammaBackprop) - /** * @brief Computes Kl_div_loss_grad or Kl_div_loss_backward. \n @@ -1340,10 +1285,10 @@ REG_OP(KlDivLossGrad) * @li label: A Tensor. Has the same type as "grads". Required. \n * @par Attributes: -* @li reduction: An optional attribute of type String. Defaults to "mean". \n +* reduction: An optional attribute of type String. Defaults to "mean". \n * @par Outputs: -* @li y: A Tensor. Has the same type as "x". \n +* y: A Tensor. Has the same type as "x". \n * @par Third-party framework compatibility * Compatible with the Pytorch operator L1LossGrad. @@ -1368,7 +1313,7 @@ REG_OP(L1LossGrad) * @li reduction: An optional string.Defaults to "mean". \n * @par Outputs: -* @li y: An ND tensor tensor with the same shape and type as "predict". \n +* y: An ND tensor tensor with the same shape and type as "predict". \n * @par Third-party framework compatibility * Compatible with the Pytorch operator LpLoss. @@ -1390,10 +1335,10 @@ REG_OP(LpLoss) * @li dout: An ND tensor of type float16, float32. \n * @par Attributes: -* @li reduction: An optional string.Defaults to "mean". \n +* reduction: An optional string.Defaults to "mean". \n * @par Outputs: -* @li y: An ND tensor tensor with the same shape and type as "predict". \n +* y: An ND tensor tensor with the same shape and type as "predict". \n * @par Third-party framework compatibility * Compatible with the Pytorch operator MseLossGrad. @@ -1414,10 +1359,10 @@ REG_OP(MseLossGrad) * @li label: An ND Tensor of dtype float16 or float32.\n * * @par Attributes: -* @li reduction:An optional str from sum, none, mean, Defaults to "mean".\n +* reduction:An optional str from sum, none, mean, Defaults to "mean".\n * * @par Outputs: -* @li y: when reduction=sum/mean, y is scale. when reduction=none, y has +* y: when reduction=sum/mean, y is scale. when reduction=none, y has * same type and shape as "predict".\n */ REG_OP(MseLoss) @@ -1445,7 +1390,7 @@ REG_OP(MseLoss) * Must be one of the following: "none", "mean", "sum". \n * @par Outputs: -* @li gradient: A Tensor. Has the same type as "predict". \n +* gradient: A Tensor. Has the same type as "predict". \n * @par Third-party framework compatibility * Compatible with the Pytorch operator SmoothL1LossBackward. @@ -1480,7 +1425,7 @@ REG_OP(SmoothL1LossGradV2) * the output,'sum': the output will be summed. Default: 'mean'. \n * @par Outputs: -* @li loss: Indicates the loss between the predictive value and target value. +* loss: Indicates the loss between the predictive value and target value. * Has the same dimensions as "predict". \n * @par Third-party framework compatibility @@ -1498,12 +1443,12 @@ REG_OP(SmoothL1LossV2) * @brief Computes Centralization. result = x - mean(x, axes) * @par Inputs: -* @li x: An ND tensor of type float16, float32. +* x: An ND tensor of type float16, float32. * @par Attributes: -* @li axes: The dimensions to reduce. Must be one of the following types: int, list, tuple, NoneType. +* axes: The dimensions to reduce. Must be one of the following types: int, list, tuple, NoneType. * Must be in the range [-rank(x), rank(x)). * @par Outputs: -* @li y: A Tensor. Has the same type as "x". \n +* y: A Tensor. Has the same type as "x". \n * @par Third-party framework compatibility * custom operator \n @@ -1521,7 +1466,7 @@ REG_OP(Centralization) *@par Inputs: *One inputs, including: -* @li x: A tensor . Must be one of the following types: +* x: A tensor . Must be one of the following types: * float16, float32, int32, uint32, int8, uint8. \n *@par Attributes: @@ -1546,14 +1491,14 @@ REG_OP(Roll) logistic loss between input_x and input_y (containing 1 or -1). \n *@par Inputs: - *One inputs, including: + *Tow inputs, including: * @li input_x: A tensor. Must be one of the following types: * float16, float32. \n * @li input_y: A tensor. Must be one of the following types: * float16, float32. \n *@par Attributes: - *@li lambd: An optional string.Defaults to "mean". \n + *reduction: An optional string.Defaults to "mean". \n *@par Outputs: *output_z: while reduction == "none", A Tensor with the same type and shape of input_x's. \n @@ -1580,10 +1525,10 @@ REG_OP(SoftMarginLoss) * @li pos_weight: An optional ND tensor of type float16, float32. \n * @par Attributes: -* @li reduction: An optional string.Defaults to "mean". \n +* reduction: An optional string.Defaults to "mean". \n * @par Outputs: -* @li gradient: An ND tensor tensor with the same shape and type as "predict". \n +* gradient: An ND tensor tensor with the same shape and type as "predict". \n * @par Third-party framework compatibility * Compatible with the Pytorch operator SigmoidCrossEntropyWithLogitsGrad. @@ -1603,24 +1548,14 @@ REG_OP(SigmoidCrossEntropyWithLogitsGradV2) * @par Inputs: * Two inputs, including: - * @li input_x: A tensor. Must be one of the following types: - * float16, float32. \n - * - * @par Inputs: - * @li target: A tensor. Must be one of the following types: - * float16, float32. \n + * @li input_x: A tensor. Must be one of the following types: float16, float32. + * @li target: A tensor. Must be one of the following types: float16, float32. \n * @par Attributes: * four Attributes, including: - * @li log_input: An optional bool. Defaults to "True" \n - * - * @par Attributes: - * @li full: An optional bool. Defaults to "False" \n - * - * @par Attributes: - * @li eps: An optional float. Defaults to "1e-8" \n - * - * @par Attributes: + * @li log_input: An optional bool. Defaults to "True" + * @li full: An optional bool. Defaults to "False" + * @li eps: An optional float. Defaults to "1e-8" * @li reduction: An optional string. Defaults to "mean" \n * @par Outputs: @@ -1641,14 +1576,14 @@ REG_OP(PoissonNllLoss) /** *@brief rnn_gen_mask * @par Inputs: - * @li seq_length: A ND Tensor of type int32. Recoed the current length of each batch.\n + * seq_length: A ND Tensor of type int32. Recoed the current length of each batch.\n * * @par Attributes: * @li num_step: A required int.\n * @li hidden_size: A required int. \n * * - * @par Output: + * @par Ouputs: * y: A mutable Tensor of type float16, with the shape of [num_step, batch_size, hidden_size]. \n * */ @@ -1666,18 +1601,16 @@ REG_OP(RnnGenMask) * @par Inputs: * Two inputs, including: * @li x: A tensor. Must be one of the following types: -* float16, float32. \n -* -* @par Inputs: +* float16, float32. * @li target: A tensor. Must be the following types: * int32. \n * @par Attributes: -* @li reduction: An optional string. Defaults to "mean" \n +* reduction: An optional string. Defaults to "mean" \n * @par Outputs: -* y: A Tensor has same element type as input x. \n -* is_target: A Tensor has same element type as input target. \n +* @li y: A Tensor has same element type as input x. \n +* @li is_target: A Tensor has same element type as input target. \n * @par Third-party framework compatibility * Compatible with the Pytorch operator MultiLabelMarginLoss. \n diff --git a/third_party/fwkacllib/inc/ops/nn_ops.h b/third_party/fwkacllib/inc/ops/nn_ops.h index 49fd02fa..5b1a4dd0 100644 --- a/third_party/fwkacllib/inc/ops/nn_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_ops.h @@ -106,16 +106,16 @@ REG_OP(FusedBatchNormV2) .OP_END_FACTORY_REG(FusedBatchNormV2) /** - * @brief: Large amount of data sort.First operator of TopK. + * @brief Large amount of data sort.First operator of TopK. * @par Inputs: * two input, including: * @li input_data: A Tensor. Data to be sorted. Support float16 * @li input_index: A Tensor. Range(0, 2048). Datatype and format is same as input_data. * @par Attributes: - * @li k_num: Int.Number to be sorted. + * k_num: Int.Number to be sorted. * @par Outputs: - * 1 output, including: - * @li output_proposal: A Tensor. Datatype and format is same as input_data. Proposal sorted for each channel. + * One output, including: + * output_proposal: A Tensor. Datatype and format is same as input_data. Proposal sorted for each channel. */ REG_OP(SegmentSort) .INPUT(input_data, TensorType({DT_FLOAT16})) @@ -127,13 +127,13 @@ REG_OP(SegmentSort) /** * @brief: Large amount of data sort.Second operator of TopK. * @par Inputs: - * two input, including: - * @li input_proposal: A Tensor. Proposal sorted for each channel. Support float16 + * One input, including: + * input_proposal: A Tensor. Proposal sorted for each channel. Support float16 * @par Attributes: - * @li k_num: Int.Number to be sorted. + * k_num: Int.Number to be sorted. * @par Outputs: - * 1 output, including: - * @li output_proposal: A Tensor. Datatype and format is same as input_data. Proposal sorted for each channel. + * One output, including: + * output_proposal: A Tensor. Datatype and format is same as input_data. Proposal sorted for each channel. */ REG_OP(MultiMerge) .INPUT(input_proposal, TensorType({DT_FLOAT16})) @@ -142,14 +142,14 @@ REG_OP(MultiMerge) .OP_END_FACTORY_REG(MultiMerge) /** - * @brief: Large amount of data sort.Third operator of TopK. + * @brief Large amount of data sort.Third operator of TopK. * @par Inputs: - * two input, including: - * @li input_proposal: A Tensor. Proposal sorted for each channel. Support float16 + * One input, including: + * input_proposal: A Tensor. Proposal sorted for each channel. Support float16 * @par Attributes: - * @li k_num: Int.Number to be sorted. + * k_num: Int.Number to be sorted. * @par Outputs: - * 2 output, including: + * Two output, including: * @li output_data: A Tensor. Datatype and format is same as input_data. Data sorted. * @li output_index: A Tensor. int32. Data index. */ diff --git a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h index 80a21333..72363d18 100644 --- a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h @@ -29,7 +29,7 @@ namespace ge { /** *@brief Performs pooling on the input. *@par Inputs: -*@li x: An NCHW tensor of type float16, float32, int8. +* x: An NCHW tensor of type float16, float32, int8. *@par Attributes: *@li mode: An optional int32, specifying the pooling algorithm, either "0" (max pooling) or "1" (avg pooling). Defaults to "0". *@li global_pooling: An optional bool. Defaults to "false". @@ -50,6 +50,7 @@ namespace ge { *dilation[2]: An optional int32, specifying the left dilation. Defaults to "1". *dilation[3]: An optional int32, specifying the right dilation. Defaults to "1". *@li ceil_mode: An optional int32, either "0" (ceil mode) or "1" (floor mode). Defaults to "0". +*@li data_format: An optional string, Specify the data format of the input and output data. With the default format "NCHW". *@par Outputs: *y: An NCHW tensor of type float16, float32, int32. *@attention Constraints: @@ -204,7 +205,7 @@ REG_OP(AvgPool3D) *y: The average pooled output tensor . \n *@attention Constraints: -*@li "ksize" is in the range [1, 255]. "strides" is in the range [1, 63] +*"ksize" is in the range [1, 255]. "strides" is in the range [1, 63] *@par Third-party framework compatibility * Compatible with the TensorFlow operator AvgPool3D. @@ -281,10 +282,10 @@ REG_OP(AvgPool3DGrad) * @li data_format: A string, format of input data . \n * @par Outputs: -* @output: The average pooled output tensor . \n +* output: The average pooled output tensor . \n * @attention Constraints: -* @li "ksize" is in the range [1, 255]. "strides" is in the range [1, 63] +* "ksize" is in the range [1, 255]. "strides" is in the range [1, 63] * @par Third-party framework compatibility * Compatible with the TensorFlow operator AvgPool3DGradD. @@ -430,6 +431,47 @@ REG_OP(MaxPool3D) .ATTR(data_format, String, "NDHWC") .OP_END_FACTORY_REG(MaxPool3D) +/** +* @brief Performs max pooling3d on both max values and indices. +* +* @par Inputs: +* One input: +* x: An 6D tensor. Supported type: float16. Format as NDC1HWC0. +* @par Attributes: +* @li ksize: A required list of int32 values, +* specifying the size of the window for each dimension of the input tensor. +* No default value. +* @li strides: A required list of int32 values, +* specifying the stride of the sliding window for each dimension of +* the input tensor. No default value. +* @li pads: A required 3*2-dimension-list of int32 values. +* specifying the pad of three dimension of input, implement with 0. +* @li dilation: dilation of kernel. default value is {1,1,1,1,1}. +* @li ceil_mode: default value is false. +* @li data_format: the format of torch input, default value is "NCDHW". +* @li argmax_type: the function of this field is to determine the type of +* output argmax, "bitmask" is the default value, the argmax will return +* a img2col bitmask. "index_int32" and "index_int64" represent the torch +* output indices. +* @par Outputs: +* y: An 6D tensor. the maxpool3d output(max value), format as NDoC1HoWoC0. +* @par Outputs: +* argmax: A 5D uint16 tensor. the indice output. +* format as NC1HWC0, actually it represent N, Do, C1*ksize, Ho*Wo//16, 16. +*/ +REG_OP(MaxPool3DWithArgmax) + .INPUT(x, TensorType::RealNumberType()) + .OUTPUT(y, TensorType::RealNumberType()) + .OUTPUT(argmax, TensorType::IndexNumberType()) + .REQUIRED_ATTR(ksize, ListInt) + .REQUIRED_ATTR(strides, ListInt) + .REQUIRED_ATTR(pads, ListInt) + .ATTR(dilation, ListInt, {1, 1, 1, 1, 1}) + .ATTR(ceil_mode, Bool, false) + .ATTR(data_format, String, "NCDHW") + .ATTR(argmax_type, String, "bitmask") + .OP_END_FACTORY_REG(MaxPool3DWithArgmax) + /** *@brief Applies a 2D adaptive max pooling over an input signal conposed of several input planes. \n * The output is of size H x W, for any input size. @@ -522,8 +564,7 @@ REG_OP(MaxPool3DGradGrad) * y: A mutable tensor. Has the same shape and type as "x1" . \n * @attention Constraints: -* @li Computing gradients of global pooling is not supported, which means -* "ksize < x1". +* @li ksize is limited by buffer with full tiling. * @li "ksize" is in the range [1, 255]. "strides" is in the range [1, 63] * @par Third-party framework compatibility @@ -568,7 +609,7 @@ REG_OP(MaxPoolGrad) * @li Other dimensions of ksize and strides is 1 . \n * @par Outputs: -* @li y: Has the same type and format as input "x1" . \n +* y: Has the same type and format as input "x1" . \n * @par Third-party framework compatibility * @li Compatible with the TensorFlow operator MaxPoolGradGrad. @@ -588,7 +629,7 @@ REG_OP(MaxPoolGradGrad) *@brief Performs max_pool_ext2 on the input . \n *@par Inputs: -* Two inputs: +* Three inputs: *@li x: An NC1HWC0 Tensor of type float16. *@li strides: A required type of int32 values, specifying the stride of the sliding window for each dimension of the input tensor. No default value. *@li ksize: A required type of int32 values, specifying the size of the window for each dimension of the input tensor. No default value. @@ -635,7 +676,8 @@ REG_OP(MaxPoolV2) *@li strides: A required list of int8, int16, int32, or int64 values, * specifying the stride of the sliding window for each dimension of * the input tensor. No default value. -*@li padding: A required string. No default value . \n +*@li padding: A required string. No default value . +*@li Targmax:An optional int with default value 7 . \n *@par Outputs: *@li y: A Tensor. Has the same type and format as input "x". @@ -645,7 +687,7 @@ REG_OP(MaxPoolV2) * ksize[1] * ksize[2] <= 255. *@li "stride is a list that has length 4: strides[0] = 1 or strides[3] = 1, * strides[1] <= 63, strides[0] >= 1, strides[2] <= 63, strides[2] >= 1. -*@li "padding" is either "SAME" or "VALID" . \n +*@li "padding" is either "SAME" or "VALID" . *@par Third-party framework compatibility * Compatible with the TensorFlow operator MaxPoolWithArgmax. @@ -710,14 +752,15 @@ REG_OP(MaxPoolGradWithArgmax) *@brief Performs transform mask to argmax . \n *@par Inputs: -* Two input: -*x: An NC1HWC0 Tensor of type float16. -*mask: An NC1HWC0 Tensor of type uint16 . \n +* Two inputs: +*@li x: An NC1HWC0 Tensor of type float16. +*@li mask: An NC1HWC0 Tensor of type uint16 . \n *@par Attributes: *@li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for each dimension of the input tensor. No default value. *@li strides: A required list of int8, int16, int32, or int64 values, specifying the stride of the sliding window for each dimension of the input tensor. No default value. -*@li padding: A required string. No default value . \n +*@li padding: A required string. No default value . +*@li originshape:A required list of int8, int16, int32, or int64 values, No default value. \n *@par Outputs: *argmax: An NC1HWC0 Tensor of type int32 . \n @@ -754,7 +797,7 @@ REG_OP(Mask2Argmax) * @li strides: A required list, specifying the stride of the sliding window. * @li padding: A required string, window sliding mode. Either SAME or VALID. * @par Outputs: -* @li y:Result tensor. Supported type: float, double, int32, +* y:Result tensor. Supported type: float, double, int32, * uint8, int16, int8, int64, uint16, half, uint32, uint64 * @attention Constraints: @@ -767,7 +810,7 @@ REG_OP(Mask2Argmax) * (shape_max_pool[2] * shape_max_pool[3] + 31) // 16, 16), else failed . \n * @par Third-party framework compatibility -* @li Compatible with the TensorFlow operator MaxPoolGradGradWithArgmax. +* Compatible with the TensorFlow operator MaxPoolGradGradWithArgmax. */ REG_OP(MaxPoolGradGradWithArgmax) .INPUT(x, TensorType::RealNumberType()) @@ -931,11 +974,11 @@ REG_OP(AvgPoolV2GradD) .OP_END_FACTORY_REG(AvgPoolV2GradD) /** -*@brief :upsample the layer +*@brief upsample the layer, similar to the nearest-neighbor difference scaling algorithm. *@par Inputs: * one input, including: -*@li x: A tensor of type float16 or float32. +* x: A tensor of type float16 or float32. *@par Attributes: *@li scale: A optional float32, scale factor of x. Defaults to "1.0". *@li stride_h: An optional int32, broadcast the axis of h. Defaults to "2". @@ -1419,7 +1462,7 @@ REG_OP(MaxPoolV3) * the floor function will be used. Default False \n * @par Outputs: -* y: A mutable tensor. Has the same shape and type as "x1" . \n +* out_grad: A mutable tensor. Has the same shape and type as "x1" . \n * @attention Constraints: * @li Computing gradients of global pooling is not supported, which means @@ -1447,8 +1490,8 @@ REG_OP(MaxPoolV3Grad) *@brief Performs Dilation2D on the input . \n *@par Inputs: -*x: A tensor of shape is 4d, format is support NHWC. -*filter: A tensor of shape is 3d, the type is same with x, and the c dimension is same with x. \n +*@li x: A tensor of shape is 4d, format is support NHWC. +*@li filter: A tensor of shape is 3d, the type is same with x, and the c dimension is same with x. \n *@par Attributes: *@li strides: A required list of 4 ints, specifying the stride of the sliding window. The strides of the N and C dimensions are 1. @@ -1480,9 +1523,9 @@ REG_OP(Dilation2D) *@brief Performs Dilation2DBackpropFilter on the input. \n *@par Inputs: -*x: A tensor of shape is 4d, format is support NHWC. -*filter: A tensor of shape is 3d, the type is same with x, and the c dimension is same with x. -*out_backprop: Has the same type and format as input x and the c dimension is same with x. \n +*@li x: A tensor of shape is 4d, format is support NHWC. +*@li filter: A tensor of shape is 3d, the type is same with x, and the c dimension is same with x. +*@li out_backprop: Has the same type and format as input x and the c dimension is same with x. \n *@par Attributes *@li strides: A required list of 4 ints, specifying the stride of the sliding window. The strides of the N and C dimension are 1. @@ -1519,9 +1562,9 @@ REG_OP(Dilation2DBackpropFilter) *@brief Performs Dilation2DBackpropInput on the input. \n *@par Inputs: -*x: A tensor of shape is 4d, format is support NHWC. -*filter: A tensor of shape is 3d, the type is same with x, and the c dimension is same with x. -*out_backprop: Has the same type and format as input x and the c dimension is same with x. \n +*@li x: A tensor of shape is 4d, format is support NHWC. +*@li filter: A tensor of shape is 3d, the type is same with x, and the c dimension is same with x. +*@li out_backprop: Has the same type and format as input x and the c dimension is same with x. \n *@par Attributes *@li strides: A required list of 4 ints, specifying the stride of the sliding window. The strides of the N and C dimension are 1. diff --git a/third_party/fwkacllib/inc/ops/nn_training_ops.h b/third_party/fwkacllib/inc/ops/nn_training_ops.h index 75e91aee..9dd502cd 100644 --- a/third_party/fwkacllib/inc/ops/nn_training_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_training_ops.h @@ -289,7 +289,8 @@ REG_OP(SparseApplyAdagradV2D) * Should be from a Variable(). *@li lr: A scalar. Has the same type as "var". *@li grad: A tensor for the gradient. Has the same type as "var". -* +*@li momentum: Momentum. Must be a scalar. + *@par Attributes: *@li use_nesterov: An optional bool. Defaults to "False". * If "True", the tensor passed to compute grad will be @@ -701,7 +702,7 @@ REG_OP(ApplyPowerSignD) /** *@brief Updates "var" as FOBOS algorithm with fixed learning rate. * prox_v = var - alpha * delta -* var = sign(prox_v)/(1+alpha*l2) * max{|prox_v|-alpha*l1,0} +* var = sign(prox_v)/(1+alpha * l2) * max{|prox_v|-alpha * l1,0} * *@attention Constraints: * the input tensors must have the same shape. @@ -2128,10 +2129,12 @@ REG_OP(FusedMulApplyMomentumExtern) * otherwise the behavior is undefined, but may exhibit less contention. * *@par Outputs: -* var: A mutable tensor. Has the same type as input "var". +* @li var: A mutable tensor. Has the same type as input "var". +* @li accum: A mutable tensor. Has the same type as input "accum". * *@attention Constraints: -* The input tensors must have the same shape. +* @li var: A mutable tensor. Has the same type as input "var". +* @li accum: A mutable tensor. Has the same type as input "accum". * *@par Third-party framework compatibility * Compatible with the TensorFlow operator ResourceApplyKerasMomentum. diff --git a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h index ca1c24eb..01ff77cb 100644 --- a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h +++ b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h @@ -28,8 +28,8 @@ namespace ge { *@brief Computes the for the gelu of "x" . \n *@par Inputs: -*Two inputs, including: -* @li x: A Tensor. Must be one of the following types: float16, float32 +*One input, including: +*x: A Tensor. Must be one of the following types: float16, float32 *@par Outputs: *y: A Tensor. Has the same type as "x". @@ -66,8 +66,8 @@ REG_OP(GeluGrad) *@brief Computes the for the fast_gelu of "x" . \n *@par Inputs: -*Two inputs, including: -* @li x: A Tensor. Must be one of the following types: float16, float32 +*One input, including: +*x: A Tensor. Must be one of the following types: float16, float32 *@par Outputs: *y: A Tensor. Has the same type as "x". @@ -83,7 +83,7 @@ REG_OP(FastGelu) *@brief Computes the gradient for the fast_gelu of "x" . \n *@par Inputs: -*Three inputs, including: +*Two inputs, including: * @li dy: A Tensor. Must be one of the following types: float16, float32 * @li x: A Tensor of the same type as "dy" . \n @@ -169,7 +169,7 @@ REG_OP(Relu) * x: A Tensor of type RealNumberType . \n * @par Outputs: -* y: A Tensor of type RealNumberType . \n +* y: A Tensor with the same type as x . \n * @par Third-party framework compatibility * Compatible with the TensorFlow operator Relu6. @@ -209,8 +209,12 @@ REG_OP(Relu6D) * backprops = gradients * (features > 0) * (features < 6) . \n * @par Inputs: -* @li features: A Tensor of type RealNumberType. -* @li gradients: A Tensor of type RealNumberType . \n +* @li gradients: A Tensor of type RealNumberType. The backpropagated + gradients to the corresponding Relu6 operation. +* @li features: A Tensor with the same type as gradients.he features passed + as input to the corresponding Relu6 operation, or its output; + using either one produces the same result. \n + * @par Outputs: * backprops: A Tensor of type RealNumberType . \n @@ -228,7 +232,7 @@ REG_OP(Relu6Grad) *Applies the element-wise function: * Computes the backward for the elu: if x>0, 1; otherwise elu() + alpha . *@par Inputs: -*One inputs, including: +*Two inputs, including: * @li grads: A tensor. Must be one of the following types: * float16, float32. * @li activations: A tensor. Must be one of the following types: @@ -238,7 +242,7 @@ REG_OP(Relu6Grad) *y: A Tensor with the same type and shape of grads's. * *@par Attributes: -*@li alpha: scalar parameter, default value = 1.0 +*alpha: scalar parameter, default value = 1.0 */ REG_OP(EluGradV2) .INPUT(grads, TensorType({DT_FLOAT, DT_FLOAT16})) @@ -539,13 +543,9 @@ REG_OP(Elu) *x: A float16, float32, for the input data type . \n *@par Attributes: -*alpha1: A float32. Defines at which negative value the ELU saturates. Defaults to "1.0" . \n - -*@par Attributes: -*alpha2: A float32. Defines at which negative value the ELU saturates. Defaults to "1.0" . \n - -*@par Attributes: -*alpha3: A float32. Defines at which positive value the ELU saturates. Defaults to "1.0" . \n +*@li alpha1: A float32. Defines at which negative value the ELU saturates. Defaults to "1.0" . +*@li alpha2: A float32. Defines at which negative value the ELU saturates. Defaults to "1.0" . +*@li alpha3: A float32. Defines at which positive value the ELU saturates. Defaults to "1.0" . \n *@par Outputs: *y: A float16, float32, for the normalized result . \n @@ -706,8 +706,8 @@ REG_OP(Mish) * @li x: A Tensor. Must be one of the following types: float16, float32 * @li tanhx: A Tensor. shape, datatype and format is same as x * @par Outputs: - * 1 output, including: - * @li x_grad: A Tensor. shape, datatype and format is same as x + * One output, including: + * x_grad: A Tensor. shape, datatype and format is same as x */ REG_OP(MishGrad) @@ -721,20 +721,20 @@ REG_OP(MishGrad) * @brief pytorch hardtanh_backward operator. * * @par Inputs: - * 2 inputs, including: + * Two inputs, including: * @li result, minimum tensor of the linear region range, * datatype: float16/float32, format:ND/5HD. * @li grad, maximum tensor of the linear region range, * datatype:float16/float32, format:ND/5HD. \n * @par Attributes: - * 2 attributes, including: + * Two attributes, including: * @li min_val, minimum value of the linear region range, datatype:float. * @li max_val, maximum value of the linear region range, datatype:float. \n * @par Outputs: - * 1 output, including: - * @li y, hardtanh_backward output tensor, datatype and format is same as + * One output, including: + * y, hardtanh_backward output tensor, datatype and format is same as * input result. \n * @attention Constraints: @@ -756,7 +756,7 @@ REG_OP(HardtanhGrad) * @par Inputs: * One inputs, including: -* @li x: A mutable Tensor. Must be one of the following types: +* x: A mutable Tensor. Must be one of the following types: * float16, float32. \n * @par Attributes: @@ -765,7 +765,7 @@ REG_OP(HardtanhGrad) * @li threshold: An optional float. Defaults to "20.0" \n * @par Outputs: -* @li y: A mutable Tensor. Has the same type as "x" \n +* y: A mutable Tensor. Has the same type as "x" \n * @par Third-party framework compatibility * Compatible with the Pytorch operator Softplus. @@ -792,7 +792,7 @@ REG_OP(SoftplusV2) * @li threshold: An optional float. Defaults to "20.0" \n * @par Outputs: -* @li output_backprops: A mutable Tensor. Has the same type as "input_gradients" \n +* output_backprops: A mutable Tensor. Has the same type as "input_gradients" \n * @par Third-party framework compatibility * Compatible with the Pytorch operator SoftplusGrad. @@ -809,13 +809,16 @@ REG_OP(SoftplusV2Grad) * @brief ThresholdedRelu takes one input data (Tensor) and produces one output data (Tensor) * where the rectified linear function, y = x for x > alpha, y = 0 otherwise, is applied to the tensor elementwise. * - * @par inputs + * @par Inputs: * one input including: - * @li x: input A Tensor. Must be one of the following types: float32, float16 + * x: input A Tensor. Must be one of the following types: float32, float16 * - * @par output + * @par Attributes: + * alpha: An optional float. Defaults to 1.0. \n + + * @par Outputs: * one output including: - * @li y:A Tensor of the same type as x + * y:A Tensor of the same type as x * */ REG_OP(ThresholdedRelu) @@ -829,14 +832,14 @@ REG_OP(ThresholdedRelu) * @par Inputs: * One inputs, including: -* @li input_x: A tensor. Must be one of the following types: +* input_x: A tensor. Must be one of the following types: * float16, float32. \n * @par Attributes: -* @li lambd: An optional float. Defaults to 0.5. \n +* lambd: An optional float. Defaults to 0.5. \n * @par Outputs: -* y: A Tensor with the same dtype and shape of input_x's. \n +* output_y: A Tensor with the same dtype and shape of input_x's. \n * @par Third-party framework compatibility * Compatible with the Pytorch operator Hardshrink. \n @@ -863,7 +866,7 @@ REG_OP(HardShrink) *backprops: A Tensor with the same type and shape of features's. \n * *@par Attributes: -*@li lambd: An optional float.Defaults to 0.5. \n +*lambd: An optional float.Defaults to 0.5. \n * *@par Third-party framework compatibility *Compatible with the Pytorch operator Hardshrink_backward. \n @@ -880,7 +883,7 @@ REG_OP(HardShrink) * @par Inputs: * One inputs, including: -* @li input_x: A tensor. Must be one of the following types: +* input_x: A tensor. Must be one of the following types: * float16, float32, int32. \n * @par Attributes: @@ -905,11 +908,11 @@ REG_OP(HardSigmoid) * @par Inputs: * One inputs, including: -* @li input_x: A tensor. Must be one of the following types: +* input_x: A tensor. Must be one of the following types: * float16, float32. \n * @par Attributes: -* @li lambd: An optional float. Defaults to 0.5. \n +* lambd: An optional float. Defaults to 0.5. \n * @par Outputs: * y: A Tensor with the same dtype and shape of input_x's. \n @@ -933,7 +936,7 @@ REG_OP(SoftShrink) * @li input_x: A tensor of the same dtype as "input_grad". \n * @par Attributes: -* @li lambd: An optional float. Defaults to 0.5. \n +* lambd: An optional float. Defaults to 0.5. \n * @par Outputs: * y: A Tensor of the same dtype and shape as "input_graxd". \n @@ -976,12 +979,12 @@ REG_OP(LogSigmoidGrad) *@par Inputs: *One inputs, including: -* @li x: A tensor. Must be one of the following types: +* x: A tensor. Must be one of the following types: * float16, float32. \n *@par Outputs: *One outputs, including: -* @li y: A tensor with the same type and shape of x's. \n +* y: A tensor with the same type and shape of x's. \n *@par Third-party framework compatibility *Compatible with the Pytorch operator LogSigmoid. \n @@ -1003,7 +1006,7 @@ REG_OP(LogSigmoid) *@par Outputs: *One outputs, including: -* @li y: A tensor with the same type and shape of x's. \n +* y: A tensor with the same type and shape of x's. \n * @par Attributes: * @li alpha: An optional float. Defaults to 0.16666666. \n diff --git a/third_party/fwkacllib/inc/ops/pad_ops.h b/third_party/fwkacllib/inc/ops/pad_ops.h index 6854c866..9d0e7a62 100644 --- a/third_party/fwkacllib/inc/ops/pad_ops.h +++ b/third_party/fwkacllib/inc/ops/pad_ops.h @@ -33,8 +33,8 @@ namespace ge { *@li value: A 0D scalar. Specifies the value to fill the returned tensor. * Must be one of the following types: -* float16, float32, double, int32, uint8, int16, int8, complex64, int64, -* qint8, quint8, qint32, uint16, complex128, uint32, uint64. +* float16, float32, double, int32, uint8, int16, int8, complex64, int64, bool, +* qint8, quint8, qint32, qint16, quint16, uint16, complex128, uint32, uint64, . * *@par Outputs: * y: A tensor. Has the same type as "value". @@ -46,8 +46,14 @@ namespace ge { */ REG_OP(Fill) .INPUT(dims, TensorType::IndexNumberType()) - .INPUT(value, TensorType::BasicType()) - .OUTPUT(y, TensorType::BasicType()) + .INPUT(value, TensorType({DT_FLOAT, DT_DOUBLE, DT_INT32, DT_UINT8, DT_INT16, + DT_INT8, DT_COMPLEX64, DT_INT64, DT_BOOL, DT_QINT8, + DT_QUINT8, DT_QINT32, DT_QINT16, DT_QUINT16, DT_UINT16, + DT_COMPLEX128, DT_FLOAT16, DT_UINT32, DT_UINT64})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_DOUBLE, DT_INT32, DT_UINT8, DT_INT16, + DT_INT8, DT_COMPLEX64, DT_INT64, DT_BOOL, DT_QINT8, + DT_QUINT8, DT_QINT32, DT_QINT16, DT_QUINT16, DT_UINT16, + DT_COMPLEX128, DT_FLOAT16, DT_UINT32, DT_UINT64})) .OP_END_FACTORY_REG(Fill) /** @@ -213,11 +219,11 @@ REG_OP(PadV2) *@brief Pads a tensor . \n *@par Inputs: -*x: A Tensor. Must be one of the following types: float16, float32, int32 . \n -*constant_values: A Tensor. Must have the same type as input. +*@li x: A Tensor. Must be one of the following types: float16, float32, int32 . \n +*@li constant_values: A Tensor. Must have the same type as input. *@par Attributes: -*paddings: An optional "vector>". Defaults to "{}". +*paddings: A required Attribute. * For each dimension D of input, paddings[D, 0] indicates how many * values to add before the contents of tensor in that dimension, * and paddings[D, 1] indicates how many values to add after the @@ -461,7 +467,7 @@ REG_OP(FillV2) * @li dims: An required listInt to specify the shape that the value to fill. * @par Outputs: -* @li y: A Tensor. Has the shape specify by attr shape, and full of the value specify by attr value. +* y: A Tensor. Has the shape specify by attr shape, and full of the value specify by attr value. * @par Third-party framework compatibility * Compatible with the ONNX operator ConstantOfShape. diff --git a/third_party/fwkacllib/inc/ops/parsing_ops.h b/third_party/fwkacllib/inc/ops/parsing_ops.h index b625180a..e578997c 100644 --- a/third_party/fwkacllib/inc/ops/parsing_ops.h +++ b/third_party/fwkacllib/inc/ops/parsing_ops.h @@ -54,27 +54,26 @@ REG_OP(StringToNumber) /** *@brief Convert serialized tensorflow.TensorProto prototype to Tensor. *@brief Parse an Example prototype. -*@par Input: -*serialized: A Tensor of type string. -*dense_defaults: DYNAMIC INPUT Tensor type as string, float, int64. \n +*@par Inputs: +*@li serialized: A Tensor of type string. +*@li dense_defaults: DYNAMIC INPUT Tensor type as string, float, int64. \n *@par Attributes: -*num_sparse: type int num of inputs sparse_indices , sparse_values, sparse_shapes -*out_type: output type -*sparse_keys: ListString -*sparse_types: types of sparse_values -*dense_keys: ListString -*dense_shapes: output of dense_defaults shape -*dense_types: output of dense_defaults type \n +*@li num_sparse: type int num of inputs sparse_indices , sparse_values, sparse_shapes +*@li sparse_keys: ListString +*@li sparse_types: types of sparse_values +*@li dense_keys: ListString +*@li Tdense: output of dense_defaults type +*@li dense_shapes: output of dense_defaults shape \n *@par Outputs: -*sparse_indices: A Tensor of type string. -*sparse_values: Has the same type as sparse_types. -*sparse_shapes: A Tensor of type int64 -*dense_values: Has the same type as dense_defaults. +*@li sparse_indices: A Tensor of type string. +*@li sparse_values: Has the same type as sparse_types. +*@li sparse_shapes: A Tensor of type int64 +*@li dense_values: Has the same type as dense_defaults. *Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. -**/ +*/ REG_OP(ParseSingleExample) .INPUT(serialized, TensorType({DT_STRING})) .DYNAMIC_INPUT(dense_defaults, TensorType({DT_STRING,DT_FLOAT,DT_INT64})) @@ -92,16 +91,16 @@ REG_OP(ParseSingleExample) /** *@brief Decodes raw file into tensor . \n -*@par Input: +*@par Inputs: *bytes: A Tensor of type string. *@par Attributes: -*little_endian: bool ture -*out_type: output type +*@li little_endian: bool ture +*@li out_type: output type *@par Outputs: *Output: A Tensor -**/ +*/ REG_OP(DecodeRaw) .INPUT(bytes, TensorType({DT_STRING})) .OUTPUT(output, TensorType({DT_BOOL,DT_FLOAT16,DT_DOUBLE,DT_FLOAT, @@ -147,18 +146,20 @@ REG_OP(ParseTensor) *@par Inputs: *Inputs include: -*records: Each string is a record/row in the csv and all records should have the +*@li records: Each string is a record/row in the csv and all records should have the *same format. \n -*record_defaults: One tensor per column of the input record, with either a +*@li record_defaults: One tensor per column of the input record, with either a *scalar default value for that column or an empty vector if the column is *required. \n *@par Attributes: -*OUT_TYPE: The numeric type to interpret each string in string_tensor as . \n -*field_delim: char delimiter to separate fields in a record. \n -*use_quote_delim: If false, treats double quotation marks as regular characters +*@li OUT_TYPE: The numeric type to interpret each string in string_tensor as . \n +*@li field_delim: char delimiter to separate fields in a record. \n +*@li use_quote_delim: If false, treats double quotation marks as regular characters *inside of the string fields (ignoring RFC 4180, Section 2, Bullet 5). \n -*na_value: Additional string to recognize as NA/NaN. \n +*@li na_value: Additional string to recognize as NA/NaN. \n +*@li select_cols: Optional sorted list of column indices to select. If specified, +only this subset of columns will be parsed and returned. *@par Outputs: *output: A Tensor. Has the same type as x . \n @@ -186,25 +187,25 @@ REG_OP(DecodeCSV) /** *@brief Convert serialized tensorflow.TensorProto prototype to Tensor. *@brief Parse an Example prototype. -*@par Input: -*serialized: A Tensor of type string. \n -*name:A Tensor of type string. \n -*sparse_keys: Dynamic input tensor of string. \n -*dense_keys: Dynamic input tensor of string \n -*dense_defaults: Dynamic input tensor type as string, float, int64. \n +*@par Inputs: +*@li serialized: A Tensor of type string. \n +*@li name:A Tensor of type string. \n +*@li sparse_keys: Dynamic input tensor of string. \n +*@li dense_keys: Dynamic input tensor of string \n +*@li dense_defaults: Dynamic input tensor type as string, float, int64. \n *@par Attributes: -*Nsparse: Number of sparse_keys, sparse_indices and sparse_shapes \n -*Ndense: Number of dense_keys \n -*sparse_types: types of sparse_values \n -*Tdense: Type of dense_defaults dense_defaults and dense_values \n -*dense_shapes: output of dense_defaults shape \n +*@li Nsparse: Number of sparse_keys, sparse_indices and sparse_shapes \n +*@li Ndense: Number of dense_keys \n +*@li sparse_types: types of sparse_values \n +*@li Tdense: Type of dense_defaults dense_defaults and dense_values \n +*@li dense_shapes: output of dense_defaults shape \n *@par Outputs: -*sparse_indices: A Tensor of type string. \n -*sparse_values: Has the same type as sparse_types. \n -*sparse_shapes: A Tensor of type int64 \n -*dense_values: Has the same type as dense_defaults. \n +*@li sparse_indices: A Tensor of type string. \n +*@li sparse_values: Has the same type as sparse_types. \n +*@li sparse_shapes: A Tensor of type int64 \n +*@li dense_values: Has the same type as dense_defaults. \n *@par Third-party framework compatibility \n *@li compatible with tensorflow StringToNumber operator. \n */ @@ -228,37 +229,37 @@ REG_OP(ParseExample) /** *@brief Transforms a scalar brain.SequenceExample proto (as strings) into typed *tensors. -*@par Input: -*serialized: A Tensor of type string. \n -*feature_list_dense_missing_assumed_empty:A Tensor of type string. \n -*context_sparse_keys: Dynamic input tensor of string. \n -*context_dense_keys: Dynamic input tensor of string \n -*feature_list_sparse_keys: Dynamic input tensor of string \n -*feature_list_dense_keys: Dynamic input tensor of string \n -*context_dense_defaults: Dynamic input tensor of string, float, int64 \n -*debug_name: A Tensor of type string. \n +*@par Inputs: +*@li serialized: A Tensor of type string. \n +*@li feature_list_dense_missing_assumed_empty:A Tensor of type string. \n +*@li context_sparse_keys: Dynamic input tensor of string. \n +*@li context_dense_keys: Dynamic input tensor of string \n +*@li feature_list_sparse_keys: Dynamic input tensor of string \n +*@li feature_list_dense_keys: Dynamic input tensor of string \n +*@li context_dense_defaults: Dynamic input tensor of string, float, int64 \n +*@li debug_name: A Tensor of type string. \n *@par Attributes: -*Ncontext_sparse: Number of context_sparse_keys, context_sparse_indices and context_sparse_shapes \n -*Ncontext_dense: Number of context_dense_keys \n -*Nfeature_list_sparse: Number of feature_list_sparse_keys \n -*Nfeature_list_dense: Number of feature_list_dense_keys \n -*context_sparse_types: Types of context_sparse_values \n -*Tcontext_dense: Number of dense_keys \n -*feature_list_dense_types: Types of feature_list_dense_values \n -*context_dense_shapes: Shape of context_dense \n -*feature_list_sparse_types: Type of feature_list_sparse_values \n -*feature_list_dense_shapes: Shape of feature_list_dense \n +*@li Ncontext_sparse: Number of context_sparse_keys, context_sparse_indices and context_sparse_shapes \n +*@li Ncontext_dense: Number of context_dense_keys \n +*@li Nfeature_list_sparse: Number of feature_list_sparse_keys \n +*@li Nfeature_list_dense: Number of feature_list_dense_keys \n +*@li context_sparse_types: Types of context_sparse_values \n +*@li Tcontext_dense: Number of dense_keys \n +*@li feature_list_dense_types: Types of feature_list_dense_values \n +*@li context_dense_shapes: Shape of context_dense \n +*@li feature_list_sparse_types: Type of feature_list_sparse_values \n +*@li feature_list_dense_shapes: Shape of feature_list_dense \n *@par Outputs: -*context_sparse_indices: Dynamic output tensor of type int64. \n -*context_sparse_values: Dynamic output tensor of type string, float, int64. \n -*context_sparse_shapes: Dynamic output tensor of type int64 \n -*context_dense_values: Dynamic output tensor of type string, float, int64. \n -*feature_list_sparse_indices: Dynamic output tensor of type int64. \n -*feature_list_sparse_values: Dynamic output tensor of type string, float, int64. \n -*feature_list_sparse_shapes: Dynamic output tensor of type int64 \n -*feature_list_dense_values: Dynamic output tensor of type string, float, int64. \n +*@li context_sparse_indices: Dynamic output tensor of type int64. \n +*@li context_sparse_values: Dynamic output tensor of type string, float, int64. \n +*@li context_sparse_shapes: Dynamic output tensor of type int64 \n +*@li context_dense_values: Dynamic output tensor of type string, float, int64. \n +*@li feature_list_sparse_indices: Dynamic output tensor of type int64. \n +*@li feature_list_sparse_values: Dynamic output tensor of type string, float, int64. \n +*@li feature_list_sparse_shapes: Dynamic output tensor of type int64 \n +*@li feature_list_dense_values: Dynamic output tensor of type string, float, int64. \n *@par Third-party framework compatibility \n *@li compatible with tensorflow StringToNumber operator. \n */ diff --git a/third_party/fwkacllib/inc/ops/quantize_ops.h b/third_party/fwkacllib/inc/ops/quantize_ops.h index 69d5e67e..0636833c 100644 --- a/third_party/fwkacllib/inc/ops/quantize_ops.h +++ b/third_party/fwkacllib/inc/ops/quantize_ops.h @@ -63,10 +63,11 @@ REG_OP(Dequantize) /** *@brief Quantizes the input . \n *@par Inputs: -*x: shape and dtype of input_x. \n -*scales: shape and dtype of input_scales. \n -*zero_points: shape and dtype of input_zero_points \n +*@li x: shape and dtype of input_x. \n +*@li scales: shape and dtype of input_scales. \n +*@li zero_points: shape and dtype of input_zero_points \n *@par Attributes: +*@li dtype: required, type. *@li axis: the processed dim. \n *@par Outputs: *y: shape and dtype of output_y, should be same shape as input, dtype is same as the quantified type . \n @@ -91,7 +92,8 @@ REG_OP(Quantize) *@li offset: A required float16, specifying the offset. *@li sqrt_mode: A optional bool, specifying whether to perform square root on "scale", either "True" or "False". Defaults to "False". *@li round_mode: An optional string, specifying the float16 to int8 cast type. -* The value range is [Round, Floor, Ceiling, Truncate]. Defaults to "Round" . \n +* The value range is [Round, Floor, Ceil, Truncate]. Defaults to "Round" . +*@li dst_type: A optional int32, specifying the output data type. Defaults to "DT_INT8" . \n *@par Outputs: *y: The quantized output tensor of type int8 and with format NC1HWC0 . \n diff --git a/third_party/fwkacllib/inc/ops/ragged_array_ops.h b/third_party/fwkacllib/inc/ops/ragged_array_ops.h index 20484623..5af2dd74 100644 --- a/third_party/fwkacllib/inc/ops/ragged_array_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_array_ops.h @@ -37,13 +37,18 @@ namespace ge { *deprecated name. *@li indices: Indices in the outermost dimension of `params` of the values that should be *gathered. + +*@par Attributes: +*@li PARAMS_RAGGED_RANK:The ragged rank of the params_nested_splits. +*@li Tsplits:A type of output_nested_splits. *@li OUTPUT_RAGGED_RANK: The ragged rank of the output RaggedTensor. `output_nested_splits` will contain *this number of `row_splits` tensors. This value should equal *`indices.shape.ndims + params.ragged_rank - 1` . \n *@par Outputs: -*y:A Returns The `nested_row_splits` tensors that define the row-partitioning for the -*returned RaggedTensor.The `flat_values` for the returned RaggedTensor . \n +*@li output_nested_splits:A Returns The `nested_row_splits` tensors that define the row-partitioning for the +*returned RaggedTensor.The `flat_values` for the returned RaggedTensor . +*@li output_dense_values:The `flat_values` for the returned RaggedTensor. \n *@par Third-party framework compatibility * Compatible with tensorflow RaggedGather operator. diff --git a/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h b/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h index 020e3da4..ceaa64e4 100644 --- a/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h @@ -61,7 +61,6 @@ REG_OP(RaggedTensorToSparse) *@brief Create a dense tensor from a ragged tensor, possibly altering its shape . \n *@par Inputs: -*Six inputs, including: *@li shape:A `Tensor`. Must be one of the following types: `int64`, `int32`. *@li values:A 1D tensor representing the values of the ragged tensor. *@li default_value:A `Tensor`. Must have the same type as `values`. @@ -78,7 +77,7 @@ The types of the row partition tensors. At present, these can be: is preceeded by "FIRST_DIM_SIZE" . \n *@par Outputs: -*@li result: A `Tensor`. Has the same type as `values`. +*result: A `Tensor`. Has the same type as `values`. */ REG_OP(RaggedTensorToTensor) .INPUT(shape, TensorType({DT_INT32, DT_INT64})) diff --git a/third_party/fwkacllib/inc/ops/ragged_math_ops.h b/third_party/fwkacllib/inc/ops/ragged_math_ops.h index 258b0ca1..4376437f 100644 --- a/third_party/fwkacllib/inc/ops/ragged_math_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_math_ops.h @@ -35,7 +35,11 @@ namespace ge { *@li deltas: The deltas of each range . \n *@par Outputs: -*y:A Returns The `row_splits` for the returned `RaggedTensor`.The `flat_values` for the returned `RaggedTensor` . \n +*@li rt_dense_values:The `flat_values` for the returned `RaggedTensor`. +*@li rt_nested_splits:The `row_splits` for the returned `RaggedTensor`. \n + +*@par Attributes: +*Tsplits:A type of rt_nested_splits. *@attention Constraints: *The input tensors `starts`, `limits`, and `deltas` may be scalars or vectors. diff --git a/third_party/fwkacllib/inc/ops/random_ops.h b/third_party/fwkacllib/inc/ops/random_ops.h index b65a68f1..66f9b65f 100644 --- a/third_party/fwkacllib/inc/ops/random_ops.h +++ b/third_party/fwkacllib/inc/ops/random_ops.h @@ -147,6 +147,32 @@ REG_OP(RandomGamma) .ATTR(seed2, Int, 0) .OP_END_FACTORY_REG(RandomGamma) +/** +*@brief Returns the random permutation of integers from 0 to n-1. \n + +*@par Attributes: +*@li n: An required int. +*@li dtype: An optional str. Defaults to int64 . +*@li layout: An optional int. Defaults to 0 . \n + +*@par Outputs: +*out: A required Tensor. Must be one of the following types: + float16, float32, float32, int8, uint8, int16, int32, int64. \n + +*@attention Constraints: +*The implementation for Randperm on Ascend uses AICPU, with bad performance. + +*@par Third-party framework compatibility +*@li compatible with Pytorch Randperm operator. +*/ +REG_OP(Randperm) + .OUTPUT(out, TensorType({DT_INT64, DT_INT32, DT_INT16, + DT_UINT8, DT_INT8, DT_FLOAT16, DT_FLOAT32, DT_DOUBLE})) + .REQUIRED_ATTR(n, Int) + .ATTR(layout, Int, 0) + .ATTR(dtype, Type, DT_INT64) + .OP_END_FACTORY_REG(Randperm) + /** *@brief Outputs random values from the Poisson distribution(s) described by rate . \n @@ -157,11 +183,12 @@ REG_OP(RandomGamma) *@par Attributes: *@li dtype: An optional type from: half, float32, float64, int32, int64. Defaults to int64. -*@li seed: An optional int. Defaults to 0. -*@li seed2: An optional int. Defaults to 0 . \n +*@li seed: An optional int. Defaults to 0. If either seed or seed2 are set to be non-zero, +the random number generator is seeded by the given seed. Otherwise, it is seeded by a random seed. +*@li seed2: An optional int. Defaults to 0 . A second seed to avoid seed collision. \n *@par Outputs: -*y: A Tensor of type dtype . \n +*y: A Tensor of type dtype float16, float, double, int32, int64. \n *@attention Constraints: *The implementation for RandomPoisson on Ascend uses AICPU, with bad performance. @@ -188,11 +215,13 @@ REG_OP(RandomPoisson) *x: A Tensor. The tensor to be shuffled . \n *@par Attributes: -*@li seed: An optional int. Defaults to 0. -*@li seed2: An optional int. Defaults to 0 . \n +*@li seed: An optional int. Defaults to 0. If either seed or seed2 are set to be non-zero, +the random number generator is seeded by the given seed. Otherwise, it is seeded by a random seed. +*@li seed2: An optional int. Defaults to 0 . A second seed to avoid seed collision. \n *@par Outputs: -*y: A Tensor. Has the same type as x . \n +*y: A Tensor. Has the same type as x . A Tensor of type float16, float, +*double, int32, int64, int16, uint16, int8, uint8, int32,int64. \n *@attention Constraints: *The implementation for RandomShuffle on Ascend uses AICPU, with bad performance. @@ -220,11 +249,12 @@ REG_OP(RandomShuffle) *@par Attributes: *@li dtype: A type from: half, float16, float32, float64. The type of the output. -*@li seed: An optional int. Defaults to 0. -*@li seed2: An optional int. Defaults to 0 . \n +*@li seed: An optional int. Defaults to 0. If either seed or seed2 are set to be non-zero, +the random number generator is seeded by the given seed. Otherwise, it is seeded by a random seed. +*@li seed2: An optional int. Defaults to 0 . A second seed to avoid seed collision. \n *@par Outputs: -*y: A Tensor of type dtype . \n +*y: A Tensor of type float32, float16, double. \n *@attention Constraints: *The implementation for RandomStandardNormal on Ascend uses AICPU, with bad performance. @@ -240,6 +270,28 @@ REG_OP(RandomStandardNormal) .ATTR(seed2, Int, 0) .OP_END_FACTORY_REG(RandomStandardNormal) +/** +*@brief Output random value from separate normal distribution. \n + +*@par Inputs: +*Inputs include: +*mean: The mean is a tensor with the mean of each output element’s normal distribution . +*std: The std is a tensor with the standard deviation of each output element’s normal distribution. \n +*@par Outputs: +*y: A Tensor of type dtype . \n + +*@attention Constraints: +*The implementation for Normal on Ascend uses AICPU, with bad performance. + +*@par Third-party framework compatibility +*@li compatible with Pytorch Normal operator. +*/ +REG_OP(Normal) + .INPUT(mean, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(std, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OP_END_FACTORY_REG(Normal) + /** *@brief Outputs random integers from a uniform distribution . \n @@ -250,8 +302,9 @@ REG_OP(RandomStandardNormal) * @li max: A Tensor. Must have the same type as minval. 0-D . \n *@par Attributes: -*@li seed: An optional int. Defaults to 0. -*@li seed2: An optional int. Defaults to 0 . \n +*@li seed: An optional int. Defaults to 0. If either seed or seed2 are set to be non-zero, +the random number generator is seeded by the given seed. Otherwise, it is seeded by a random seed. +*@li seed2: An optional int. Defaults to 0 . A second seed to avoid seed collision. \n *@par Outputs: *y: A Tensor. Has the same type as min . \n @@ -280,8 +333,9 @@ REG_OP(RandomUniformInt) *@par Attributes: *@li dtype: A type from: half, float16, float32, float64. The type of the output. -*@li seed: An optional int. Defaults to 0. -*@li seed2: An optional int. Defaults to 0 . \n +*@li seed: An optional int. Defaults to 0. If either seed or seed2 are set to be non-zero, +the random number generator is seeded by the given seed. Otherwise, it is seeded by a random seed. +*@li seed2: An optional int. Defaults to 0 . A second seed to avoid seed collision. \n *@par Outputs: *y: A Tensor of type dtype . \n @@ -308,11 +362,14 @@ REG_OP(RandomUniform) *shape: A Tensor. Must be one of the following types: int32, int64 . \n *@par Attributes: -*@li seed: An optional int. Defaults to 0. -*@li seed2: An optional int. Defaults to 0 . \n +*@li seed: An optional int. Defaults to 0.If either `seed` or `seed2` +are set to be non-zero, the random number generator is seeded by the given +seed. Otherwise, it is seeded by a random seed. +*@li seed2: An optional int. Defaults to 0 . A second seed to avoid seed collision. \n *@par Outputs: -*size: A Tensor of types: float16, float32, double . \n +*y: A Tensor of types: float16, float32, double . A tensor of the specified shape +filled with random truncated normal values. \n *@attention Constraints: *The implementation for TruncatedNormal on Ascend uses AICPU, with bad performance. @@ -505,15 +562,15 @@ REG_OP(RandomChoiceWithMask) *@par Inputs: *Inputs including: -* @li x: A required Tensor. Must be one of the following types: - float16, float32, int8, uint8, int16, uint16, int32, uint32, int64, uint64 . \n +* x: A required Tensor. Must be one of the following types: + float16, float32, int8, uint8, int16, uint16, int32, uint32, int64, uint64 . \n *@par Attributes: -*@li group: A required int32, specifying the number of groups to split the channel dimension into. Defaults to "1" . \n +* group: A required int32, specifying the number of groups to split the channel dimension into. Defaults to "1" . \n *@par Outputs: -*y: A required Tensor. Has same type and shape as "x". Must be one of the following types: - float16, float32, int8, uint8, int16, uint16, int32, uint32, int64, uint64 . \n +* y: A required Tensor. Has same type and shape as "x". Must be one of the following types: + float16, float32, int8, uint8, int16, uint16, int32, uint32, int64, uint64 . \n *@attention Constraints: *@li "group" must be greater than 0 and must evenly divide the channel dimension size. @@ -584,6 +641,50 @@ REG_OP(DropoutV2) .OUTPUT(seed, TensorType({ DT_FLOAT })) .REQUIRED_ATTR(p, Float) .OP_END_FACTORY_REG(DropoutV2) + +/** +* @brief The Bernoulli distribution with probability . \n + +* @par Inputs: +* @li x: A ND Tensor. Must be one of the following data types: + int8, uint8, int16, int32, int64, bool, float32, float64 . +* @li p: A ND Tensor. The probability of an element to be zeroed. + Must be one of the following data types: float32, float64. \n + +* @par Attributes: +* seed: An Integer, the seed of the random generator. Default value -1 + to use current timestamp, otherwise it should be a positive integer. + +* @par Outputs: +* y: A tensor with the same shape and type as "x". +*/ + +REG_OP(Bernoulli) + .INPUT(x, TensorType({ DT_INT8, DT_UINT8, DT_INT16, DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE})) + .INPUT(p, TensorType({ DT_FLOAT, DT_DOUBLE })) + .OUTPUT(y, TensorType({ DT_INT8, DT_UINT8, DT_INT16, DT_INT32, DT_INT64, DT_BOOL, DT_FLOAT, DT_DOUBLE})) + .ATTR(seed, Int, -1) + .OP_END_FACTORY_REG(Bernoulli) + +/** + * @brief: Fill the input tensor with values drawn from the uniform distribution U(from, to). \n + + * @par Inputs: + * x: A Tensor. Must be one of the following types: float16, float, double. \n + + * @par Attributes: + * @li from: The lower bound of the uniform. Defaults: 0.0 + * @li to: The upper bound of the uniform. Defaults: 1.0 \n + + * @par Outputs: + * y: A Tensor has the same type as x. \n + */ +REG_OP(Uniform) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .ATTR(from, Float, 0.0) + .ATTR(to, Float, 1.0) + .OP_END_FACTORY_REG(Uniform) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_RANDOM_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/reduce_ops.h b/third_party/fwkacllib/inc/ops/reduce_ops.h index 97c7b8e1..1578ba59 100644 --- a/third_party/fwkacllib/inc/ops/reduce_ops.h +++ b/third_party/fwkacllib/inc/ops/reduce_ops.h @@ -576,7 +576,7 @@ REG_OP(ReduceAll) *@li axis: A mutable Tensor. The dimensions to reduce . \n *@par Attributes: -*@li keep_dims: A bool. If true, retains reduced dimensions with length 1. Defaults to "False" . \n +*keep_dims: A bool. If true, retains reduced dimensions with length 1. Defaults to "False" . \n *@par Outputs: *y: A Tensor. Has the same type and format as input "x" . \n @@ -967,9 +967,9 @@ REG_OP(EuclideanNormD) Defaults to "0.00001" . \n *@par Outputs: -*y: A Tensor of type float16 or float32 for the normalized "x". -*batch_mean: A Tensor of type float32 for the result mean. -*batch_ variance: A Tensor of type float32 for the result variance . \n +*@li y: A Tensor of type float16 or float32 for the normalized "x". +*@li batch_mean: A Tensor of type float32 for the result mean. +*@li batch_ variance: A Tensor of type float32 for the result variance . \n *@attention Constraints: *For Ascend 310, the result accuracy fails to reach 0.001 due to the square root instruction. @@ -987,7 +987,7 @@ REG_OP(INInferV2) .OP_END_FACTORY_REG(INInferV2) /** -*@brief Performs reduced instance normalization . \n +*@brief Performs reduce instance normalization. \n *@par Inputs: *x: A Tensor of type float16 or float32. \n @@ -1008,32 +1008,31 @@ REG_OP(INTrainingReduceV2) /** -*@brief Performs update instance normalization . \n +*@brief Performs update instance normalization. \n *@par Inputs: -* Seven inputs, including: (NC1HWC0supported) +* Seven inputs, including: *@li x: A Tensor of type float16 or float32. *@li sum: A Tensor of type float32 for the output of operator INTrainingReduceV2. *@li square_sum: A Tensor of type float32 for the output of operator INTrainingReduceV2. *@li gamma: A Tensor of type float32, for the scaling gamma. *@li beta: A Tensor of type float32, for the scaling beta. *@li mean: A Tensor of type float32, for the updated mean. -*@li variance: A Tensor of type float32, for the updated variance . \n +*@li variance: A Tensor of type float32, for the updated variance. \n *@par Attributes: *@li momentum: A required float32, specifying the momentum to update mean and var. -*@li epsilon: A required float32, specifying the small value added to variance to avoid dividing by zero . \n +*@li epsilon: A required float32, specifying the small value added to variance to avoid dividing by zero. \n *@par Outputs: * Three outputs *@li y: A Tensor of type float16 or float32, for normalized "x". *@li batch_mean: A Tensor of type float32, for the updated mean. -*@li batch_variance: A Tensor of type float32, for the updated variance . \n +*@li batch_variance: A Tensor of type float32, for the updated variance. \n *@attention Constraints: -*@li This operator is a InstanceNorm fusion operator for updating the moving averages for training. +* This operator is a InstanceNorm fusion operator for updating the moving averages for training. * This operator is used in conjunction with INTrainingReduceV2. -*@li For Ascend 310, the result accuracy fails to reach 1‰ due to the square root instruction. */ REG_OP(INTrainingUpdateV2) .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -1051,6 +1050,80 @@ REG_OP(INTrainingUpdateV2) .OP_END_FACTORY_REG(INTrainingUpdateV2) +/** +*@brief Performs the backpropagation of InstanceNorm. \n + +*@par Inputs: +* Seven inputs, including: +*@li dy: A Tensor of type float16 or float32. +*@li x: A Tensor of type float16 or float32. +*@li variance: A Tensor of type float32, for the variance of "x". +*@li mean: A Tensor of type float32, for the mean of "x". +*@li res_gamma: A Tensor of type float32. +*@li res_beta: A Tensor of type float32. +*@li gamma: A Tensor of type float32. \n + +*@par Outputs: +*pd_x: A Tensor of type float16 or float32, for the offset of "x". \n + +*@attention Constraints: +* The preceding layer of this operator must be INTrainingUpdateGrad. \n +*/ +REG_OP(INTrainingReduceGrad) + .INPUT(dy, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(variance, TensorType({DT_FLOAT})) + .INPUT(mean, TensorType({DT_FLOAT})) + .INPUT(res_gamma, TensorType({DT_FLOAT})) + .INPUT(res_beta, TensorType({DT_FLOAT})) + .INPUT(gamma, TensorType({DT_FLOAT})) + .OUTPUT(pd_x, TensorType({DT_FLOAT16,DT_FLOAT})) + .OP_END_FACTORY_REG(INTrainingReduceGrad) + +/** +*@brief Performs the backpropagation of InstanceNorm. \n + +*@par Inputs: +* Four inputs, including: +*@li dy: A Tensor of type float16 or float32, for the gradient. +*@li x: A Tensor of type float16 or float32. +*@li variance: A Tensor of type float32, for the variance of "x". +*@li mean: A Tensor of type float32, for the mean of "x". \n + +*@par Outputs: +*@li res_gamma: A Tensor of type float32. +*@li res_beta: A Tensor of type float32. \n + +*/ +REG_OP(INTrainingUpdateGrad) + .INPUT(dy, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(variance, TensorType({DT_FLOAT})) + .INPUT(mean, TensorType({DT_FLOAT})) + .OUTPUT(res_gamma, TensorType({DT_FLOAT})) + .OUTPUT(res_beta, TensorType({DT_FLOAT})) + .OP_END_FACTORY_REG(INTrainingUpdateGrad) + +/** +*@brief Performs the backpropagation of InstanceNorm. \n + +*@par Inputs: +* Two inputs, including: +*@li res_gamma: A Tensor of type float32. +*@li res_beta: A Tensor of type float32. \n + +*@par Outputs: +*@li pd_gamma: A Tensor of type float32. +*@li pd_beta: A Tensor of type float32. \n + +*/ +REG_OP(INTrainingUpdateGradGammaBeta) + .INPUT(res_gamma, TensorType({DT_FLOAT})) + .INPUT(res_beta, TensorType({DT_FLOAT})) + .OUTPUT(pd_gamma, TensorType({DT_FLOAT})) + .OUTPUT(pd_beta, TensorType({DT_FLOAT})) + .OP_END_FACTORY_REG(INTrainingUpdateGradGammaBeta) + /** *@brief Performs reduced group normalization . \n @@ -1063,7 +1136,7 @@ REG_OP(INTrainingUpdateV2) *@par Attributes: -*@li num_groups: Int, specifying the num of groups. required, same to GNTrainingUpdate . \n +*num_groups: Int, specifying the num of groups. required, same to GNTrainingUpdate . \n *@attention Constraints: * This operator is a GroupNorm fusion operator for updating the moving averages for training. @@ -1081,7 +1154,7 @@ REG_OP(GNTrainingReduce) *@brief Performs update group normalization . \n *@par Inputs: -* Eight inputs, including: (NCHW NHWC supported) +* Seven inputs, including: (NCHW NHWC supported) *@li x: A Tensor of type float16 or float32. *@li sum: A 5D Tensor of type float32, shape is [N, G, 1, 1, 1] for NCHW, [N, 1, 1, G, 1] for NHWC @@ -1145,8 +1218,8 @@ include: *@li keep_dims:A bool, An optional bool. Defaults to False. If True, retain reduced dimensions with length 1.. *@li separator:string. -*@par output: -*@li output::A Tensor of type string.. +*@par Outputs: +*output:A Tensor of type string. */ REG_OP(ReduceJoin) .INPUT(input, TensorType({DT_STRING})) @@ -1160,7 +1233,7 @@ REG_OP(ReduceJoin) * @brief Calculates the standard deviation and average value of Tensors. * @par Inputs: -* @li x: A Tensor. Must be one of the following types: +* x: A Tensor. Must be one of the following types: * float16, float32. \n * @par Attributes: diff --git a/third_party/fwkacllib/inc/ops/resource_variable_ops.h b/third_party/fwkacllib/inc/ops/resource_variable_ops.h index 74ac83f8..156f2f34 100644 --- a/third_party/fwkacllib/inc/ops/resource_variable_ops.h +++ b/third_party/fwkacllib/inc/ops/resource_variable_ops.h @@ -33,10 +33,12 @@ namespace ge { *y:A Tensor of type resource. \n *@par Attributes: -* @li container: optional, string. -* @li shared_name: optional, string. -* @li dtype: required, type. -* @li shape: optional, ListInt. \n +* @li container: optional, string. the container this +variable is placed in. +* @li shared_name: optional, string.the name by which + this variable is referred to. +* @li dtype: required, type. the output of type. +* @li shape: optional, ListInt. the output of shape. \n *@see VarHandleOp. */ @@ -53,11 +55,11 @@ REG_OP(VarHandleOp) *@brief Assigns a new value to a variable. \n *@par Inputs: -*resource:Handle to the resource in which to store the variable. -*value:The value to set the new tensor to use. \n +*@li resource:Handle to the resource in which to store the variable. +*@li value:The value to set the new tensor to use. \n *@par Attributes: -* @li dtype: required, type. \n +* dtype: required, type. \n *@see AssignVariableOp. */ @@ -73,11 +75,11 @@ REG_OP(AssignVariableOp) *@brief Adds a value to the current value of a variable. \n *@par Inputs: -*resource:Handle to the resource in which to store the variable. -*value:The value by which the variable will be incremented. \n +*@li resource:Handle to the resource in which to store the variable. +*@li value:The value by which the variable will be incremented. \n *@par Attributes: -* @li dtype: required, type. \n +* dtype: required, type. \n *@see AssignAddVariableOp. */ @@ -93,11 +95,11 @@ REG_OP(AssignAddVariableOp) *@brief Subtracts a value to the current value of a variable. \n *@par Inputs: -*resource:Handle to the resource in which to store the variable. -*value:The value by which the variable will be incremented. \n +*@li resource:Handle to the resource in which to store the variable. +*@li value:The value by which the variable will be incremented. \n *@par Attributes: -* @li dtype: required, type. \n +* dtype: required, type. \n *@see AssignSubVariableOp. */ diff --git a/third_party/fwkacllib/inc/ops/rnn.h b/third_party/fwkacllib/inc/ops/rnn.h index 80546860..20828a89 100644 --- a/third_party/fwkacllib/inc/ops/rnn.h +++ b/third_party/fwkacllib/inc/ops/rnn.h @@ -127,9 +127,7 @@ REG_OP(DynamicLSTM) *@li cell_clip:An float identifying the cell clip in the op. Default to -1. *@li num_proj:An integer identifying the num projection in the op. Default to 0. *@li time_major:An bool identifying the time major in the op. Default to false. -*@li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported. *@li forget_bias:An float identifying the forget bias in the op. Default to 0. -*@li is_training:An bool identifying is training in the op. Default to true. *@par Outputs: *eight outputs: \n @@ -491,7 +489,6 @@ REG_OP(DynamicLSTMV2) *ten inputs: \n *@li w:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li init_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li dy:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li dh:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. @@ -504,10 +501,11 @@ REG_OP(DynamicLSTMV2) *@par Outputs: -*eight outputs: \n +*four outputs: \n *@li dx:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@li dc_prev:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dgate:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_NZ. */ REG_OP(LSTMInputGrad) .INPUT(w, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -571,13 +569,13 @@ REG_OP(DynamicLSTMGradCell) .INPUT(f, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(o, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(tanhct, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(mask, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(t_state, TensorType({DT_INT32, DT_INT32})) + .INPUT(mask, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(dgate, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(dct_1, TensorType({DT_FLOAT16, DT_FLOAT})) - .ATTR(forget_bias, Float, 1) - .ATTR(activation, String, "") - .ATTR(direction, String, "Forward") + .ATTR(forget_bias, Float, 1.0) + .ATTR(activation, String, "tanh") + .ATTR(direction, String, "UNIDIRECTIONAL") .ATTR(gate_order, String, "ijfo") .OP_END_FACTORY_REG(DynamicLSTMGradCell) @@ -1070,7 +1068,7 @@ REG_OP(GRUV2HiddenGradCell) * If "False", "grad_weight" will not be scale by word_frequency. \n * @par Outputs: -* @li grad_weight: A mutable output Tensor of new word grad has the same type as "grads". \n +* y: A mutable output Tensor of new word grad has the same type as "grads". \n * @par Third-party framework compatibility * Compatible with the Pytorch operator EmbeddingDenseGrad. @@ -1222,7 +1220,7 @@ REG_OP(CommonGRU) * is equivalent to the size of indices. This matches the CSR format.. \n * @par Outputs: -* @li grad_weight: A mutable output Tensor of new word grad has the same type as "grads". \n +* y: A mutable output Tensor of new word grad has the same type as "grads". \n * @par Third-party framework compatibility * Compatible with the Pytorch operator EmbeddingBag. diff --git a/third_party/fwkacllib/inc/ops/rpn_ops.h b/third_party/fwkacllib/inc/ops/rpn_ops.h index 089af326..850b3e5a 100644 --- a/third_party/fwkacllib/inc/ops/rpn_ops.h +++ b/third_party/fwkacllib/inc/ops/rpn_ops.h @@ -28,12 +28,12 @@ namespace ge { * iou_threshold with higher scoring box according to their * intersection-over-union (IoU) . \n -*@par Input: -* @li box_scores: 2-D tensor with shape of [N, 8], including proposal boxes and +* @par Inputs: +* box_scores: 2-D tensor with shape of [N, 8], including proposal boxes and * corresponding confidence scores . \n * @par Attributes: -* @li iou_threshold: An optional float. The threshold for deciding whether boxes +* iou_threshold: An optional float. The threshold for deciding whether boxes * overlap too much with respect to IOU . \n * @par Outputs: diff --git a/third_party/fwkacllib/inc/ops/sdca_ops.h b/third_party/fwkacllib/inc/ops/sdca_ops.h index 34c6a268..601b360b 100644 --- a/third_party/fwkacllib/inc/ops/sdca_ops.h +++ b/third_party/fwkacllib/inc/ops/sdca_ops.h @@ -45,7 +45,13 @@ namespace ge { *corresponding weights in sparse_weights. This field maybe omitted for the dense approach.It's a dynamic input. *@li sparse_weights: a list of vectors where each value is the weight associated with a sparse feature group. *@li dense_weights: a list of vectors where the values are the weights associated with a dense feature group.It's a dynamic input. -*@li example_state_data: a list of vectors containing the example state data. +*@li example_state_data: a list of vectors containing the example state data. \n + +*@par Attributes: +*@li adaptive: the type is bool default false. +*@li num_sparse_features:The num of sparse. +*@li num_sparse_features_with_values: The num of sparse_feature_values +*@li num_dense_features:The num of dense. *@li loss_type: Type of the primal loss. Currently SdcaSolver supports logistic, squared and hinge losses. *@li l1: Symmetric l1 regularization strength. *@li l2: Symmetric l2 regularization strength. @@ -53,10 +59,10 @@ namespace ge { *@li num_inner_iterations: Number of iterations per mini-batch . \n *@par Outputs: -*y: A Returns a list of vectors containing the updated example state +*@li out_example_state_data: A Returns a list of vectors containing the updated example state *data.a list of vectors where each value is the delta -*weights associated with a sparse feature group.a list of vectors where the values are the delta -*weights associated with a dense feature group . \n +*@li out_delta_sparse_weights:weights associated with a sparse feature group.a list of vectors where the values are the delta +*@li out_delta_dense_weights:weights associated with a dense feature group . \n *@par Third-party framework compatibility * Compatible with tensorflow SdcaOptimizerV2 operator. diff --git a/third_party/fwkacllib/inc/ops/selection_ops.h b/third_party/fwkacllib/inc/ops/selection_ops.h index 1c26e033..43f72ef3 100644 --- a/third_party/fwkacllib/inc/ops/selection_ops.h +++ b/third_party/fwkacllib/inc/ops/selection_ops.h @@ -258,7 +258,7 @@ REG_OP(GatherV2D) REG_OP(GatherElements) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT64})) - .INPUT(index, TensorType({DT_INT64})) + .INPUT(index, TensorType({DT_INT32, DT_INT64})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT64})) .ATTR(dim, Int, 0) .OP_END_FACTORY_REG(GatherElements) @@ -508,7 +508,7 @@ REG_OP(UnsortedSegmentSum) *@par Inputs: *One inputs, including: -* @li assist: A tensor. Must be one of the following types: +* assist: A tensor. Must be one of the following types: * float16, float32. \n * @par Attributes: @@ -970,10 +970,11 @@ REG_OP(TopKV2) * for matrices) . \n * @par Attributes: -* @li sorted: An optional bool. Defaults to true. +* @li sorted: Defaults to true. * If true, the resulting "k" elements will be sorted by the values in descending * order. -* @li T: Indicator of indices type . \n +* @li largest:If true the resulting `k` elements will be sorted by the values in descending order. +* @li dim:0-D. Number of top elements to look for along the last dimension (along each row for matrices). \n * @par Outputs: * @li values: A Tensor, specifying the sorted data. Has the same type as @@ -982,7 +983,7 @@ REG_OP(TopKV2) * @see TopK() * @par Third-party framework compatibility -* @li Compatible with the TensorFlow operator TopKV2. +* Compatible with the TensorFlow operator TopKV2. */ REG_OP(TopK) .INPUT(x, TensorType::RealNumberType()) @@ -1085,7 +1086,6 @@ REG_OP(InTopKD) * @brief Says whether the targets are in the top "k" predictions . \n * @par Inputs: -* Two inputs, including: * @li x1: A 2D Tensor of type float32. A "batch_size * classes" tensor. * @li x2: A 1D Tensor of type IndexNumberType. A batch_size tensor of class ids. * @li k: A 1D Tensor of the same type as "x2". @@ -1618,12 +1618,12 @@ REG_OP(UnsortedSegmentMinD) * y: A Tensor of type RealNumberType . \n * @attention Constraints: -* @li segment_ids must be non-negative tensor. +* segment_ids must be non-negative tensor. * @see UnsortedSegmentSum(), UnsortedSegmentProd(), * @par Third-party framework compatibility -* @li Compatible with the TensorFlow operator UnsortedSegmentMax. +* Compatible with the TensorFlow operator UnsortedSegmentMax. */ REG_OP(UnsortedSegmentMax) .INPUT(x, TensorType::RealNumberType()) @@ -1875,15 +1875,15 @@ REG_OP(Crop) *@par Inputs: *One inputs, including: -* @li x: A tensor . Must be one of the following types: +* x: A tensor . Must be one of the following types: * float16, float32, int32, uint32, int8, uint8. \n *@par Attributes: -* @li axis: Axis along which to cummin. \n +* axis: Axis along which to cummin. \n *@par Outputs: -* y: A Tensor with the same type and shape of x's. \n -* indices: A Tensor with the int32 type and the same shape of x's. \n +* @li y: A Tensor with the same type and shape of x's. +* @li indices: A Tensor with the int32 type and the same shape of x's. \n *@par Third-party framework compatibility *Compatible with the Pytorch operator Cummin. \n @@ -1968,17 +1968,14 @@ REG_OP(WriteSelect) .OP_END_FACTORY_REG(WriteSelect) /** -*@brief Read data by stride . \n +*@brief Read data by stride. *@par Inputs: -*One input: -*x: A Tensor. Must be one of the following types: float16, int8 . \n +*x: A Tensor. Must be one of the following types: float16, int8. \n *@par Attributes: -*@li axis: A required int32, specifying the index of axis to read by stride . \n - -*@par Attributes: -*@li stride: A required int32, specifying the value of reading stride . \n +*@li axis: A required int32, specifying the index of axis to read by stride. \n +*@li stride: A required int32, specifying the value of reading stride. \n *@par Outputs: *y: A Tensor of the same type as "x". @@ -1991,16 +1988,14 @@ REG_OP(StridedRead) .OP_END_FACTORY_REG(StridedRead) /** -*@brief: Write data by stride . \n +*@brief Write data by stride. *@par Inputs: -*x: A Tensor. Must be one of the following types: float16, int8 . \n - -*@par Attributes: -*@li axis: A required int32, specifying the index of axis to write by stride . \n +*x: A Tensor. Must be one of the following types: float16, int8. \n *@par Attributes: -*@li stride: A required int32, specifying the value of writing stride . \n +*@li axis: A required int32, specifying the index of axis to write by stride. \n +*@li stride: A required int32, specifying the value of writing stride. \n *@par Outputs: *y: A Tensor. Has the same type as "x". @@ -2076,10 +2071,10 @@ REG_OP(CumulativeLogsumexpD) * @li updates: A Tensor of the same type as "var". \n * @par Attributes: -* @li axis: An required int to specify the axis to perform indices add. \n +* axis: An required int to specify the axis to perform indices add. \n * @par Outputs: -* @li var: A Tensor. Same as input "var". +* var: A Tensor. Same as input "var". * @par Third-party framework compatibility * Compatible with the Pytorch operator index_add_. @@ -2104,7 +2099,7 @@ REG_OP(InplaceIndexAdd) * @li value: A Tensor of dtype float16 or float32 or int64 or int32 or int8. * @par Outputs: -* @li y: A tensor. Must be one of the following dtypes: +* y: A tensor. Must be one of the following dtypes: * float16, float32, int64, int32, int8. */ REG_OP(MaskedFill) @@ -2123,7 +2118,7 @@ REG_OP(MaskedFill) * @li mask: A Tensor of dtype is bool. \n * @par Outputs: -* @li y: A tensor with the same type as x. \n +* y: A tensor with the same type as x. \n * @par Third-party framework compatibility * Compatible with the Numpy operator select. @@ -2134,13 +2129,50 @@ REG_OP(MaskedSelectV2) .INPUT(mask, TensorType({DT_BOOL})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(MaskedSelectV2) + +/** +* @brief Choose the value of X with value according to mask. + +* @par Inputs: +* two inputs, including: +* @li x: A Tensor of dtype is float16 or float32 or float64 or int64 or int32 or int16 or int8 or uint8. +* @li mask: A Tensor of dtype is bool. \n + +* @par Outputs: +* @li y: A tensor with the same type as x. \n + +*/ +REG_OP(MaskedSelect) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, DT_UINT8, DT_INT8, DT_INT16, DT_INT32, DT_INT64})) + .INPUT(mask, TensorType({DT_BOOL})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, DT_UINT8, DT_INT8, DT_INT16, DT_INT32, DT_INT64})) + .OP_END_FACTORY_REG(MaskedSelect) + +/** +* @brief update the value of X with value according to mask. + +* @par Inputs: +* three inputs, including: +* @li x: A Tensor of dtype is float16 or float32 or float64 or int64 or int32 or int16 or int8 or uint8. +* @li mask: A Tensor of dtype is bool. +* @li updates: A tensor with the same type as x. \n + +* @par Outputs: +* @li y: A tensor with the same type as x. \n +*/ +REG_OP(MaskedScatter) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, DT_UINT8, DT_INT8, DT_INT16, DT_INT32, DT_INT64})) + .INPUT(mask, TensorType({DT_BOOL})) + .INPUT(updates, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, DT_UINT8, DT_INT8, DT_INT16, DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, DT_UINT8, DT_INT8, DT_INT16, DT_INT32, DT_INT64})) + .OP_END_FACTORY_REG(MaskedScatter) /** * @brief Slice a tensor at its last dim, e.x. a[..., begin:end:stride]. \n * @par Inputs: * One inputs, including: -* @li x: A Tensor. Must be one of the following types: float16, float32, int16, int32. +* x: A Tensor. Must be one of the following types: float16, float32, int16, int32. * @par Attributes: * @li start: An attribute of type Int, start index of last dim. \n @@ -2148,7 +2180,7 @@ REG_OP(MaskedSelectV2) * @li stride: An attribute of type Int, stride of slice. \n * @par Outputs: -* @li y: A Tensor. Has the same type as "x". \n +* y: A Tensor. Has the same type as "x". \n * @par Third-party framework compatibility * No compatibility @@ -2162,39 +2194,36 @@ REG_OP(SliceLastDim) .OP_END_FACTORY_REG(SliceLastDim) /** -* @brief Extracts a strided slice of a tensor. Roughly speaking, this op \n -* extracts a slice of size (end-begin)/stride from the given input tensor. \n -* Starting at the location specified by begin the slice continues by \n +* @brief Extracts a strided slice of a tensor. Roughly speaking, this op +* extracts a slice of size (end-begin)/stride from the given input tensor. +* Starting at the location specified by begin the slice continues by * adding stride to the index until all dimensions are not less than end. \n * * @par Inputs: -* Four inputs, including: -* @li x: A Tensor. Must be one of the following types: float32, float64, int32, uint8, int16, int8, \n -* complex64, int64, qint8, quint8, qint32, qint16, quint16, uint16, \n -* complex128, float16, uint32, uint64, complex64, complex128. \n +* Five inputs, including: +* @li x: A Tensor. Must be one of the following types: float32, float64, int32, uint8, int16, int8, +* complex64, int64, qint8, quint8, qint32, qint16, quint16, uint16, +* complex128, float16, uint32, uint64, complex64, complex128. * @li begin: A Tensor of type int32 or int64, for the index of the first value to select. -* * @li end: A Tensor of type int32 or int64, for the index of the last value to select. -* * @li axes: A Tensor of type int32 or int64, indicate axis to be select. -* -* @li strides: A Tensor of type int32 or int64, for the increment. +* @li strides: A Tensor of type int32 or int64, for the increment. \n * * @par Attributes: -* @li begin_mask: A Tensor of type int32. \n -* A bitmask where a bit "i" being "1" means to ignore the begin \n +* @li begin_mask: A Tensor of type int32. +* A bitmask where a bit "i" being "1" means to ignore the begin * value and instead use the largest interval possible. -* @li end_mask: A Tensor of type int32. \n +* @li end_mask: A Tensor of type int32. * Analogous to "begin_mask". -* @li ellipsis_mask: A Tensor of type int32. \n -* A bitmask where bit "i" being "1" means the "i"th position \n +* @li ellipsis_mask: A Tensor of type int32. +* A bitmask where bit "i" being "1" means the "i"th position * is actually an ellipsis. -* @li new_axis_mask: A Tensor of type int32. \n -* A bitmask where bit "i" being "1" means the "i"th \n +* @li new_axis_mask: A Tensor of type int32. +* A bitmask where bit "i" being "1" means the "i"th * specification creates a new shape 1 dimension. -* @li shrink_axis_mask: A Tensor of type int32. \n -* A bitmask where bit "i" implies that the "i"th \n -* specification should shrink the dimensionality. +* @li shrink_axis_mask: A Tensor of type int32. +* A bitmask where bit "i" implies that the "i"th +* specification should shrink the dimensionality. \n * * @par Outputs: * y: A Tensor. Has the same type as "x". @@ -2231,7 +2260,7 @@ REG_OP(StridedSliceV2) * float16, float32, int32. \n * @par Attributes: -* @li dim: A required int. Used to select the dimension of this tensor. \n +* dim: A required int. Used to select the dimension of this tensor. \n *@par Outputs: *y: A Tensor with the same type and shape of input_x's. \n @@ -2307,6 +2336,34 @@ REG_OP(MaskedFillRange) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32})) .REQUIRED_ATTR(axis, Int) .OP_END_FACTORY_REG(MaskedFillRange) + +/** +* @brief After a set of sorted data and a new set of data are re-sorted, get the first k data. \n +* +* @par Inputs: +* Six inputs, including: +* @li topk_pq_distance: A sorted Tensor, Will be updated after calculation. Must be one of the following types: float32, float16. +* @li topk_pq_index: A Tensor of type int32, index corresponding to topk_pq_distance. +* @li topk_pq_ivf: A Tensor of type int32 , the bucket number corresponding to topk_pq_distance. +* @li pq_distance: A Tensor of type float32 or float16, the new data set will be reordered with topk_pq_distance and updated to topk_pq_distance. +* @li pq_index: A Tensor of type int32, index corresponding to pq_distance. +* @li pq_ivf: A scalar of type int32 , the bucket number corresponding to pq_distance. \n +* +* @par Attributes: +* @li order: A string, indicates the sorting method of topk_pq_distance. \n +* +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(InplaceTopKDistance) + .INPUT(topk_pq_distance, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(topk_pq_index, TensorType({DT_INT32})) + .INPUT(topk_pq_ivf, TensorType({DT_INT32})) + .INPUT(pq_distance, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(pq_index, TensorType({DT_INT32})) + .INPUT(pq_ivf, TensorType({DT_INT32})) + .ATTR(order, String, "asc") + .OP_END_FACTORY_REG(InplaceTopKDistance) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_SELECTION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/sparse_ops.h b/third_party/fwkacllib/inc/ops/sparse_ops.h index a1fc9ee6..8eb7b521 100644 --- a/third_party/fwkacllib/inc/ops/sparse_ops.h +++ b/third_party/fwkacllib/inc/ops/sparse_ops.h @@ -281,9 +281,9 @@ REG_OP(SparseSliceGrad) * @li size: A 1D Tensor of type int64. The size of the slice . \n *@par Outputs: -*y_indices: A Tensor of type int64. -*y_values: A Tensor. Has the same type as "values". -*y_values: A Tensor of type int64 . \n +*@li y_indices: A Tensor of type int64. +*@li y_values: A Tensor. Has the same type as "values". +*@li y_shape: A Tensor of type int64 . \n *@par Third-party framework compatibility * Compatible with the TensorFlow operator SparseSlice. @@ -313,8 +313,8 @@ REG_OP(SparseSlice) * @li sum_indices: A 2D Tensor of type int64. The indices of the sum SparseTensor, with size [nnz(sum), ndims] . \n *@par Outputs: -*x1_val_grad: A Tensor. Has the same type as "backprop_val_grad". -*x2_val_grad: A Tensor. Has the same type as "backprop_val_grad" . \n +*@li x1_val_grad: A Tensor. Has the same type as "backprop_val_grad". +*@li x2_val_grad: A Tensor. Has the same type as "backprop_val_grad" . \n *@par Third-party framework compatibility * Compatible with the TensorFlow operator SparseAddGrad. @@ -363,7 +363,7 @@ REG_OP(SparseFillEmptyRowsGrad) *@par Inputs: * @li x1_indices: A 2D Tensor of type int32 or int64. -* @li The indices of the matrix "SparseTensor", with size [nnz, 2]. +*The indices of the matrix "SparseTensor", with size [nnz, 2]. * @li x1_values: A 1D Tensor. The values of the SparseTensor, with size [nnz]. * @li x1_shape: A 1D Tensor of type int64. The shape of the SparseTensor, with size [2]. * @li x2: A dense matrix Tensor of the same type as "x1_values". 2D . \n @@ -373,9 +373,9 @@ REG_OP(SparseFillEmptyRowsGrad) *@par Attributes: *@li adjoint_a: An optional bool. Defaults to "False".Use the adjoint of A in the matrix multiply. -*@li If A is complex, this is transpose(conj(A)). Otherwise it is transpose(A). +*If A is complex, this is transpose(conj(A)). Otherwise it is transpose(A). *@li adjoint_b: An optional bool. Defaults to "False".Use the adjoint of B in the matrix multiply. -*@li If B is complex, this is transpose(conj(B)). Otherwise it is transpose(B) . \n +*If B is complex, this is transpose(conj(B)). Otherwise it is transpose(B) . \n *@par Third-party framework compatibility * Compatible with the TensorFlow operator SparseTensorDenseMatMul. @@ -400,9 +400,13 @@ REG_OP(SparseTensorDenseMatMul) * @li indices: A 0D, 1D, or 2D Tensor of type int32 or int64. * @li output_shape: A 1D Tensor of the same type as "sparse_indices". The shape of the dense output tensor. * @li values: A 1D Tensor. Values corresponding to each row of "sparse_indices", -* @li or a scalar value to be used for all sparse indices. +or a scalar value to be used for all sparse indices. * @li default_value: A Tensor of the same type as "sparse_values" . \n +*@par Attributes: +*validate_indices: If true, indices are checked to make sure they are sorted in +lexicographic order and that there are no repeats. \n + *@par Outputs: *y: A Tensor. Has the same type as "values" . \n @@ -427,7 +431,6 @@ REG_OP(SparseToDense) *Concatenation is with respect to the dense versions of these sparse tensors . \n *@par Inputs: -*3 or 5 inputs,contains: * @li indices:A list of at least 2 `Tensor` objects with type `int64`.2-D. *Indices of each input `SparseTensor`.It's a dynamic input. * @li values:A list with the same length as `indices` of `Tensor` objects with the same type. @@ -700,7 +703,6 @@ REG_OP(SparseReduceMaxSparse) *@brief Computes the sum of elements across dimensions of a SparseTensor . \n *@par Inputs: -*4 or 5 inputs, including: * @li x_indices: A 2D Tensor of type int64. *"N x R" matrix with the indices of non-empty values in a *SparseTensor, possibly not in canonical ordering. @@ -711,13 +713,11 @@ REG_OP(SparseReduceMaxSparse) *A length-"K" vector containing the reduction axes . \n *@par Attributes: -* keep_dims: An optional bool. Defaults to "False". +*keep_dims: An optional bool. Defaults to "False". *If true, retains reduced dimensions with length 1 . \n *@par Outputs: -* @li y_indices: A Tensor of type int64. -* @li y_values: A Tensor. Has the same type as "input_values". -* @li y_shape: A Tensor of type int64 . \n +*y: A Tensor. Has the same type as "x_values". \n *@par Third-party framework compatibility * Compatible with the TensorFlow operator SparseReduceSum. @@ -818,7 +818,6 @@ REG_OP(SparseSplit) *@brief Generates sparse cross from a list of sparse and dense tensors . \n *@par Inputs: -*8 or 10 inputs, including: * @li indices: A list of 2D Tensor objects of type int64. * Indices of each input SparseTensor.It's a dynamic input. * @li values: A list of 1D Tensor objects of type int64 or string. @@ -899,9 +898,8 @@ REG_OP(AddManySparseToTensorsMap) *@brief Reads SparseTensors from a "SparseTensorsMap" and concatenate them . \n *@par Inputs: -*2 or 4 inputs, including: * handles: A 1D Tensor of type int64. -* The "N" serialized SparseTensor objects . \n +*The "N" serialized SparseTensor objects . \n *@par Attributes: * @li dtype: A tf.DType. The "dtype" of the SparseTensor objects stored in the "SparseTensorsMap". @@ -911,9 +909,9 @@ REG_OP(AddManySparseToTensorsMap) *The shared name for the "SparseTensorsMap" read by this op . \n *@par Outputs: -* @li indices: A Tensor of type int64. -* @li values: A Tensor of type "dtype". -* @li shape: A Tensor of type int64 . \n +* @li indices: A Tensor of type int64.2-D. The `indices` of the minibatch `SparseTensor`. +* @li values: A Tensor of type "dtype". 1-D. The `values` of the minibatch `SparseTensor`. +* @li shape: A Tensor of type int64 . 1-D. The `shape` of the minibatch `SparseTensor`. \n *@par Third-party framework compatibility * Compatible with the TensorFlow operator TakeManySparseFromTensorsMap. @@ -989,8 +987,7 @@ REG_OP(SerializeManySparse) *@brief Deserializes SparseTensor objects . \n *@par Inputs: -*Two inputs, including: -* serialized_sparse: A Tensor. The serialized SparseTensor objects. +*serialized_sparse: A Tensor. The serialized SparseTensor objects. *The last dimension must have 3 columns . \n *@par Attributes: diff --git a/third_party/fwkacllib/inc/ops/spectral_ops.h b/third_party/fwkacllib/inc/ops/spectral_ops.h index 34ccb398..ab9e1dec 100644 --- a/third_party/fwkacllib/inc/ops/spectral_ops.h +++ b/third_party/fwkacllib/inc/ops/spectral_ops.h @@ -31,10 +31,10 @@ namespace ge { inner-most dimension of `x`. \n *@par Inputs: -*@li x: A Tensor. Must be the following types: complex64, complex128. \n +*x: A Tensor. Must be the following types: complex64, complex128. \n *@par Outputs: -*@li y: A complex tensor of the same rank as `x`. \n +*y: A complex tensor of the same rank as `x`. \n *@par Third-party framework compatibility * Compatible with TensorFlow IFFT operator. @@ -52,7 +52,7 @@ REG_OP(IFFT) *@li fft_length: An int32 tensor of shape [1]. The FFT length . \n *@par Outputs: -*@li y: A complex64 tensor of the same rank as `input`. The inner-most +*y: A complex64 tensor of the same rank as `input`. The inner-most dimension of `input` is replaced with the `fft_length / 2 + 1` unique frequency components of its 1D Fourier transform . \n @@ -73,7 +73,7 @@ REG_OP(RFFT) *@li fft_length: An int32 tensor of shape [1]. The FFT length. \n *@par Outputs: -*@li y: A float32 tensor of the same rank as `input`. The inner-most +* y: A float32 tensor of the same rank as `input`. The inner-most dimension of `input` is replaced with the `fft_length` samples of its inverse 1D Fourier transform. \n @@ -91,10 +91,10 @@ REG_OP(IRFFT) *@brief 2D fast Fourier transform. \n *@par Inputs: -*@li x: A complex64 tensor. +*x: A complex64 tensor. *@par Outputs: -*@li y: A complex64 tensor of the same shape as `input`. The inner-most 2 +*y: A complex64 tensor of the same shape as `input`. The inner-most 2 dimensions of `input` are replaced with their 2D Fourier transform. \n *@par Third-party framework compatibility @@ -110,10 +110,10 @@ REG_OP(FFT2D) innermost dimension of the input. \n *@par Inputs: -*@li x: A Tensor. Must be the following types: complex64, complex128. \n +*x: A Tensor. Must be the following types: complex64, complex128. \n *@par Outputs: -*@li y: A complex tensor with the same shape as input. The innermost dimension +*y: A complex tensor with the same shape as input. The innermost dimension of the input is replaced by its 1-dimensional Fourier transform. \n *@par Third-party framework compatibility @@ -129,10 +129,10 @@ REG_OP(FFT) innermost dimension of the input. \n *@par Inputs: -*@li x: A Tensor. Must be the following types: complex64, complex128. \n +*x: A Tensor. Must be the following types: complex64, complex128. \n *@par Outputs: -*@li y: A complex tensor with the same shape as input. The innermost dimension +*y: A complex tensor with the same shape as input. The innermost dimension of the input is replaced by its inverse two-dimensional Fourier transform. \n *@par Third-party framework compatibility diff --git a/third_party/fwkacllib/inc/ops/split_combination_ops.h b/third_party/fwkacllib/inc/ops/split_combination_ops.h index fe25a46f..98d4d111 100644 --- a/third_party/fwkacllib/inc/ops/split_combination_ops.h +++ b/third_party/fwkacllib/inc/ops/split_combination_ops.h @@ -161,14 +161,11 @@ REG_OP(SplitVD) /** *@brief Concatenates a list of N tensors along the first dimension. *@par Inputs: -* Two inputs, including: -* @li values: A list of Tensors. Must be one of the following types: int8, int16, int32, +* One input, including: +* values: A list of Tensors. Must be one of the following types: int8, int16, int32, * int64, uint8, uint16, uint32, uint64, float16, float32. * Tensors to be concatenated. All must have size 1 in the first dimension and same shape. -* It's a dynamic input. -* @li shape: A Tensor of the same type as "x". -* The final shape of the result. Should be equal to the shapes of any input -* but with the number of input values in the first dimension . \n +* It's a dynamic input. \n *@par Attributes: * @li shape: A required list of ints. diff --git a/third_party/fwkacllib/inc/ops/state_ops.h b/third_party/fwkacllib/inc/ops/state_ops.h index 3c8e32b6..d1ec00b5 100644 --- a/third_party/fwkacllib/inc/ops/state_ops.h +++ b/third_party/fwkacllib/inc/ops/state_ops.h @@ -104,7 +104,7 @@ REG_OP(DestroyTemporaryVariable) *@brief Checks whether a tensor has been initialized. Outputs boolean scalar indicating whether the tensor has been initialized . \n *@par Inputs: -*x: A tensor . \n +*x: A Tensor of type float16, float32, double, bool, int8, uint8, uint16, int16, int32, uint32, uint64, int64. *@par Outputs: *y: A tensor, indicating whether "x" has been initialized . \n diff --git a/third_party/fwkacllib/inc/ops/stateful_random_ops.h b/third_party/fwkacllib/inc/ops/stateful_random_ops.h index c2f65c6a..f4eb763c 100644 --- a/third_party/fwkacllib/inc/ops/stateful_random_ops.h +++ b/third_party/fwkacllib/inc/ops/stateful_random_ops.h @@ -32,7 +32,10 @@ namespace ge { *@par Inputs: *This op may use some OS-provided source of non-determinism (e.g. an RNG), *so each execution will give different results. Inputs included: -*@li shape: The shape of the output tensor . \n +*shape: The shape of the output tensor . \n + +*@par Attributes: +*dtype: required, type. \n *@par Outputs: *y:A Returns Non-deterministic integer values with specified shape . \n @@ -54,13 +57,10 @@ REG_OP(NonDeterministicInts) *counter is an unspecified implementation detail . \n *@par Inputs: -*@li resource: The handle of the resource variable that stores the state of the RNG. +*@li x: The handle of the resource variable that stores the state of the RNG. *@li algorithm: The RNG algorithm. *@li delta: The amount of advancement . \n -*@par Outputs: -*y:A Returns the created operation . \n - *@par Third-party framework compatibility * Compatible with tensorflow RngSkip operator. */ @@ -81,11 +81,16 @@ power of two. The bias is small for values of `maxval - minval` significantly smaller than the range of the output (either `2^32` or `2^64`) . \n *@par Inputs: -*@li resource: The handle of the resource variable that stores the state of the RNG. +*@li x: The handle of the resource variable that stores the state of the RNG. *@li algorithm: The RNG algorithm. *@li shape: The shape of the output tensor. -*@li minval: Minimum value (inclusive, scalar). -*@li maxval: Maximum value (exclusive, scalar) . \n +*@li counts: A 0/1-D Tensor or Python value. The counts of the binomial +distribution. Must be broadcastable with the leftmost dimension defined by `shape`. +*@li probs: A 0/1-D Tensor or Python value. The probability of success for the +binomial distribution. Must be broadcastable with the leftmost dimension defined by `shape`.\n + +*@par Attributes: +*dtype: required, type. \n *@par Outputs: *y:A Returns Random values with specified shape . \n @@ -109,7 +114,7 @@ REG_OP(StatefulRandomBinomial) *The generated values will have mean 0 and standard deviation 1 . \n *@par Inputs: -*@li resource: The handle of the resource variable that stores the state of the RNG. +*@li x: The handle of the resource variable that stores the state of the RNG. *@li algorithm: The RNG algorithm. *@li shape: The shape of the output tensor . \n @@ -134,7 +139,7 @@ REG_OP(StatefulStandardNormalV2) *deviations from the mean are dropped and re-picked . \n *@par Inputs: -*@li resource: The handle of the resource variable that stores the state of the RNG. +*@li x: The handle of the resource variable that stores the state of the RNG. *@li algorithm: The RNG algorithm. *@li shape: The shape of the output tensor . \n @@ -158,7 +163,7 @@ The generated values follow a uniform distribution in the range `[0, 1)`. The lower bound 0 is included in the range, while the upper bound 1 is excluded. *@par Inputs: -*@li resource: The handle of the resource variable that stores the state of the RNG. +*@li x: The handle of the resource variable that stores the state of the RNG. *@li algorithm: The RNG algorithm. *@li shape: The shape of the output tensor . \n @@ -181,7 +186,7 @@ REG_OP(StatefulUniform) The generated values are uniform integers covering the whole range of `dtype` . \n *@par Inputs: -*@li resource: The handle of the resource variable that stores the state of the RNG. +*@li x: The handle of the resource variable that stores the state of the RNG. *@li algorithm: The RNG algorithm. *@li shape: The shape of the output tensor . \n @@ -209,7 +214,7 @@ power of two. The bias is small for values of `maxval - minval` significantly smaller than the range of the output (either `2^32` or `2^64`) . \n *@par Inputs: -*@li resource: The handle of the resource variable that stores the state of the RNG. +*@li x: The handle of the resource variable that stores the state of the RNG. *@li algorithm: The RNG algorithm. *@li shape: The shape of the output tensor. *@li minval: Minimum value (inclusive, scalar). diff --git a/third_party/fwkacllib/inc/ops/string_ops.h b/third_party/fwkacllib/inc/ops/string_ops.h index f9cc2549..a78d63a1 100644 --- a/third_party/fwkacllib/inc/ops/string_ops.h +++ b/third_party/fwkacllib/inc/ops/string_ops.h @@ -295,7 +295,7 @@ REG_OP(StringSplit) *@par Inputs: include: -*@li input:A Tensor of type string. The text to be processed. \n +*input:A Tensor of type string. The text to be processed. \n *@par Attributes: *@li pattern:A string. The regular expression to match the input. @@ -303,8 +303,8 @@ include: *@li replace_global:An optional bool. Defaults to True. If True, the replacement is global, otherwise the replacement is done only on the first match. -*@par output: -*@li output::A Tensor of type string. +*@par Outputs: +*output::A Tensor of type string. */ REG_OP(StaticRegexReplace) .INPUT(input, TensorType({DT_STRING})) @@ -322,13 +322,13 @@ REG_OP(StaticRegexReplace) *@par Inputs: include: -*@li input:A Tensor of type string. The text to be processed. \n +*input:A Tensor of type string. The text to be processed. \n *@par Attributes: -*@li pattern:A string. The regular expression to match the input. +*pattern:A string. The regular expression to match the input. -*@par output: -*@li output::A bool tensor with the same shape as `input`. +*@par Outputs: +*output::A bool tensor with the same shape as `input`. */ REG_OP(StaticRegexFullMatch) .INPUT(input, TensorType({DT_STRING})) @@ -347,10 +347,10 @@ include: *@li num_segments:A Tensor. Must be one of the following types: int32, int64. A scalar. *@par Attributes: -*@li separator:An optional string. Defaults to "". The separator to use when joining. +*separator:An optional string. Defaults to "". The separator to use when joining. -*@par output: -*@li output::A Tensor of type string.. +*@par Outputs: +*output::A Tensor of type string.. */ REG_OP(UnsortedSegmentJoin) .INPUT(input, TensorType({DT_STRING})) @@ -366,13 +366,13 @@ REG_OP(UnsortedSegmentJoin) *@par Inputs: include: -*@li input:A Tensor of type string. The text to be processed. +*input:A Tensor of type string. The text to be processed. *@par Attributes: -*@li encoding:An optional string. Defaults to "". +*encoding:An optional string. Defaults to "". -*@par output: -*@li output::A Tensor of type string.. +*@par Outputs: +*output::A Tensor of type string.. */ REG_OP(StringLower) .INPUT(input, TensorType({DT_STRING})) @@ -386,13 +386,13 @@ REG_OP(StringLower) *@par Inputs: include: -*@li input:A Tensor of type string. The text to be processed. +*input:A Tensor of type string. The text to be processed. *@par Attributes: -*@li encoding:An optional string. Defaults to "". +*encoding:An optional string. Defaults to "". -*@par output: -*@li output::A Tensor of type string.. +*@par Outputs: +*output::A Tensor of type string.. */ REG_OP(StringUpper) .INPUT(input, TensorType({DT_STRING})) @@ -901,10 +901,10 @@ REG_OP(DecodeBase64) *@brief StringNormalization performs string operations for basic cleaning . \n *@par Inputs: -*@li input: only accepts [C] or [1, C] UTF-8 strings tensor . \n +*input: only accepts [C] or [1, C] UTF-8 strings tensor . \n *@par Outputs: -*@li output: UTF-8 strings tensor after cleaning . \n +*output: UTF-8 strings tensor after cleaning . \n *@par Attributes: *@li stopwords : list of strings (default is empty). @@ -919,13 +919,13 @@ case-sensitive. Default is false. *string enum that cases output to be lowercased/uppercases/unchanged. Valid values are "LOWER", "UPPER", "NONE". Default is "NONE". -*@li local : string (default is "en_US"). +*@li locale : string (default is "C"). *Environment dependent string that denotes the locale according to which output -strings needs to be upper/lowercased.Default en_US or platform specific equivalent -as decided by the implementation . \n +strings needs to be upper/lowercased.Default C or platform specific equivalent +as decided by the implementation. \n *@attention Constraints: -*@li input can be either a 1-D or 2-D tensor, the shape of 2-D tensor must be [1, C]. +*input can be either a 1-D or 2-D tensor, the shape of 2-D tensor must be [1, C]. */ REG_OP(StringNormalizer) .INPUT(input, TensorType({DT_STRING})) @@ -933,7 +933,7 @@ REG_OP(StringNormalizer) .ATTR(stopwords, ListString, {}) .ATTR(is_case_sensitive, Bool, false) .ATTR(case_change_action, String, "NONE") - .ATTR(local, String, "en_US") + .ATTR(locale, String, "C") .OP_END_FACTORY_REG(StringNormalizer) } // namespace ge diff --git a/third_party/fwkacllib/inc/ops/transformation_ops.h b/third_party/fwkacllib/inc/ops/transformation_ops.h index 4a46e35f..f403fe12 100644 --- a/third_party/fwkacllib/inc/ops/transformation_ops.h +++ b/third_party/fwkacllib/inc/ops/transformation_ops.h @@ -29,15 +29,15 @@ namespace ge { *@par Inputs: *The input handle must have the resource type. Inputs include: -*@li x:A list of Tensor objects. One or more tensors from which +*x:A list of Tensor objects. One or more tensors from which the enqueued tensors should be taken . \n *@par Outputs: -*@li y:A list of Tensor objects. One or more tensors from which +*y:A list of Tensor objects. One or more tensors from which the enqueued tensors should be taken . \n *@par Attributes: -*@li type: An optional ge::DataType. It refers to the target data type of outputs . \n +*type: An optional ge::DataType. It refers to the target data type of outputs . \n *@par Third-party framework compatibility *Compatible with tensorflow QueueIsClosed operator. @@ -723,11 +723,12 @@ REG_OP(CompressFcOp) *@brief Performs Col2im for each batch entry. \n *@par Inputs: -*@li input_x: The Col Tensor. 5-D, shape: `(n, c1, kernel_h*kernel_w, ho*wo, c0)`. -where ho/wo is do = (output_d + 2*padding_d - dilation_d*(kernel_d - 1) - 1)//stride_d + 1 \n +*@li x: The Col Tensor. 4-D, shape: `(n, c, kernel_h*kernel_w, ho*wo)`. +where ho/wo is do = (output_d + 2*padding_d - dilation_d*(kernel_d - 1) - 1)//stride_d + 1. +*@li output_size: The img shape Tensor. 1-D, shape:`(2)`, value: (output_h, output_w). \n *@par Outputs: -*@li output_y: The img Tensor. 5-D, shape: `(n, c1, output_h, output_w, c0)`. \n +*y: The img Tensor. 4-D, shape: `(n, c, output_h, output_w)`. \n *@par Attributes: *@li kernel_shape: ListInt, value: `(kernel_h, kernel_w)`, the shape of kernel in convolution. @@ -909,7 +910,7 @@ output shape would be [max(ngram_indexes) + 1]. If input shape is [N, C], this o *@li either pool_strings or pool_int64s attributes must be present but not both. */ -REG_OP(TfidVectorizer) +REG_OP(TfIdfVectorizer) .INPUT(input, TensorType({DT_INT32, DT_INT64, DT_STRING})) .OUTPUT(output, TensorType({DT_FLOAT})) .REQUIRED_ATTR(max_gram_length, Int) @@ -921,7 +922,7 @@ REG_OP(TfidVectorizer) .ATTR(pool_int64s, ListInt, {}) .ATTR(pool_strings, ListString, {}) .ATTR(weights, ListFloat, {}) - .OP_END_FACTORY_REG(TfidVectorizer) + .OP_END_FACTORY_REG(TfIdfVectorizer) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_TRANSFORMATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/runtime/base.h b/third_party/fwkacllib/inc/runtime/base.h index 7fc1cdea..70e42dc9 100644 --- a/third_party/fwkacllib/inc/runtime/base.h +++ b/third_party/fwkacllib/inc/runtime/base.h @@ -20,7 +20,7 @@ #include #include "toolchain/prof_callback.h" -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) extern "C" { #endif @@ -357,7 +357,7 @@ RTS_API rtError_t rtLabelCreateExV2(rtLabel_t *label, rtModel_t model, rtStream_ */ RTS_API rtError_t rtGetTaskIdAndStreamID(uint32_t *taskId, uint32_t *streamId); -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/runtime/config.h b/third_party/fwkacllib/inc/runtime/config.h index a244c793..76836e7b 100644 --- a/third_party/fwkacllib/inc/runtime/config.h +++ b/third_party/fwkacllib/inc/runtime/config.h @@ -19,7 +19,7 @@ #include "base.h" -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) extern "C" { #endif @@ -43,6 +43,7 @@ typedef enum tagRtChipType { CHIP_LHISI, CHIP_DC, CHIP_CLOUD_V2, + CHIP_NO_DEVICE, CHIP_END, } rtChipType_t; @@ -53,11 +54,11 @@ typedef enum tagRtAicpuScheType { } rtAicpuScheType; typedef enum tagRtDeviceCapabilityType { - RT_SCHEDULE_SOFTWARE = 0, // SoftWare Schedule - RT_SCHEDULE_SOFTWARE_OPT, - RT_SCHEDULE_HARDWARE, // HWTS Schedule - RT_AICPU_BLOCKING_OP_NOT_SUPPORT, - RT_AICPU_BLOCKING_OP_SUPPORT, // 1910/1980/1951 ts support AICPU blocking operation + RT_SCHEDULE_SOFTWARE = 0, // Software Schedule + RT_SCHEDULE_SOFTWARE_OPT, + RT_SCHEDULE_HARDWARE, // HWTS Schedule + RT_AICPU_BLOCKING_OP_NOT_SUPPORT, + RT_AICPU_BLOCKING_OP_SUPPORT, // 1910/1980/1951 ts support AICPU blocking operation } rtDeviceCapabilityType; typedef enum tagRtVersion { @@ -235,7 +236,7 @@ RTS_API rtError_t rtSetOpWaitTimeOut(uint32_t timeout); */ RTS_API rtError_t rtSetOpExecuteTimeOut(uint32_t timeout); -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/runtime/context.h b/third_party/fwkacllib/inc/runtime/context.h index e95d4c89..c597a657 100644 --- a/third_party/fwkacllib/inc/runtime/context.h +++ b/third_party/fwkacllib/inc/runtime/context.h @@ -19,7 +19,7 @@ #include "base.h" -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) extern "C" { #endif @@ -157,7 +157,7 @@ RTS_API rtError_t rtGetGroupCount(uint32_t *count); */ RTS_API rtError_t rtSetCtxINFMode(bool mode); -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/runtime/dev.h b/third_party/fwkacllib/inc/runtime/dev.h index 18d837eb..4a9a5817 100644 --- a/third_party/fwkacllib/inc/runtime/dev.h +++ b/third_party/fwkacllib/inc/runtime/dev.h @@ -19,7 +19,7 @@ #include "base.h" -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) extern "C" { #endif @@ -80,15 +80,15 @@ typedef enum tagMemoryInfo { } rtMemoryInfo_t; typedef enum tagRtDeviceModuleType { - RT_MODULE_TYPE_SYSTEM = 0, - RT_MODULE_TYPE_AICPU, - RT_MODULE_TYPE_CCPU, - RT_MODULE_TYPE_DCPU, - RT_MODULE_TYPE_AICORE, - RT_MODULE_TYPE_TSCPU, - RT_MODULE_TYPE_PCIE, - RT_MODULE_TYPE_VECTOR_CORE -} tagRtDeviceModuleType_t; + RT_MODULE_TYPE_SYSTEM = 0, /**< system info*/ + RT_MODULE_TYPE_AICPU, /** < aicpu info*/ + RT_MODULE_TYPE_CCPU, /**< ccpu_info*/ + RT_MODULE_TYPE_DCPU, /**< dcpu info*/ + RT_MODULE_TYPE_AICORE, /**< AI CORE info*/ + RT_MODULE_TYPE_TSCPU, /**< tscpu info*/ + RT_MODULE_TYPE_PCIE, /**< PCIE info*/ + RT_MODULE_TYPE_VECTOR_CORE, /**< VECTOR CORE info*/ +} rtDeviceModuleType_t; /** * @ingroup dvrt_dev @@ -380,7 +380,7 @@ RTS_API rtError_t rtSetDeviceWithoutTsd(int32_t device); */ RTS_API rtError_t rtDeviceResetWithoutTsd(int32_t device); -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/runtime/dvfsprofile.h b/third_party/fwkacllib/inc/runtime/dvfsprofile.h index 6e451695..33e2f4c1 100644 --- a/third_party/fwkacllib/inc/runtime/dvfsprofile.h +++ b/third_party/fwkacllib/inc/runtime/dvfsprofile.h @@ -19,7 +19,7 @@ #include "base.h" -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) extern "C" { #endif @@ -56,7 +56,7 @@ RTS_API rtError_t rtUnsetDvfsProfile(); */ RTS_API rtError_t rtGetDvfsProfile(DvfsProfileMode *pmode); -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/runtime/event.h b/third_party/fwkacllib/inc/runtime/event.h index 1cd1a198..81b635c3 100644 --- a/third_party/fwkacllib/inc/runtime/event.h +++ b/third_party/fwkacllib/inc/runtime/event.h @@ -19,7 +19,7 @@ #include "base.h" -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) extern "C" { #endif @@ -41,16 +41,6 @@ typedef enum rtEventWaitStatus { #define RT_EVENT_DDSYNC 0x04U #define RT_EVENT_TIME_LINE 0x08U -#define RT_EVENT_DDSYNC_NS 0x01U -#define RT_EVENT_STREAM_MARK 0x02U -#define RT_EVENT_DDSYNC 0x04U -#define RT_EVENT_TIME_LINE 0x08U - -#define RT_EVENT_DDSYNC_NS 0x01U -#define RT_EVENT_STREAM_MARK 0x02U -#define RT_EVENT_DDSYNC 0x04U -#define RT_EVENT_TIME_LINE 0x08U - /** * @ingroup dvrt_event * @brief create event instance @@ -282,7 +272,7 @@ RTS_API rtError_t rtNotifyGetAddrOffset(rtNotify_t notify, uint64_t *devAddrOffs */ RTS_API rtError_t rtSetIpcNotifyPid(const char *name, int32_t pid[], int num); -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/runtime/kernel.h b/third_party/fwkacllib/inc/runtime/kernel.h index 9b0221c7..c1b9bd6d 100644 --- a/third_party/fwkacllib/inc/runtime/kernel.h +++ b/third_party/fwkacllib/inc/runtime/kernel.h @@ -20,7 +20,7 @@ #include "base.h" #include "stream.h" -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) extern "C" { #endif @@ -647,7 +647,7 @@ RTS_API rtError_t rtStartMDCProfiler(void **addr, uint32_t length); */ RTS_API rtError_t rtStopMDCProfiler(void *addr); -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/runtime/mem.h b/third_party/fwkacllib/inc/runtime/mem.h index bace4bc6..b049e762 100644 --- a/third_party/fwkacllib/inc/runtime/mem.h +++ b/third_party/fwkacllib/inc/runtime/mem.h @@ -24,7 +24,7 @@ #include "config.h" #include "stream.h" -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) extern "C" { #endif @@ -547,7 +547,7 @@ RTS_API rtError_t rtSetIpcMemPid(const char *name, int32_t pid[], int num); */ RTS_API rtError_t rtRDMADBSend(uint32_t dbIndex, uint64_t dbInfo, rtStream_t stream); -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/runtime/rt_ffts.h b/third_party/fwkacllib/inc/runtime/rt_ffts.h old mode 100755 new mode 100644 index 720da7cd..f2809218 --- a/third_party/fwkacllib/inc/runtime/rt_ffts.h +++ b/third_party/fwkacllib/inc/runtime/rt_ffts.h @@ -1,5 +1,5 @@ /* - * Copyright (c) Huawei Technologies Co. , Ltd. 2021. All rights reserved. + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * Description: ffts interface */ @@ -8,7 +8,7 @@ #include "base.h" -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) extern "C" { #endif @@ -19,8 +19,8 @@ extern "C" { #define RT_FFTS_MANUAL_SRC_DEPEND_TBL_LEN 32U typedef enum tagFftsType { - RT_FFTS_TYPE_AUTO_THREAD = 2, // ffts auto thread mode, same as ffts define - RT_FFTS_TYPE_MANUAL_THREAD = 3, // ffts manual thread mode, same as ffts define + RT_FFTS_TYPE_AUTO_THREAD = 2, // ffts auto thread mode, same as ffts define + RT_FFTS_TYPE_MANUAL_THREAD = 3, // ffts manual thread mode, same as ffts define } rtFftsType_t; typedef enum tagFftsSubTaskType { @@ -37,7 +37,7 @@ typedef enum tagFftsSubTaskType { } rtFftsSubTaskType_t; typedef struct tagManualThreadDmuInfo { - uint64_t dataAddr; // device mem + uint64_t dataAddr; // device mem uint16_t numOuter; uint16_t numInner; uint32_t strideOuter; @@ -50,44 +50,43 @@ typedef struct tagManualThreadDependency { } rtManualThreadDependency_t; typedef struct tagManualThreadAicAivInfo { - uint64_t taskParamAddr; // device mem + uint64_t taskParamAddr; // device mem uint16_t taskParamOffset; // when satMode=1 and FP16 computation with none INF inputs overflows/underflows, results will be +/-INF of FP16 - // when satMode=0 and FP16 computation with none INF inputs overflows/underflows - // results will be saturated to +/- MAX of FP16 + // when satMode=0 and FP16 computation with none INF inputs overflows/underflows, + // results will be saturated to +/-MAX of FP16 uint8_t satMode; - uint8_t scheduleMode; // 0:normal mode, 1:batch mode, 2:sync mode, 3: reserved - uint8_t iCachePrefetchCnt; // units is 2K - uint8_t prefetchEnableBitmap; // 8 bit bitmap 1 0 1 0 - uint8_t prefetchOnceBitmap; // 8 bit bitmap 1 0 1 0 - uint16_t prefetchOnceDmuNum; // prefetch_once_dmu_descriptor_index in ffts - // num: thread0_prefetch_dmu_descriptor_index - prefetch_once_dmu_descriptor_index - uint16_t threadPrefetchDmuIdx[RT_FFTS_MAX_MANUAL_THREAD_NUM]; // max valid is threadDim + uint8_t scheduleMode; // 0:normal mode, 1:batch mode, 2:sync mode 3:reserved + uint8_t iCachePrefetchCnt; // units is 2K + uint8_t prefetchEnableBitmap; // 8 bit bitmap 1 0 1 0 + uint8_t prefetchOnceBitmap; // 8 bit bitmap 1 0 1 0 + uint16_t prefetchOnceDmuNum; // prefetch_once_dmu_descriptor_index in ffts + // num: thread0_prefetch_dmu_descriptor_index – prefetch_once_dmu_descriptor_index + uint16_t threadPrefetchDmuIdx[RT_FFTS_MAX_MANUAL_THREAD_NUM]; // max valid is threadDim uint16_t threadBlkDim[RT_FFTS_MAX_MANUAL_THREAD_NUM]; const char *threadTaskFuncStub[RT_FFTS_MAX_MANUAL_THREAD_NUM]; - rtManualThreadDmuInfo_t *prefetchList; // dmu desc 0-64k, length is the last threadPrefetchDmuIdx[threadDim - 1] + rtManualThreadDmuInfo_t *prefetchList; // dmu desc 0-64k, length is the last threadPrefetchDmuIdx[threadDim-1] rtManualThreadDependency_t srcDepTbl[RT_FFTS_MAX_TICKET_CACHE_PER_SUBTASK]; } rtManualThreadAicAivInfo_t; typedef struct tagAutoThreadPrefetch { - uint64_t dataAddr; // device mem + uint64_t dataAddr; // device mem uint32_t dataAddrOffset; uint32_t nonTailDataLen; uint32_t tailDataLen; } rtAutoThreadPrefetch_t; typedef struct tagAutoThreadAicAivInfo { - uint64_t taskParamAddr; // device mem + uint64_t taskParamAddr; // device mem uint16_t taskParamOffset; // when satMode=1 and FP16 computation with none INF inputs overflows/underflows, results will be +/-INF of FP16 - // when satMode=0 and FP16 computation with none INF inputs overflows/underflows - // results will be saturated to +/- MAX of FP16 + // when satMode=0 and FP16 computation with none INF inputs overflows/underflows, results will be saturated to +/-MAX of FP16 uint8_t satMode; - uint8_t scheduleMode; // 0:normal mode, 1:batch mode, 2:sync mode, 3: reserved - uint8_t iCachePrefetchCnt; // units is 2K - uint8_t prefetchEnableBitmap; // 8 bit bitmap - uint8_t prefetchOnceBitmap; // 8 bit bitmap + uint8_t scheduleMode; // 0:normal mode, 1:batch mode, 2:sync mode 3:reserved + uint8_t iCachePrefetchCnt; // units is 2K + uint8_t prefetchEnableBitmap; // 8 bit bitmap + uint8_t prefetchOnceBitmap; // 8 bit bitmap uint16_t tailBlkDim; uint16_t nonTailBlkDim; @@ -95,13 +94,13 @@ typedef struct tagAutoThreadAicAivInfo { const char *nonTailTaskFuncStub; const char *tailTaskFuncStub; - // for prefetch, valid num is prefetchEnableBitmap bit count - // if prefetchEnableBitmap = '00010011', need prefetch number is 3, srcPrefetch is only 0, 1, 2 is valid + // for prefetch, valid num is prefetchEnableBitmap bit count. + // if prefetchEnableBitmap='00010011', need prefetch number is 3, srcPrefetch is only 0, 1, 2 is valid rtAutoThreadPrefetch_t srcPrefetch[RT_FFTS_MAX_TICKET_CACHE_PER_SUBTASK]; } rtAutoThreadAicAivInfo_t; typedef struct tagAutoThreadCacheInfo { - uint64_t dataAddr; // device mem + uint64_t dataAddr; // device mem uint32_t dataAddrOffset; uint32_t nonTailDataLen; uint32_t tailDataLen; @@ -109,7 +108,7 @@ typedef struct tagAutoThreadCacheInfo { } rtAutoThreadCacheInfo_t; typedef struct tagManualThreadCacheInfo { - rtManualThreadDmuInfo_t *dmuList; // 0-64k + rtManualThreadDmuInfo_t *dmuList; // 0-64k uint16_t dmuNum; uint16_t sliceDmuIdx[RT_FFTS_MAX_MANUAL_THREAD_NUM]; uint16_t ticketCacheRefCntTbl[RT_FFTS_MAX_MANUAL_THREAD_NUM]; @@ -152,11 +151,11 @@ typedef struct tagFftsSubTaskInfo { } rtFftsSubTaskInfo_t; typedef struct tagFftsDescInfo { - uint8_t tm; // thread subtask kickstart mode, 0:order, 1:disorder - uint8_t di; // discard invalidate - uint8_t dw; // discard write back - uint8_t df; // discard flush - uint8_t dataSplitUnit; // split source or ticket cache by 2~dataSplitUnit MB + uint8_t tm; // thread subtask kickstart mode, 0:order, 1:disorder + uint8_t di; // discard invalidate + uint8_t dw; // discard write back + uint8_t df; // discard flush + uint8_t dataSplitUnit; // split source or ticket cache by 2^dataSplitUnit MB uint8_t prefetchOstNum; uint8_t cacheMaintainOstNum; uint8_t aicPrefetchUpper; @@ -166,20 +165,20 @@ typedef struct tagFftsDescInfo { } rtFftsDescInfo_t; typedef struct tagFftsTaskInfo { - rtFftsType_t fftsType; + rtFftsType_t fftsType; uint16_t subTaskNum; uint16_t tickCacheNum; rtFftsDescInfo_t fftsDesc; // sub task desc, real num is subTaskNum rtFftsSubTaskInfo_t subTask[RT_FFTS_MAX_SUB_TASK_NUM]; - // ticket cache, real number is ticketCacheNum + // ticket cache, real number is tickCacheNum. rtTicketCache_t ticketCache[RT_FFTS_MAX_TICKET_CACHE_NUM]; } rtFftsTaskInfo_t; RTS_API rtError_t rtFftsTaskLaunch(rtFftsTaskInfo_t *fftsTaskInfo, rtStream_t stream); -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) } #endif -#endif //__CCE_RUNTIME_FFTS_H +#endif // __CCE_RUNTIME_FFTS_H diff --git a/third_party/fwkacllib/inc/runtime/rt_model.h b/third_party/fwkacllib/inc/runtime/rt_model.h index a7618b45..d4af72c5 100644 --- a/third_party/fwkacllib/inc/runtime/rt_model.h +++ b/third_party/fwkacllib/inc/runtime/rt_model.h @@ -19,7 +19,7 @@ #include "base.h" -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) extern "C" { #endif @@ -490,7 +490,7 @@ RTS_API rtError_t rtDebugRegister(rtModel_t model, uint32_t flag, const void *ad */ RTS_API rtError_t rtDebugUnRegister(rtModel_t model); -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/runtime/rt_stars.h b/third_party/fwkacllib/inc/runtime/rt_stars.h index 188656b1..016c352a 100644 --- a/third_party/fwkacllib/inc/runtime/rt_stars.h +++ b/third_party/fwkacllib/inc/runtime/rt_stars.h @@ -8,7 +8,7 @@ #include "base.h" -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) extern "C" { #endif @@ -23,6 +23,7 @@ extern "C" { */ RTS_API rtError_t rtStarsTaskLaunch(const void *taskSqe, uint32_t sqeLen, rtStream_t stream); + /** * @ingroup rt_stars * @brief create cdq instance. @@ -76,10 +77,11 @@ RTS_API rtError_t rtCdqEnQueue(const char *queName, uint32_t cdqeIndex, void *da * @param [in] stream launch task on the stream * @return RT_ERROR_NONE for ok, others failed */ -RTS_API rtError_t rtCdqEnQueuePtrMode(const char *queName, uint32_t cdqeIndex, const void *prtAddr, +RTS_API rtError_t rtCdqEnQueuePtrMode(const char *queName, uint32_t cdqeIndex, const void *ptrAddr, rtStream_t stream); -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) + } #endif #endif // __CCE_RUNTIME_STARS_H diff --git a/third_party/fwkacllib/inc/runtime/stream.h b/third_party/fwkacllib/inc/runtime/stream.h index f9981514..3a078e99 100644 --- a/third_party/fwkacllib/inc/runtime/stream.h +++ b/third_party/fwkacllib/inc/runtime/stream.h @@ -20,7 +20,7 @@ #include "base.h" #include "event.h" -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) extern "C" { #endif @@ -211,7 +211,7 @@ RTS_API rtError_t rtDebugRegisterForStream(rtStream_t stream, uint32_t flag, con */ RTS_API rtError_t rtDebugUnRegisterForStream(rtStream_t stream); -#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +#if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h index 07b32149..9350f9d4 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h +++ b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h @@ -84,6 +84,7 @@ #endif #include +#include namespace Msprofiler { namespace Api { @@ -105,6 +106,37 @@ extern "C" { MSVP_PROF_API uint64_t ProfGetOpExecutionTime(const void *data, uint32_t len, uint32_t index); +typedef int Status; +typedef struct aclprofSubscribeConfig aclprofSubscribeConfig1; +/// +/// @ingroup AscendCL +/// @brief subscribe profiling data of graph +/// @param [in] graphId: the graph id subscribed +/// @param [in] profSubscribeConfig: pointer to config of model subscribe +/// @return Status result of function +/// +Status aclgrphProfGraphSubscribe(const uint32_t graphId, + const aclprofSubscribeConfig1 *profSubscribeConfig); + +/// +/// @ingroup AscendCL +/// @brief unsubscribe profiling data of graph +/// @param [in] graphId: the graph id subscribed +/// @return Status result of function +/// +Status aclgrphProfGraphUnSubscribe(const uint32_t graphId); + +/** + * @ingroup AscendCL + * @brief get graph id from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * + * @retval graph id of subscription data + * @retval 0 for failed + */ +size_t aclprofGetGraphId(const void *opInfo, size_t opInfoLen, uint32_t index); #ifdef __cplusplus } #endif diff --git a/third_party/fwkacllib/inc/toolchain/prof_callback.h b/third_party/fwkacllib/inc/toolchain/prof_callback.h index 5073cfb1..36b55216 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_callback.h +++ b/third_party/fwkacllib/inc/toolchain/prof_callback.h @@ -54,6 +54,17 @@ struct ReporterData { unsigned char *data; // the data content }; +/** + * @name HashData + * @brief struct of data to hash + */ +struct HashData { + int deviceId; // the index of device + size_t dataLen; // the length of data + unsigned char *data; // the data content + uint64_t hashId; // the id of hashed data +}; + /** * @name MsprofReporterModuleId * @brief module id of data to report @@ -75,6 +86,7 @@ enum MsprofReporterCallbackType { MSPROF_REPORTER_INIT, // init reporter MSPROF_REPORTER_UNINIT, // uninit reporter MSPROF_REPORTER_DATA_MAX_LEN, // data max length for calling report callback + MSPROF_REPORTER_HASH // hash data to id }; /** From d541b001dafdf4d5fb06e13c380e2489af471693 Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Thu, 29 Jul 2021 16:50:39 +0800 Subject: [PATCH 34/59] temporary fix of conflicting definitions --- metadef | 2 +- third_party/fwkacllib/inc/toolchain/prof_acl_api.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/metadef b/metadef index 21178899..e7b48d87 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit 211788997dcc9aa63527541a44d511388c06bce5 +Subproject commit e7b48d87d861921299e7c0fe293aaeac61136900 diff --git a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h index 9350f9d4..11e259b9 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h +++ b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h @@ -106,7 +106,7 @@ extern "C" { MSVP_PROF_API uint64_t ProfGetOpExecutionTime(const void *data, uint32_t len, uint32_t index); -typedef int Status; +typedef uint32_t Status; typedef struct aclprofSubscribeConfig aclprofSubscribeConfig1; /// /// @ingroup AscendCL From f2d2c36150a2a71cc2946e4c1dfc8896f4cd4845 Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Sat, 14 Aug 2021 16:23:54 +0800 Subject: [PATCH 35/59] update ascend software package 16 Aug 21 --- inc/external/acl/OWNERS | 9 + inc/external/acl/acl_prof.h | 37 --- inc/external/acl/error_codes/rt_error_codes.h | 3 - inc/framework/common/fmk_error_codes.h | 8 +- inc/framework/common/ge_compiler_options.h | 2 +- inc/framework/common/l2_cache_optimize.h | 2 +- inc/framework/common/profiling/ge_profiling.h | 2 +- .../common/profiling/ge_runner_profiling.h | 2 +- inc/framework/common/string_util.h | 12 +- inc/framework/common/taskdown_common.h | 2 +- inc/framework/memory/memory_api.h | 2 +- inc/framework/omg/ge_init.h | 2 +- inc/framework/omg/omg.h | 2 +- inc/framework/omg/parser/model_parser.h | 12 +- inc/framework/omg/parser/op_parser.h | 2 +- inc/framework/omg/parser/parser_api.h | 6 +- inc/framework/omg/parser/parser_factory.h | 2 +- inc/framework/omg/parser/weights_parser.h | 2 +- metadef | 2 +- .../aicpu/aicpu_schedule/aicpu_op_type_list.h | 120 +++++----- third_party/fwkacllib/inc/cce/aicpu_engine.h | 1 + .../inc/external/runtime/rt_error_codes.h | 212 +++++++++--------- .../inc/mmpa/sub_inc/mmpa_typedef_win.h | 166 +++++++------- .../fwkacllib/inc/mmpa/sub_inc/mmpa_win.h | 2 +- third_party/fwkacllib/inc/ops/aipp.h | 2 +- third_party/fwkacllib/inc/ops/all_ops.h | 2 +- third_party/fwkacllib/inc/ops/array_ops.h | 34 +-- third_party/fwkacllib/inc/ops/audio_ops.h | 2 +- .../fwkacllib/inc/ops/avg_pool_1d_ops.h | 2 +- third_party/fwkacllib/inc/ops/batch_ops.h | 2 +- third_party/fwkacllib/inc/ops/bitwise_ops.h | 2 +- .../fwkacllib/inc/ops/boosted_trees_ops.h | 2 +- .../inc/ops/candidate_sampling_ops.h | 2 +- .../fwkacllib/inc/ops/case_condition_ops.h | 53 +++++ third_party/fwkacllib/inc/ops/condtake_ops.h | 2 +- .../fwkacllib/inc/ops/control_flow_ops.h | 2 +- .../inc/ops/coordinates_1d_to_2d_ops.h | 48 ++++ third_party/fwkacllib/inc/ops/correlation.h | 2 +- third_party/fwkacllib/inc/ops/ctc_ops.h | 4 +- third_party/fwkacllib/inc/ops/data_flow_ops.h | 2 +- .../inc/ops/elewise_calculation_ops.h | 2 +- .../fwkacllib/inc/ops/functional_ops.h | 2 +- third_party/fwkacllib/inc/ops/get_data_ops.h | 2 +- third_party/fwkacllib/inc/ops/globalavgpool.h | 96 ++++---- third_party/fwkacllib/inc/ops/hcom_ops.h | 2 +- third_party/fwkacllib/inc/ops/hvd_ops.h | 2 +- third_party/fwkacllib/inc/ops/image_ops.h | 2 +- .../fwkacllib/inc/ops/index_to_addr_ops.h | 63 ++++++ third_party/fwkacllib/inc/ops/internal_ops.h | 2 +- third_party/fwkacllib/inc/ops/linalg_ops.h | 2 +- third_party/fwkacllib/inc/ops/list_ops.h | 2 +- third_party/fwkacllib/inc/ops/logging_ops.h | 34 ++- third_party/fwkacllib/inc/ops/lookup_ops.h | 2 +- third_party/fwkacllib/inc/ops/math_ops.h | 2 +- .../inc/ops/matrix_calculation_ops.h | 103 +++------ .../fwkacllib/inc/ops/nn_batch_norm_ops.h | 2 +- .../fwkacllib/inc/ops/nn_calculation_ops.h | 93 ++++---- third_party/fwkacllib/inc/ops/nn_detect_ops.h | 9 +- third_party/fwkacllib/inc/ops/nn_norm_ops.h | 2 +- third_party/fwkacllib/inc/ops/nn_ops.h | 2 +- .../fwkacllib/inc/ops/nn_pooling_ops.h | 28 ++- .../fwkacllib/inc/ops/nn_training_ops.h | 2 +- third_party/fwkacllib/inc/ops/no_op.h | 2 +- .../fwkacllib/inc/ops/nonlinear_fuc_ops.h | 18 +- .../fwkacllib/inc/ops/npu_loss_scale_ops.h | 2 +- third_party/fwkacllib/inc/ops/outfeed_ops.h | 2 +- third_party/fwkacllib/inc/ops/pad_ops.h | 2 +- third_party/fwkacllib/inc/ops/parsing_ops.h | 2 +- third_party/fwkacllib/inc/ops/quantize_ops.h | 7 +- .../fwkacllib/inc/ops/ragged_array_ops.h | 2 +- .../fwkacllib/inc/ops/ragged_conversion_ops.h | 2 +- .../fwkacllib/inc/ops/ragged_math_ops.h | 2 +- third_party/fwkacllib/inc/ops/random_ops.h | 2 +- third_party/fwkacllib/inc/ops/reduce_ops.h | 2 +- .../fwkacllib/inc/ops/resource_variable_ops.h | 2 +- third_party/fwkacllib/inc/ops/rnn.h | 6 +- third_party/fwkacllib/inc/ops/rpn_ops.h | 2 +- third_party/fwkacllib/inc/ops/save_ops.h | 2 +- third_party/fwkacllib/inc/ops/sdca_ops.h | 2 +- third_party/fwkacllib/inc/ops/selection_ops.h | 76 +++++-- third_party/fwkacllib/inc/ops/set_ops.h | 2 +- .../fwkacllib/inc/ops/slice_write_ops.h | 50 +++++ third_party/fwkacllib/inc/ops/sparse_ops.h | 2 +- third_party/fwkacllib/inc/ops/spectral_ops.h | 2 +- .../fwkacllib/inc/ops/split_combination_ops.h | 2 +- third_party/fwkacllib/inc/ops/state_ops.h | 2 +- .../fwkacllib/inc/ops/stateful_random_ops.h | 2 +- .../fwkacllib/inc/ops/stateless_random_ops.h | 2 +- third_party/fwkacllib/inc/ops/string_ops.h | 2 +- third_party/fwkacllib/inc/ops/swap_co_ops.h | 2 +- .../inc/ops/target_crop_and_resize.h | 2 +- .../fwkacllib/inc/ops/transformation_ops.h | 28 ++- .../fwkacllib/inc/ops/warp_perspective_ops.h | 2 +- third_party/fwkacllib/inc/opt_info/opt_info.h | 2 +- third_party/fwkacllib/inc/runtime/base.h | 96 +++++++- third_party/fwkacllib/inc/runtime/config.h | 10 +- third_party/fwkacllib/inc/runtime/context.h | 10 +- third_party/fwkacllib/inc/runtime/dev.h | 10 +- .../fwkacllib/inc/runtime/dvfsprofile.h | 10 +- third_party/fwkacllib/inc/runtime/event.h | 10 +- third_party/fwkacllib/inc/runtime/kernel.h | 53 ++++- third_party/fwkacllib/inc/runtime/mem.h | 10 +- third_party/fwkacllib/inc/runtime/rt.h | 10 +- third_party/fwkacllib/inc/runtime/rt_ffts.h | 17 +- third_party/fwkacllib/inc/runtime/rt_model.h | 10 +- third_party/fwkacllib/inc/runtime/rt_stars.h | 17 +- third_party/fwkacllib/inc/runtime/stream.h | 10 +- .../fwkacllib/inc/soft_dp/ExternalSoftDp.h | 22 +- .../fwkacllib/inc/tdt/index_transform.h | 20 +- third_party/fwkacllib/inc/tdt/status.h | 2 +- third_party/fwkacllib/inc/toolchain/plog.h | 118 +++++----- .../fwkacllib/inc/toolchain/prof_callback.h | 16 +- .../inc/toolchain/tuning_tool/tune_api.h | 18 +- 113 files changed, 1185 insertions(+), 752 deletions(-) create mode 100755 inc/external/acl/OWNERS create mode 100644 third_party/fwkacllib/inc/ops/case_condition_ops.h create mode 100644 third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h create mode 100644 third_party/fwkacllib/inc/ops/index_to_addr_ops.h create mode 100644 third_party/fwkacllib/inc/ops/slice_write_ops.h diff --git a/inc/external/acl/OWNERS b/inc/external/acl/OWNERS new file mode 100755 index 00000000..8552e853 --- /dev/null +++ b/inc/external/acl/OWNERS @@ -0,0 +1,9 @@ +approvers: +- ji_chen +- wqtshg +- zhangfan_hq +reviewers: +- justin_zhao +- zhangyongfeng88 +options: + no_parent_owners: true \ No newline at end of file diff --git a/inc/external/acl/acl_prof.h b/inc/external/acl/acl_prof.h index a93374b0..3784d8c6 100644 --- a/inc/external/acl/acl_prof.h +++ b/inc/external/acl/acl_prof.h @@ -40,20 +40,13 @@ typedef enum { ACL_AICORE_MEMORY_BANDWIDTH = 2, ACL_AICORE_L0B_AND_WIDTH = 3, ACL_AICORE_RESOURCE_CONFLICT_RATIO = 4, - ACL_AICORE_MEMORY_UB = 5, ACL_AICORE_NONE = 0xFF } aclprofAicoreMetrics; -typedef enum { - ACL_STEP_START = 0, // step start - ACL_STEP_END = 1 // step end -} aclprofStepTag; - typedef struct aclprofConfig aclprofConfig; typedef struct aclprofStopConfig aclprofStopConfig; typedef struct aclprofAicoreEvents aclprofAicoreEvents; typedef struct aclprofSubscribeConfig aclprofSubscribeConfig; -typedef struct aclprofStepInfo aclprofStepInfo; /** * @ingroup AscendCL @@ -329,36 +322,6 @@ ACL_FUNC_VISIBILITY uint64_t aclprofGetOpDuration(const void *opInfo, size_t opI */ ACL_FUNC_VISIBILITY size_t aclprofGetModelId(const void *opInfo, size_t opInfoLen, uint32_t index); -/** - * @ingroup AscendCL - * @brief - * - * @param stepInfo [IN] pointer to stepInfo data - * @param aclprofstepTag [IN] start or end flag - * @param stream [IN] steam info - * - * @retval 0 for failed - */ -ACL_FUNC_VISIBILITY aclError aclprofGetStepTimestamp(aclprofStepInfo *stepInfo, aclprofStepTag tag, aclrtStream stream); - -/** - * @ingroup AscendCL - * @brief create pointer to aclprofStepInfo data - * - * - * @retval aclprofStepInfo pointer - */ -ACL_FUNC_VISIBILITY aclprofStepInfo *aclprofCreateStepInfo(); - -/** - * @ingroup AscendCL - * @brief destroy aclprofStepInfo pointer - * - * - * @retval void - */ -ACL_FUNC_VISIBILITY void aclprofDestroyStepInfo(aclprofStepInfo *stepinfo); - #ifdef __cplusplus } #endif diff --git a/inc/external/acl/error_codes/rt_error_codes.h b/inc/external/acl/error_codes/rt_error_codes.h index a1392cc6..1c196c48 100644 --- a/inc/external/acl/error_codes/rt_error_codes.h +++ b/inc/external/acl/error_codes/rt_error_codes.h @@ -44,7 +44,6 @@ static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callbac static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type -static const int32_t ACL_ERROR_RT_WAIT_TIMEOUT = 107019; // wait timeout static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error @@ -57,7 +56,6 @@ static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event res static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource -static const int32_t ACL_ERROR_RT_NO_CDQ_RESOURCE = 207011; // no cdq resource static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error @@ -96,7 +94,6 @@ static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // devic static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception -static const int32_t ACL_ERROR_RT_CDQ_BATCH_ABNORMAL = 507037; // cdq alloc batch abnormal static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error diff --git a/inc/framework/common/fmk_error_codes.h b/inc/framework/common/fmk_error_codes.h index e910e346..188809bd 100644 --- a/inc/framework/common/fmk_error_codes.h +++ b/inc/framework/common/fmk_error_codes.h @@ -20,14 +20,18 @@ #if defined(_MSC_VER) #ifdef FUNC_VISIBILITY #define GE_FUNC_VISIBILITY _declspec(dllexport) +#define GE_OBJECT_VISIBILITY #else #define GE_FUNC_VISIBILITY +#define GE_OBJECT_VISIBILITY #endif #else #ifdef FUNC_VISIBILITY #define GE_FUNC_VISIBILITY __attribute__((visibility("default"))) +#define GE_OBJECT_VISIBILITY #else #define GE_FUNC_VISIBILITY +#define GE_OBJECT_VISIBILITY __attribute__((visibility("hidden"))) #endif #endif @@ -70,7 +74,9 @@ class GE_FUNC_VISIBILITY StatusFactory { class GE_FUNC_VISIBILITY ErrorNoRegisterar { public: - ErrorNoRegisterar(uint32_t err, const std::string &desc) { StatusFactory::Instance()->RegisterErrorNo(err, desc); } + ErrorNoRegisterar(uint32_t err, const std::string &desc) { + StatusFactory::Instance()->RegisterErrorNo(err, desc); + } ~ErrorNoRegisterar() {} }; diff --git a/inc/framework/common/ge_compiler_options.h b/inc/framework/common/ge_compiler_options.h index 5c947346..6876740e 100644 --- a/inc/framework/common/ge_compiler_options.h +++ b/inc/framework/common/ge_compiler_options.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/common/l2_cache_optimize.h b/inc/framework/common/l2_cache_optimize.h index fdb1c8b5..e3606582 100644 --- a/inc/framework/common/l2_cache_optimize.h +++ b/inc/framework/common/l2_cache_optimize.h @@ -104,7 +104,7 @@ class GE_FUNC_VISIBILITY L2CacheOptimize { // maximum common divisor uint32_t Measure(uint32_t x, uint32_t y) { - if (x == 0 || y == 0) return RC_VALUE_DEFAULT; + if ((x == 0) || (y == 0)) return RC_VALUE_DEFAULT; uint32_t z = y; while (x % y != 0) { z = x % y; diff --git a/inc/framework/common/profiling/ge_profiling.h b/inc/framework/common/profiling/ge_profiling.h index c87c082c..58cddc4e 100644 --- a/inc/framework/common/profiling/ge_profiling.h +++ b/inc/framework/common/profiling/ge_profiling.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/common/profiling/ge_runner_profiling.h b/inc/framework/common/profiling/ge_runner_profiling.h index 27e19bce..1c594c5b 100644 --- a/inc/framework/common/profiling/ge_runner_profiling.h +++ b/inc/framework/common/profiling/ge_runner_profiling.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/common/string_util.h b/inc/framework/common/string_util.h index f0368363..677b1971 100644 --- a/inc/framework/common/string_util.h +++ b/inc/framework/common/string_util.h @@ -45,16 +45,16 @@ class GE_FUNC_VISIBILITY StringUtils { public: static std::string &Ltrim(std::string &s) { #if __cplusplus >= 201103L - (void)s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) { return !std::isspace(c); })); + (void)s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) { return std::isspace(c) == 0; })); #else (void)s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); #endif return s; } // lint -esym(551,*) - static std::string &Rtrim(std::string &s) { /*lint !e618*/ + static std::string &Rtrim(std::string &s) { /*lint !e618*/ #if __cplusplus >= 201103L - (void)s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) { return !std::isspace(c); })); + (void)s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) { return std::isspace(c) == 0; })); #else (void)s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); #endif @@ -67,7 +67,9 @@ class GE_FUNC_VISIBILITY StringUtils { /// @param [in] string to be trimmed /// @return string after trim /// - static std::string &Trim(std::string &s) { return Ltrim(Rtrim(s)); } + static std::string &Trim(std::string &s) { + return Ltrim(Rtrim(s)); + } /// /// @ingroup domi_common @@ -92,7 +94,7 @@ class GE_FUNC_VISIBILITY StringUtils { } auto str_size = str.size(); - if (str_size > 0 && str[str_size - 1] == delim) { + if ((str_size > 0) && (str[str_size - 1] == delim)) { elems.emplace_back(""); } diff --git a/inc/framework/common/taskdown_common.h b/inc/framework/common/taskdown_common.h index f2f731be..81a532dd 100644 --- a/inc/framework/common/taskdown_common.h +++ b/inc/framework/common/taskdown_common.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/memory/memory_api.h b/inc/framework/memory/memory_api.h index a316fd59..da36cdd6 100644 --- a/inc/framework/memory/memory_api.h +++ b/inc/framework/memory/memory_api.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/omg/ge_init.h b/inc/framework/omg/ge_init.h index 42fd8979..67ef1082 100644 --- a/inc/framework/omg/ge_init.h +++ b/inc/framework/omg/ge_init.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/omg/omg.h b/inc/framework/omg/omg.h index a0cdb449..acd36883 100644 --- a/inc/framework/omg/omg.h +++ b/inc/framework/omg/omg.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/omg/parser/model_parser.h b/inc/framework/omg/parser/model_parser.h index 67f9338d..d311706d 100644 --- a/inc/framework/omg/parser/model_parser.h +++ b/inc/framework/omg/parser/model_parser.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -36,7 +36,7 @@ using Status = domi::Status; namespace domi { using GetGraphCallback = std::function( - const google::protobuf::Message *root_proto, const std::string &graph)>; + const google::protobuf::Message *root_proto, const std::string &graph)>; using GetGraphCallbackV2 = std::function; @@ -109,7 +109,9 @@ class GE_FUNC_VISIBILITY ModelParser { * @return SUCCESS * @return Others failed */ - virtual Status ToJson(const char *model_file, const char *json_file) { return domi::SUCCESS; } + virtual Status ToJson(const char *model_file, const char *json_file) { + return domi::SUCCESS; + } /* * @ingroup domi_omg @@ -129,7 +131,9 @@ class GE_FUNC_VISIBILITY ModelParser { * @return SUCCESS * @return Others failed */ - virtual Status ParseProto(const std::string &serialized_proto, ge::ComputeGraphPtr &graph) { return UNSUPPORTED; } + virtual Status ParseProto(const std::string &serialized_proto, ge::ComputeGraphPtr &graph) { + return UNSUPPORTED; + } /** * @ingroup domi_omg diff --git a/inc/framework/omg/parser/op_parser.h b/inc/framework/omg/parser/op_parser.h index 70bec218..7d02b257 100644 --- a/inc/framework/omg/parser/op_parser.h +++ b/inc/framework/omg/parser/op_parser.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/omg/parser/parser_api.h b/inc/framework/omg/parser/parser_api.h index 6c223665..a493e29f 100644 --- a/inc/framework/omg/parser/parser_api.h +++ b/inc/framework/omg/parser/parser_api.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -24,8 +24,8 @@ namespace ge { // Initialize parser -GE_FUNC_VISIBILITY Status ParserInitialize(const std::map& options); +GE_FUNC_VISIBILITY Status ParserInitialize(const std::map &options); // Finalize parser, release all resources GE_FUNC_VISIBILITY Status ParserFinalize(); } // namespace ge -#endif // INC_FRAMEWORK_OMG_PARSER_PARSER_API_H_ +#endif // INC_FRAMEWORK_OMG_PARSER_PARSER_API_H_ diff --git a/inc/framework/omg/parser/parser_factory.h b/inc/framework/omg/parser/parser_factory.h index 9d6590c0..06aaecb7 100644 --- a/inc/framework/omg/parser/parser_factory.h +++ b/inc/framework/omg/parser/parser_factory.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/omg/parser/weights_parser.h b/inc/framework/omg/parser/weights_parser.h index e4436044..a568f927 100644 --- a/inc/framework/omg/parser/weights_parser.h +++ b/inc/framework/omg/parser/weights_parser.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/metadef b/metadef index e7b48d87..51418f61 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit e7b48d87d861921299e7c0fe293aaeac61136900 +Subproject commit 51418f61f26599c85bee2b57328afbbf1c9927c7 diff --git a/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h b/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h index 703225e8..7e0f94a8 100644 --- a/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h +++ b/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h @@ -1,60 +1,60 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef AICPU_OP_TYPE_LIST_H_ -#define AICPU_OP_TYPE_LIST_H_ - -enum OpKernelType { - TF_KERNEL, - CPU_KERNEL -}; - -enum ReturnCode { - OP_TYPE_NOT_SUPPORT, - FORMAT_NOT_SUPPORT, - DTYPE_NOT_SUPPORT -}; - -#pragma pack(push, 1) -//One byte alignment -struct SysOpInfo { - uint64_t opLen; - uint64_t opType; - OpKernelType kernelsType; -}; - -struct OpParamInfo { - uint64_t num; - uint64_t dtypeList; - uint64_t formatList; -}; - -struct SysOpCheckInfo { - uint64_t opListNum; - uint64_t offSetLen; - uint64_t sysOpInfoList; - uint64_t opParamInfoList; -}; - -struct SysOpCheckResp { - uint64_t opListNum; - bool isWithoutJson; - uint64_t returnCodeList; - uint64_t sysOpInfoList; - uint64_t opParamInfoList; -}; -#pragma pack(pop) -#endif // AICPU_OP_TYPE_LIST_H_ +/** + * Copyright 2019-2020 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. + */ + +#ifndef AICPU_OP_TYPE_LIST_H_ +#define AICPU_OP_TYPE_LIST_H_ + +enum OpKernelType { + TF_KERNEL, + CPU_KERNEL +}; + +enum ReturnCode { + OP_TYPE_NOT_SUPPORT, + FORMAT_NOT_SUPPORT, + DTYPE_NOT_SUPPORT +}; + +#pragma pack(push, 1) +//One byte alignment +struct SysOpInfo { + uint64_t opLen; + uint64_t opType; + OpKernelType kernelsType; +}; + +struct OpParamInfo { + uint64_t num; + uint64_t dtypeList; + uint64_t formatList; +}; + +struct SysOpCheckInfo { + uint64_t opListNum; + uint64_t offSetLen; + uint64_t sysOpInfoList; + uint64_t opParamInfoList; +}; + +struct SysOpCheckResp { + uint64_t opListNum; + bool isWithoutJson; + uint64_t returnCodeList; + uint64_t sysOpInfoList; + uint64_t opParamInfoList; +}; +#pragma pack(pop) +#endif // AICPU_OP_TYPE_LIST_H_ diff --git a/third_party/fwkacllib/inc/cce/aicpu_engine.h b/third_party/fwkacllib/inc/cce/aicpu_engine.h index 042d952b..bc2e415f 100644 --- a/third_party/fwkacllib/inc/cce/aicpu_engine.h +++ b/third_party/fwkacllib/inc/cce/aicpu_engine.h @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #ifndef AICPU_ENGINE_H__ #define AICPU_ENGINE_H__ diff --git a/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h b/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h index 9f216a56..c5423d36 100644 --- a/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h +++ b/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h @@ -1,103 +1,109 @@ -/** -* @file rt_error_codes.h -* -* Copyright (C) Huawei Technologies Co., Ltd. 2019-2020. All Rights Reserved. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -*/ - -#ifndef __INC_EXTERNEL_RT_ERROR_CODES_H__ -#define __INC_EXTERNEL_RT_ERROR_CODES_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -static const int32_t ACL_RT_SUCCESS = 0; // success - -static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid -static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id -static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null -static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context -static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context -static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal -static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned -static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed -static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed -static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream -static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread -static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set -static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create -static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream -static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type -static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle -static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type -static const int32_t ACL_ERROR_RT_WAIT_TIMEOUT = 107019; // wait timeout - -static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support -static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error -static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error -static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow -static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device -static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail -static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission -static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource -static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource -static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource -static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource -static const int32_t ACL_ERROR_RT_NO_CDQ_RESOURCE = 207011; // no cdq resource - -static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error -static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout -static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception -static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception -static const int32_t ACL_ERROR_RT_CDQ_BATCH_ABNORMAL = 507037; // cdq alloc batch abnormal - -static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error -static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error -static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect - -#ifdef __cplusplus -} -#endif - -#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ +/** + * Copyright 2019-2020 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. + */ + +#ifndef __INC_EXTERNEL_RT_ERROR_CODES_H__ +#define __INC_EXTERNEL_RT_ERROR_CODES_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static const int32_t ACL_RT_SUCCESS = 0; // success + +static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid +static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id +static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null +static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context +static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context +static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal +static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned +static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed +static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed +static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream +static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread +static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set +static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create +static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream +static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type +static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle +static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type +static const int32_t ACL_ERROR_RT_WAIT_TIMEOUT = 107019; // wait timeout + +static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support +static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error +static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error +static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow +static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device +static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail +static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission +static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource +static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource +static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource +static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource +static const int32_t ACL_ERROR_RT_NO_CDQ_RESOURCE = 207011; // no cdq resource + +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout +static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception +static const int32_t ACL_ERROR_RT_CDQ_BATCH_ABNORMAL = 507037; // cdq alloc batch abnormal + +static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error +static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error +static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect + +#ifdef __cplusplus +} +#endif + +#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_win.h b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_win.h index 58ebb1a0..1627d7a9 100644 --- a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_win.h +++ b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_win.h @@ -1,83 +1,83 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef MMPA_TYPEDEF_WIN_H -#define MMPA_TYPEDEF_WIN_H - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif // __cpluscplus -#endif // __cpluscplus - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - -#define EN_OK 0 -#define EN_ERR 1 -#define EN_ERROR (-1) -#define EN_INVALID_PARAM (-2) -#define EN_TIMEOUT (-3) - -#define HANDLE_INVALID_VALUE (-1) -#define INVALID_SOCKET_HANDLE INVALID_SOCKET -#define MMPA_MEM_MAX_LEN (0x7fffffff) -#define MMPA_PROCESS_ERROR (0x7fffffff) - -#define MMPA_ONE_THOUSAND 1000 -#define MMPA_COMPUTER_BEGIN_YEAR 1900 -#define SUMMER_TIME_OR_NOT (-1) -#define MMPA_ZERO 0 -#define MMPA_VALUE_ONE 1 -#define MMPA_SOCKET_MAIN_EDITION 2 -#define MMPA_SOCKET_SECOND_EDITION 0 -#define MMPA_PIPE_BUF_SIZE 1024 -#define MMPA_MAX_SCANDIR_COUNT 1024 -#define MAX_IOVEC_SIZE 32 -#define MMPA_PIPE_COUNT 2 -#define MMPA_THREADNAME_SIZE 16 -#define MMPA_MIN_OS_NAME_SIZE (MAX_COMPUTERNAME_LENGTH + 1) -#define MMPA_MIN_OS_VERSION_SIZE 64 - -#define MMPA_MAX_NI 19 -#define MMPA_MIDDLE_NI 5 -#define MMPA_LOW_NI (-5) -#define MMPA_MIN_NI (-20) -#define MMPA_MAX_FILE 128 - -#define MMPA_MAX_THREAD_PIO 99 -#define MMPA_MIDDLE_THREAD_PIO 66 -#define MMPA_LOW_THREAD_PIO 33 -#define MMPA_MIN_THREAD_PIO 1 - -#define MMPA_THREAD_SCHED_RR 0 -#define MMPA_THREAD_SCHED_FIFO 0 -#define MMPA_THREAD_SCHED_OTHER 0 -#define MMPA_THREAD_MIN_STACK_SIZE 0 - -#define MM_MUTEX_INITIALIZER NULL - -#ifdef __cplusplus -#if __cplusplus -} -#endif // __cpluscplus -#endif // __cpluscplus -#endif // _MMPA_TYPEDEF_WIN_H_ +/** + * Copyright 2019-2020 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. + */ + +#ifndef MMPA_TYPEDEF_WIN_H +#define MMPA_TYPEDEF_WIN_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif // __cpluscplus +#endif // __cpluscplus + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#define EN_OK 0 +#define EN_ERR 1 +#define EN_ERROR (-1) +#define EN_INVALID_PARAM (-2) +#define EN_TIMEOUT (-3) + +#define HANDLE_INVALID_VALUE (-1) +#define INVALID_SOCKET_HANDLE INVALID_SOCKET +#define MMPA_MEM_MAX_LEN (0x7fffffff) +#define MMPA_PROCESS_ERROR (0x7fffffff) + +#define MMPA_ONE_THOUSAND 1000 +#define MMPA_COMPUTER_BEGIN_YEAR 1900 +#define SUMMER_TIME_OR_NOT (-1) +#define MMPA_ZERO 0 +#define MMPA_VALUE_ONE 1 +#define MMPA_SOCKET_MAIN_EDITION 2 +#define MMPA_SOCKET_SECOND_EDITION 0 +#define MMPA_PIPE_BUF_SIZE 1024 +#define MMPA_MAX_SCANDIR_COUNT 1024 +#define MAX_IOVEC_SIZE 32 +#define MMPA_PIPE_COUNT 2 +#define MMPA_THREADNAME_SIZE 16 +#define MMPA_MIN_OS_NAME_SIZE (MAX_COMPUTERNAME_LENGTH + 1) +#define MMPA_MIN_OS_VERSION_SIZE 64 + +#define MMPA_MAX_NI 19 +#define MMPA_MIDDLE_NI 5 +#define MMPA_LOW_NI (-5) +#define MMPA_MIN_NI (-20) +#define MMPA_MAX_FILE 128 + +#define MMPA_MAX_THREAD_PIO 99 +#define MMPA_MIDDLE_THREAD_PIO 66 +#define MMPA_LOW_THREAD_PIO 33 +#define MMPA_MIN_THREAD_PIO 1 + +#define MMPA_THREAD_SCHED_RR 0 +#define MMPA_THREAD_SCHED_FIFO 0 +#define MMPA_THREAD_SCHED_OTHER 0 +#define MMPA_THREAD_MIN_STACK_SIZE 0 + +#define MM_MUTEX_INITIALIZER NULL + +#ifdef __cplusplus +#if __cplusplus +} +#endif // __cpluscplus +#endif // __cpluscplus +#endif // _MMPA_TYPEDEF_WIN_H_ diff --git a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h index e6b6f71e..b17234b8 100644 --- a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h +++ b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h @@ -1,4 +1,4 @@ -/** +/** * Copyright 2019-2020 Huawei Technologies Co., Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/third_party/fwkacllib/inc/ops/aipp.h b/third_party/fwkacllib/inc/ops/aipp.h index 86805f72..6db4d783 100644 --- a/third_party/fwkacllib/inc/ops/aipp.h +++ b/third_party/fwkacllib/inc/ops/aipp.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/all_ops.h b/third_party/fwkacllib/inc/ops/all_ops.h index cc11f5f9..d63c2daa 100644 --- a/third_party/fwkacllib/inc/ops/all_ops.h +++ b/third_party/fwkacllib/inc/ops/all_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/array_ops.h b/third_party/fwkacllib/inc/ops/array_ops.h index 450c893e..acac3d6c 100644 --- a/third_party/fwkacllib/inc/ops/array_ops.h +++ b/third_party/fwkacllib/inc/ops/array_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -1249,38 +1249,6 @@ REG_OP(ExpandD) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) .REQUIRED_ATTR(shape, ListInt) .OP_END_FACTORY_REG(ExpandD) - -/** -*@brief Finds unique elements in a 1D tensor. \n - -*@par Inputs: -*x: 1D tensor. Must be one of the following types: -* float16, float32, double, int64, int32, int16, uint16, int8 ,uint8. \n - -*@par Attributes: -*@li return_inverse: Whether to also return the indices for where elements in the original -* input ended up in the returned unique list. -*@li return_inverse: Whether to also return the counts for each unique element. - -*@par Outputs: -*@li y1: The output list of unique scalar elements. Has the same type as "x". -*@li y2: Representing the indices for where elements in the original input map to in the output. -*@li y3: Representing the number of occurrences for each unique value or tensor. \n - -* @par Third-party framework compatibility -* Compatible with the troch operator _unique2. -*/ - -REG_OP(UniqueWithCountsAndSorting) - .INPUT(x, TensorType({ DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, \ - DT_INT32, DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE })) - .OUTPUT(y1, TensorType({ DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, \ - DT_INT32, DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE })) - .OUTPUT(y2, TensorType({ DT_INT32, DT_INT64 })) - .OUTPUT(y3, TensorType({ DT_INT32, DT_INT64 })) - .ATTR(return_inverse, Bool, false) - .ATTR(return_counts, Bool, false) - .OP_END_FACTORY_REG(UniqueWithCountsAndSorting) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_ARRAY_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/audio_ops.h b/third_party/fwkacllib/inc/ops/audio_ops.h index f05135d1..d9883253 100644 --- a/third_party/fwkacllib/inc/ops/audio_ops.h +++ b/third_party/fwkacllib/inc/ops/audio_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h b/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h index d0800a08..9583eff9 100644 --- a/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h +++ b/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/batch_ops.h b/third_party/fwkacllib/inc/ops/batch_ops.h index ca4fe1db..4b78951d 100644 --- a/third_party/fwkacllib/inc/ops/batch_ops.h +++ b/third_party/fwkacllib/inc/ops/batch_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/bitwise_ops.h b/third_party/fwkacllib/inc/ops/bitwise_ops.h index dac78118..d032476d 100644 --- a/third_party/fwkacllib/inc/ops/bitwise_ops.h +++ b/third_party/fwkacllib/inc/ops/bitwise_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/boosted_trees_ops.h b/third_party/fwkacllib/inc/ops/boosted_trees_ops.h index 08e54824..550e8b7d 100644 --- a/third_party/fwkacllib/inc/ops/boosted_trees_ops.h +++ b/third_party/fwkacllib/inc/ops/boosted_trees_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h b/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h index 890c52ae..e20607bf 100644 --- a/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h +++ b/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/case_condition_ops.h b/third_party/fwkacllib/inc/ops/case_condition_ops.h new file mode 100644 index 00000000..85064845 --- /dev/null +++ b/third_party/fwkacllib/inc/ops/case_condition_ops.h @@ -0,0 +1,53 @@ +/** + * Copyright 2019-2020 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. + */ + +/*! + * \file case_condition_ops.h + * \brief + */ +#ifndef OPS_BUILT_IN_OP_PROTO_INC_CASE_CONDITION_OPS_H_ +#define OPS_BUILT_IN_OP_PROTO_INC_CASE_CONDITION_OPS_H_ + +#include "graph/operator_reg.h" + +namespace ge { +/** +*@brief x[0] is i, x[1] is j and x[2] is k when algorithm is LU, +y = 0 when i >= k && j < k, +y = 1 when i == k && j == k, +y = 2 when i > k && j == k, +y = 3 when i == k && j > k, +y = 4 when i > k && j > k, +default y = 5 +use for lu decomposition +*@par Inputs: +*x: A Tensor of type int32/int64/uint64. \n + +*@par Attributes: +*algorithm: A string, only support LU now +*@par Outputs: +*y: A Tensor of type int32 +*/ +REG_OP(CaseCondition) + .INPUT(x, TensorType({DT_INT32, DT_INT64, DT_UINT64})) + .OUTPUT(y, TensorType({DT_INT32})) + .ATTR(algorithm, String, "LU") + .OP_END_FACTORY_REG(CaseCondition) + +} // namespace ge + + +#endif // OPS_BUILT_IN_OP_PROTO_INC_CASE_CONDITION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/condtake_ops.h b/third_party/fwkacllib/inc/ops/condtake_ops.h index 029cffbf..5e91eb07 100644 --- a/third_party/fwkacllib/inc/ops/condtake_ops.h +++ b/third_party/fwkacllib/inc/ops/condtake_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/control_flow_ops.h b/third_party/fwkacllib/inc/ops/control_flow_ops.h index cd993599..53a213f7 100644 --- a/third_party/fwkacllib/inc/ops/control_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/control_flow_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h b/third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h new file mode 100644 index 00000000..79a64c2c --- /dev/null +++ b/third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h @@ -0,0 +1,48 @@ +/** + * Copyright 2019-2020 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. + */ + +/*! + * \file coordinates_1d_to_2d_ops.h + * \brief + */ +#ifndef OPS_BUILT_IN_OP_PROTO_INC_COORDINATES_1D_TO_2D_OPS_H_ +#define OPS_BUILT_IN_OP_PROTO_INC_COORDINATES_1D_TO_2D_OPS_H_ + +#include "graph/operator_reg.h" + +namespace ge { +/** +*@brief Convert one-dimensional coordinates to two-dimensional coordinates. +*@par Inputs: +*@li x: A Tensor of type int32/int64/uint64. One-dimensional coordinates. +*@li shape: A Tensor of type int32/int64/uint64. 4D tensor [N,C,H,W]. +*@par Outputs: +*@li row: row of two-dimensional +*@li col: col of two-dimensional +*@li n: col number of two-dimensional +*/ +REG_OP(Coordinates1DTo2D) + .INPUT(x, TensorType({DT_INT32, DT_INT64, DT_UINT64})) + .INPUT(shape, TensorType({DT_INT32, DT_INT64, DT_UINT64})) + .OUTPUT(row, TensorType({DT_INT32, DT_INT64, DT_UINT64})) + .OUTPUT(col, TensorType({DT_INT32, DT_INT64, DT_UINT64})) + .OUTPUT(n, TensorType({DT_INT32, DT_INT64, DT_UINT64})) + .OP_END_FACTORY_REG(Coordinates1DTo2D) + +} // namespace ge + + +#endif // OPS_BUILT_IN_OP_PROTO_INC_COORDINATES_1D_TO_2D_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/correlation.h b/third_party/fwkacllib/inc/ops/correlation.h index caebba50..c7262cbb 100644 --- a/third_party/fwkacllib/inc/ops/correlation.h +++ b/third_party/fwkacllib/inc/ops/correlation.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/ctc_ops.h b/third_party/fwkacllib/inc/ops/ctc_ops.h index bbc610ff..7729432e 100644 --- a/third_party/fwkacllib/inc/ops/ctc_ops.h +++ b/third_party/fwkacllib/inc/ops/ctc_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -164,7 +164,7 @@ REG_OP(CTCBeamSearchDecoder) * Compatible with Pytorch CTCLoss operator. *@par Restrictions: -*The length of Label should in [4, 1000]. +*The limit of Label’s length is 1K. */ REG_OP(CTCLossV2) .INPUT(log_probs, TensorType({DT_FLOAT, DT_DOUBLE})) diff --git a/third_party/fwkacllib/inc/ops/data_flow_ops.h b/third_party/fwkacllib/inc/ops/data_flow_ops.h index 32454d27..2bbbdd0e 100644 --- a/third_party/fwkacllib/inc/ops/data_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/data_flow_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index b4299026..2246e66a 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/functional_ops.h b/third_party/fwkacllib/inc/ops/functional_ops.h index 7cfe39c4..e1fbe6b3 100644 --- a/third_party/fwkacllib/inc/ops/functional_ops.h +++ b/third_party/fwkacllib/inc/ops/functional_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/get_data_ops.h b/third_party/fwkacllib/inc/ops/get_data_ops.h index e5518ef8..33dc4f14 100644 --- a/third_party/fwkacllib/inc/ops/get_data_ops.h +++ b/third_party/fwkacllib/inc/ops/get_data_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/globalavgpool.h b/third_party/fwkacllib/inc/ops/globalavgpool.h index 06f03d30..b0fff691 100644 --- a/third_party/fwkacllib/inc/ops/globalavgpool.h +++ b/third_party/fwkacllib/inc/ops/globalavgpool.h @@ -1,49 +1,49 @@ -/** - * Copyright 2019 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. - */ - -/*! - * \file globalavgpool.h - * \brief - */ -#ifndef OPS_BUILT_IN_OP_PROTO_INC_GLOBALAVERAGEPOOL_H_ -#define OPS_BUILT_IN_OP_PROTO_INC_GLOBALAVERAGEPOOL_H_ - -#include "graph/operator_reg.h" - -namespace ge { -/** -*@brief GlobalAveragePool consumes an input tensor X and applies average pooling across the values in the same channel. -This is equivalent to AveragePool with kernel size equal to the spatial dimension of input tensor \n - -*@par Inputs: -*@li x: Input data tensor from the previous operator; dimensions for image case are (N x C x H x W), -where N is the batch size, C is the number of channels, and H and W are the height and the width of the data. -For non image case, the dimensions are in the form of (N x C x D1 x D2 ... Dn), where N is the batch size. - -*@par Outputs: -*y: Output data tensor from pooling across the input tensor. The output tensor has the same rank as the input. -The first two dimensions of output shape are the same as the input (N x C), while the other dimensions are all 1 - -*@par Restrictions: -*Warning: This operator can be integrated only by configuring INSERT_OP_FILE of aclgrphBuildModel. Please do not use it directly. -*/ -REG_OP(GlobalAveragePool) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) - .OP_END_FACTORY_REG(GlobalAveragePool) -} // namespace ge - +/** + * Copyright 2019-2020 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. + */ + +/*! + * \file globalavgpool.h + * \brief + */ +#ifndef OPS_BUILT_IN_OP_PROTO_INC_GLOBALAVERAGEPOOL_H_ +#define OPS_BUILT_IN_OP_PROTO_INC_GLOBALAVERAGEPOOL_H_ + +#include "graph/operator_reg.h" + +namespace ge { +/** +*@brief GlobalAveragePool consumes an input tensor X and applies average pooling across the values in the same channel. +This is equivalent to AveragePool with kernel size equal to the spatial dimension of input tensor \n + +*@par Inputs: +*@li x: Input data tensor from the previous operator; dimensions for image case are (N x C x H x W), +where N is the batch size, C is the number of channels, and H and W are the height and the width of the data. +For non image case, the dimensions are in the form of (N x C x D1 x D2 ... Dn), where N is the batch size. + +*@par Outputs: +*y: Output data tensor from pooling across the input tensor. The output tensor has the same rank as the input. +The first two dimensions of output shape are the same as the input (N x C), while the other dimensions are all 1 + +*@par Restrictions: +*Warning: This operator can be integrated only by configuring INSERT_OP_FILE of aclgrphBuildModel. Please do not use it directly. +*/ +REG_OP(GlobalAveragePool) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OP_END_FACTORY_REG(GlobalAveragePool) +} // namespace ge + #endif // OPS_BUILT_IN_OP_PROTO_INC_GLOBALAVGPOOL_H_ \ No newline at end of file diff --git a/third_party/fwkacllib/inc/ops/hcom_ops.h b/third_party/fwkacllib/inc/ops/hcom_ops.h index 497f6a68..6db276a9 100644 --- a/third_party/fwkacllib/inc/ops/hcom_ops.h +++ b/third_party/fwkacllib/inc/ops/hcom_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/hvd_ops.h b/third_party/fwkacllib/inc/ops/hvd_ops.h index 00299ef7..a49ec5ed 100644 --- a/third_party/fwkacllib/inc/ops/hvd_ops.h +++ b/third_party/fwkacllib/inc/ops/hvd_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/image_ops.h b/third_party/fwkacllib/inc/ops/image_ops.h index 2327e76e..85102c34 100644 --- a/third_party/fwkacllib/inc/ops/image_ops.h +++ b/third_party/fwkacllib/inc/ops/image_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/index_to_addr_ops.h b/third_party/fwkacllib/inc/ops/index_to_addr_ops.h new file mode 100644 index 00000000..c6bbaaa8 --- /dev/null +++ b/third_party/fwkacllib/inc/ops/index_to_addr_ops.h @@ -0,0 +1,63 @@ +/** + * Copyright 2019-2020 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. + */ + +/*! + * \file index_to_addr_ops.h + * \brief + */ +#ifndef OPS_BUILT_IN_OP_PROTO_INC_INDEX_TO_ADDR_OPS_H_ +#define OPS_BUILT_IN_OP_PROTO_INC_INDEX_TO_ADDR_OPS_H_ + +#include "graph/operator_reg.h" + +namespace ge { + +/** +*@brief get block tensor according to base addr tensor, for hccl remote read to use. +*@par Inputs: +*@li base_addr: A Tensor of type int64/uint64. \n +*@li row:A Tensor of type int64/uint64. \n +*@li col: A Tensor of type int64/uint64. + +*@par Outputs: +*addr_table: list of [rank id, host addr, device addr, read size] + +*@par Attributes: +*@li ori_shape: An required list int. Shape of base tensor. +*@li block_size: An required list int. Shape of split block tensor. +*@li ori_storage_mode: An optional string from: '"Matrix", "UT"'. Defaults to +"Matrix". Currently only support Matrix storage +*@li block_storage_mode: An optional string from: '"Matrix", "UT"'. Defaults to +"Matrix". Currently only support Matrix storage +*@li rank_id: An optional int of rank id. Defaults is 0 +*@li dtype: An optional Type of base tensor. Defaults is DT_FLOAT +*/ +REG_OP(IndexToAddr) + .INPUT(base_addr, TensorType({DT_INT64, DT_UINT64})) + .INPUT(x, TensorType({DT_INT64, DT_UINT64})) + .OUTPUT(addrs_table, TensorType({DT_INT64, DT_UINT64})) + .REQUIRED_ATTR(ori_shape, ListInt) + .REQUIRED_ATTR(block_size, ListInt) + .ATTR(ori_storage_mode, String, "Matrix") + .ATTR(block_storage_mode, String, "Matrix") + .ATTR(rank_id, Int, 0) + .ATTR(dtype, Type, DT_FLOAT) + .OP_END_FACTORY_REG(IndexToAddr) + +} // namespace ge + + +#endif // OPS_BUILT_IN_OP_PROTO_INC_INDEX_TO_ADDR_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/internal_ops.h b/third_party/fwkacllib/inc/ops/internal_ops.h index bcc3f1c3..9dde14a5 100644 --- a/third_party/fwkacllib/inc/ops/internal_ops.h +++ b/third_party/fwkacllib/inc/ops/internal_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/linalg_ops.h b/third_party/fwkacllib/inc/ops/linalg_ops.h index f6cc8694..4975e8c4 100644 --- a/third_party/fwkacllib/inc/ops/linalg_ops.h +++ b/third_party/fwkacllib/inc/ops/linalg_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/list_ops.h b/third_party/fwkacllib/inc/ops/list_ops.h index 0aa94e73..53024878 100644 --- a/third_party/fwkacllib/inc/ops/list_ops.h +++ b/third_party/fwkacllib/inc/ops/list_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/logging_ops.h b/third_party/fwkacllib/inc/ops/logging_ops.h index 03be7757..a20370fd 100644 --- a/third_party/fwkacllib/inc/ops/logging_ops.h +++ b/third_party/fwkacllib/inc/ops/logging_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -111,6 +111,38 @@ REG_OP(PrintV2) .INPUT(x, TensorType({DT_STRING})) .ATTR(output_stream, String, "stderr") .OP_END_FACTORY_REG(PrintV2) + +/** +*@brief Prints a list of tensors. \n + +*@par Inputs: +*x: A tensor passwd through this op . \n +*data: A list of tensors to print out when op is evaluated. \n + +*@par Attributes: +*message: A string, prefix of the error message. \n +*first_n: Only log first_n number of times. Negative numbers +*log always; this is the default. \n +*summarize: Only print this many entries of each tensor. +*If None, then a maximum of 3 elements are printed per input tensor. \n + +*@par Third-party framework compatibility +*Compatible with tensorflow Print operator . \n + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(PrintV3) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT16, DT_UINT16, DT_UINT8, DT_INT32, + DT_INT64, DT_UINT32, DT_UINT64, DT_DOUBLE, DT_STRING})) + .DYNAMIC_INPUT(data, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT16, DT_UINT16, DT_UINT8, DT_INT32, + DT_INT64, DT_UINT32, DT_UINT64, DT_DOUBLE, DT_STRING})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT16, DT_UINT16, DT_UINT8, DT_INT32, + DT_INT64, DT_UINT32, DT_UINT64, DT_DOUBLE, DT_STRING})) + .ATTR(message, String, "") + .ATTR(first_n, Int, -1) + .ATTR(summarize, Int, 3) + .OP_END_FACTORY_REG(PrintV3) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_LOGGING_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/lookup_ops.h b/third_party/fwkacllib/inc/ops/lookup_ops.h index b1fc254f..3fdc01fe 100644 --- a/third_party/fwkacllib/inc/ops/lookup_ops.h +++ b/third_party/fwkacllib/inc/ops/lookup_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/math_ops.h b/third_party/fwkacllib/inc/ops/math_ops.h index 6eb418d8..0631b4d1 100644 --- a/third_party/fwkacllib/inc/ops/math_ops.h +++ b/third_party/fwkacllib/inc/ops/math_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index 81c6a29e..be6d9f38 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -88,11 +88,11 @@ REG_OP(MatMul) * Compatible with the TensorFlow operator BatchMatmul. */ REG_OP(MatMulV2) - .INPUT(x1, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) - .INPUT(x2, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) + .INPUT(x1, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8, DT_INT4})) + .INPUT(x2, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8 DT_INT4})) .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) - .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8})) + .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8, DT_INT4})) .ATTR(transpose_x1, Bool, false) .ATTR(transpose_x2, Bool, false) .ATTR(offset_x, Int, 0) @@ -180,12 +180,12 @@ REG_OP(MatMulV2Compress) */ REG_OP(GEMM) - .INPUT(a, TensorType({DT_FLOAT16, DT_INT8})) - .INPUT(b, TensorType({DT_FLOAT16, DT_INT8})) - .INPUT(c, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) - .INPUT(alpha, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) - .INPUT(beta, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .INPUT(a, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32})) + .INPUT(b, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32})) + .INPUT(c, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32})) + .INPUT(alpha, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32})) + .INPUT(beta, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32})) .ATTR(transpose_a, Bool, false) .ATTR(transpose_b, Bool, false) .OP_END_FACTORY_REG(GEMM) @@ -246,10 +246,10 @@ REG_OP(BatchMatMul) */ REG_OP(BatchMatMulV2) - .INPUT(x1, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) - .INPUT(x2, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8})) + .INPUT(x1, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8, DT_INT4})) + .INPUT(x2, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8, DT_INT4})) .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) - .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8})) + .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8, DT_INT4})) .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) .ATTR(adj_x1, Bool, false) .ATTR(adj_x2, Bool, false) @@ -531,61 +531,6 @@ REG_OP(ScatterAdd) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterAdd) -/** -*@brief Use a scalar to modify the tensor. \n - -*@par Inputs: -*inputs, including: -*@li index: An ND Tensor . \n - -*Must be one of the following types: float16, float32, int32, int8, uint8 - -*@par Attributes: -* dim : the axis along which to index . -* value : the source element(s) to scatter . \n - -*@par Outputs: -*y: A Tensor. Has the same type and format as input "index" . \n - -*@par Third-party framework compatibility -* Compatible with the Pytorch operator ScatterScalar. -*/ -REG_OP(ScatterScalar) - .INPUT(index, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .REQUIRED_ATTR(dim, Int) - .REQUIRED_ATTR(value, Float) - .OP_END_FACTORY_REG(ScatterScalar) - -/** -*@brief Use a tensor to modify the tensor . \n - -*@par Inputs: -* Two inputs, including: -*@li index: An ND Tensor . \n - -*Must be one of the following types: float16, float32, int32, int8, uint8 - -*@li src: An ND Tensor . \n - -*Must be one of the following types: float16, float32, int32, int8, uint8 - -*@par Attributes: -* dim : the axis along which to index . \n - -*@par Outputs: -*y: A Tensor. Has the same type and format as input "index" . \n - -*@par Third-party framework compatibility -* Compatible with the Pytorch operator ScatterTensor. -*/ -REG_OP(ScatterTensor) - .INPUT(index, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .INPUT(src, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) - .REQUIRED_ATTR(dim, Int) - .OP_END_FACTORY_REG(ScatterTensor) - /** *@brief Divides a variable reference by sparse updates . \n @@ -839,10 +784,10 @@ REG_OP(DiagPart) * Yes */ REG_OP(FullyConnection) - .INPUT(x, TensorType({DT_FLOAT16, DT_INT8})) - .INPUT(w, TensorType({DT_FLOAT16, DT_INT8})) + .INPUT(x, TensorType({DT_FLOAT16, DT_INT8, DT_INT4})) + .INPUT(w, TensorType({DT_FLOAT16, DT_INT8, DT_INT4})) .OPTIONAL_INPUT(b, TensorType({DT_FLOAT16, DT_INT32,DT_FLOAT32})) - .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8})) + .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8, DT_INT4})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_INT32,DT_FLOAT32})) .REQUIRED_ATTR(num_output, Int) .ATTR(transpose, Bool, false) @@ -1197,10 +1142,12 @@ REG_OP(IndexAdd) * @par Inputs: * Three inputs, including: -* @li x1: A Tensor. Must be one of the following types: -* float16, float32, int32, int8, uint8. +* @li x1: A Tensor. Must be one of the following types: +*float16, float32, double, int32, uint8, int16, int8, complex64, int64, +*qint8, quint8, qint32, uint16, complex128, uint32, uint64. \n + * @li x2: A Tensor of the same type as "x1". -* @li indices: A Tensor of the indices, type should be int32. +* @li indices: A Tensor of the indices, * @par Attributes: * @li accumulate: Does it support self accumulation.Defaults to 0. @@ -1215,10 +1162,10 @@ REG_OP(IndexAdd) * Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(IndexPut) - .INPUT(x1, TensorType({DT_INT64, DT_INT32, DT_INT8, DT_UINT8, DT_FLOAT32, DT_FLOAT16})) - .INPUT(x2, TensorType({DT_INT64, DT_INT32, DT_INT8, DT_UINT8, DT_FLOAT32, DT_FLOAT16})) - .INPUT(indices, TensorType({DT_INT64, DT_INT32})) - .OUTPUT(y, TensorType({DT_INT64, DT_INT32, DT_INT8, DT_UINT8, DT_FLOAT32, DT_FLOAT16})) + .INPUT(x1, TensorType::BasicType()) + .INPUT(x2, TensorType::BasicType()) + .OUTPUT(y, TensorType::BasicType()) + .REQUIRED_ATTR(indices, ListInt) .ATTR(accumulate, Int, 0) .OP_END_FACTORY_REG(IndexPut) diff --git a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h index 9629976e..8bcbad14 100644 --- a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h index a55cebe2..452e945e 100644 --- a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -869,59 +869,60 @@ REG_OP(Conv2D) /** *@brief Computes a 2D convolution given 4D "x" and "filter_compress" tensors. *@par Inputs: -* @li x: A 4D tensor of input images. -* @li filter_compress: A 4D tensor of compressed filters. -* @li compress_index: A 1D Tensor dtype of int8. -* @li bias: An optional 1D tensor. -* @li offset_w: An optional 1D tensor for quantized convolution. Reserved. +*@li x: A 4D tensor of input images. +*@li filter_compress: A 4D tensor of compressed filter data blocks. +*@li compress_index: A 1D tensor of index for decompression. +*@li bias: An optional 1D tensor of additive biases to the filter outputs. +* The data is stored in the order of: [out_channels]. +*@li offset_w: Reserved. +*\n +*\n +* The following are the supported data types and data formats: +*\n +*\n +| Tensor | x | filter_compress | compress_index | bias | y |\n +| :-------: | :-----: | :--------------: | :------------: | :-----: | :-----: |\n +| Data Type | int8 | int8 | int8 | int32 | int32 |\n +| Format | NCHW | NCHW | ND | ND | NCHW |\n +| | NHWC | HWCN | | | NHWC |\n +*\n +* For float32 type, the actual calculation on the chip is based on +* float16. +*\n * -* The input and output tensor attributes are listed as follows: -* @verbatim - |Tensor | x | filter_compress | bias | offset_w | y - -----------|---------|---------|---------|----------|-------- - |Data Type | float16 | float16 | float16 | _ | float16 - | |---------|---------|---------|----------|-------- - | | float32 | float32 | float32 | _ | float32 - | |---------|---------|---------|----------|-------- - | | int8 | int8 | int32 | int8 | int32 - -----------|---------|---------|---------|----------|-------- - |Format | NCHW | NCHW | ND | ND | NCHW - | | NHWC | NHWC | | | NHWC - | | | HWCN | | | -@endverbatim -* It should be noted that the data types must correspond to each other, but the -* format does not need to . \n - *@par Attributes: -* @li strides: A list of 4 integers. Specifying the strides of the -* convolution along the height and width. The dimension order is determined -* by the data format of "x". By default the N and C dimensions are set to 1. -* @li pads: A list of 4 integers. Specifying the top, bottom, left and right -* padding. -* @li dilations: A list of 4 integers. Specifying the dilation rate to use -* for dilated convolution. Has the same dimension order and value as "strides". -* @li groups: Number of blocked connections from input channels to output -* channels. Input channels and output channels must both be divisible by -* "groups".Type is int32. -* @li offset_x: An optional integer for quantized convolution. Type is int32. -* Defaults to "0". -* @li data_format: An optional string from: "NHWC", "NCHW". Specifying the -* data format of the input and output images. Type is string. -* Defaults to "NHWC". Reserved . \n - +*@li strides: Required. A list of 4 integers. The stride of the sliding window +* for each dimension of input. The dimension order is determined by the data +* format of "x". The N and C dimensions must be set to 1. +*@li pads: Required. A list of 4 integers. The number of pixels to add to each +* (top, bottom, left, right) side of the input. +*@li dilations: Optional. A list of 4 integers. The dilation factor for each +* dimension of input. The dimension order is determined by the data format of +* "x". The N and C dimensions must be set to 1. Defaults to [1, 1, 1, 1]. +*@li groups: Optional. An integer of type int32. The number of blocked +* connections from input channels to output channels. In_channels and +* out_channels must both be divisible by "groups". Only support 1. +*@li offset_x: Optional. An integer of type int32. The negative offset added +* to the input image for int8 type. Ensure that the output is within the +* effective range. Defaults to 0. +*@li data_format: Reserved. +* *@par Outputs: -* @li y: A 4D Tensor of output images . \n - +* y: A 4D Tensor of output feature map. Has the same type as "x". With the +* format "NHWC", the data is stored in the order of: [batch, out_height, +* out_width, out_channels]. +*\n +* *@par Restrictions: -*Warning: THIS FUNCTION IS DEPRECATED. +*Warning: THIS FUNCTION IS EXPERIMENTAL. */ REG_OP(Conv2DCompress) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8})) - .INPUT(filter_compress, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8})) + .INPUT(x, TensorType({DT_INT8})) + .INPUT(filter_compress, TensorType({DT_INT8})) .INPUT(compress_index, TensorType({DT_INT8})) - .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OPTIONAL_INPUT(bias, TensorType({DT_INT32})) .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OUTPUT(y, TensorType({DT_INT32})) .REQUIRED_ATTR(strides, ListInt) .REQUIRED_ATTR(pads, ListInt) .ATTR(dilations, ListInt, {1, 1, 1, 1}) diff --git a/third_party/fwkacllib/inc/ops/nn_detect_ops.h b/third_party/fwkacllib/inc/ops/nn_detect_ops.h index bd14df77..98e18234 100644 --- a/third_party/fwkacllib/inc/ops/nn_detect_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_detect_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -1002,9 +1002,12 @@ REG_OP(SPP) *@par Inputs: * Three inputs, including: *@li x: An NC1HWC0 tensor of type float16 or float32, describing the feature -* map. +* map. The data of x must be greater than or equal to "0.0". *@li rois: A tensor of type float16 or float32, with 3D shape -* [batch, 5, roi_max_num], describing the RIOs. +* [batch, 5, roi_max_num], describing the RIOs. Each ROI consists of five +* elements: "batch_id", "x1", "y1", "x2", and "y2", which "batch_id" indicates +* the index of the input feature map, "x1", "y1", "x2", or "y2" must be +* greater than or equal to "0.0". * roi_max_num must be less than or equal to 6000 and must be divided by 16. *@li roi_actual_num: A optional tensor of type int32, with shape [batch, 8], specifying * the number of ROIs per batch . \n diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index 9ce7abfd..d66c8948 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/nn_ops.h b/third_party/fwkacllib/inc/ops/nn_ops.h index 5b1a4dd0..a08b610b 100644 --- a/third_party/fwkacllib/inc/ops/nn_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h index 72363d18..a0a1abdc 100644 --- a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -1402,6 +1402,7 @@ REG_OP(MaxPoolGradWithArgmaxV2) * @li pads:A required list of int8, int16, int32, or int64 values, * a data to caculate when padding_mode is "CALCULATED". * @li data_format: An optional string. Defaults to "NHWC" . +* If data_format = "NC1HWC0", ori_format must be "NCHW". * @li global_pooling bool, Whether to use the global pooling. * If global_pooling = true, kernel size and paddings will be ignored. * Default False @@ -1786,5 +1787,30 @@ REG_OP(SubSampleLabels) .REQUIRED_ATTR(positive_fraction, Float) .OP_END_FACTORY_REG(SubSampleLabels) +/** +*@brief Computes GlobalLpPool, GlobalLpPool consumes an input tensor X and applies lp pool pooling across the +values in the same channel. \n + +*@par Inputs: +* x: A Tensor of type float16 or float32 . \n + +*@par Attributes: +*@li p: Optional. Must be one of the following types: float32. Defaults to 2.0. \n + +*@par Outputs: +* y: A Tensor. Has the same type as "x", when shape of x is [N,C,H,W], shape of y is [N,C,1,1]. +*@par Third-party framework compatibility +* Compatible with the onnx operator GlobalLpPool. +*@par Restrictions: +*Warning: THIS FUNCTION IS DEPRECATED. +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ + +REG_OP(GlobalLpPool) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(p, Float, 2.0) + .OP_END_FACTORY_REG(GlobalLpPool); + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_POOLING_OPS_H diff --git a/third_party/fwkacllib/inc/ops/nn_training_ops.h b/third_party/fwkacllib/inc/ops/nn_training_ops.h index 9dd502cd..5b49e947 100644 --- a/third_party/fwkacllib/inc/ops/nn_training_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_training_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/no_op.h b/third_party/fwkacllib/inc/ops/no_op.h index b27b1fa0..7834591c 100644 --- a/third_party/fwkacllib/inc/ops/no_op.h +++ b/third_party/fwkacllib/inc/ops/no_op.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h index 01ff77cb..d46f9c8f 100644 --- a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h +++ b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -98,6 +98,22 @@ REG_OP(FastGeluGrad) .OUTPUT(z, TensorType({DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(FastGeluGrad) +/** +* @brief Compute hardswish of "x" element-wise . \n + +*@par Inputs: +*One input, including: +*x: A Tensor. Must be one of the following types: float16, float32 + +*@par Outputs: +*y: A Tensor. Has the same type as "x". +*@par Third-party framework compatibility +* Compatible with the Torch operator Hardswish. +*/ +REG_OP(Hardswish) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(Hardswish) /** *@brief Computes the gradient for the tanh of "x" . \n diff --git a/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h b/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h index f36d2935..8d7ef9f9 100644 --- a/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h +++ b/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/outfeed_ops.h b/third_party/fwkacllib/inc/ops/outfeed_ops.h index 53b9d701..e0b783bc 100644 --- a/third_party/fwkacllib/inc/ops/outfeed_ops.h +++ b/third_party/fwkacllib/inc/ops/outfeed_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/pad_ops.h b/third_party/fwkacllib/inc/ops/pad_ops.h index 9d0e7a62..7780de05 100644 --- a/third_party/fwkacllib/inc/ops/pad_ops.h +++ b/third_party/fwkacllib/inc/ops/pad_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/parsing_ops.h b/third_party/fwkacllib/inc/ops/parsing_ops.h index e578997c..03024f96 100644 --- a/third_party/fwkacllib/inc/ops/parsing_ops.h +++ b/third_party/fwkacllib/inc/ops/parsing_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/quantize_ops.h b/third_party/fwkacllib/inc/ops/quantize_ops.h index 0636833c..2a284780 100644 --- a/third_party/fwkacllib/inc/ops/quantize_ops.h +++ b/third_party/fwkacllib/inc/ops/quantize_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -96,18 +96,19 @@ REG_OP(Quantize) *@li dst_type: A optional int32, specifying the output data type. Defaults to "DT_INT8" . \n *@par Outputs: -*y: The quantized output tensor of type int8 and with format NC1HWC0 . \n +*y: The quantized output tensor of type int8 or int4 and with format NC1HWC0 . \n *@par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. */ REG_OP(AscendQuant) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT32})) - .OUTPUT(y, TensorType({DT_INT8})) + .OUTPUT(y, TensorType({DT_INT8, DT_INT4})) .REQUIRED_ATTR(scale, Float) .REQUIRED_ATTR(offset, Float) .ATTR(sqrt_mode, Bool, false) .ATTR(round_mode, String, "Round") + .ATTR(dst_type, Int, DT_INT8) .OP_END_FACTORY_REG(AscendQuant) /** diff --git a/third_party/fwkacllib/inc/ops/ragged_array_ops.h b/third_party/fwkacllib/inc/ops/ragged_array_ops.h index 5af2dd74..9d116760 100644 --- a/third_party/fwkacllib/inc/ops/ragged_array_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_array_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h b/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h index ceaa64e4..2e253ed4 100644 --- a/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/ragged_math_ops.h b/third_party/fwkacllib/inc/ops/ragged_math_ops.h index 4376437f..b2caa0be 100644 --- a/third_party/fwkacllib/inc/ops/ragged_math_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_math_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/random_ops.h b/third_party/fwkacllib/inc/ops/random_ops.h index 66f9b65f..830e775a 100644 --- a/third_party/fwkacllib/inc/ops/random_ops.h +++ b/third_party/fwkacllib/inc/ops/random_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/reduce_ops.h b/third_party/fwkacllib/inc/ops/reduce_ops.h index 1578ba59..c827bec9 100644 --- a/third_party/fwkacllib/inc/ops/reduce_ops.h +++ b/third_party/fwkacllib/inc/ops/reduce_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/resource_variable_ops.h b/third_party/fwkacllib/inc/ops/resource_variable_ops.h index 156f2f34..a5d7f9c3 100644 --- a/third_party/fwkacllib/inc/ops/resource_variable_ops.h +++ b/third_party/fwkacllib/inc/ops/resource_variable_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/rnn.h b/third_party/fwkacllib/inc/ops/rnn.h index 20828a89..6813ad78 100644 --- a/third_party/fwkacllib/inc/ops/rnn.h +++ b/third_party/fwkacllib/inc/ops/rnn.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -285,9 +285,9 @@ REG_OP(DynamicRNN) *@li num_proj:An integer identifying the num projection in the op. Default to 0. *@li time_major:An bool identifying the time major in the op. Default to true. *@li activation:An string identifying the type of activation function in the op. Default to "tanh". -*Only tanh is currently supported. +*Support "tanh" and "clip". *@li recurrent_activation:An string identifying the type of activation function in the op. Default to "sigmoid". -*Supprot "sigmoid" and "hard_sigmoid". In general, set "hard_sigmoid" for TF Keras LSTM. +*Support "sigmoid" and "hard_sigmoid". In general, set "hard_sigmoid" for TF Keras LSTM. *@li forget_bias:An float identifying the forget bias in the op. Default to 0. *@li gate_order:An string identifying the type of gate order in the op. Support "ijfo" and "ifco". Default to "ijfo". *Set "ijfo" for TF operator LSTM, Set "ifco" for TF Keras LSTM. diff --git a/third_party/fwkacllib/inc/ops/rpn_ops.h b/third_party/fwkacllib/inc/ops/rpn_ops.h index 850b3e5a..90707602 100644 --- a/third_party/fwkacllib/inc/ops/rpn_ops.h +++ b/third_party/fwkacllib/inc/ops/rpn_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/save_ops.h b/third_party/fwkacllib/inc/ops/save_ops.h index 5ce6c2e0..0ce473b7 100644 --- a/third_party/fwkacllib/inc/ops/save_ops.h +++ b/third_party/fwkacllib/inc/ops/save_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/sdca_ops.h b/third_party/fwkacllib/inc/ops/sdca_ops.h index 601b360b..e8f3e6b6 100644 --- a/third_party/fwkacllib/inc/ops/sdca_ops.h +++ b/third_party/fwkacllib/inc/ops/sdca_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/selection_ops.h b/third_party/fwkacllib/inc/ops/selection_ops.h index 43f72ef3..ac404e8f 100644 --- a/third_party/fwkacllib/inc/ops/selection_ops.h +++ b/third_party/fwkacllib/inc/ops/selection_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -1895,6 +1895,33 @@ REG_OP(Cummin) .REQUIRED_ATTR(axis, Int) .OP_END_FACTORY_REG(Cummin) +/** +*@brief Returns a namedtuple (values, indices) where values is the cumulative +* the cumulative maximum of elements of input in the dimension dim. +* And indices is the index location of each maximum value found in the dimension dim. \n + +*@par Inputs: +*One inputs, including: +* x: A tensor . Must be one of the following types: +* float16, float32, int32, uint32, int8, uint8. \n + +*@par Attributes: +* dim: Axis along which to cummax. \n + +*@par Outputs: +* @li y: A Tensor with the same type and shape of x's. +* @li indices: A Tensor with the int32/int64 type and the same shape of x's. \n + +*@par Third-party framework compatibility +*Compatible with the Pytorch operator Cummax. \n +*/ +REG_OP(Cummax) + .INPUT(x, TensorType::BasicType()) + .OUTPUT(y, TensorType::BasicType()) + .OUTPUT(indices, TensorType::BasicType()) + .REQUIRED_ATTR(dim, Int) + .OP_END_FACTORY_REG(Cummax) + /** *@brief Extends the input with copies of data along a specified dimension. For example: *(1) If x = [[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]]], with shape (2, 3, 2); @@ -2129,24 +2156,6 @@ REG_OP(MaskedSelectV2) .INPUT(mask, TensorType({DT_BOOL})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(MaskedSelectV2) - -/** -* @brief Choose the value of X with value according to mask. - -* @par Inputs: -* two inputs, including: -* @li x: A Tensor of dtype is float16 or float32 or float64 or int64 or int32 or int16 or int8 or uint8. -* @li mask: A Tensor of dtype is bool. \n - -* @par Outputs: -* @li y: A tensor with the same type as x. \n - -*/ -REG_OP(MaskedSelect) - .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, DT_UINT8, DT_INT8, DT_INT16, DT_INT32, DT_INT64})) - .INPUT(mask, TensorType({DT_BOOL})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, DT_UINT8, DT_INT8, DT_INT16, DT_INT32, DT_INT64})) - .OP_END_FACTORY_REG(MaskedSelect) /** * @brief update the value of X with value according to mask. @@ -2364,6 +2373,35 @@ REG_OP(InplaceTopKDistance) .INPUT(pq_ivf, TensorType({DT_INT32})) .ATTR(order, String, "asc") .OP_END_FACTORY_REG(InplaceTopKDistance) + +/** +* @brief After a set of sorted data and a new set of data are re-sorted, get the first k data. \n +* +* @par Inputs: +* @li sorted_distance: A sorted Tensor, Will be updated after calculation. Must be one of the following types: float16. +* @li pq_ivf: A Tensor of type int32, index corresponding to sorted_distance. +* @li pq_index: A Tensor of type int32 , the bucket number corresponding to sorted_distance. \n +* +*@par Outputs: +* @li topk_distance: A Tensor of type float16, the new data set will be reordered with sorted_distance and updated to topk_distance. +* @li topk_ivf: A Tensor of type int32, index corresponding to topk_distance. +* @li topk_index: A scalar of type int32 , the bucket number corresponding to topk_distance. \n +* +* @par Attributes: +* k: get the first k data of sorted_distance. \n +* +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(TopKPQDistanceMerge) + .INPUT(sorted_distance, TensorType({DT_FLOAT16})) + .INPUT(pq_ivf, TensorType({DT_INT32})) + .INPUT(pq_index, TensorType({DT_INT32})) + .OUTPUT(topk_distance, TensorType({DT_FLOAT16})) + .OUTPUT(topk_ivf, TensorType({DT_INT32})) + .OUTPUT(topk_index, TensorType({DT_INT32})) + .REQUIRED_ATTR(k, Int) + .OP_END_FACTORY_REG(TopKPQDistanceMerge) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_SELECTION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/set_ops.h b/third_party/fwkacllib/inc/ops/set_ops.h index 04e04f1b..1d02fa15 100644 --- a/third_party/fwkacllib/inc/ops/set_ops.h +++ b/third_party/fwkacllib/inc/ops/set_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/slice_write_ops.h b/third_party/fwkacllib/inc/ops/slice_write_ops.h new file mode 100644 index 00000000..994f197c --- /dev/null +++ b/third_party/fwkacllib/inc/ops/slice_write_ops.h @@ -0,0 +1,50 @@ +/** + * Copyright 2019-2020 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. + */ + +/*! + * \file slice_write_ops.h + * \brief + */ +#ifndef OPS_BUILT_IN_OP_PROTO_INC_SLICE_WRITE_OPS_H_ +#define OPS_BUILT_IN_OP_PROTO_INC_SLICE_WRITE_OPS_H_ + +#include "graph/operator_reg.h" + +namespace ge { + +/** +*@brief write tensor value to tensor x. +*@par Inputs: +*x: A Tensor of type float16/float/double/int32/int64. \n +*begin:A Tensor of type int32/int64. \n +*value: A Tensor of type float16/float/double/int32/int64. +*@par Outputs: +*x: same tensor with input x +*/ +REG_OP(SliceWrite) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, \ + DT_INT32, DT_INT64})) + .INPUT(begin, TensorType({DT_INT32, DT_INT64})) + .INPUT(value, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, \ + DT_INT32, DT_INT64})) + .OUTPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, \ + DT_INT32, DT_INT64})) + .OP_END_FACTORY_REG(SliceWrite) + +} // namespace ge + + +#endif // OPS_BUILT_IN_OP_PROTO_INC_SLICE_WRITE_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/sparse_ops.h b/third_party/fwkacllib/inc/ops/sparse_ops.h index 8eb7b521..d9fb4d0a 100644 --- a/third_party/fwkacllib/inc/ops/sparse_ops.h +++ b/third_party/fwkacllib/inc/ops/sparse_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/spectral_ops.h b/third_party/fwkacllib/inc/ops/spectral_ops.h index ab9e1dec..d17cbfdd 100644 --- a/third_party/fwkacllib/inc/ops/spectral_ops.h +++ b/third_party/fwkacllib/inc/ops/spectral_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/split_combination_ops.h b/third_party/fwkacllib/inc/ops/split_combination_ops.h index 98d4d111..05e38589 100644 --- a/third_party/fwkacllib/inc/ops/split_combination_ops.h +++ b/third_party/fwkacllib/inc/ops/split_combination_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/state_ops.h b/third_party/fwkacllib/inc/ops/state_ops.h index d1ec00b5..49029317 100644 --- a/third_party/fwkacllib/inc/ops/state_ops.h +++ b/third_party/fwkacllib/inc/ops/state_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/stateful_random_ops.h b/third_party/fwkacllib/inc/ops/stateful_random_ops.h index f4eb763c..a3d18922 100644 --- a/third_party/fwkacllib/inc/ops/stateful_random_ops.h +++ b/third_party/fwkacllib/inc/ops/stateful_random_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/stateless_random_ops.h b/third_party/fwkacllib/inc/ops/stateless_random_ops.h index ff9daaa3..dad3c379 100644 --- a/third_party/fwkacllib/inc/ops/stateless_random_ops.h +++ b/third_party/fwkacllib/inc/ops/stateless_random_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/string_ops.h b/third_party/fwkacllib/inc/ops/string_ops.h index a78d63a1..a2699315 100644 --- a/third_party/fwkacllib/inc/ops/string_ops.h +++ b/third_party/fwkacllib/inc/ops/string_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/swap_co_ops.h b/third_party/fwkacllib/inc/ops/swap_co_ops.h index 6e8eaac3..a1bf4f8b 100644 --- a/third_party/fwkacllib/inc/ops/swap_co_ops.h +++ b/third_party/fwkacllib/inc/ops/swap_co_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/target_crop_and_resize.h b/third_party/fwkacllib/inc/ops/target_crop_and_resize.h index 9bef1d7b..9c61f2c9 100644 --- a/third_party/fwkacllib/inc/ops/target_crop_and_resize.h +++ b/third_party/fwkacllib/inc/ops/target_crop_and_resize.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/transformation_ops.h b/third_party/fwkacllib/inc/ops/transformation_ops.h index f403fe12..2151a867 100644 --- a/third_party/fwkacllib/inc/ops/transformation_ops.h +++ b/third_party/fwkacllib/inc/ops/transformation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -153,6 +153,32 @@ REG_OP(TransData) .ATTR(groups, Int, 1) .OP_END_FACTORY_REG(TransData) +/** +*@brief Do format transfer for various data format only +support "ND" to "ND_RNN_BIAS" and "ND" to "FRACTAL_ZN_RNN" + +*@par Inputs: +*src: A Tensor. For all branches can be types: float16, float32, int32, int8, bool. +* For branches without padding also can be types: int16, int64, uint8, uint16, uint32, uint64 . \n + +*@par Attributes: +*@li src_format: A string source data format, can be "ND", "ND_RNN_BIAS", "FRACTAL_ZN_RNN" etc. +*@li dst_format: A string target data format, can be "ND", "ND_RNN_BIAS", "FRACTAL_ZN_RNN" etc. +*@li input_size: A mental int32. +*@li hidden_size: A mental int32. + +*@par Outputs: +*dst: A Tensor. Has the same type as "src". +*/ +REG_OP(TransDataRNN) + .INPUT(src, TensorType::BasicType()) + .OUTPUT(dst, TensorType::BasicType()) + .REQUIRED_ATTR(src_format, String) + .REQUIRED_ATTR(dst_format, String) + .REQUIRED_ATTR(input_size, Int) + .REQUIRED_ATTR(hidden_size, Int) + .OP_END_FACTORY_REG(TransDataRNN) + /** *@brief Permutes the dimensions according to order. The returned tensor's dimension i will correspond to the input dimension order[i] . \n diff --git a/third_party/fwkacllib/inc/ops/warp_perspective_ops.h b/third_party/fwkacllib/inc/ops/warp_perspective_ops.h index 8ef69d8b..e19cbd7c 100644 --- a/third_party/fwkacllib/inc/ops/warp_perspective_ops.h +++ b/third_party/fwkacllib/inc/ops/warp_perspective_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/opt_info/opt_info.h b/third_party/fwkacllib/inc/opt_info/opt_info.h index 4dff695b..f04aa84c 100644 --- a/third_party/fwkacllib/inc/opt_info/opt_info.h +++ b/third_party/fwkacllib/inc/opt_info/opt_info.h @@ -1,5 +1,5 @@ /** - * Copyright 2021 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/runtime/base.h b/third_party/fwkacllib/inc/runtime/base.h index 70e42dc9..40c7495d 100644 --- a/third_party/fwkacllib/inc/runtime/base.h +++ b/third_party/fwkacllib/inc/runtime/base.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_BASE_H__ #define __CCE_RUNTIME_BASE_H__ @@ -94,6 +94,14 @@ typedef void (*rtTaskFailCallback)(rtExceptionInfo *exceptionInfo); typedef void (*rtDeviceStateCallback)(uint32_t devId, bool isOpen); +/** + * @ingroup profiling_base + * @brief dataType: rtProfCtrlType_t + * @brief data: data swtich or reporter function + * @brief dataLen: length of data + */ +typedef rtError_t (*rtProfCtrlHandle)(uint32_t dataType, void *data, uint32_t dataLen); + /** * @ingroup dvrt_base * @brief stream handle. @@ -118,6 +126,32 @@ typedef void *rtLabel_t; */ typedef void *rtModel_t; +#define RT_PROF_MAX_DEV_NUM 64 + +/** + * @ingroup profiling_base + * @brief profiling command info + */ +typedef struct rtProfCommandHandle { + uint64_t profSwitch; + uint64_t profSwitchHi; + uint32_t devNums; + uint32_t devIdList[RT_PROF_MAX_DEV_NUM]; + uint32_t modelId; + uint32_t type; +} rtProfCommandHandle_t; + +/** + * @ingroup profiling_base + * @brief type of app register profiling switch or reporter callback + */ +typedef enum { + RT_PROF_CTRL_INVALID = 0, + RT_PROF_CTRL_SWITCH, + RT_PROF_CTRL_REPORTER, + RT_PROF_CTRL_BUTT +} rtProfCtrlType_t; + /** * @ingroup profiling_base * @brief runtime handle. @@ -166,6 +200,57 @@ RTS_API rtError_t rtProfilerTraceEx(uint64_t id, uint64_t modelId, uint16_t tagI */ RTS_API rtError_t rtSetMsprofReporterCallback(MsprofReporterCallback callback); +/** + * @ingroup profiling_base + * @brief add the map of deviceId and GE model index, called by ge + * @param [in] geModelIdx The index of GE model + * @param [in] deviceId The id of device + * @return RT_ERROR_NONE for ok + * @return ACL_ERROR_RT_PARAM_INVALID for error input + */ +RTS_API rtError_t rtSetDeviceIdByGeModelIdx(uint32_t geModelIdx, uint32_t deviceId); + +/** + * @ingroup profiling_base + * @brief del the map of deviceId and GE model index, called by ge + * @param [in] geModelIdx The index of GE model + * @param [in] deviceId The id of device + * @return RT_ERROR_NONE for ok + * @return ACL_ERROR_RT_PARAM_INVALID for error input + */ +RTS_API rtError_t rtUnsetDeviceIdByGeModelIdx(uint32_t geModelIdx, uint32_t deviceId); + +/** + * @ingroup profiling_base + * @brief find deviceId by GE model index, called by profiling + * @param [in] geModelIdx The index of GE model + * @param [out] deviceId The id of device + * @return RT_ERROR_NONE for ok + * @return ACL_ERROR_RT_PARAM_INVALID for error input + * @return ACL_ERROR_RT_INTERNAL_ERROR for can't find deviceId by geModelIdx + */ +RTS_API rtError_t rtGetDeviceIdByGeModelIdx(uint32_t geModelIdx, uint32_t *deviceId); + +/** + * @ingroup profiling_base + * @brief set profling switch, called by profiling + * @param [in] data rtProfCommandHandle + * @param [out] len length of data + * @return RT_ERROR_NONE for ok + * @return ACL_ERROR_RT_PARAM_INVALID for error input + */ +RTS_API rtError_t rtProfSetProSwitch(void *data, uint32_t len); + +/** + * @ingroup profiling_base + * @brief register callback of upper app, called by ge or acl + * @param [in] moduleId of APP + * @param [in] callback function when switch or reporter change + * @return RT_ERROR_NONE for ok + * @return ACL_ERROR_RT_PARAM_INVALID for error input + */ +RTS_API rtError_t rtProfRegisterCtrlCallback(uint32_t moduleId, rtProfCtrlHandle callback); + /** * @ingroup dvrt_base * @brief Returns the last error from a runtime call. @@ -356,7 +441,6 @@ RTS_API rtError_t rtLabelCreateExV2(rtLabel_t *label, rtModel_t model, rtStream_ * @return RT_ERROR_INVALID_VALUE for input null ptr */ RTS_API rtError_t rtGetTaskIdAndStreamID(uint32_t *taskId, uint32_t *streamId); - #if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/runtime/config.h b/third_party/fwkacllib/inc/runtime/config.h index 76836e7b..f38be74d 100644 --- a/third_party/fwkacllib/inc/runtime/config.h +++ b/third_party/fwkacllib/inc/runtime/config.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_CONFIG_H__ #define __CCE_RUNTIME_CONFIG_H__ diff --git a/third_party/fwkacllib/inc/runtime/context.h b/third_party/fwkacllib/inc/runtime/context.h index c597a657..66b9b570 100644 --- a/third_party/fwkacllib/inc/runtime/context.h +++ b/third_party/fwkacllib/inc/runtime/context.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_CONTEXT_H__ #define __CCE_RUNTIME_CONTEXT_H__ diff --git a/third_party/fwkacllib/inc/runtime/dev.h b/third_party/fwkacllib/inc/runtime/dev.h index 4a9a5817..3499fd4c 100644 --- a/third_party/fwkacllib/inc/runtime/dev.h +++ b/third_party/fwkacllib/inc/runtime/dev.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_DEVICE_H__ #define __CCE_RUNTIME_DEVICE_H__ diff --git a/third_party/fwkacllib/inc/runtime/dvfsprofile.h b/third_party/fwkacllib/inc/runtime/dvfsprofile.h index 33e2f4c1..06f5e3c4 100644 --- a/third_party/fwkacllib/inc/runtime/dvfsprofile.h +++ b/third_party/fwkacllib/inc/runtime/dvfsprofile.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_DVFSPROFILE_H__ #define __CCE_RUNTIME_DVFSPROFILE_H__ diff --git a/third_party/fwkacllib/inc/runtime/event.h b/third_party/fwkacllib/inc/runtime/event.h index 81b635c3..c73274da 100644 --- a/third_party/fwkacllib/inc/runtime/event.h +++ b/third_party/fwkacllib/inc/runtime/event.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_EVENT_H__ #define __CCE_RUNTIME_EVENT_H__ diff --git a/third_party/fwkacllib/inc/runtime/kernel.h b/third_party/fwkacllib/inc/runtime/kernel.h index c1b9bd6d..4d5fc5c9 100644 --- a/third_party/fwkacllib/inc/runtime/kernel.h +++ b/third_party/fwkacllib/inc/runtime/kernel.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_KERNEL_H__ #define __CCE_RUNTIME_KERNEL_H__ @@ -121,6 +121,19 @@ typedef struct rtKernelLaunchNames { const char *opName; // defined for operator name } rtKernelLaunchNames_t; +/** + * @ingroup rt_kernel + * @brief args struct + */ +typedef struct tagRtArgsWithTiling { + void *args; // args host mem addr + uint32_t argsSize; // input + output + tiling addr size + tiling data size + uint32_t argsSizeWithoutTiling; // input + output + tiling addr size + uint16_t tilingAddrOffset; // tiling addr offset + uint16_t tilingDataOffset; // tiling data offset + uint16_t reserved[2]; +} rtArgsWithTiling_t; + /** * @ingroup rt_KernelConfigDump * @brief device dump type @@ -647,6 +660,36 @@ RTS_API rtError_t rtStartMDCProfiler(void **addr, uint32_t length); */ RTS_API rtError_t rtStopMDCProfiler(void *addr); +/** + * @ingroup rt_kernel + * @brief launch kernel with tiling data to device + * @param [in] stubFunc stub function + * @param [in] blockDim block dimentions + * @param [in] argsInfo argments info address for kernel function + * @param [in] smDesc shared memory description + * @param [in] stream associated stream + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtKernelLaunchWithTiling(const void *stubFunc, uint32_t blockDim, + rtArgsWithTiling_t *argsInfo, rtSmDesc_t *smDesc, rtStream_t stream_); + +/** + * @ingroup rt_kernel + * @brief launch kernel with handle and tiling data to device + * @param [in] handle program + * @param [in] devFunc device function description. + * @param [in] blockDim block dimentions + * @param [in] argsInfo argments info address for kernel function + * @param [in] smDesc shared memory description + * @param [in] stream associated stream + * @param [in] kernelInfo kernel info + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtKernelLaunchWithHandleAndTiling(void *handle, const void *devFunc, uint32_t blockDim, + rtArgsWithTiling_t *argsInfo, rtSmDesc_t *smDesc, rtStream_t stream_, const void* kernelInfo); + #if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/runtime/mem.h b/third_party/fwkacllib/inc/runtime/mem.h index b049e762..0afdeec5 100644 --- a/third_party/fwkacllib/inc/runtime/mem.h +++ b/third_party/fwkacllib/inc/runtime/mem.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_MEM_H__ #define __CCE_RUNTIME_MEM_H__ diff --git a/third_party/fwkacllib/inc/runtime/rt.h b/third_party/fwkacllib/inc/runtime/rt.h index 10f884f2..e4c3a9bb 100644 --- a/third_party/fwkacllib/inc/runtime/rt.h +++ b/third_party/fwkacllib/inc/runtime/rt.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_RT_H__ #define __CCE_RUNTIME_RT_H__ diff --git a/third_party/fwkacllib/inc/runtime/rt_ffts.h b/third_party/fwkacllib/inc/runtime/rt_ffts.h index f2809218..5a17b042 100644 --- a/third_party/fwkacllib/inc/runtime/rt_ffts.h +++ b/third_party/fwkacllib/inc/runtime/rt_ffts.h @@ -1,6 +1,17 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. - * Description: ffts interface +/** + * Copyright 2019-2020 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. */ #ifndef __CCE_RUNTIME_FFTS_H diff --git a/third_party/fwkacllib/inc/runtime/rt_model.h b/third_party/fwkacllib/inc/runtime/rt_model.h index d4af72c5..5ef62df3 100644 --- a/third_party/fwkacllib/inc/runtime/rt_model.h +++ b/third_party/fwkacllib/inc/runtime/rt_model.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_MODEL_H__ #define __CCE_RUNTIME_MODEL_H__ diff --git a/third_party/fwkacllib/inc/runtime/rt_stars.h b/third_party/fwkacllib/inc/runtime/rt_stars.h index 016c352a..2874058c 100644 --- a/third_party/fwkacllib/inc/runtime/rt_stars.h +++ b/third_party/fwkacllib/inc/runtime/rt_stars.h @@ -1,6 +1,17 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. - * Description: +/** + * Copyright 2019-2020 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. */ #ifndef __CCE_RUNTIME_STARS_H diff --git a/third_party/fwkacllib/inc/runtime/stream.h b/third_party/fwkacllib/inc/runtime/stream.h index 3a078e99..6f45fc4e 100644 --- a/third_party/fwkacllib/inc/runtime/stream.h +++ b/third_party/fwkacllib/inc/runtime/stream.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_STREAM_H__ #define __CCE_RUNTIME_STREAM_H__ diff --git a/third_party/fwkacllib/inc/soft_dp/ExternalSoftDp.h b/third_party/fwkacllib/inc/soft_dp/ExternalSoftDp.h index bef5c05d..975043b3 100644 --- a/third_party/fwkacllib/inc/soft_dp/ExternalSoftDp.h +++ b/third_party/fwkacllib/inc/soft_dp/ExternalSoftDp.h @@ -1,12 +1,18 @@ /** -* @file ExternalSoftDp.h -* -* Copyright (c) Huawei Technologies Co., Ltd. 2012-2018. All rights reserved. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -*/ + * Copyright 2019-2020 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. + */ #ifndef EXTERNALSOFTDP_H #define EXTERNALSOFTDP_H diff --git a/third_party/fwkacllib/inc/tdt/index_transform.h b/third_party/fwkacllib/inc/tdt/index_transform.h index a5af2c83..a62e0185 100644 --- a/third_party/fwkacllib/inc/tdt/index_transform.h +++ b/third_party/fwkacllib/inc/tdt/index_transform.h @@ -1,10 +1,18 @@ /** -* @file index_transform.h -* -* Copyright (C) Huawei Technologies Co., Ltd. 2018-2019. All Rights Reserved. -* -* This program is used to get logical device id by phy device id. -*/ + * Copyright 2019-2020 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. + */ #ifndef INC_TDT_INDEX_TRANSFORM_H #define INC_TDT_INDEX_TRANSFORM_H diff --git a/third_party/fwkacllib/inc/tdt/status.h b/third_party/fwkacllib/inc/tdt/status.h index d5050f35..dc9e670f 100644 --- a/third_party/fwkacllib/inc/tdt/status.h +++ b/third_party/fwkacllib/inc/tdt/status.h @@ -1,4 +1,4 @@ -/** +/** * Copyright 2019-2020 Huawei Technologies Co., Ltd * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/third_party/fwkacllib/inc/toolchain/plog.h b/third_party/fwkacllib/inc/toolchain/plog.h index 0d42e31d..6134c3e6 100644 --- a/third_party/fwkacllib/inc/toolchain/plog.h +++ b/third_party/fwkacllib/inc/toolchain/plog.h @@ -1,59 +1,59 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef _PLOG_H_ -#define _PLOG_H_ - -#ifdef __cplusplus -extern "C" { -#endif // __cplusplus - -#ifndef LINUX -#define LINUX 0 -#endif // LINUX - -#ifndef WIN -#define WIN 1 -#endif - -#ifndef OS_TYPE -#define OS_TYPE 0 -#endif // OS_TYPE - -#if (OS_TYPE == LINUX) -#define DLL_EXPORT __attribute__((visibility("default"))) -#else -#define DLL_EXPORT _declspec(dllexport) -#endif - -/** - * @ingroup plog - * @brief DlogReportInitialize: init log in service process before all device setting. - * @return: 0: SUCCEED, others: FAILED - */ -DLL_EXPORT int DlogReportInitialize(); - -/** - * @ingroup plog - * @brief DlogReportFinalize: release log resource in service process after all device reset. - * @return: 0: SUCCEED, others: FAILED - */ -DLL_EXPORT int DlogReportFinalize(); - -#ifdef __cplusplus -} -#endif // __cplusplus -#endif // D_PLOG_H_ +/** + * Copyright 2019-2020 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. + */ + +#ifndef _PLOG_H_ +#define _PLOG_H_ + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#ifndef LINUX +#define LINUX 0 +#endif // LINUX + +#ifndef WIN +#define WIN 1 +#endif + +#ifndef OS_TYPE +#define OS_TYPE 0 +#endif // OS_TYPE + +#if (OS_TYPE == LINUX) +#define DLL_EXPORT __attribute__((visibility("default"))) +#else +#define DLL_EXPORT _declspec(dllexport) +#endif + +/** + * @ingroup plog + * @brief DlogReportInitialize: init log in service process before all device setting. + * @return: 0: SUCCEED, others: FAILED + */ +DLL_EXPORT int DlogReportInitialize(); + +/** + * @ingroup plog + * @brief DlogReportFinalize: release log resource in service process after all device reset. + * @return: 0: SUCCEED, others: FAILED + */ +DLL_EXPORT int DlogReportFinalize(); + +#ifdef __cplusplus +} +#endif // __cplusplus +#endif // D_PLOG_H_ diff --git a/third_party/fwkacllib/inc/toolchain/prof_callback.h b/third_party/fwkacllib/inc/toolchain/prof_callback.h index 36b55216..dabd41c1 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_callback.h +++ b/third_party/fwkacllib/inc/toolchain/prof_callback.h @@ -1,5 +1,5 @@ /** - * Copyright 2020-2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -12,9 +12,6 @@ * 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. - * - * @file prof_callback.h - * @brief declaraion of profiling callbacks */ #ifndef MSPROFILER_PROF_CALLBACK_H_ @@ -55,10 +52,10 @@ struct ReporterData { }; /** - * @name HashData + * @name MsprofHashData * @brief struct of data to hash */ -struct HashData { +struct MsprofHashData { int deviceId; // the index of device size_t dataLen; // the length of data unsigned char *data; // the data content @@ -126,6 +123,13 @@ enum MsprofCtrlCallbackType { MSPROF_CTRL_PROF_SWITCH_OFF // for prof switch off }; +#define PROF_COMMANDHANDLE_TYPE_INIT (0) +#define PROF_COMMANDHANDLE_TYPE_START (1) +#define PROF_COMMANDHANDLE_TYPE_STOP (2) +#define PROF_COMMANDHANDLE_TYPE_FINALIZE (3) +#define PROF_COMMANDHANDLE_TYPE_MODEL_SUBSCRIBE (4) +#define PROF_COMMANDHANDLE_TYPE_MODEL_UNSUBSCRIBE (5) + #define MSPROF_MAX_DEV_NUM (64) struct MsprofCommandHandle { diff --git a/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h b/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h index 2cf6e0c4..4ba835b6 100644 --- a/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h +++ b/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h @@ -1,13 +1,19 @@ /** - * @file tune_api.h + * Copyright 2019-2020 Huawei Technologies Co., Ltd * - * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved.\n + * 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 * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n - * 描述:aoe调优接口头文件 + * 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. */ + /** @defgroup aoe aoe调优接口 */ #ifndef TUNE_API_H #define TUNE_API_H From cd952eaff2630bd077586a2e469e041c5facd46f Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Wed, 25 Aug 2021 16:09:49 +0800 Subject: [PATCH 36/59] upgrade Ascend package 25 Aug 21 --- inc/external/ge/ge_api_types.h | 12 +- inc/external/runtime/rt_error_codes.h | 4 + inc/framework/common/ge_compiler_options.h | 2 +- inc/framework/common/ge_types.h | 10 +- inc/framework/common/profiling/ge_profiling.h | 28 +- .../common/profiling/ge_runner_profiling.h | 2 +- inc/framework/common/taskdown_common.h | 2 +- inc/framework/ge_runtime/davinci_model.h | 113 --- inc/framework/ge_runtime/model_runner.h | 68 -- inc/framework/ge_runtime/op_info.h | 72 -- inc/framework/ge_runtime/task_info.h | 529 ------------- inc/framework/memory/memory_api.h | 2 +- inc/framework/omg/ge_init.h | 2 +- inc/framework/omg/omg.h | 6 +- inc/framework/omg/omg_inner_types.h | 16 +- inc/framework/omg/parser/model_parser.h | 2 +- inc/framework/omg/parser/op_parser.h | 2 +- inc/framework/omg/parser/parser_api.h | 2 +- inc/framework/omg/parser/parser_factory.h | 2 +- inc/framework/omg/parser/parser_inner_ctx.h | 12 +- inc/framework/omg/parser/weights_parser.h | 2 +- metadef | 2 +- third_party/fwkacllib/inc/ops/aipp.h | 2 +- third_party/fwkacllib/inc/ops/all_ops.h | 3 +- third_party/fwkacllib/inc/ops/array_ops.h | 31 +- third_party/fwkacllib/inc/ops/audio_ops.h | 2 +- .../fwkacllib/inc/ops/avg_pool_1d_ops.h | 2 +- third_party/fwkacllib/inc/ops/batch_ops.h | 2 +- third_party/fwkacllib/inc/ops/bitwise_ops.h | 2 +- .../fwkacllib/inc/ops/boosted_trees_ops.h | 2 +- .../inc/ops/candidate_sampling_ops.h | 2 +- .../fwkacllib/inc/ops/case_condition_ops.h | 2 +- third_party/fwkacllib/inc/ops/condtake_ops.h | 2 +- .../fwkacllib/inc/ops/control_flow_ops.h | 2 +- .../inc/ops/coordinates_1d_to_2d_ops.h | 2 +- third_party/fwkacllib/inc/ops/correlation.h | 2 +- third_party/fwkacllib/inc/ops/ctc_ops.h | 2 +- third_party/fwkacllib/inc/ops/data_flow_ops.h | 2 +- .../inc/ops/elewise_calculation_ops.h | 6 +- .../fwkacllib/inc/ops/functional_ops.h | 2 +- third_party/fwkacllib/inc/ops/get_data_ops.h | 2 +- third_party/fwkacllib/inc/ops/globalavgpool.h | 49 -- third_party/fwkacllib/inc/ops/hcom_ops.h | 2 +- third_party/fwkacllib/inc/ops/hvd_ops.h | 2 +- third_party/fwkacllib/inc/ops/image_ops.h | 2 +- .../fwkacllib/inc/ops/index_to_addr_ops.h | 2 +- third_party/fwkacllib/inc/ops/internal_ops.h | 2 +- third_party/fwkacllib/inc/ops/linalg_ops.h | 2 +- third_party/fwkacllib/inc/ops/list_ops.h | 2 +- third_party/fwkacllib/inc/ops/logging_ops.h | 2 +- third_party/fwkacllib/inc/ops/lookup_ops.h | 2 +- third_party/fwkacllib/inc/ops/math_ops.h | 2 +- .../inc/ops/matrix_calculation_ops.h | 2 +- .../fwkacllib/inc/ops/nn_batch_norm_ops.h | 2 +- .../fwkacllib/inc/ops/nn_calculation_ops.h | 2 +- third_party/fwkacllib/inc/ops/nn_detect_ops.h | 2 +- third_party/fwkacllib/inc/ops/nn_norm_ops.h | 2 +- third_party/fwkacllib/inc/ops/nn_ops.h | 2 +- .../fwkacllib/inc/ops/nn_pooling_ops.h | 25 +- .../fwkacllib/inc/ops/nn_training_ops.h | 2 +- third_party/fwkacllib/inc/ops/no_op.h | 2 +- .../fwkacllib/inc/ops/nonlinear_fuc_ops.h | 58 +- .../fwkacllib/inc/ops/npu_loss_scale_ops.h | 2 +- third_party/fwkacllib/inc/ops/outfeed_ops.h | 2 +- third_party/fwkacllib/inc/ops/pad_ops.h | 2 +- third_party/fwkacllib/inc/ops/parsing_ops.h | 2 +- third_party/fwkacllib/inc/ops/quantize_ops.h | 2 +- .../fwkacllib/inc/ops/ragged_array_ops.h | 2 +- .../fwkacllib/inc/ops/ragged_conversion_ops.h | 2 +- .../fwkacllib/inc/ops/ragged_math_ops.h | 2 +- third_party/fwkacllib/inc/ops/random_ops.h | 2 +- third_party/fwkacllib/inc/ops/reduce_ops.h | 2 +- .../fwkacllib/inc/ops/resource_variable_ops.h | 2 +- third_party/fwkacllib/inc/ops/rnn.h | 2 +- third_party/fwkacllib/inc/ops/rpn_ops.h | 2 +- third_party/fwkacllib/inc/ops/save_ops.h | 2 +- third_party/fwkacllib/inc/ops/sdca_ops.h | 2 +- third_party/fwkacllib/inc/ops/selection_ops.h | 26 +- third_party/fwkacllib/inc/ops/set_ops.h | 2 +- .../fwkacllib/inc/ops/slice_write_ops.h | 2 +- third_party/fwkacllib/inc/ops/sparse_ops.h | 2 +- third_party/fwkacllib/inc/ops/spectral_ops.h | 2 +- .../fwkacllib/inc/ops/split_combination_ops.h | 2 +- third_party/fwkacllib/inc/ops/state_ops.h | 2 +- .../fwkacllib/inc/ops/stateful_random_ops.h | 2 +- .../fwkacllib/inc/ops/stateless_random_ops.h | 2 +- third_party/fwkacllib/inc/ops/string_ops.h | 2 +- third_party/fwkacllib/inc/ops/swap_co_ops.h | 2 +- .../inc/ops/target_crop_and_resize.h | 2 +- .../fwkacllib/inc/ops/transformation_ops.h | 2 +- third_party/fwkacllib/inc/ops/vector_search.h | 48 ++ .../fwkacllib/inc/ops/warp_perspective_ops.h | 2 +- third_party/fwkacllib/inc/runtime/base.h | 32 +- third_party/fwkacllib/inc/runtime/config.h | 10 +- third_party/fwkacllib/inc/runtime/context.h | 21 +- third_party/fwkacllib/inc/runtime/dev.h | 38 +- .../fwkacllib/inc/runtime/dvfsprofile.h | 10 +- third_party/fwkacllib/inc/runtime/event.h | 10 +- third_party/fwkacllib/inc/runtime/kernel.h | 10 +- third_party/fwkacllib/inc/runtime/mem.h | 10 +- third_party/fwkacllib/inc/runtime/rt.h | 12 +- third_party/fwkacllib/inc/runtime/rt_dfx.h | 34 + third_party/fwkacllib/inc/runtime/rt_ffts.h | 17 +- .../fwkacllib/inc/runtime/rt_ffts_plus.h | 34 + .../inc/runtime/rt_ffts_plus_define.h | 715 ++++++++++++++++++ third_party/fwkacllib/inc/runtime/rt_model.h | 11 +- third_party/fwkacllib/inc/runtime/rt_stars.h | 17 +- .../fwkacllib/inc/runtime/rt_stars_define.h | 91 +++ third_party/fwkacllib/inc/runtime/stream.h | 10 +- .../fwkacllib/inc/toolchain/prof_acl_api.h | 6 +- .../fwkacllib/inc/toolchain/prof_callback.h | 40 +- third_party/fwkacllib/inc/toolchain/slog.h | 1 + 112 files changed, 1288 insertions(+), 1103 deletions(-) delete mode 100644 inc/framework/ge_runtime/davinci_model.h delete mode 100644 inc/framework/ge_runtime/model_runner.h delete mode 100644 inc/framework/ge_runtime/op_info.h delete mode 100644 inc/framework/ge_runtime/task_info.h delete mode 100644 third_party/fwkacllib/inc/ops/globalavgpool.h create mode 100644 third_party/fwkacllib/inc/ops/vector_search.h create mode 100644 third_party/fwkacllib/inc/runtime/rt_dfx.h create mode 100644 third_party/fwkacllib/inc/runtime/rt_ffts_plus.h create mode 100644 third_party/fwkacllib/inc/runtime/rt_ffts_plus_define.h create mode 100644 third_party/fwkacllib/inc/runtime/rt_stars_define.h diff --git a/inc/external/ge/ge_api_types.h b/inc/external/ge/ge_api_types.h index 6f5bbfbf..ac821281 100644 --- a/inc/external/ge/ge_api_types.h +++ b/inc/external/ge/ge_api_types.h @@ -112,6 +112,7 @@ const char *const ORIGINAL_MODEL_FILE = "ge.originalModelFile"; const char *const INPUT_FP16_NODES = "ge.INPUT_NODES_SET_FP16"; const char *const OP_DEBUG_LEVEL = "ge.opDebugLevel"; const char *const PERFORMANCE_MODE = "ge.performance_mode"; +const char *const SHAPE_GENERALIZED_BUILD_MODE = "ge.shape_generalized_build_mode"; const char *const MODIFY_MIXLIST = "ge.exec.modify_mixlist"; const char *const OP_PRECISION_MODE = "ge.exec.op_precision_mode"; } // namespace configure_option @@ -325,6 +326,11 @@ const char *const INPUT_SHAPE_RANGE = "input_shape_range"; // high: need to recompile, high execute performance mode const std::string PERFORMANCE_MODE = "ge.performance_mode"; +// For selecting the mode of shape generalization when build graph. +// shape_generalized: Shape will be generalized during graph build. +// shape_precise: Shape will not be generalized, use precise shape. +const std::string SHAPE_GENERALIZED_BUILD_MODE = "ge.shape_generalized_build_mode"; + const std::string MODIFY_MIXLIST = "ge.exec.modify_mixlist"; const std::string OP_PRECISION_MODE = "ge.exec.op_precision_mode"; @@ -407,6 +413,7 @@ static const char *const OP_BANK_PATH = ge::OP_BANK_PATH_FLAG.c_str(); static const char *const OP_BANK_UPDATE = ge::OP_BANK_UPDATE_FLAG.c_str(); static const char *const OP_DEBUG_LEVEL = ge::OP_DEBUG_LEVEL.c_str(); static const char *const PERFORMANCE_MODE = ge::PERFORMANCE_MODE.c_str(); +static const char *const SHAPE_GENERALIZED_BUILD_MODE = ge::SHAPE_GENERALIZED_BUILD_MODE.c_str(); static const char *const MODIFY_MIXLIST = ge::MODIFY_MIXLIST.c_str(); static const char *const OP_PRECISION_MODE = ge::OP_PRECISION_MODE.c_str(); @@ -437,12 +444,13 @@ const std::set ir_builder_suppported_options = {INPUT_FORMAT, OP_BANK_PATH, OP_BANK_UPDATE, PERFORMANCE_MODE, + SHAPE_GENERALIZED_BUILD_MODE, MODIFY_MIXLIST}; // for interface: aclgrphParse const std::set ir_parser_suppported_options = { - INPUT_FP16_NODES, IS_INPUT_ADJUST_HW_LAYOUT, IS_OUTPUT_ADJUST_HW_LAYOUT, OUTPUT, - OUT_NODES, ENABLE_SCOPE_FUSION_PASSES}; + INPUT_FP16_NODES, IS_INPUT_ADJUST_HW_LAYOUT, IS_OUTPUT_ADJUST_HW_LAYOUT, OUTPUT, + OUT_NODES, ENABLE_SCOPE_FUSION_PASSES}; // for interface: aclgrphBuildInitialize const std::set global_options = {CORE_TYPE, diff --git a/inc/external/runtime/rt_error_codes.h b/inc/external/runtime/rt_error_codes.h index a1392cc6..ef7e2ec7 100644 --- a/inc/external/runtime/rt_error_codes.h +++ b/inc/external/runtime/rt_error_codes.h @@ -97,6 +97,10 @@ static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vecto static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception static const int32_t ACL_ERROR_RT_CDQ_BATCH_ABNORMAL = 507037; // cdq alloc batch abnormal +static const int32_t ACL_ERROR_RT_DIE_MODE_CHANGE_ERROR = 507038; // can not change die mode +static const int32_t ACL_ERROR_RT_DIE_SET_ERROR = 507039; // single die mode can not set die +static const int32_t ACL_ERROR_RT_INVALID_DIEID = 507040; // invalid die id +static const int32_t ACL_ERROR_RT_DIE_MODE_NOT_SET = 507041; // die mode not set static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error diff --git a/inc/framework/common/ge_compiler_options.h b/inc/framework/common/ge_compiler_options.h index 6876740e..5c947346 100644 --- a/inc/framework/common/ge_compiler_options.h +++ b/inc/framework/common/ge_compiler_options.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/inc/framework/common/ge_types.h b/inc/framework/common/ge_types.h index 64231b8c..83d01c1f 100644 --- a/inc/framework/common/ge_types.h +++ b/inc/framework/common/ge_types.h @@ -41,7 +41,7 @@ enum FrameworkType { }; const std::map kFwkTypeToStr = { - {"0", "Caffe"}, {"1", "MindSpore"}, {"3", "TensorFlow"}, {"4", "Android_NN"}, {"5", "Onnx"}}; + {"0", "Caffe"}, {"1", "MindSpore"}, {"3", "TensorFlow"}, {"4", "Android_NN"}, {"5", "Onnx"}}; enum OpEngineType { ENGINE_SYS = 0, // default engine @@ -230,6 +230,14 @@ class GE_FUNC_VISIBILITY ModelListener { /// virtual Status OnComputeDone(uint32_t model_id, uint32_t data_index, uint32_t result_code, std::vector &outputs) = 0; + + virtual uint32_t GetResultCode() { + return 0; + }; + + virtual Status ResetResult() { + return SUCCESS; + }; }; // OMM configuration item diff --git a/inc/framework/common/profiling/ge_profiling.h b/inc/framework/common/profiling/ge_profiling.h index 58cddc4e..e9b207af 100644 --- a/inc/framework/common/profiling/ge_profiling.h +++ b/inc/framework/common/profiling/ge_profiling.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. @@ -18,32 +18,8 @@ #define INC_FRAMEWORK_COMMON_GE_PROFILING_H_ #include "ge/ge_api_error_codes.h" -#include "toolchain/prof_callback.h" #include "runtime/base.h" -const int MAX_DEV_NUM = 64; - -enum ProfCommandHandleType { - kProfCommandhandleInit = 0, - kProfCommandhandleStart, - kProfCommandhandleStop, - kProfCommandhandleFinalize, - kProfCommandhandleModelSubscribe, - kProfCommandhandleModelUnsubscribe -}; - -struct ProfCommandHandleData { - uint64_t profSwitch; - uint32_t devNums; // length of device id list - uint32_t devIdList[MAX_DEV_NUM]; - uint32_t modelId; -}; - -GE_FUNC_VISIBILITY ge::Status RegProfCtrlCallback(MsprofCtrlCallback func); -GE_FUNC_VISIBILITY ge::Status RegProfSetDeviceCallback(MsprofSetDeviceCallback func); -GE_FUNC_VISIBILITY ge::Status RegProfReporterCallback(MsprofReporterCallback func); -GE_FUNC_VISIBILITY ge::Status ProfCommandHandle(ProfCommandHandleType type, void *data, uint32_t len); - /// /// @brief Output the profiling data of single operator in Pytorch, and does not support multithreading /// @return Status result @@ -52,4 +28,6 @@ GE_FUNC_VISIBILITY ge::Status ProfSetStepInfo(uint64_t index_id, uint16_t tag_id GE_FUNC_VISIBILITY ge::Status ProfGetDeviceFormGraphId(uint32_t graph_id, uint32_t &device_id); +GE_FUNC_VISIBILITY void ProfSetGraphIdToDeviceMap(uint32_t graph_id, uint32_t &device_id); + #endif // INC_FRAMEWORK_COMMON_GE_PROFILING_H_ diff --git a/inc/framework/common/profiling/ge_runner_profiling.h b/inc/framework/common/profiling/ge_runner_profiling.h index 1c594c5b..27e19bce 100644 --- a/inc/framework/common/profiling/ge_runner_profiling.h +++ b/inc/framework/common/profiling/ge_runner_profiling.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/inc/framework/common/taskdown_common.h b/inc/framework/common/taskdown_common.h index 81a532dd..f2f731be 100644 --- a/inc/framework/common/taskdown_common.h +++ b/inc/framework/common/taskdown_common.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/inc/framework/ge_runtime/davinci_model.h b/inc/framework/ge_runtime/davinci_model.h deleted file mode 100644 index 91e70159..00000000 --- a/inc/framework/ge_runtime/davinci_model.h +++ /dev/null @@ -1,113 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef INC_FRAMEWORK_GE_RUNTIME_DAVINCI_MODEL_H_ -#define INC_FRAMEWORK_GE_RUNTIME_DAVINCI_MODEL_H_ - -#include -#include - -#include "ge_runtime/op_info.h" -#include "ge_runtime/task_info.h" - -namespace ge { -namespace model_runner { -class DavinciModel { - public: - DavinciModel(const std::vector> &task_info_list, - const std::vector> &data_info_list, - const std::vector> &output_info_list, - const std::vector> &constant_info_list, - const std::vector &variable_info_list, - const std::vector &wait_active_stream_list, - const std::vector &force_copy_stream_list, uint64_t mem_size = 0, uint64_t weight_size = 0, - uint64_t var_size = 0, uintptr_t logic_mem_base = 0, uintptr_t logic_weight_base = 0, - uintptr_t logic_var_base = 0, uint32_t stream_num = 0, uint32_t batch_num = 0, uint32_t event_num = 0, - int32_t priority = 0) - : task_info_list_(task_info_list), - data_info_list_(data_info_list), - output_info_list_(output_info_list), - constant_info_list_(constant_info_list), - variable_info_list_(variable_info_list), - wait_active_stream_list_(wait_active_stream_list), - force_copy_stream_list_(force_copy_stream_list), - mem_size_(mem_size), - weight_size_(weight_size), - var_size_(var_size), - logic_mem_base_(logic_mem_base), - logic_weight_base_(logic_weight_base), - logic_var_base_(logic_var_base), - stream_num_(stream_num), - batch_num_(batch_num), - event_num_(event_num), - priority_(priority) {} - ~DavinciModel() {} - - uint64_t GetMemSize() const { return mem_size_; } - uint64_t GetWeightSize() const { return weight_size_; } - uint64_t GetVarSize() const { return var_size_; } - - uintptr_t GetLogicMemBase() const { return logic_mem_base_; } - uintptr_t GetLogicWeightBase() const { return logic_weight_base_; } - uintptr_t GetLogicVarBase() const { return logic_var_base_; } - - uint32_t GetStreamNum() const { return stream_num_; } - uint32_t GetBatchNum() const { return batch_num_; } - uint32_t GetEventNum() const { return event_num_; } - - const std::vector &GetWaitActiveStreams() const { return wait_active_stream_list_; } - const std::vector &GetForceCopyStreams() const { return force_copy_stream_list_; } - - int32_t GetPriority() const { return priority_; } - - const std::vector> &GetTaskInfoList() const { return task_info_list_; } - const std::vector> &GetDataInfoList() const { return data_info_list_; } - const std::vector> &GetOutputInfoList() const { return output_info_list_; } - const std::vector> &GetConstantInfoList() const { return output_info_list_; } - const std::vector &GetVariableInfoList() const { return variable_info_list_; } - - private: - std::vector> task_info_list_; - std::vector> data_info_list_; - std::vector> output_info_list_; - std::vector> constant_info_list_; - std::vector variable_info_list_; - - std::vector wait_active_stream_list_; - std::vector force_copy_stream_list_; - - uint64_t mem_size_; - uint64_t weight_size_; - uint64_t var_size_; - - uintptr_t logic_mem_base_; - uintptr_t logic_weight_base_; - uintptr_t logic_var_base_; - - uint32_t stream_num_; - uint32_t batch_num_; - uint32_t event_num_; - - int32_t priority_; - - // Disable to copy constructor and assignment operator - DavinciModel &operator=(const DavinciModel &) = delete; - DavinciModel(const DavinciModel &) = delete; -}; -} // namespace model_runner -} // namespace ge - -#endif // INC_FRAMEWORK_GE_RUNTIME_DAVINCI_MODEL_H_ diff --git a/inc/framework/ge_runtime/model_runner.h b/inc/framework/ge_runtime/model_runner.h deleted file mode 100644 index e495dfdf..00000000 --- a/inc/framework/ge_runtime/model_runner.h +++ /dev/null @@ -1,68 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef INC_FRAMEWORK_GE_RUNTIME_MODEL_RUNNER_H_ -#define INC_FRAMEWORK_GE_RUNTIME_MODEL_RUNNER_H_ - -#include -#include -#include - -#include "common/ge_inner_error_codes.h" -#include "common/ge_types.h" -#include "ge_runtime/davinci_model.h" - -namespace ge { -namespace model_runner { -class RuntimeModel; -using RuntimeInfo = std::tuple; -class ModelRunner { - public: - static ModelRunner &Instance(); - - bool LoadDavinciModel(uint32_t device_id, uint64_t session_id, uint32_t model_id, - std::shared_ptr davinci_model, std::shared_ptr listener); - - bool DistributeTask(uint32_t model_id); - - bool LoadModelComplete(uint32_t model_id); - - const std::vector &GetTaskIdList(uint32_t model_id) const; - - const std::vector &GetStreamIdList(uint32_t model_id) const; - - const std::map> &GetRuntimeInfoMap(uint32_t model_id) const; - - void *GetModelHandle(uint32_t model_id) const; - - bool UnloadModel(uint32_t model_id); - - bool RunModel(uint32_t model_id, const InputData &input_data, OutputData *output_data); - - bool GetInputOutputDescInfo(uint32_t model_id, bool zero_copy, std::vector *input_desc, - std::vector *output_desc, std::vector *input_format, - std::vector *output_format); - - private: - ModelRunner() = default; - ~ModelRunner() = default; - - std::unordered_map> runtime_models_; -}; -} // namespace model_runner -} // namespace ge - -#endif // INC_FRAMEWORK_GE_RUNTIME_MODEL_RUNNER_H_ diff --git a/inc/framework/ge_runtime/op_info.h b/inc/framework/ge_runtime/op_info.h deleted file mode 100644 index 22c16ed6..00000000 --- a/inc/framework/ge_runtime/op_info.h +++ /dev/null @@ -1,72 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef INC_FRAMEWORK_GE_RUNTIME_OP_INFO_H_ -#define INC_FRAMEWORK_GE_RUNTIME_OP_INFO_H_ - -#include -#include -#include - -namespace ge { -namespace model_runner { -struct TensorInfo { - int64_t GetShapeSize() const { - int64_t res = 1; - if (dims.empty()) { - return 0; - } - for (auto dim : dims) { - res *= dim; - } - return res; - } - - int64_t GetDim(uint32_t index) { - if (index >= dims.size()) { - return 0; - } - return dims[index]; - } - - std::vector dims; - uint32_t datatype; - uint32_t format; - uint32_t real_dim_cnt; - uint32_t size; - bool is_output; -}; - -struct OpInfo { - uint32_t index; - std::string name; - std::string type; - bool var_is_broadcast; - std::vector input_addrs; - std::vector output_addrs; - std::vector input_tensors; - std::vector output_tensors; - std::vector weight_tensors; - std::vector src_name; - std::vector src_index; - std::string weight_data; -}; - -using TensorInfoPtr = std::shared_ptr; -using OpInfoPtr = std::shared_ptr; -} // namespace model_runner -} // namespace ge -#endif // INC_FRAMEWORK_GE_RUNTIME_OP_INFO_H_ diff --git a/inc/framework/ge_runtime/task_info.h b/inc/framework/ge_runtime/task_info.h deleted file mode 100644 index abc4783d..00000000 --- a/inc/framework/ge_runtime/task_info.h +++ /dev/null @@ -1,529 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef INC_FRAMEWORK_GE_RUNTIME_TASK_INFO_H_ -#define INC_FRAMEWORK_GE_RUNTIME_TASK_INFO_H_ - -#include -#include -#include -#include -#include - -#include "cce/taskdown_api.h" - -namespace ge { -namespace model_runner { -enum TaskInfoType { - CCE = 0, - TBE, - AICPU, - LABEL_SET, - LABEL_SWITCH, - LABEL_GOTO, - EVENT_RECORD, - EVENT_WAIT, - FUSION_START, - FUSION_END, - HCCL, - PROFILER_TRACE, - MEMCPY_ASYNC, - STREAM_SWITCH, - STREAM_ACTIVE, - // Insert new task type here - REVSERVED = 23 -}; - -class TaskInfo { - public: - virtual ~TaskInfo() {} - uint32_t stream_id() const { - return stream_id_; - } - TaskInfoType type() const { - return type_; - } - std::string op_name() const { - return op_name_; - } - bool dump_flag() const { - return dump_flag_; - } - - protected: - TaskInfo(const std::string &op_name, uint32_t stream_id, TaskInfoType type, bool dump_flag) - : op_name_(op_name), stream_id_(stream_id), type_(type), dump_flag_(dump_flag) {} - - private: - std::string op_name_; - uint32_t stream_id_; - TaskInfoType type_; - bool dump_flag_; -}; - -class CceTaskInfo : public TaskInfo { - public: - CceTaskInfo(const std::string &op_name, uint32_t stream_id, const cce::ccOpContext &ctx, const std::string &stub_func, - uint32_t block_dim, const std::vector &args, uint32_t args_size, - const std::vector &sm_desc, const std::vector &flow_table, - const std::vector &args_offset, bool is_flowtable) - : TaskInfo(op_name, stream_id, TaskInfoType::CCE, false), - ctx_(ctx), - stub_func_(stub_func), - block_dim_(block_dim), - args_(args), - args_size_(args_size), - sm_desc_(sm_desc), - flow_table_(flow_table), - args_offset_(args_offset), - is_flowtable_(is_flowtable) {} - ~CceTaskInfo() override {} - - cce::ccOpContext cc_context() const { - return ctx_; - } - std::string stub_func() const { - return stub_func_; - } - uint32_t block_dim() const { - return block_dim_; - } - const std::vector &args() const { - return args_; - } - uint32_t args_size() const { - return args_size_; - } - const std::vector &sm_desc() const { - return sm_desc_; - } - const std::vector &flow_table() const { - return flow_table_; - } - const std::vector &args_offset() const { - return args_offset_; - } - bool is_flowtable() const { - return is_flowtable_; - } - - private: - cce::ccOpContext ctx_; - std::string stub_func_; - uint32_t block_dim_; - std::vector args_; - uint32_t args_size_; - std::vector sm_desc_; - std::vector flow_table_; - std::vector args_offset_; - bool is_flowtable_; -}; - -class TbeTaskInfo : public TaskInfo { - public: - TbeTaskInfo(const std::string &op_name, uint32_t stream_id, const std::string &stub_func, uint32_t block_dim, - const std::vector &args, uint32_t args_size, const std::vector &sm_desc, void *binary, - uint32_t binary_size, const std::vector &meta_data, const std::vector &input_data_addrs, - const std::vector &output_data_addrs, const std::vector &workspace_addrs, bool dump_flag) - : TaskInfo(op_name, stream_id, TaskInfoType::TBE, dump_flag), - stub_func_(stub_func), - block_dim_(block_dim), - args_(args), - args_size_(args_size), - sm_desc_(sm_desc), - binary_(binary), - binary_size_(binary_size), - meta_data_(meta_data), - input_data_addrs_(input_data_addrs), - output_data_addrs_(output_data_addrs), - workspace_addrs_(workspace_addrs) {} - ~TbeTaskInfo() override {} - - const std::string &stub_func() const { - return stub_func_; - } - uint32_t block_dim() const { - return block_dim_; - } - const std::vector &args() const { - return args_; - } - uint32_t args_size() const { - return args_size_; - } - const std::vector &sm_desc() const { - return sm_desc_; - } - void *binary() const { - return binary_; - } - uint32_t binary_size() const { - return binary_size_; - } - const std::vector &meta_data() const { - return meta_data_; - } - const std::vector &input_data_addrs() const { - return input_data_addrs_; - } - const std::vector &output_data_addrs() const { - return output_data_addrs_; - } - const std::vector &workspace_addrs() const { - return workspace_addrs_; - } - - void SetBinary(void *binary, uint32_t binary_size) { - binary_ = binary; - binary_size_ = binary_size; - } - - private: - std::string stub_func_; - uint32_t block_dim_; - std::vector args_; - uint32_t args_size_; - std::vector sm_desc_; - void *binary_; - uint32_t binary_size_; - std::vector meta_data_; - std::vector input_data_addrs_; - std::vector output_data_addrs_; - std::vector workspace_addrs_; -}; - -class AicpuTaskInfo : public TaskInfo { - public: - AicpuTaskInfo(const std::string &op_name, uint32_t stream_id, const string &so_name, const std::string &kernel_name, - const std::string &node_def, const std::string &ext_info, const std::vector &input_data_addrs, - const std::vector &output_data_addrs, bool dump_flag) - : TaskInfo(op_name, stream_id, TaskInfoType::AICPU, dump_flag), - so_name_(so_name), - kernel_name_(kernel_name), - node_def_(node_def), - ext_info_(ext_info), - input_data_addrs_(input_data_addrs), - output_data_addrs_(output_data_addrs) {} - ~AicpuTaskInfo() override {} - - const std::string &so_name() const { - return so_name_; - } - const std::string &kernel_name() const { - return kernel_name_; - } - const std::string &node_def() const { - return node_def_; - } - const std::vector &input_data_addrs() const { - return input_data_addrs_; - } - const std::vector &output_data_addrs() const { - return output_data_addrs_; - } - const std::string &ext_info() const { - return ext_info_; - } - - private: - std::string so_name_; - std::string kernel_name_; - std::string node_def_; - std::string ext_info_; - std::vector input_data_addrs_; - std::vector output_data_addrs_; -}; - -class LabelSetTaskInfo : public TaskInfo { - public: - LabelSetTaskInfo(const std::string &op_name, uint32_t stream_id, uint32_t label_id) - : TaskInfo(op_name, stream_id, TaskInfoType::LABEL_SET, false), label_id_(label_id) {} - ~LabelSetTaskInfo() override {} - uint32_t label_id() const { - return label_id_; - } - - private: - uint32_t label_id_; -}; - -class LabelGotoTaskInfo : public TaskInfo { - public: - LabelGotoTaskInfo(const std::string &op_name, uint32_t stream_id, uint32_t label_id) - : TaskInfo(op_name, stream_id, TaskInfoType::LABEL_GOTO, false), label_id_(label_id) {} - ~LabelGotoTaskInfo() override {} - uint32_t label_id() const { - return label_id_; - } - - private: - uint32_t label_id_; -}; - -class LabelSwitchTaskInfo : public TaskInfo { - public: - LabelSwitchTaskInfo(const std::string &op_name, uint32_t stream_id, uint32_t label_size, - const std::vector &label_list, void *cond) - : TaskInfo(op_name, stream_id, TaskInfoType::LABEL_SWITCH, false), - label_size_(label_size), - label_list_(label_list), - cond_(cond) {} - ~LabelSwitchTaskInfo() override {} - uint32_t label_size() const { - return label_size_; - } - const std::vector &label_list() const { - return label_list_; - } - void *cond() const { - return cond_; - } - - private: - uint32_t label_size_; - std::vector label_list_; - void *cond_; -}; - -class EventTaskInfo : public TaskInfo { - public: - uint32_t event_id() const { - return event_id_; - } - - protected: - EventTaskInfo(const std::string &op_name, uint32_t stream_id, TaskInfoType type, uint32_t event_id) - : TaskInfo(op_name, stream_id, type, false), event_id_(event_id) {} - ~EventTaskInfo() override {} - - uint32_t event_id_; -}; - -class EventRecordTaskInfo : public EventTaskInfo { - public: - EventRecordTaskInfo(const std::string &op_name, uint32_t stream_id, uint32_t event_id) - : EventTaskInfo(op_name, stream_id, TaskInfoType::EVENT_RECORD, event_id) {} - ~EventRecordTaskInfo() override {} -}; - -class EventWaitTaskInfo : public EventTaskInfo { - public: - EventWaitTaskInfo(const std::string &op_name, uint32_t stream_id, uint32_t event_id) - : EventTaskInfo(op_name, stream_id, TaskInfoType::EVENT_WAIT, event_id) {} - ~EventWaitTaskInfo() override {} -}; - -class FusionStartTaskInfo : public TaskInfo { - public: - explicit FusionStartTaskInfo(const std::string &op_name, uint32_t stream_id) - : TaskInfo(op_name, stream_id, TaskInfoType::FUSION_START, false) {} - ~FusionStartTaskInfo() override {} -}; - -class FusionEndTaskInfo : public TaskInfo { - public: - explicit FusionEndTaskInfo(const std::string &op_name, uint32_t stream_id) - : TaskInfo(op_name, stream_id, TaskInfoType::FUSION_END, false) {} - ~FusionEndTaskInfo() override {} -}; - -class HcclTaskInfo : public TaskInfo { - public: - HcclTaskInfo(const std::string &op_name, uint32_t stream_id, const std::string hccl_type, void *input_data_addr, - void *output_data_addr, int64_t workspace_size, int64_t hccl_stream_num, - const std::vector &private_def, void *ops_kernel_store, int32_t count, int64_t root_id, - int64_t op_type, int64_t data_type, const std::string &group, bool dump_flag) - : TaskInfo(op_name, stream_id, TaskInfoType::HCCL, dump_flag), - hccl_type_(hccl_type), - input_data_addr_(input_data_addr), - output_data_addr_(output_data_addr), - workspace_size_(workspace_size), - hccl_stream_num_(hccl_stream_num), - private_def_(private_def), - ops_kernel_store_(ops_kernel_store), - count_(count), - root_id_(root_id), - op_type_(op_type), - data_type_(data_type), - group_(group) {} - ~HcclTaskInfo() override {} - - const std::string &hccl_type() const { - return hccl_type_; - } - void *input_data_addr() const { - return input_data_addr_; - } - void *output_data_addr() const { - return output_data_addr_; - } - int64_t workspace_size() const { - return workspace_size_; - } - int64_t hccl_stream_num() const { - return hccl_stream_num_; - } - const std::vector &private_def() const { - return private_def_; - } - void *ops_kernel_store() const { - return ops_kernel_store_; - } - int32_t count() const { - return count_; - } - int64_t root_id() const { - return root_id_; - } - int64_t op_type() const { - return op_type_; - } - int64_t data_type() const { - return data_type_; - } - const std::string &group() const { - return group_; - } - - private: - std::string hccl_type_; - void *input_data_addr_; - void *output_data_addr_; - int64_t workspace_size_; - int64_t hccl_stream_num_; - std::vector private_def_; - void *ops_kernel_store_; - int32_t count_; - int64_t root_id_; - int64_t op_type_; - int64_t data_type_; - std::string group_; -}; - -class ProfilerTraceTaskInfo : public TaskInfo { - public: - ProfilerTraceTaskInfo(const std::string &op_name, uint32_t stream_id, uint64_t log_id, bool notify, uint32_t flat) - : TaskInfo(op_name, stream_id, TaskInfoType::PROFILER_TRACE, false), - log_id_(log_id), - notify_(notify), - flat_(flat) {} - ~ProfilerTraceTaskInfo() override {} - - uint64_t log_id() const { - return log_id_; - } - bool notify() const { - return notify_; - } - uint32_t flat() const { - return flat_; - } - - private: - uint64_t log_id_; - bool notify_; - uint32_t flat_; -}; - -class MemcpyAsyncTaskInfo : public TaskInfo { - public: - MemcpyAsyncTaskInfo(const std::string &op_name, uint32_t stream_id, void *dst, uint64_t dst_max, void *src, - uint64_t count, uint32_t kind, bool dump_flag) - : TaskInfo(op_name, stream_id, TaskInfoType::MEMCPY_ASYNC, dump_flag), - dst_(dst), - dst_max_(dst_max), - src_(src), - count_(count), - kind_(kind) {} - ~MemcpyAsyncTaskInfo() override {} - - void *dst() const { - return dst_; - } - uint64_t dst_max() const { - return dst_max_; - } - void *src() const { - return src_; - } - uint64_t count() const { - return count_; - } - uint32_t kind() const { - return kind_; - } - - private: - void *dst_; - uint64_t dst_max_; - void *src_; - uint64_t count_; - int32_t kind_; -}; - -class StreamSwitchTaskInfo : public TaskInfo { - public: - StreamSwitchTaskInfo(const std::string &op_name, uint32_t stream_id, int64_t true_stream_id, void *input_addr, - void *value_addr, int64_t cond, int64_t data_type) - : TaskInfo(op_name, stream_id, TaskInfoType::STREAM_SWITCH, false), - true_stream_id_(true_stream_id), - input_addr_(input_addr), - value_addr_(value_addr), - cond_(cond), - data_type_(data_type) {} - ~StreamSwitchTaskInfo() override {} - - int64_t true_stream_id() const { - return true_stream_id_; - } - void *input_addr() const { - return input_addr_; - } - void *value_addr() const { - return value_addr_; - } - int64_t cond() const { - return cond_; - } - int64_t data_type() const { - return data_type_; - } - - private: - int64_t true_stream_id_; - void *input_addr_; - void *value_addr_; - int64_t cond_; - int64_t data_type_; -}; - -class StreamActiveTaskInfo : public TaskInfo { - public: - StreamActiveTaskInfo(const std::string &op_name, uint32_t stream_id, uint32_t active_stream_id) - : TaskInfo(op_name, stream_id, TaskInfoType::STREAM_ACTIVE, false), active_stream_id_(active_stream_id) {} - ~StreamActiveTaskInfo() override {} - - uint32_t active_stream_id() const { - return active_stream_id_; - } - - private: - uint32_t active_stream_id_; -}; -} // namespace model_runner -} // namespace ge - -#endif // INC_FRAMEWORK_GE_RUNTIME_TASK_INFO_H_ diff --git a/inc/framework/memory/memory_api.h b/inc/framework/memory/memory_api.h index da36cdd6..a316fd59 100644 --- a/inc/framework/memory/memory_api.h +++ b/inc/framework/memory/memory_api.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/inc/framework/omg/ge_init.h b/inc/framework/omg/ge_init.h index 67ef1082..42fd8979 100644 --- a/inc/framework/omg/ge_init.h +++ b/inc/framework/omg/ge_init.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/inc/framework/omg/omg.h b/inc/framework/omg/omg.h index acd36883..37d9e26b 100644 --- a/inc/framework/omg/omg.h +++ b/inc/framework/omg/omg.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. @@ -101,8 +101,8 @@ GE_FUNC_VISIBILITY Status SetOutputNodeInfo(ge::Graph &graph, const std::string GE_FUNC_VISIBILITY Status GetOutputLeaf(ge::NodePtr node, std::vector> &output_nodes_info); -GE_FUNC_VISIBILITY void GetOutputNodesNameAndIndex(std::vector> &output_nodes_info, - std::vector &output_nodes_name); +GE_FUNC_VISIBILITY void CreateOutputNodesInfo(std::vector> &output_nodes_info, + std::vector &output_nodes_name); GE_FUNC_VISIBILITY void UpdateOmgCtxWithParserCtx(); diff --git a/inc/framework/omg/omg_inner_types.h b/inc/framework/omg/omg_inner_types.h index 0b799bf2..a3621d8b 100644 --- a/inc/framework/omg/omg_inner_types.h +++ b/inc/framework/omg/omg_inner_types.h @@ -73,7 +73,9 @@ struct OMGBufferData { }; struct OmgContext { - OmgContext() { format = DOMI_TENSOR_ND; } + OmgContext() { + format = DOMI_TENSOR_ND; + } domiTensorFormat_t format; // format of the input specified by the command line @@ -96,14 +98,14 @@ struct OmgContext { // default out nodes (this is used for determing the orders) std::vector> default_out_nodes; // save the output node of the network, value = topName, - // topName indicates the output name of the operator. - std::vector user_out_nodes_top_vec; + // tensorName indicates the output name of the operator. + std::vector user_out_tensors; // net out nodes (where user_out_nodes or leaf nodes) std::vector net_out_nodes; - // net out nodes top names(only caffe has top) - std::vector out_top_names; - // net data nodes top names(only caffe has top) - std::vector data_top_names; + // net out nodes tensor names(caffe or onnx) + std::vector out_tensor_names; + // net data nodes tensor names(caffe or onnx) + std::vector data_tensor_names; // preferential format used by the entire network domiTensorFormat_t net_format = DOMI_TENSOR_RESERVED; domi::FrameworkType type = domi::FRAMEWORK_RESERVED; diff --git a/inc/framework/omg/parser/model_parser.h b/inc/framework/omg/parser/model_parser.h index d311706d..70444e0a 100644 --- a/inc/framework/omg/parser/model_parser.h +++ b/inc/framework/omg/parser/model_parser.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/inc/framework/omg/parser/op_parser.h b/inc/framework/omg/parser/op_parser.h index 7d02b257..70bec218 100644 --- a/inc/framework/omg/parser/op_parser.h +++ b/inc/framework/omg/parser/op_parser.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/inc/framework/omg/parser/parser_api.h b/inc/framework/omg/parser/parser_api.h index a493e29f..23df0177 100644 --- a/inc/framework/omg/parser/parser_api.h +++ b/inc/framework/omg/parser/parser_api.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/inc/framework/omg/parser/parser_factory.h b/inc/framework/omg/parser/parser_factory.h index 06aaecb7..9d6590c0 100644 --- a/inc/framework/omg/parser/parser_factory.h +++ b/inc/framework/omg/parser/parser_factory.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/inc/framework/omg/parser/parser_inner_ctx.h b/inc/framework/omg/parser/parser_inner_ctx.h index b23da53f..5de54704 100644 --- a/inc/framework/omg/parser/parser_inner_ctx.h +++ b/inc/framework/omg/parser/parser_inner_ctx.h @@ -46,14 +46,14 @@ struct ParserContext { // operator std::map> out_nodes_map; // save the output node of the network, value = topName, - // topName indicates the output name of the operator. - std::vector user_out_nodes_top_vec; + // tensorName indicates the output name of the operator. + std::vector user_out_tensors; // net out nodes (where user_out_nodes or leaf nodes) std::vector net_out_nodes; - // net data nodes top names(only caffe has top) - std::vector data_top_names; - // net out nodes top names(only caffe has top) - std::vector out_top_names; + // net out nodes tensor names(caffe or onnx) + std::vector out_tensor_names; + // net data nodes tensor names(caffe or onnx) + std::vector data_tensor_names; // Whether to use dynamic batch size or dynamic image size bool is_dynamic_input = false; bool train_flag = false; diff --git a/inc/framework/omg/parser/weights_parser.h b/inc/framework/omg/parser/weights_parser.h index a568f927..e4436044 100644 --- a/inc/framework/omg/parser/weights_parser.h +++ b/inc/framework/omg/parser/weights_parser.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/metadef b/metadef index 51418f61..2d1913e6 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit 51418f61f26599c85bee2b57328afbbf1c9927c7 +Subproject commit 2d1913e65a016e04a9599e1d2e49fd02136638bd diff --git a/third_party/fwkacllib/inc/ops/aipp.h b/third_party/fwkacllib/inc/ops/aipp.h index 6db4d783..86805f72 100644 --- a/third_party/fwkacllib/inc/ops/aipp.h +++ b/third_party/fwkacllib/inc/ops/aipp.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/all_ops.h b/third_party/fwkacllib/inc/ops/all_ops.h index d63c2daa..b15f2292 100644 --- a/third_party/fwkacllib/inc/ops/all_ops.h +++ b/third_party/fwkacllib/inc/ops/all_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -77,4 +77,5 @@ #include "transformation_ops.h" #include "condtake_ops.h" #include "warp_perspective_ops.h" +#include "vector_search.h" #endif // OPS_BUILT_IN_OP_PROTO_INC_ALL_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/array_ops.h b/third_party/fwkacllib/inc/ops/array_ops.h index acac3d6c..4b45f4cf 100644 --- a/third_party/fwkacllib/inc/ops/array_ops.h +++ b/third_party/fwkacllib/inc/ops/array_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -1221,8 +1221,9 @@ REG_OP(Expand) REG_OP(NonZero) .INPUT(x, TensorType({DT_DOUBLE, DT_FLOAT, DT_FLOAT16, DT_INT8, DT_UINT8, DT_INT16, \ DT_UINT16, DT_INT32, DT_UINT32, DT_INT64, DT_UINT64, DT_BOOL})) - .OUTPUT(y, TensorType({DT_INT64})) + .OUTPUT(y, TensorType({DT_INT64, DT_INT32})) .ATTR(transpose, Bool, false) + .ATTR(dtype, Type, DT_INT64) .OP_END_FACTORY_REG(NonZero) /** @@ -1249,6 +1250,32 @@ REG_OP(ExpandD) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) .REQUIRED_ATTR(shape, ListInt) .OP_END_FACTORY_REG(ExpandD) + +/** +* @brief Calculate buckets limit and offset. \n + +* @par Inputs: +* Three inputs, including: +* @li bucket_list: A 1-D tensor of type int32 with the value of ivf_counts and ivf_offset index. \n +* @li ivf_counts: A 1-D tensor of type int32 with the value of ivf counts. \n +* @li ivf_offset: A 1-D tensor of type int32 with the value of ivf offset. \n + +* @par Attributes: +* total_limit: A int64 type maximum value of the sum of ivf_counts corresponding to bucket_list. \n + +* @par Outputs: +* @li buckets_limit: A 1-D tensor of type int32 with the sum <= total_limit. \n +* @li buckets_offset: A 1-D tensor of type int32 with the value of ivf_offset corresponding to bucket_list. \n +*/ +REG_OP(CalcBucketsLimitAndOffset) + .INPUT(bucket_list, TensorType({DT_INT32})) + .INPUT(ivf_counts, TensorType({DT_INT32})) + .INPUT(ivf_offset, TensorType({DT_INT32})) + .OUTPUT(buckets_limit, TensorType({DT_INT32})) + .OUTPUT(buckets_offset, TensorType({DT_INT32})) + .REQUIRED_ATTR(total_limit, Int) + .OP_END_FACTORY_REG(CalcBucketsLimitAndOffset) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_ARRAY_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/audio_ops.h b/third_party/fwkacllib/inc/ops/audio_ops.h index d9883253..f05135d1 100644 --- a/third_party/fwkacllib/inc/ops/audio_ops.h +++ b/third_party/fwkacllib/inc/ops/audio_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h b/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h index 9583eff9..d0800a08 100644 --- a/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h +++ b/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/batch_ops.h b/third_party/fwkacllib/inc/ops/batch_ops.h index 4b78951d..ca4fe1db 100644 --- a/third_party/fwkacllib/inc/ops/batch_ops.h +++ b/third_party/fwkacllib/inc/ops/batch_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/bitwise_ops.h b/third_party/fwkacllib/inc/ops/bitwise_ops.h index d032476d..dac78118 100644 --- a/third_party/fwkacllib/inc/ops/bitwise_ops.h +++ b/third_party/fwkacllib/inc/ops/bitwise_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/boosted_trees_ops.h b/third_party/fwkacllib/inc/ops/boosted_trees_ops.h index 550e8b7d..08e54824 100644 --- a/third_party/fwkacllib/inc/ops/boosted_trees_ops.h +++ b/third_party/fwkacllib/inc/ops/boosted_trees_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h b/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h index e20607bf..890c52ae 100644 --- a/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h +++ b/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/case_condition_ops.h b/third_party/fwkacllib/inc/ops/case_condition_ops.h index 85064845..85dba609 100644 --- a/third_party/fwkacllib/inc/ops/case_condition_ops.h +++ b/third_party/fwkacllib/inc/ops/case_condition_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/condtake_ops.h b/third_party/fwkacllib/inc/ops/condtake_ops.h index 5e91eb07..029cffbf 100644 --- a/third_party/fwkacllib/inc/ops/condtake_ops.h +++ b/third_party/fwkacllib/inc/ops/condtake_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/control_flow_ops.h b/third_party/fwkacllib/inc/ops/control_flow_ops.h index 53a213f7..cd993599 100644 --- a/third_party/fwkacllib/inc/ops/control_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/control_flow_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h b/third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h index 79a64c2c..f52c90b0 100644 --- a/third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h +++ b/third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/correlation.h b/third_party/fwkacllib/inc/ops/correlation.h index c7262cbb..caebba50 100644 --- a/third_party/fwkacllib/inc/ops/correlation.h +++ b/third_party/fwkacllib/inc/ops/correlation.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/third_party/fwkacllib/inc/ops/ctc_ops.h b/third_party/fwkacllib/inc/ops/ctc_ops.h index 7729432e..6e908091 100644 --- a/third_party/fwkacllib/inc/ops/ctc_ops.h +++ b/third_party/fwkacllib/inc/ops/ctc_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/data_flow_ops.h b/third_party/fwkacllib/inc/ops/data_flow_ops.h index 2bbbdd0e..32454d27 100644 --- a/third_party/fwkacllib/inc/ops/data_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/data_flow_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index 2246e66a..bcf50058 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. @@ -137,10 +137,10 @@ REG_OP(MinimumGrad) REG_OP(Cast) .INPUT(x, TensorType({DT_BOOL, DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT32, DT_UINT8, DT_INT64, DT_UINT64, DT_INT16, DT_UINT16, DT_DOUBLE, DT_COMPLEX64, - DT_COMPLEX128, DT_QINT8, DT_QUINT8, DT_QINT16, DT_QUINT16, DT_QINT32})) + DT_COMPLEX128, DT_QINT8, DT_QUINT8, DT_QINT16, DT_QUINT16, DT_QINT32, DT_BF16})) .OUTPUT(y, TensorType({DT_BOOL, DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT32, DT_UINT8, DT_INT64, DT_UINT64, DT_INT16, DT_UINT16, DT_DOUBLE, DT_COMPLEX64, - DT_COMPLEX128, DT_QINT8, DT_QUINT8, DT_QINT16, DT_QUINT16, DT_QINT32})) + DT_COMPLEX128, DT_QINT8, DT_QUINT8, DT_QINT16, DT_QUINT16, DT_QINT32, DT_BF16})) .REQUIRED_ATTR(dst_type, Int) .OP_END_FACTORY_REG(Cast) diff --git a/third_party/fwkacllib/inc/ops/functional_ops.h b/third_party/fwkacllib/inc/ops/functional_ops.h index e1fbe6b3..7cfe39c4 100644 --- a/third_party/fwkacllib/inc/ops/functional_ops.h +++ b/third_party/fwkacllib/inc/ops/functional_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/get_data_ops.h b/third_party/fwkacllib/inc/ops/get_data_ops.h index 33dc4f14..e5518ef8 100644 --- a/third_party/fwkacllib/inc/ops/get_data_ops.h +++ b/third_party/fwkacllib/inc/ops/get_data_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/globalavgpool.h b/third_party/fwkacllib/inc/ops/globalavgpool.h deleted file mode 100644 index b0fff691..00000000 --- a/third_party/fwkacllib/inc/ops/globalavgpool.h +++ /dev/null @@ -1,49 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -/*! - * \file globalavgpool.h - * \brief - */ -#ifndef OPS_BUILT_IN_OP_PROTO_INC_GLOBALAVERAGEPOOL_H_ -#define OPS_BUILT_IN_OP_PROTO_INC_GLOBALAVERAGEPOOL_H_ - -#include "graph/operator_reg.h" - -namespace ge { -/** -*@brief GlobalAveragePool consumes an input tensor X and applies average pooling across the values in the same channel. -This is equivalent to AveragePool with kernel size equal to the spatial dimension of input tensor \n - -*@par Inputs: -*@li x: Input data tensor from the previous operator; dimensions for image case are (N x C x H x W), -where N is the batch size, C is the number of channels, and H and W are the height and the width of the data. -For non image case, the dimensions are in the form of (N x C x D1 x D2 ... Dn), where N is the batch size. - -*@par Outputs: -*y: Output data tensor from pooling across the input tensor. The output tensor has the same rank as the input. -The first two dimensions of output shape are the same as the input (N x C), while the other dimensions are all 1 - -*@par Restrictions: -*Warning: This operator can be integrated only by configuring INSERT_OP_FILE of aclgrphBuildModel. Please do not use it directly. -*/ -REG_OP(GlobalAveragePool) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) - .OP_END_FACTORY_REG(GlobalAveragePool) -} // namespace ge - -#endif // OPS_BUILT_IN_OP_PROTO_INC_GLOBALAVGPOOL_H_ \ No newline at end of file diff --git a/third_party/fwkacllib/inc/ops/hcom_ops.h b/third_party/fwkacllib/inc/ops/hcom_ops.h index 6db276a9..497f6a68 100644 --- a/third_party/fwkacllib/inc/ops/hcom_ops.h +++ b/third_party/fwkacllib/inc/ops/hcom_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/third_party/fwkacllib/inc/ops/hvd_ops.h b/third_party/fwkacllib/inc/ops/hvd_ops.h index a49ec5ed..00299ef7 100644 --- a/third_party/fwkacllib/inc/ops/hvd_ops.h +++ b/third_party/fwkacllib/inc/ops/hvd_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/third_party/fwkacllib/inc/ops/image_ops.h b/third_party/fwkacllib/inc/ops/image_ops.h index 85102c34..2327e76e 100644 --- a/third_party/fwkacllib/inc/ops/image_ops.h +++ b/third_party/fwkacllib/inc/ops/image_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/index_to_addr_ops.h b/third_party/fwkacllib/inc/ops/index_to_addr_ops.h index c6bbaaa8..3af17a45 100644 --- a/third_party/fwkacllib/inc/ops/index_to_addr_ops.h +++ b/third_party/fwkacllib/inc/ops/index_to_addr_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/internal_ops.h b/third_party/fwkacllib/inc/ops/internal_ops.h index 9dde14a5..bcc3f1c3 100644 --- a/third_party/fwkacllib/inc/ops/internal_ops.h +++ b/third_party/fwkacllib/inc/ops/internal_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/linalg_ops.h b/third_party/fwkacllib/inc/ops/linalg_ops.h index 4975e8c4..f6cc8694 100644 --- a/third_party/fwkacllib/inc/ops/linalg_ops.h +++ b/third_party/fwkacllib/inc/ops/linalg_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/list_ops.h b/third_party/fwkacllib/inc/ops/list_ops.h index 53024878..0aa94e73 100644 --- a/third_party/fwkacllib/inc/ops/list_ops.h +++ b/third_party/fwkacllib/inc/ops/list_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/logging_ops.h b/third_party/fwkacllib/inc/ops/logging_ops.h index a20370fd..dd565657 100644 --- a/third_party/fwkacllib/inc/ops/logging_ops.h +++ b/third_party/fwkacllib/inc/ops/logging_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/lookup_ops.h b/third_party/fwkacllib/inc/ops/lookup_ops.h index 3fdc01fe..b1fc254f 100644 --- a/third_party/fwkacllib/inc/ops/lookup_ops.h +++ b/third_party/fwkacllib/inc/ops/lookup_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/math_ops.h b/third_party/fwkacllib/inc/ops/math_ops.h index 0631b4d1..6eb418d8 100644 --- a/third_party/fwkacllib/inc/ops/math_ops.h +++ b/third_party/fwkacllib/inc/ops/math_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index be6d9f38..e82251bb 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h index 8bcbad14..9629976e 100644 --- a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h index 452e945e..ed7cb9b5 100644 --- a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/nn_detect_ops.h b/third_party/fwkacllib/inc/ops/nn_detect_ops.h index 98e18234..0011c72e 100644 --- a/third_party/fwkacllib/inc/ops/nn_detect_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_detect_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index d66c8948..9ce7abfd 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/nn_ops.h b/third_party/fwkacllib/inc/ops/nn_ops.h index a08b610b..5b1a4dd0 100644 --- a/third_party/fwkacllib/inc/ops/nn_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h index a0a1abdc..ee599a76 100644 --- a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -1810,7 +1810,28 @@ REG_OP(GlobalLpPool) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(p, Float, 2.0) - .OP_END_FACTORY_REG(GlobalLpPool); + .OP_END_FACTORY_REG(GlobalLpPool) + +/** +*@brief GlobalAveragePool consumes an input tensor X and applies average pooling across the values in the same channel. +This is equivalent to AveragePool with kernel size equal to the spatial dimension of input tensor \n + +*@par Inputs: +*@li x: Input data tensor from the previous operator; dimensions for image case are (N x C x H x W), +where N is the batch size, C is the number of channels, and H and W are the height and the width of the data. +For non image case, the dimensions are in the form of (N x C x D1 x D2 ... Dn), where N is the batch size. + +*@par Outputs: +*y: Output data tensor from pooling across the input tensor. The output tensor has the same rank as the input. +The first two dimensions of output shape are the same as the input (N x C), while the other dimensions are all 1 + +*@par Restrictions: +*Warning: This operator can be integrated only by configuring INSERT_OP_FILE of aclgrphBuildModel. Please do not use it directly. +*/ +REG_OP(GlobalAveragePool) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OP_END_FACTORY_REG(GlobalAveragePool); } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_POOLING_OPS_H diff --git a/third_party/fwkacllib/inc/ops/nn_training_ops.h b/third_party/fwkacllib/inc/ops/nn_training_ops.h index 5b49e947..9dd502cd 100644 --- a/third_party/fwkacllib/inc/ops/nn_training_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_training_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/third_party/fwkacllib/inc/ops/no_op.h b/third_party/fwkacllib/inc/ops/no_op.h index 7834591c..b27b1fa0 100644 --- a/third_party/fwkacllib/inc/ops/no_op.h +++ b/third_party/fwkacllib/inc/ops/no_op.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h index d46f9c8f..067357de 100644 --- a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h +++ b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. @@ -41,6 +41,45 @@ REG_OP(Gelu) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(Gelu) +/** +* @brief Compute hard_swish of "x" element-wise . \n + +*@par Inputs: +*One input, including: +*x: A Tensor. Must be one of the following types: float16, float32 + +*@par Outputs: +*y: A Tensor. Has the same type as "x". +*@par Third-party framework compatibility +* Compatible with the Torch operator HardSwish. +*/ +REG_OP(HardSwish) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(HardSwish) + +/** +*@brief Computes the for the Swish of "x" . \n + +*@par Inputs: +*One input, including: +*x: A Tensor. Must be one of the following types: float16, float32 + +*@par Outputs: +*y: A Tensor. Has the same type as "x". + +*@par Attributes: +*scale: scalar parameter, default value = 1.0 + +*@par Third-party framework compatibility +*Compatible with the Torch operator Swish +*/ +REG_OP(Swish) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(scale, Float, 1.0) + .OP_END_FACTORY_REG(Swish) + /** *@brief Computes the gradient for the gelu of "x" . \n @@ -98,23 +137,6 @@ REG_OP(FastGeluGrad) .OUTPUT(z, TensorType({DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(FastGeluGrad) -/** -* @brief Compute hardswish of "x" element-wise . \n - -*@par Inputs: -*One input, including: -*x: A Tensor. Must be one of the following types: float16, float32 - -*@par Outputs: -*y: A Tensor. Has the same type as "x". -*@par Third-party framework compatibility -* Compatible with the Torch operator Hardswish. -*/ -REG_OP(Hardswish) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) - .OP_END_FACTORY_REG(Hardswish) - /** *@brief Computes the gradient for the tanh of "x" . \n diff --git a/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h b/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h index 8d7ef9f9..f36d2935 100644 --- a/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h +++ b/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/outfeed_ops.h b/third_party/fwkacllib/inc/ops/outfeed_ops.h index e0b783bc..53b9d701 100644 --- a/third_party/fwkacllib/inc/ops/outfeed_ops.h +++ b/third_party/fwkacllib/inc/ops/outfeed_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/pad_ops.h b/third_party/fwkacllib/inc/ops/pad_ops.h index 7780de05..9d0e7a62 100644 --- a/third_party/fwkacllib/inc/ops/pad_ops.h +++ b/third_party/fwkacllib/inc/ops/pad_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/third_party/fwkacllib/inc/ops/parsing_ops.h b/third_party/fwkacllib/inc/ops/parsing_ops.h index 03024f96..e578997c 100644 --- a/third_party/fwkacllib/inc/ops/parsing_ops.h +++ b/third_party/fwkacllib/inc/ops/parsing_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/quantize_ops.h b/third_party/fwkacllib/inc/ops/quantize_ops.h index 2a284780..0ed46e80 100644 --- a/third_party/fwkacllib/inc/ops/quantize_ops.h +++ b/third_party/fwkacllib/inc/ops/quantize_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/ragged_array_ops.h b/third_party/fwkacllib/inc/ops/ragged_array_ops.h index 9d116760..5af2dd74 100644 --- a/third_party/fwkacllib/inc/ops/ragged_array_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_array_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h b/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h index 2e253ed4..ceaa64e4 100644 --- a/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/ragged_math_ops.h b/third_party/fwkacllib/inc/ops/ragged_math_ops.h index b2caa0be..4376437f 100644 --- a/third_party/fwkacllib/inc/ops/ragged_math_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_math_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/random_ops.h b/third_party/fwkacllib/inc/ops/random_ops.h index 830e775a..66f9b65f 100644 --- a/third_party/fwkacllib/inc/ops/random_ops.h +++ b/third_party/fwkacllib/inc/ops/random_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/reduce_ops.h b/third_party/fwkacllib/inc/ops/reduce_ops.h index c827bec9..1578ba59 100644 --- a/third_party/fwkacllib/inc/ops/reduce_ops.h +++ b/third_party/fwkacllib/inc/ops/reduce_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/third_party/fwkacllib/inc/ops/resource_variable_ops.h b/third_party/fwkacllib/inc/ops/resource_variable_ops.h index a5d7f9c3..156f2f34 100644 --- a/third_party/fwkacllib/inc/ops/resource_variable_ops.h +++ b/third_party/fwkacllib/inc/ops/resource_variable_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/rnn.h b/third_party/fwkacllib/inc/ops/rnn.h index 6813ad78..cc0bff00 100644 --- a/third_party/fwkacllib/inc/ops/rnn.h +++ b/third_party/fwkacllib/inc/ops/rnn.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/rpn_ops.h b/third_party/fwkacllib/inc/ops/rpn_ops.h index 90707602..850b3e5a 100644 --- a/third_party/fwkacllib/inc/ops/rpn_ops.h +++ b/third_party/fwkacllib/inc/ops/rpn_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/save_ops.h b/third_party/fwkacllib/inc/ops/save_ops.h index 0ce473b7..5ce6c2e0 100644 --- a/third_party/fwkacllib/inc/ops/save_ops.h +++ b/third_party/fwkacllib/inc/ops/save_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/sdca_ops.h b/third_party/fwkacllib/inc/ops/sdca_ops.h index e8f3e6b6..601b360b 100644 --- a/third_party/fwkacllib/inc/ops/sdca_ops.h +++ b/third_party/fwkacllib/inc/ops/sdca_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/selection_ops.h b/third_party/fwkacllib/inc/ops/selection_ops.h index ac404e8f..7f7c4fc8 100644 --- a/third_party/fwkacllib/inc/ops/selection_ops.h +++ b/third_party/fwkacllib/inc/ops/selection_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -178,7 +178,7 @@ REG_OP(GatherNd) .OP_END_FACTORY_REG(GatherNd) /** -*@brief Gather slices from "x" according to "indices" by corresponding axis . \n +*@brief Gather slices from "x" according to "indices" by corresponding axis . *@par Inputs: *Three inputs, including: @@ -187,16 +187,19 @@ REG_OP(GatherNd) * uint16, complex128, float16, uint32, uint64, complex64, complex128. * @li indices: A Tensor of type int32 or int64. * @li axis: A Tensor of type as int32 or int64, -* Must be in the range [-rank(input_tensor), rank(input_tensor)) . \n +* Must be in the range [-rank(input_tensor), rank(input_tensor)) . + +*@par Attributes: +* batch_dims: An optional int. Defaults to 0. *@par Outputs: -*y: A Tensor. Has the same type as "x" . \n +*y: A Tensor. Has the same type as "x" . *@attention Constraints: *Value in indices must be in range [0, x.shape[axis]) *@par Third-party framework compatibility -* Compatible with the TensorFlow operator GatherV2 . \n +* Compatible with the TensorFlow operator GatherV2 . */ REG_OP(GatherV2) @@ -204,6 +207,7 @@ REG_OP(GatherV2) .INPUT(indices, TensorType::IndexNumberType()) .INPUT(axis, TensorType::IndexNumberType()) .OUTPUT(y, TensorType::BasicType()) + .ATTR(batch_dims, Int, 0) .OP_END_FACTORY_REG(GatherV2) /** @@ -1216,19 +1220,20 @@ REG_OP(StridedSliceAssignD) * @li x: A Tensor. Must be one of the following types: float32, float64, int32, uint8, int16, int8, * int64, qint8, quint8, qint32, qint16, quint16, uint16, * float16, uint32, uint64, complex64, complex128. -* @li indices: A Tensor of type int32 or int64 . \n +* @li indices: A Tensor of type int32 or int64 . *@par Attributes: -*validate_indices: A bool specifying whether to verify the argument of "indice" . \n +* @li validate_indices: A bool specifying whether to verify the argument of "indice" . +* @li batch_dims: An optional int. Defaults to 0. *@par Outputs: -*y: A Tensor. Has the same type as "x" . \n +*y: A Tensor. Has the same type as "x" . *@attention Constraints: -* "indices" is in the range [0, x.shape[0]) . \n +* "indices" is in the range [0, x.shape[0]) . *@par Third-party framework compatibility -* Compatible with the TensorFlow operator Gather . \n +* Compatible with the TensorFlow operator Gather . */ REG_OP(Gather) @@ -1236,6 +1241,7 @@ REG_OP(Gather) .INPUT(indices, TensorType::IndexNumberType()) .OUTPUT(y, TensorType::BasicType()) .ATTR(validate_indices, Bool, true) + .ATTR(batch_dims, Int, 0) .OP_END_FACTORY_REG(Gather) /** diff --git a/third_party/fwkacllib/inc/ops/set_ops.h b/third_party/fwkacllib/inc/ops/set_ops.h index 1d02fa15..04e04f1b 100644 --- a/third_party/fwkacllib/inc/ops/set_ops.h +++ b/third_party/fwkacllib/inc/ops/set_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/slice_write_ops.h b/third_party/fwkacllib/inc/ops/slice_write_ops.h index 994f197c..0c161b2d 100644 --- a/third_party/fwkacllib/inc/ops/slice_write_ops.h +++ b/third_party/fwkacllib/inc/ops/slice_write_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/sparse_ops.h b/third_party/fwkacllib/inc/ops/sparse_ops.h index d9fb4d0a..8eb7b521 100644 --- a/third_party/fwkacllib/inc/ops/sparse_ops.h +++ b/third_party/fwkacllib/inc/ops/sparse_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/spectral_ops.h b/third_party/fwkacllib/inc/ops/spectral_ops.h index d17cbfdd..ab9e1dec 100644 --- a/third_party/fwkacllib/inc/ops/spectral_ops.h +++ b/third_party/fwkacllib/inc/ops/spectral_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/split_combination_ops.h b/third_party/fwkacllib/inc/ops/split_combination_ops.h index 05e38589..98d4d111 100644 --- a/third_party/fwkacllib/inc/ops/split_combination_ops.h +++ b/third_party/fwkacllib/inc/ops/split_combination_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/state_ops.h b/third_party/fwkacllib/inc/ops/state_ops.h index 49029317..d1ec00b5 100644 --- a/third_party/fwkacllib/inc/ops/state_ops.h +++ b/third_party/fwkacllib/inc/ops/state_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/stateful_random_ops.h b/third_party/fwkacllib/inc/ops/stateful_random_ops.h index a3d18922..f4eb763c 100644 --- a/third_party/fwkacllib/inc/ops/stateful_random_ops.h +++ b/third_party/fwkacllib/inc/ops/stateful_random_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/stateless_random_ops.h b/third_party/fwkacllib/inc/ops/stateless_random_ops.h index dad3c379..ff9daaa3 100644 --- a/third_party/fwkacllib/inc/ops/stateless_random_ops.h +++ b/third_party/fwkacllib/inc/ops/stateless_random_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/string_ops.h b/third_party/fwkacllib/inc/ops/string_ops.h index a2699315..a78d63a1 100644 --- a/third_party/fwkacllib/inc/ops/string_ops.h +++ b/third_party/fwkacllib/inc/ops/string_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/swap_co_ops.h b/third_party/fwkacllib/inc/ops/swap_co_ops.h index a1bf4f8b..6e8eaac3 100644 --- a/third_party/fwkacllib/inc/ops/swap_co_ops.h +++ b/third_party/fwkacllib/inc/ops/swap_co_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/target_crop_and_resize.h b/third_party/fwkacllib/inc/ops/target_crop_and_resize.h index 9c61f2c9..9bef1d7b 100644 --- a/third_party/fwkacllib/inc/ops/target_crop_and_resize.h +++ b/third_party/fwkacllib/inc/ops/target_crop_and_resize.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/transformation_ops.h b/third_party/fwkacllib/inc/ops/transformation_ops.h index 2151a867..3560db11 100644 --- a/third_party/fwkacllib/inc/ops/transformation_ops.h +++ b/third_party/fwkacllib/inc/ops/transformation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/vector_search.h b/third_party/fwkacllib/inc/ops/vector_search.h new file mode 100644 index 00000000..e3099511 --- /dev/null +++ b/third_party/fwkacllib/inc/ops/vector_search.h @@ -0,0 +1,48 @@ +/** + * Copyright 2021 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. + */ + +/*! + * \file vector_search.h + * \brief + */ +#ifndef OPS_BUILT_IN_OP_PROTO_INC_VECTOR_SEARCH_H_ +#define OPS_BUILT_IN_OP_PROTO_INC_VECTOR_SEARCH_H_ +#include "graph/operator_reg.h" + +namespace ge { +/** +* @brief Generate ADC(asymmetric distance computation) table. \n +* +* @par Inputs: +* Four inputs, including: +* @li query: A Tensor. Must be one of the following types: float16, float32. +* @li code_book: A Tensor. Must be one of the following types: float16, float32. +* @li centroids: A Tensor. Must be one of the following types: float16, float32. +* @li bucket_list: A Tensor. Must be one of the following types: int32, int64. +* +* @par Outputs: +* @li adc_tables: A Tensor. Must be one of the following types: float16, float32. +*/ +REG_OP(GenADC) + .INPUT(query, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(code_book, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(centroids, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(bucket_list, TensorType({DT_INT32, DT_INT64})) + .OUTPUT(adc_tables, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(GenADC) +} // namespace ge + +#endif // OPS_BUILT_IN_OP_PROTO_INC_VECTOR_SEARCH_H_ diff --git a/third_party/fwkacllib/inc/ops/warp_perspective_ops.h b/third_party/fwkacllib/inc/ops/warp_perspective_ops.h index e19cbd7c..8ef69d8b 100644 --- a/third_party/fwkacllib/inc/ops/warp_perspective_ops.h +++ b/third_party/fwkacllib/inc/ops/warp_perspective_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/runtime/base.h b/third_party/fwkacllib/inc/runtime/base.h index 40c7495d..fc2cd038 100644 --- a/third_party/fwkacllib/inc/runtime/base.h +++ b/third_party/fwkacllib/inc/runtime/base.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_BASE_H__ #define __CCE_RUNTIME_BASE_H__ @@ -36,6 +36,16 @@ extern "C" { typedef int32_t rtError_t; static const int32_t RT_ERROR_NONE = 0; // success +/** + * @ingroup dvrt_base + * @brief device mode. + */ +typedef enum tagRtDeviceMode { + RT_DEVICE_MODE_SINGLE_DIE = 0, + RT_DEVICE_MODE_MULTI_DIE = 1, + RT_DEVICE_MODE_RESERVED +} rtDeviceMode; + /** * @ingroup dvrt_base * @brief runtime exception numbers. @@ -170,18 +180,6 @@ RTS_API rtError_t rtProfilerInit(const char *profDir, const char *address, const */ RTS_API rtError_t rtProfilerConfig(uint16_t type); -/** - * @ingroup profiling_base - * @brief start rts profiler. - */ -RTS_API rtError_t rtProfilerStart(uint64_t profConfig, int32_t numsDev, uint32_t *deviceList); - -/** - * @ingroup profiling_base - * @brief stop rts profiler. - */ -RTS_API rtError_t rtProfilerStop(uint64_t profConfig, int32_t numsDev, uint32_t *deviceList); - /** * @ingroup profiling_base * @brief ts send keypoint profiler log. diff --git a/third_party/fwkacllib/inc/runtime/config.h b/third_party/fwkacllib/inc/runtime/config.h index f38be74d..76836e7b 100644 --- a/third_party/fwkacllib/inc/runtime/config.h +++ b/third_party/fwkacllib/inc/runtime/config.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_CONFIG_H__ #define __CCE_RUNTIME_CONFIG_H__ diff --git a/third_party/fwkacllib/inc/runtime/context.h b/third_party/fwkacllib/inc/runtime/context.h index 66b9b570..bb6bf111 100644 --- a/third_party/fwkacllib/inc/runtime/context.h +++ b/third_party/fwkacllib/inc/runtime/context.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_CONTEXT_H__ #define __CCE_RUNTIME_CONTEXT_H__ @@ -60,6 +60,17 @@ typedef struct tagRtGroupInfo { */ RTS_API rtError_t rtCtxCreate(rtContext_t *ctx, uint32_t flags, int32_t device); +/** + * @ingroup rt_context + * @brief create context and associates it with the calling thread + * @param [out] ctx created context + * @param [in] flags context creation flag. set to 0. + * @param [in] device device to create context on + * @param [in] deviceMode the device mode + * @return RT_ERROR_NONE for ok + */ +RTS_API rtError_t rtCtxCreateV2(rtContext_t *ctx, uint32_t flags, int32_t device, rtDeviceMode deviceMode); + /** * @ingroup rt_context * @brief create context and associates it with the calling thread diff --git a/third_party/fwkacllib/inc/runtime/dev.h b/third_party/fwkacllib/inc/runtime/dev.h index 3499fd4c..3d3da22e 100644 --- a/third_party/fwkacllib/inc/runtime/dev.h +++ b/third_party/fwkacllib/inc/runtime/dev.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_DEVICE_H__ #define __CCE_RUNTIME_DEVICE_H__ @@ -150,6 +150,34 @@ RTS_API rtError_t rtGetDeviceInfo(uint32_t deviceId, int32_t moduleType, int32_t */ RTS_API rtError_t rtSetDevice(int32_t device); +/** + * @ingroup dvrt_dev + * @brief set target device for current thread + * @param [int] device the device id + * @param [int] deviceMode the device mode + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtSetDeviceV2(int32_t device, rtDeviceMode deviceMode); + +/** + * @ingroup dvrt_dev + * @brief set target die for current thread + * @param [int] die the die id + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtSetDie(int32_t die); + +/** + * @ingroup dvrt_dev + * @brief get target die of current thread + * @param [in|out] die the die id + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtGetDie(int32_t *die); + /** * @ingroup dvrt_dev * @brief set target device for current thread diff --git a/third_party/fwkacllib/inc/runtime/dvfsprofile.h b/third_party/fwkacllib/inc/runtime/dvfsprofile.h index 06f5e3c4..33e2f4c1 100644 --- a/third_party/fwkacllib/inc/runtime/dvfsprofile.h +++ b/third_party/fwkacllib/inc/runtime/dvfsprofile.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_DVFSPROFILE_H__ #define __CCE_RUNTIME_DVFSPROFILE_H__ diff --git a/third_party/fwkacllib/inc/runtime/event.h b/third_party/fwkacllib/inc/runtime/event.h index c73274da..81b635c3 100644 --- a/third_party/fwkacllib/inc/runtime/event.h +++ b/third_party/fwkacllib/inc/runtime/event.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_EVENT_H__ #define __CCE_RUNTIME_EVENT_H__ diff --git a/third_party/fwkacllib/inc/runtime/kernel.h b/third_party/fwkacllib/inc/runtime/kernel.h index 4d5fc5c9..f33b51d3 100644 --- a/third_party/fwkacllib/inc/runtime/kernel.h +++ b/third_party/fwkacllib/inc/runtime/kernel.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_KERNEL_H__ #define __CCE_RUNTIME_KERNEL_H__ diff --git a/third_party/fwkacllib/inc/runtime/mem.h b/third_party/fwkacllib/inc/runtime/mem.h index 0afdeec5..b049e762 100644 --- a/third_party/fwkacllib/inc/runtime/mem.h +++ b/third_party/fwkacllib/inc/runtime/mem.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_MEM_H__ #define __CCE_RUNTIME_MEM_H__ diff --git a/third_party/fwkacllib/inc/runtime/rt.h b/third_party/fwkacllib/inc/runtime/rt.h index e4c3a9bb..6c2f5318 100644 --- a/third_party/fwkacllib/inc/runtime/rt.h +++ b/third_party/fwkacllib/inc/runtime/rt.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_RT_H__ #define __CCE_RUNTIME_RT_H__ @@ -29,5 +29,7 @@ #include "stream.h" #include "rt_stars.h" #include "rt_ffts.h" +#include "rt_ffts_plus.h" +#include "rt_dfx.h" #endif // __CCE_RUNTIME_RT_H__ diff --git a/third_party/fwkacllib/inc/runtime/rt_dfx.h b/third_party/fwkacllib/inc/runtime/rt_dfx.h new file mode 100644 index 00000000..d5927575 --- /dev/null +++ b/third_party/fwkacllib/inc/runtime/rt_dfx.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + * Description: dfx interface + */ + +#ifndef CCE_RUNTIME_RT_DFX_H +#define CCE_RUNTIME_RT_DFX_H + +#include "base.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +// max task tag buffer is 1024(include '\0') +#define TASK_TAG_MAX_LEN 1024U + +/** + * @brief set task tag. + * once set is only use by one task and thread local. + * attention: + * 1. it's used for dump current task in active stream now. + * 2. it must be called be for task submit and will be invalid after task submit. + * @param [in] taskTag task tag, usually it's can be node name or task name. + * must end with '\0' and max len is TASK_TAG_MAX_LEN. + * @return RT_ERROR_NONE for ok + * @return other failed + */ +RTS_API rtError_t rtSetTaskTag(const char *taskTag); + +#if defined(__cplusplus) +} +#endif +#endif // CCE_RUNTIME_RT_DFX_H diff --git a/third_party/fwkacllib/inc/runtime/rt_ffts.h b/third_party/fwkacllib/inc/runtime/rt_ffts.h index 5a17b042..f2809218 100644 --- a/third_party/fwkacllib/inc/runtime/rt_ffts.h +++ b/third_party/fwkacllib/inc/runtime/rt_ffts.h @@ -1,17 +1,6 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + * Description: ffts interface */ #ifndef __CCE_RUNTIME_FFTS_H diff --git a/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h b/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h new file mode 100644 index 00000000..61eee9f3 --- /dev/null +++ b/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + * Description: ffts plus interface + */ + +#ifndef __CCE_RUNTIME_FFTS_PLUS_H +#define __CCE_RUNTIME_FFTS_PLUS_H + +#include "base.h" +#include "rt_ffts_plus_define.h" +#include "rt_stars_define.h" + +#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +extern "C" { +#endif + +#pragma pack(push) +#pragma pack (1) + +typedef struct tagFftsPlusTaskInfo { + const rtFftsPlusSqe_t *fftsPlusSqe; + const void *descBuf; // include total context + size_t descBufLen; // the length of descBuf +} rtFftsPlusTaskInfo_t; + +#pragma pack(pop) + +RTS_API rtError_t rtGetAddrAndPrefCntWithHandle(void *handle, const void *devFunc, void **addr, uint32_t *prefetchCnt); +RTS_API rtError_t rtFftsPlusTaskLaunch(rtFftsPlusTaskInfo_t *fftsPlusTaskInfo, rtStream_t stream); + +#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +} +#endif +#endif // __CCE_RUNTIME_FFTS_H diff --git a/third_party/fwkacllib/inc/runtime/rt_ffts_plus_define.h b/third_party/fwkacllib/inc/runtime/rt_ffts_plus_define.h new file mode 100644 index 00000000..9887b943 --- /dev/null +++ b/third_party/fwkacllib/inc/runtime/rt_ffts_plus_define.h @@ -0,0 +1,715 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + * Description: the definition of ffts plus + */ + +#ifndef __CCE_RUNTIME_FFTS_PLUS_DEFINE_H +#define __CCE_RUNTIME_FFTS_PLUS_DEFINE_H + +#include "base.h" + +#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +extern "C" { +#endif + +#pragma pack(push) +#pragma pack (1) + +// hardware context type +typedef enum tagFftsPlusHwType { + RT_HW_CTX_TYPE_AIC = 0, + RT_HW_CTX_TYPE_AIV = 1, + RT_HW_CTX_TYPE_NOTIFY_WAIT = 3, + RT_HW_CTX_TYPE_NOTIFY_RECORD = 4, + RT_HW_CTX_TYPE_WRITE_VALUE = 5, + RT_HW_CTX_TYPE_MIX_AIC = 6, + RT_HW_CTX_TYPE_MIX_AIV = 7, + RT_HW_CTX_TYPE_SDMA = 8, + RT_HW_CTX_TYPE_FLUSH_DATA = 9, + RT_HW_CTX_TYPE_INVALIDATE_DATA = 10, + RT_HW_CTX_TYPE_WRITEBACK_DATA = 11, + RT_HW_CTX_TYPE_AICPU = 12, + RT_HW_CTX_TYPE_LOAD = 13, + RT_HW_CTX_TYPE_MAX, +} rtFftsPlusHwType_t; + +// hardware context type +typedef enum tagFftsPlusSoftType { + RT_SOFT_CTX_TYPE_COND_SWITCH = 1, + RT_SOFT_CTX_TYPE_CASE_SWITCH = 2, + RT_SOFT_CTX_TYPE_AT_START = 3, + RT_SOFT_CTX_TYPE_AT_END = 4, + RT_SOFT_CTX_TYPE_LABEL = 5, + RT_SOFT_CTX_TYPE_MAX, +} rtFftsPlusSoftType_t; + +typedef enum tagFftsPlusContextType { + RT_CTX_TYPE_AICORE = 0x0000, + RT_CTX_TYPE_AIV = 0x0001, + RT_CTX_TYPE_NOTIFY_WAIT = 0x0003, + RT_CTX_TYPE_NOTIFY_RECORD = 0x0004, + RT_CTX_TYPE_WRITE_VALUE = 0x0005, + RT_CTX_TYPE_MIX_AIC = 0x0006, + RT_CTX_TYPE_MIX_AIV = 0x0007, + RT_CTX_TYPE_SDMA = 0x0008, + RT_CTX_TYPE_FLUSH_DATA = 0x0009, + RT_CTX_TYPE_INVALIDATE_DATA = 0x000A, + RT_CTX_TYPE_WRITEBACK_DATA = 0x000B, + RT_CTX_TYPE_AICPU = 0x000C, + RT_CTX_TYPE_COND_SWITCH = 0x010D, + RT_CTX_TYPE_CASE_SWITCH = 0x020D, + RT_CTX_TYPE_AT_START = 0x0300, + RT_CTX_TYPE_AT_END = 0x0400, + RT_CTX_TYPE_LABEL = 0x0500, +}rtFftsPlusContextType_t; + +// condition type +typedef enum tagFftsPlusCondType { + RT_COND_TYPE_EQUAL = 0, + RT_COND_TYPE_NOTEQUAL = 1, + RT_COND_TYPE_GREATER = 2, + RT_COND_TYPE_GREATER_OR_EQUAL = 3, + RT_COND_TYPE_LESS = 4, + RT_COND_TYPE_LESS_OR_EQUAL = 5, + RT_COND_TYPE_MAX, +} rtFftsPlusCondType_t; + +// the definition of ffts plus context + +#define RT_CTX_SUCCESSOR_NUM 26 + +// ffts plus common context +typedef struct tagFftsPlusComCtx { + // 0-3 bytes + uint16_t contextType; + uint8_t successorNum; + uint8_t rsv1 : 7; + uint8_t aten : 1; + // 4-7 + uint8_t rsv2; + uint8_t rsv3; + uint8_t predCntInit; + uint8_t predCnt; + // 8-11 + uint32_t rsv4; + // 12-63 + uint16_t successorList[RT_CTX_SUCCESSOR_NUM]; + // 64-71 + uint32_t rsv5[2]; + // 72-75 + uint16_t threadId; + uint16_t threadDim; + // 76-127 + uint32_t res6[13]; +} rtFftsPlusComCtx_t; + +// aic/aiv context +typedef struct tagFftsPlusAicAivCtx { + // 0-3 bytes + uint16_t contextType; + uint8_t successorNum; + uint8_t resv : 7; + uint8_t aten : 1; + // 4-7 + uint8_t prefetchConfig; + uint8_t resv1; + uint8_t predCntInit; + uint8_t predCnt; + // 8-11 + uint32_t resv2; + // 12-63 + uint16_t successorList[RT_CTX_SUCCESSOR_NUM]; + // 64-67 + uint16_t resv3 : 1; + uint16_t schem : 2; + uint16_t icachePrefetchCnt : 5; + uint16_t resv4 : 7; + uint16_t atm : 1; + uint16_t prefetchEnableBitmap : 4; + uint16_t res6 : 4; + uint16_t prefetchOnceBitmap : 4; + uint16_t res7 : 4; + // 68-71 + uint16_t pmg : 2; + uint16_t ns : 1; + uint16_t partId : 8; + uint16_t res8 : 1; + uint16_t qos : 4; + uint16_t res9; + // 72-75 + uint16_t threadId; + uint16_t threadDim; + // 76-79 + uint16_t nonTailBlockdim; + uint16_t tailBlockdim; + // 80-83 + uint32_t taskParamPtrBaseL; + // 84-87 + uint16_t taskParamPtrBaseH; + uint16_t taskParamPtrOffset; + // 88-95 + uint32_t res10; + uint32_t res11; + // 96-103 + uint32_t nonTailTaskStartPcL; + uint16_t nonTailTaskStartPcH; + uint16_t res12; + // 104-111 + uint32_t tailTaskStartPcL; + uint16_t tailTaskStartPcH; + uint16_t res13; + // 112-119 + uint32_t res14; + uint32_t res15; + // 120-127 + uint16_t srcSlot[4]; // src_slot0-3(context ID for source data which is out of subgraph) +} rtFftsPlusAicAivCtx_t; + +// mix aic/aiv context +typedef struct tagFftsPlusMixAicAivCtx { + // 0-3 bytes + uint16_t contextType; + uint8_t successorNum; + uint8_t reserved1 : 7; + uint8_t aten : 1; + // 4-7 + uint8_t prefetchConfig; + uint8_t reserved2; + uint8_t predCntInit; + uint8_t predCnt; + // 8-11 + uint32_t reserved3; + // 12-63 + uint16_t successorList[RT_CTX_SUCCESSOR_NUM]; + // 64-67 + uint16_t reserved4 : 1; + uint16_t schem : 2; + uint16_t aicIcachePrefetchCnt : 5; + uint16_t aivIcachePrefetchCnt : 5; + uint16_t reserved5 : 2; + uint16_t atm : 1; + uint16_t prefetchEnableBitmap : 4; + uint16_t reserved6 : 4; + uint16_t prefetchOnceBitmap : 4; + uint16_t reserved7 : 4; + // 68-71 + uint16_t pmg : 2; + uint16_t ns : 1; + uint16_t partId : 8; + uint16_t reserved8 : 1; + uint16_t qos : 4; + uint8_t nonTailBlockRatioN; + uint8_t tailBlockRatioN; + // 72-75 + uint16_t threadId; + uint16_t threadDim; + // 76-79 + uint16_t nonTailBlockdim; + uint16_t tailBlockdim; + // 80-87 + uint32_t aicTaskParamPtrL; + uint16_t aicTaskParamPtrH; + uint16_t aicTaskParamPtrOffset; + // 88-95 + uint32_t aivTaskParamPtrL; + uint16_t aivTaskParamPtrH; + uint16_t aivTaskParamPtrOffset; + // 96-103 + uint32_t nonTailAicTaskStartPcL; + uint16_t nonTailAicTaskStartPcH; + uint16_t tailAicTaskStartPcH; + // 104-111 + uint32_t tailAicTaskStartPcL; + uint32_t nonTailAivTaskStartPcL; + // 112-119 + uint16_t nonTailAivTaskStartPcH; + uint16_t tailAivTaskStartPcH; + uint32_t tailAivTaskStartPcL; + // 120-127 + uint16_t srcSlot[4]; // src_slot0-3(context ID for source data which is out of subgraph) +} rtFftsPlusMixAicAivCtx_t; + +// sdma context +typedef struct tagFftsPlusSdmaCtx { + // 0-3 bytes + uint16_t contextType; + uint8_t successorNum; + uint8_t res1 : 7; + uint8_t aten : 1; + // 4-7 + uint8_t res2; + uint8_t res3; + uint8_t predCntInit; + uint8_t predCnt; + // 8-11 + uint32_t res4; + // 12-63 + uint16_t successorList[RT_CTX_SUCCESSOR_NUM]; + // 64-67 + uint8_t res5; + uint8_t res6 : 7; + uint8_t atm : 1; + uint16_t res7; + // 68-71 + uint16_t pmg : 2; + uint16_t ns : 1; + uint16_t partId : 8; + uint16_t res8 : 1; + uint16_t qos : 4; + uint16_t res9; + // 72-75 + uint16_t threadId; + uint16_t threadDim; + // 76-79 + uint32_t sdmaSqeHeader; // (FORMAT/MPAMNS/PARTID/DRO/SRO/QOS/DNS/SNS/DSSV/SSSV/IE/UPCODE) + // 80-83 + uint16_t sourceStreamId; + uint16_t sourceSubstreamId; + // 84-87 + uint16_t destinationStreamId; + uint16_t destinationSubstreamId; + // 88-127 + uint32_t sourceAddressBaseL; + uint32_t sourceAddressBaseH; + uint32_t sourceAddressOffset; + uint32_t destinationAddressBaseL; + uint32_t destinationAddressBaseH; + uint32_t destinationAddressOffset; + uint32_t nonTailDataLength; + uint32_t tailDataLength; + uint32_t res10[2]; +} rtFftsPlusSdmaCtx_t; + +// ffts plus notify record/wait context +typedef struct tagFftsPlusNotifyCtx { + // 0-3 bytes + uint16_t contextType; + uint8_t successorNum; + uint8_t res : 7; + uint8_t aten : 1; + // 4-7 + uint8_t res1; + uint8_t res2; + uint8_t predCntInit; + uint8_t predCnt; + // 8-11 + uint32_t res3; + // 12-63 + uint16_t successorList[RT_CTX_SUCCESSOR_NUM]; + // 64-67 + uint16_t res4 : 14; + uint16_t satm : 1; + uint16_t atm : 1; + uint16_t res6; + // 68-71 + uint32_t res7; + // 72-75 + uint16_t threadId; + uint16_t threadDim; + // 76-79 + uint16_t notifyIdBase; + uint8_t autoWindow; + uint8_t res8; + // 80-127 + uint32_t res9[4]; + uint16_t notifyId[16]; +} rtFftsPlusNotifyCtx_t; + +// write Value context +typedef struct tagFftsPlusWriteValueCtx { + // 0-3 bytes + uint16_t contextType; + uint8_t successorNum; + uint8_t resv1 : 7; + uint8_t aten : 1; + // 4-7 + uint8_t resv2; + uint8_t resv3; + uint8_t predCntInit; + uint8_t predCnt; + // 8-11 + uint32_t resv4; + // 12-63 + uint16_t successorList[RT_CTX_SUCCESSOR_NUM]; + // 64-67 + uint16_t resv5 : 15; + uint16_t atm : 1; + uint16_t resv6; + // 68-71 + uint32_t resv7; + // 72-75 + uint16_t threadId; + uint16_t threadDim; + // 76-79 + uint8_t awSize : 3; + uint8_t awSnoop : 1; + uint8_t resv8 : 4; + uint8_t awCache : 4; + uint8_t awProt : 3; + uint8_t awVa : 1; + + uint8_t arSize : 3; + uint8_t arSnoop : 1; + uint8_t resv9 : 4; + uint8_t arCache : 4; + uint8_t arProt : 3; + uint8_t arVa : 1; + // 80-83 + uint32_t writeAddressBaseL; + // 84-87 + uint32_t writeAddressBaseH: 17; + uint32_t res10: 15; + // 88-91 + uint32_t writeAddressOffset; + // 92-95 + uint32_t res11; + // 96-111 + uint32_t writeValue[4]; // write_value_00 -> write_value_03 + // 112-127 + uint32_t res12[4]; +} rtFftsPlusWriteValueCtx_t; + +// ai cpu context +typedef struct tagFftsPlusAiCpuCtx { + // 0-3 bytes + uint16_t contextType; + uint8_t successorNum; + uint8_t res1 : 7; + uint8_t aten : 1; + // 4-7 + uint8_t res2; + uint8_t res3; + uint8_t predCntInit; + uint8_t predCnt; + // 8-11 + uint32_t res4; + // 12-63 + uint16_t successorContextID[RT_CTX_SUCCESSOR_NUM]; + // 64-67 + uint16_t res5 : 15; + uint16_t atm : 1; + uint16_t res6; + // 68-71 + uint16_t sqeIndex; + uint8_t kernelType : 7; + uint8_t bm : 1; + uint8_t topicType : 4; + uint8_t qos : 3; + uint8_t res7 : 1; + // 72-75 + uint16_t threadId; + uint16_t threadDim; + // 76-79 + uint16_t nonTailBlockdim; + uint16_t tailBlockdim; + // 80-115 + uint32_t usrData[9]; // usr_data0 -> usr_data8 usr_data2(task_param_base_l) usr_data3(task_param_base_h) + // 116--119 + uint32_t res8; + // 120-123 + uint32_t subtopicId : 12; + uint32_t topicId : 6; + uint32_t groupId : 6; + uint32_t usrDataLength : 8; + // 124-127 + uint32_t taskParamOffset; +} rtFftsPlusAiCpuCtx_t; + +// data context +typedef struct tagFftsPlusDataCtx { + // 0-3 bytes + uint16_t contextType; + uint8_t successorNum; + uint8_t res1 : 7; + uint8_t aten : 1; + // 4-7 + uint8_t res2; + uint8_t res3; + uint8_t cntInit; // cons_cnt_init / prod_cnt_init + uint8_t cnt; // cons_cnt / prod_cnt + // 8-11 + uint32_t res4; + // 12-63 + uint16_t successorList[RT_CTX_SUCCESSOR_NUM]; + // 64-67 + uint16_t res5 : 15; + uint16_t atm : 1; + uint16_t res6; + // 68-71 + uint16_t pmg : 2; + uint16_t ns : 1; + uint16_t partId : 8; + uint16_t res7 : 1; + uint16_t qos : 4; + uint16_t res8; + // 72-75 + uint16_t threadId; + uint16_t threadDim; + // 76-79 + uint16_t origConsumerCounter; + uint16_t runConsumerCounter; + // 80-83 + uint32_t addressBaseL; + // 84-87 + uint32_t addressBaseH; + // 88-91 + uint32_t addressOffset; + // 92-95 + uint32_t res9; + // 96-99 + uint16_t nonTailNumOutter; + uint16_t nonTailNumInner; + // 100-103 + uint32_t nonTailLengthInner; + // 104-107 + uint32_t nonTailStrideOutter; + // 108-111 + uint32_t nonTailStrideInner; + // 112-115 + uint16_t tailNumOutter; + uint16_t tailNumInner; + // 116-119 + uint32_t tailLengthInner; + // 120-123 + uint32_t tailStrideOutter; + // 124-127 + uint32_t tailStrideInner; +} rtFftsPlusDataCtx_t; + +// at start context +typedef struct tagFftsPlusAtStartCtx { + // 0-3 bytes + uint16_t contextType; + uint8_t successorNum; + uint8_t rs1 : 7; + uint8_t aten : 1; + // 4-7 + uint8_t rs2; + uint8_t rs3; + uint8_t predCntInit; + uint8_t predCnt; + // 8-11 + uint32_t rs4; + // 12-63 + uint16_t successorList[RT_CTX_SUCCESSOR_NUM]; + // 64-67 + uint16_t rs5; + uint16_t rs6; + // 68-71 + uint16_t rs7; + uint16_t rs8; + // 72-75 + uint16_t threadId; + uint16_t threadDim; + // 76-79 + uint16_t threadIdInit; + uint16_t threadWindowSize; + // 80-127 + uint16_t res9[12]; +} rtFftsPlusAtStartCtx_t; + +// at end context +#define RT_CTX_SUCC_AT_START_SLOT_NUM 12 +#define RT_CTX_SUCC_OUT_LABEL_SLOT_NUM 12 + +typedef struct tagFftsPlusAtEndCtx { + // 0-3 bytes + uint16_t contextType; + uint8_t atStartSlotNumber; + uint8_t outLabelSlotNumber : 7; + uint8_t aten : 1; + // 4-7 + uint8_t res1; + uint8_t res2; + uint8_t predCntInit; + uint8_t predCnt; + // 8-11 + uint32_t res3; + // 12-59 + uint16_t succAtStartSlot[RT_CTX_SUCC_AT_START_SLOT_NUM]; + uint16_t succOutLabelSlot[RT_CTX_SUCC_OUT_LABEL_SLOT_NUM]; + // 60-63 + uint16_t res4; + uint16_t res5; + // 64-67 + uint16_t res6; + uint16_t res7; + // 68-71 + uint16_t res8; + uint16_t res9; + // 72-75 + uint16_t threadId; + uint16_t res10; + // 76-79 + uint16_t res11; + uint16_t res12; + // 80-127 + uint32_t res13[12]; +} rtFftsPlusAtEndCtx_t; + +// label context +typedef struct tagFftsPlusLabelCtx { + // 0-3 bytes + uint16_t contextType; + uint8_t successorNum; + uint8_t res1; + // 4-7 + uint8_t res2; + uint8_t res3; + uint8_t predCntInit; + uint8_t predCnt; + // 8-11 + uint32_t res4; + // 12-63 + uint16_t successorList[RT_CTX_SUCCESSOR_NUM]; + // 64-79 + uint16_t res5[8]; + // 80-127 + uint32_t res6[12]; +} rtFftsPlusLabelCtx_t; + +// case switch context +typedef struct tagFftsPlusCaseSwitchCtx { + // 0-3 bytes + uint16_t contextType; + uint8_t successorNum; + uint8_t resv0 : 7; + uint8_t aten : 1; + // 4-7 + uint8_t startLabelId; + uint8_t labelListLen; + uint8_t predCntInit; + uint8_t predCnt; + // 8-11 + uint32_t resv1; + // 12-63 + uint16_t successorList[RT_CTX_SUCCESSOR_NUM]; + // 64-67 + uint16_t resv2 : 15; + uint16_t atm : 1; + uint16_t resv3; + // 68-71 + uint32_t resv4; + // 72-75 + uint16_t threadId; + uint16_t threadDim; + // 76-79 + uint8_t arSize : 3; + uint8_t snoop : 1; + uint8_t resv5 : 4; + uint8_t arCache : 4; + uint8_t arProt : 3; + uint8_t va : 1; + uint16_t resv6; + // 80-83 + uint32_t loadAddress0BaseL; + // 84-87 + uint32_t loadAddress0BaseH : 17; + uint32_t resv7 : 14; + uint32_t ld0En : 1; + // 88-91 + uint32_t loadAddress0Offset; + // 92-95 + uint32_t resv8; + // 96-99 + uint32_t loadAddress1BaseL; + // 100-103 + uint32_t loadAddress1BaseH : 17; + uint32_t resv9 : 14; + uint32_t ld1En : 1; + // 104-107 + uint32_t loadAddress1Offset; + // 108-127 + uint32_t resv10[5]; +} rtFftsPlusCaseSwitchCtx_t; + +// case default context +typedef struct tagFftsPlusCaseDefCtx { + // 0-3 bytes + uint16_t contextType; + uint8_t successorNum; + uint8_t rs0 : 7; + uint8_t aten : 1; + // 4-7 + uint8_t startLabelId; + uint8_t labelListLen; + uint8_t predCntInit; + uint8_t predCnt; + // 8-11 + uint32_t rs1; + // 12-63 + uint16_t successorList[RT_CTX_SUCCESSOR_NUM]; + // 64-67 + uint16_t rs2; + uint16_t rs3; + // 68-127 + uint32_t rs4[15]; +} rtFftsPlusCaseDefCtx_t; + +// condition switch context +#define RT_CTX_TRUE_SUCCESSOR_NUM 13 +#define RT_CTX_FALSE_SUCCESSOR_NUM 13 + +typedef struct tagFftsPlusCondSwitchCtx { + // 0-3 bytes + uint16_t contextType; + uint8_t trueSuccessorNum; + uint8_t falseSuccessorNum : 7; + uint8_t aten : 1; + // 4-7 + uint8_t condition; + uint8_t res1; + uint8_t predCntInit; + uint8_t predCnt; + // 8-11 + uint32_t res2; + // 12-63 + uint16_t trueSuccessorList[RT_CTX_TRUE_SUCCESSOR_NUM]; + uint16_t falseSuccessorList[RT_CTX_FALSE_SUCCESSOR_NUM]; + // 64-67 + uint16_t res3 : 15; + uint16_t atm : 1; + uint16_t res4; + // 68-71 + uint32_t res5; + // 72-75 + uint16_t threadId; + uint16_t threadDim; + // 76-79 + uint8_t arSize : 3; + uint8_t snoop : 1; + uint8_t res6 : 4; + uint8_t arCache : 4; + uint8_t arProt : 3; + uint8_t va : 1; + uint16_t res7; + // 80-83 + uint32_t loadAddress0BaseL; + // 84-87 + uint32_t loadAddress0BaseH : 17; + uint32_t res8 : 14; + uint32_t ld0En : 1; + // 88-91 + uint32_t loadAddress0Offset; + // 92-95 + uint32_t res9; + // 96-99 + uint32_t loadAddress1BaseL; + // 100-103 + uint32_t loadAddress1BaseH : 17; + uint32_t res10 : 14; + uint32_t ld1En : 1; + // 104-107 + uint32_t loadAddress1Offset; + // 108-127 + uint32_t res11[3]; + uint32_t cmpValue1; + uint32_t cmpValue2; +} rtFftsPlusCondSwitchCtx_t; + +#pragma pack(pop) + +#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +} +#endif +#endif // __CCE_RUNTIME_FFTS_PLUS_DEFINE_H diff --git a/third_party/fwkacllib/inc/runtime/rt_model.h b/third_party/fwkacllib/inc/runtime/rt_model.h index 5ef62df3..d0ffe9c8 100644 --- a/third_party/fwkacllib/inc/runtime/rt_model.h +++ b/third_party/fwkacllib/inc/runtime/rt_model.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_MODEL_H__ #define __CCE_RUNTIME_MODEL_H__ @@ -53,6 +53,7 @@ typedef enum tagModelTaskType { RT_MODEL_TASK_ALL_KERNEL, RT_MODEL_TASK_PROFILER_TRACE_EX, RT_MODEL_TASK_FFTS_TASK, + RT_MODEL_TASK_FFTS_PLUS_TASK, } rtModelTaskType_t; typedef enum tagModelStreamType { diff --git a/third_party/fwkacllib/inc/runtime/rt_stars.h b/third_party/fwkacllib/inc/runtime/rt_stars.h index 2874058c..016c352a 100644 --- a/third_party/fwkacllib/inc/runtime/rt_stars.h +++ b/third_party/fwkacllib/inc/runtime/rt_stars.h @@ -1,17 +1,6 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + * Description: */ #ifndef __CCE_RUNTIME_STARS_H diff --git a/third_party/fwkacllib/inc/runtime/rt_stars_define.h b/third_party/fwkacllib/inc/runtime/rt_stars_define.h new file mode 100644 index 00000000..d77a8a8e --- /dev/null +++ b/third_party/fwkacllib/inc/runtime/rt_stars_define.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + * Description: the definition of stars + */ + +#ifndef __CCE_RUNTIME_STARS_DEFINE__H +#define __CCE_RUNTIME_STARS_DEFINE__H + +#include "base.h" + +#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +extern "C" { +#endif + +#pragma pack(push) +#pragma pack (1) + +typedef struct tagStarsSqeHeader { + uint8_t type : 6; + uint8_t l1Lock : 1; + uint8_t l1Unlock : 1; + + uint8_t ie : 2; + uint8_t preP : 2; + uint8_t postP : 2; + uint8_t wrCqe : 1; + uint8_t reserved : 1; + + uint16_t blockDim; + + uint16_t rtStreamId; + uint16_t taskId; +} rtStarsSqeHeader_t; + +// ffts+ type +typedef enum tagFftsPlusType { + RT_FFTS_PLUS_TYPE_RES1 = 2, // Reserved + RT_FFTS_PLUS_TYPE_RES2 = 3, // Reserved + RT_FFTS_PLUS_TYPE = 4, // FFTS+ mode +} rtFftsPlusType_t; + +// ffts+ sqe +typedef struct tagFftsPlusSqe { + // 0-7 bytes + rtStarsSqeHeader_t sqeHeader; + // 8-11 bytes + uint16_t fftsType : 3; + uint16_t reserved1 : 9; + uint16_t wrrRatio : 4; + uint16_t reserved2; + // 12-15 bytes + uint16_t sqeIndex; + uint8_t kernelCredit; + uint8_t reserved4; + // 16-23 bytes + uint32_t stackPhyBaseL; + uint32_t stackPhyBaseH; + // 24-31 bytes + uint16_t totalContextNum; + uint16_t readyContextNum; + uint16_t preloadContextNum; + uint16_t reserved5; + // 32-35 bytes + uint16_t reserved6; + uint16_t prefetchOstNum : 5; + uint16_t reserved9 : 3; + uint16_t cmaintOstNum : 5; + uint16_t reserved10 : 3; + // 36-39 bytes + uint16_t aicPrefetchLower : 5; + uint16_t reserved11 : 3; + uint16_t aicPrefetchUpper : 5; + uint16_t reserved12 : 3; + uint16_t aivPrefetchLower : 5; + uint16_t Reserved13 : 3; + uint16_t aivPrefetchUpper : 5; + uint16_t Reserved14 : 3; + // 40-47 bytes + uint32_t contextAddressBaseL; + uint32_t contextAddressBaseH : 17; + uint32_t reserved15 : 15; + // 48-63 bytes + uint32_t reserved16[4]; +} rtFftsPlusSqe_t; + +#pragma pack(pop) + +#if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) +} +#endif +#endif // __CCE_RUNTIME_STARS_DEFINE__H \ No newline at end of file diff --git a/third_party/fwkacllib/inc/runtime/stream.h b/third_party/fwkacllib/inc/runtime/stream.h index 6f45fc4e..3a078e99 100644 --- a/third_party/fwkacllib/inc/runtime/stream.h +++ b/third_party/fwkacllib/inc/runtime/stream.h @@ -1,18 +1,18 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd - * + * Copyright 2020 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. - */ +*/ #ifndef __CCE_RUNTIME_STREAM_H__ #define __CCE_RUNTIME_STREAM_H__ diff --git a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h index 11e259b9..d65aac83 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h +++ b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h @@ -115,7 +115,7 @@ typedef struct aclprofSubscribeConfig aclprofSubscribeConfig1; /// @param [in] profSubscribeConfig: pointer to config of model subscribe /// @return Status result of function /// -Status aclgrphProfGraphSubscribe(const uint32_t graphId, +MSVP_PROF_API Status aclgrphProfGraphSubscribe(const uint32_t graphId, const aclprofSubscribeConfig1 *profSubscribeConfig); /// @@ -124,7 +124,7 @@ Status aclgrphProfGraphSubscribe(const uint32_t graphId, /// @param [in] graphId: the graph id subscribed /// @return Status result of function /// -Status aclgrphProfGraphUnSubscribe(const uint32_t graphId); +MSVP_PROF_API Status aclgrphProfGraphUnSubscribe(const uint32_t graphId); /** * @ingroup AscendCL @@ -136,7 +136,7 @@ Status aclgrphProfGraphUnSubscribe(const uint32_t graphId); * @retval graph id of subscription data * @retval 0 for failed */ -size_t aclprofGetGraphId(const void *opInfo, size_t opInfoLen, uint32_t index); +MSVP_PROF_API size_t aclprofGetGraphId(const void *opInfo, size_t opInfoLen, uint32_t index); #ifdef __cplusplus } #endif diff --git a/third_party/fwkacllib/inc/toolchain/prof_callback.h b/third_party/fwkacllib/inc/toolchain/prof_callback.h index dabd41c1..e6ac64bf 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_callback.h +++ b/third_party/fwkacllib/inc/toolchain/prof_callback.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020-2020 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. @@ -12,6 +12,9 @@ * 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. + * + * @file prof_callback.h + * @brief declaraion of profiling callbacks */ #ifndef MSPROFILER_PROF_CALLBACK_H_ @@ -21,6 +24,11 @@ extern "C" { #endif // __cplusplus +#if (OS_TYPE != LINUX) +#define MSVP_PROF_API __declspec(dllexport) +#else +#define MSVP_PROF_API __attribute__((visibility("default"))) +#endif #include "stddef.h" #include "stdint.h" @@ -97,7 +105,6 @@ enum MsprofReporterCallbackType { */ typedef int32_t (*MsprofReporterCallback)(uint32_t moduleId, uint32_t type, void *data, uint32_t len); - #define MSPROF_OPTIONS_DEF_LEN_MAX (2048) /** @@ -118,25 +125,16 @@ enum MsprofCtrlCallbackType { MSPROF_CTRL_INIT_ACL_JSON, // start profiling with acl.json MSPROF_CTRL_INIT_GE_OPTIONS, // start profiling with ge env and options MSPROF_CTRL_FINALIZE, // stop profiling - MSPROF_CTRL_REPORT_FUN_P, // for report callback - MSPROF_CTRL_PROF_SWITCH_ON, // for prof switch on - MSPROF_CTRL_PROF_SWITCH_OFF // for prof switch off + MSPROF_CTRL_INIT_DYNA = 0xFF, // start profiling for dynamic profiling }; -#define PROF_COMMANDHANDLE_TYPE_INIT (0) -#define PROF_COMMANDHANDLE_TYPE_START (1) -#define PROF_COMMANDHANDLE_TYPE_STOP (2) -#define PROF_COMMANDHANDLE_TYPE_FINALIZE (3) -#define PROF_COMMANDHANDLE_TYPE_MODEL_SUBSCRIBE (4) -#define PROF_COMMANDHANDLE_TYPE_MODEL_UNSUBSCRIBE (5) - -#define MSPROF_MAX_DEV_NUM (64) - -struct MsprofCommandHandle { - uint64_t profSwitch; - uint32_t devNums; // length of device id list - uint32_t devIdList[MSPROF_MAX_DEV_NUM]; - uint32_t modelId; +enum MsprofCommandHandleType { + PROF_COMMANDHANDLE_TYPE_INIT = 0, + PROF_COMMANDHANDLE_TYPE_START, + PROF_COMMANDHANDLE_TYPE_STOP, + PROF_COMMANDHANDLE_TYPE_FINALIZE, + PROF_COMMANDHANDLE_TYPE_MODEL_SUBSCRIBE, + PROF_COMMANDHANDLE_TYPE_MODEL_UNSUBSCRIBE }; /** @@ -165,7 +163,7 @@ typedef void (*MsprofSetDeviceCallback)(uint32_t devId, bool isOpenDevice); * @param [in] dataLen: Length of data * @return 0:SUCCESS, >0:FAILED */ -int32_t MsprofInit(uint32_t dataType, void *data, uint32_t dataLen); +MSVP_PROF_API int32_t MsprofInit(uint32_t dataType, void *data, uint32_t dataLen); /* * @name AscendCL @@ -173,7 +171,7 @@ int32_t MsprofInit(uint32_t dataType, void *data, uint32_t dataLen); * @param NULL * @return 0:SUCCESS, >0:FAILED */ -int32_t MsprofFinalize(); +MSVP_PROF_API int32_t MsprofFinalize(); #ifdef __cplusplus } #endif diff --git a/third_party/fwkacllib/inc/toolchain/slog.h b/third_party/fwkacllib/inc/toolchain/slog.h index cc7c83ca..a4680efe 100644 --- a/third_party/fwkacllib/inc/toolchain/slog.h +++ b/third_party/fwkacllib/inc/toolchain/slog.h @@ -204,6 +204,7 @@ enum { FV, MDCMAP, TUNE, + HSS, /**< helper */ INVLID_MOUDLE_ID }; From 62d3820145cde8256b3421c06d2fe0123bca91b1 Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Sat, 4 Sep 2021 11:04:34 +0800 Subject: [PATCH 37/59] update Ascend package 4 Sep 21 --- metadef | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metadef b/metadef index 2d1913e6..6d8b7ee8 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit 2d1913e65a016e04a9599e1d2e49fd02136638bd +Subproject commit 6d8b7ee8a902320a9f8aba043fb5dd06e4073729 From 157f245493e2d9dcf0fc9550c6ceca3db71dc05e Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Thu, 9 Sep 2021 16:19:54 +0800 Subject: [PATCH 38/59] upgrade Ascend package 09 Sep 21 --- metadef | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/metadef b/metadef index 6d8b7ee8..60df4b39 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit 6d8b7ee8a902320a9f8aba043fb5dd06e4073729 +Subproject commit 60df4b39a6f639c21dd7deb220b93345451938f5 From 608553b8fe649fbe11c67a2558f5782c80e31b00 Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Thu, 4 Nov 2021 15:53:22 +0800 Subject: [PATCH 39/59] upgrade Ascend package 4 Nov 21 --- ge/common/model/ge_model.cc | 9 +- ge/common/model/ge_model.h | 12 +- inc/external/acl/OWNERS | 1 + inc/external/acl/acl_mdl.h | 6 +- inc/external/acl/acl_rt.h | 39 +- inc/external/acl/acl_tdt.h | 31 +- inc/external/acl/acl_tdt_queue.h | 437 ++++++++++++++++++ inc/external/acl/error_codes/rt_error_codes.h | 4 + inc/external/acl/ops/acl_dvpp.h | 2 +- inc/external/ge/ge_api_error_codes.h | 20 +- inc/external/ge/ge_api_types.h | 2 + inc/external/ge/ge_ir_build.h | 2 +- inc/external/hccl/hccl_types.h | 1 + inc/external/runtime/rt_error_codes.h | 4 + inc/framework/common/ge_compiler_options.h | 2 +- inc/framework/common/profiling/ge_profiling.h | 2 +- .../common/profiling/ge_runner_profiling.h | 2 +- inc/framework/common/taskdown_common.h | 2 +- inc/framework/memory/memory_api.h | 2 +- inc/framework/omg/ge_init.h | 2 +- inc/framework/omg/omg.h | 2 +- inc/framework/omg/parser/model_parser.h | 2 +- inc/framework/omg/parser/op_parser.h | 2 +- inc/framework/omg/parser/parser_api.h | 2 +- inc/framework/omg/parser/parser_factory.h | 2 +- inc/framework/omg/parser/weights_parser.h | 2 +- metadef | 2 +- .../aicpu/aicpu_schedule/aicpu_op_type_list.h | 9 +- third_party/fwkacllib/inc/hccl/base.h | 41 ++ third_party/fwkacllib/inc/mmpa/mmpa_api.h | 1 - .../fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h | 172 +++---- .../fwkacllib/inc/mmpa/sub_inc/mmpa_win.h | 16 +- third_party/fwkacllib/inc/ops/aipp.h | 2 +- third_party/fwkacllib/inc/ops/all_ops.h | 2 +- third_party/fwkacllib/inc/ops/array_ops.h | 117 ++++- third_party/fwkacllib/inc/ops/audio_ops.h | 2 +- .../fwkacllib/inc/ops/avg_pool_1d_ops.h | 2 +- third_party/fwkacllib/inc/ops/batch_ops.h | 2 +- third_party/fwkacllib/inc/ops/bitwise_ops.h | 2 +- .../fwkacllib/inc/ops/boosted_trees_ops.h | 2 +- .../inc/ops/candidate_sampling_ops.h | 2 +- .../fwkacllib/inc/ops/case_condition_ops.h | 2 +- third_party/fwkacllib/inc/ops/cluster.h | 58 +++ third_party/fwkacllib/inc/ops/condtake_ops.h | 2 +- .../fwkacllib/inc/ops/control_flow_ops.h | 2 +- .../inc/ops/coordinates_1d_to_2d_ops.h | 2 +- third_party/fwkacllib/inc/ops/correlation.h | 2 +- third_party/fwkacllib/inc/ops/ctc_ops.h | 2 +- third_party/fwkacllib/inc/ops/data_flow_ops.h | 7 +- .../inc/ops/elewise_calculation_ops.h | 58 +-- .../fwkacllib/inc/ops/functional_ops.h | 2 +- third_party/fwkacllib/inc/ops/get_data_ops.h | 2 +- third_party/fwkacllib/inc/ops/hcom_ops.h | 2 +- third_party/fwkacllib/inc/ops/hvd_ops.h | 2 +- third_party/fwkacllib/inc/ops/image_ops.h | 45 +- .../fwkacllib/inc/ops/index_to_addr_ops.h | 2 +- third_party/fwkacllib/inc/ops/internal_ops.h | 2 +- third_party/fwkacllib/inc/ops/linalg_ops.h | 10 +- third_party/fwkacllib/inc/ops/list_ops.h | 2 +- third_party/fwkacllib/inc/ops/logging_ops.h | 2 +- third_party/fwkacllib/inc/ops/lookup_ops.h | 2 +- third_party/fwkacllib/inc/ops/math_ops.h | 57 ++- .../inc/ops/matrix_calculation_ops.h | 82 +++- .../fwkacllib/inc/ops/nn_batch_norm_ops.h | 33 +- .../fwkacllib/inc/ops/nn_calculation_ops.h | 263 +++++------ third_party/fwkacllib/inc/ops/nn_detect_ops.h | 176 ++++++- third_party/fwkacllib/inc/ops/nn_norm_ops.h | 2 +- third_party/fwkacllib/inc/ops/nn_ops.h | 2 +- .../fwkacllib/inc/ops/nn_pooling_ops.h | 2 +- .../fwkacllib/inc/ops/nn_training_ops.h | 15 +- third_party/fwkacllib/inc/ops/no_op.h | 2 +- .../fwkacllib/inc/ops/nonlinear_fuc_ops.h | 44 +- .../fwkacllib/inc/ops/npu_loss_scale_ops.h | 2 +- third_party/fwkacllib/inc/ops/ocr_ops.h | 268 +++++++++++ third_party/fwkacllib/inc/ops/outfeed_ops.h | 2 +- third_party/fwkacllib/inc/ops/pad_ops.h | 34 +- third_party/fwkacllib/inc/ops/parsing_ops.h | 2 +- third_party/fwkacllib/inc/ops/quantize_ops.h | 40 +- .../fwkacllib/inc/ops/ragged_array_ops.h | 2 +- .../fwkacllib/inc/ops/ragged_conversion_ops.h | 2 +- .../fwkacllib/inc/ops/ragged_math_ops.h | 2 +- third_party/fwkacllib/inc/ops/random_ops.h | 22 +- third_party/fwkacllib/inc/ops/reduce_ops.h | 25 +- .../fwkacllib/inc/ops/resource_variable_ops.h | 2 +- third_party/fwkacllib/inc/ops/rnn.h | 58 ++- third_party/fwkacllib/inc/ops/rpn_ops.h | 2 +- third_party/fwkacllib/inc/ops/save_ops.h | 2 +- third_party/fwkacllib/inc/ops/sdca_ops.h | 2 +- third_party/fwkacllib/inc/ops/selection_ops.h | 46 +- third_party/fwkacllib/inc/ops/set_ops.h | 2 +- .../fwkacllib/inc/ops/slice_write_ops.h | 2 +- third_party/fwkacllib/inc/ops/sparse_ops.h | 2 +- third_party/fwkacllib/inc/ops/spectral_ops.h | 2 +- .../fwkacllib/inc/ops/split_combination_ops.h | 4 +- third_party/fwkacllib/inc/ops/state_ops.h | 2 +- .../fwkacllib/inc/ops/stateful_random_ops.h | 2 +- .../fwkacllib/inc/ops/stateless_random_ops.h | 2 +- third_party/fwkacllib/inc/ops/string_ops.h | 2 +- third_party/fwkacllib/inc/ops/swap_co_ops.h | 2 +- .../inc/ops/target_crop_and_resize.h | 2 +- .../fwkacllib/inc/ops/transformation_ops.h | 12 +- third_party/fwkacllib/inc/ops/vector_search.h | 90 +++- .../fwkacllib/inc/ops/warp_perspective_ops.h | 2 +- third_party/fwkacllib/inc/runtime/base.h | 48 +- third_party/fwkacllib/inc/runtime/config.h | 69 +-- third_party/fwkacllib/inc/runtime/context.h | 16 +- third_party/fwkacllib/inc/runtime/dev.h | 56 ++- .../fwkacllib/inc/runtime/dvfsprofile.h | 16 +- third_party/fwkacllib/inc/runtime/event.h | 38 +- third_party/fwkacllib/inc/runtime/kernel.h | 81 ++-- third_party/fwkacllib/inc/runtime/mem.h | 153 +++--- third_party/fwkacllib/inc/runtime/rt.h | 16 +- third_party/fwkacllib/inc/runtime/rt_dfx.h | 19 +- third_party/fwkacllib/inc/runtime/rt_ffts.h | 34 +- .../fwkacllib/inc/runtime/rt_ffts_plus.h | 27 +- .../inc/runtime/rt_ffts_plus_define.h | 59 ++- third_party/fwkacllib/inc/runtime/rt_model.h | 36 +- third_party/fwkacllib/inc/runtime/rt_stars.h | 33 +- .../fwkacllib/inc/runtime/rt_stars_define.h | 23 +- third_party/fwkacllib/inc/runtime/stream.h | 42 +- third_party/fwkacllib/inc/toolchain/plog.h | 4 +- .../fwkacllib/inc/toolchain/prof_acl_api.h | 58 +-- .../fwkacllib/inc/toolchain/prof_callback.h | 7 +- .../fwkacllib/inc/toolchain/prof_reporter.h | 5 +- 124 files changed, 2550 insertions(+), 785 deletions(-) create mode 100644 inc/external/acl/acl_tdt_queue.h create mode 100644 third_party/fwkacllib/inc/ops/cluster.h create mode 100644 third_party/fwkacllib/inc/ops/ocr_ops.h diff --git a/ge/common/model/ge_model.cc b/ge/common/model/ge_model.cc index 7fc58b6d..b90c3466 100755 --- a/ge/common/model/ge_model.cc +++ b/ge/common/model/ge_model.cc @@ -34,7 +34,6 @@ void GeModel::Init() { } GeModel::GeModel() { - attrs_.InitDefault(); Init(); } @@ -78,12 +77,12 @@ void GeModel::SetPlatformVersion(const std::string &platform_version) { this->pl void GeModel::SetPlatformType(uint8_t platform_type) { this->platform_type_ = platform_type; } -void GeModel::SetAttr(const ProtoAttrMapHelper &attrs) { attrs_ = attrs; } +void GeModel::SetAttr(const ProtoAttrMap &attrs) { attrs_ = attrs; } -ProtoAttrMapHelper GeModel::MutableAttrMap() { return attrs_; } +ProtoAttrMap &GeModel::MutableAttrMap() { return attrs_; } -ConstProtoAttrMapHelper GeModel::GetAttrMap() const { - return ConstProtoAttrMapHelper(attrs_.GetProtoOwner(), attrs_.GetProtoMsg()); +ConstProtoAttrMap &GeModel::GetAttrMap() const { + return attrs_; } Status GeModel::GetSessionId(uint32_t model_id, uint64_t &session_id) const { diff --git a/ge/common/model/ge_model.h b/ge/common/model/ge_model.h index 0e791746..256c6db0 100755 --- a/ge/common/model/ge_model.h +++ b/ge/common/model/ge_model.h @@ -17,10 +17,12 @@ #ifndef GE_MODEL_GE_MODEL_H_ #define GE_MODEL_GE_MODEL_H_ -#include #include #include #include + +#include "securec.h" +#include "runtime/rt.h" #include "common/tbe_kernel_store.h" #include "common/cust_aicpu_kernel_store.h" #include "framework/common/debug/log.h" @@ -60,9 +62,9 @@ class GeModel : public AttrHolder { void SetPlatformVersion(const std::string &platform_version); void SetPlatformType(uint8_t platform_type); - void SetAttr(const ProtoAttrMapHelper &attrs); + void SetAttr(const ProtoAttrMap &attrs); - ProtoAttrMapHelper MutableAttrMap() override; + ProtoAttrMap &MutableAttrMap() override; using AttrHolder::SetAttr; using AttrHolder::GetAllAttrs; @@ -77,12 +79,12 @@ class GeModel : public AttrHolder { } protected: - ConstProtoAttrMapHelper GetAttrMap() const override; + ConstProtoAttrMap &GetAttrMap() const override; private: void Init(); - ProtoAttrMapHelper attrs_; /*lint !e148*/ + ProtoAttrMap attrs_; /*lint !e148*/ Graph graph_; std::shared_ptr task_; /*lint !e148*/ diff --git a/inc/external/acl/OWNERS b/inc/external/acl/OWNERS index 8552e853..b4b22068 100755 --- a/inc/external/acl/OWNERS +++ b/inc/external/acl/OWNERS @@ -5,5 +5,6 @@ approvers: reviewers: - justin_zhao - zhangyongfeng88 +- w00267184 options: no_parent_owners: true \ No newline at end of file diff --git a/inc/external/acl/acl_mdl.h b/inc/external/acl/acl_mdl.h index 522dbd38..778fa519 100644 --- a/inc/external/acl/acl_mdl.h +++ b/inc/external/acl/acl_mdl.h @@ -869,7 +869,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPInputFormat(aclmdlAIPP *aippParmsSet, * * @see aclmdlCreateAIPP */ -ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, int8_t csc_switch, int16_t cscMatrixR0C0, +ACL_FUNC_VISIBILITY aclError aclmdlSetAIPPCscParams(aclmdlAIPP *aippParmsSet, int8_t cscSwitch, int16_t cscMatrixR0C0, int16_t cscMatrixR0C1, int16_t cscMatrixR0C2, int16_t cscMatrixR1C0, int16_t cscMatrixR1C1, int16_t cscMatrixR1C2, int16_t cscMatrixR2C0, int16_t cscMatrixR2C1, int16_t cscMatrixR2C2, @@ -1106,7 +1106,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, size_t index, a * * @param modelId [IN] model id * @param index [IN] index of tensor - * @param aippinfo [OUT] Pointer for static aipp info + * @param aippInfo [OUT] Pointer for static aipp info * * @retval ACL_SUCCESS The function is successfully executed. * @retval ACL_ERROR_MODEL_AIPP_NOT_EXIST The tensor of index is not configured with aipp @@ -1115,7 +1115,7 @@ ACL_FUNC_VISIBILITY aclError aclmdlGetAippType(uint32_t modelId, size_t index, a * @see aclmdlLoadFromFile | aclmdlLoadFromMem | aclmdlLoadFromFileWithMem | * aclmdlLoadFromMemWithMem | aclmdlGetInputIndexByName */ -ACL_FUNC_VISIBILITY aclError aclmdlGetFirstAippInfo(uint32_t modelId, size_t index, aclAippInfo *aippinfo); +ACL_FUNC_VISIBILITY aclError aclmdlGetFirstAippInfo(uint32_t modelId, size_t index, aclAippInfo *aippInfo); /** * @ingroup AscendCL diff --git a/inc/external/acl/acl_rt.h b/inc/external/acl/acl_rt.h index 50dbc34d..7ea27cba 100644 --- a/inc/external/acl/acl_rt.h +++ b/inc/external/acl/acl_rt.h @@ -541,7 +541,7 @@ ACL_FUNC_VISIBILITY aclError aclrtSynchronizeEvent(aclrtEvent event); * * @see aclrtCreateEvent | aclrtRecordEvent | aclrtSynchronizeStream */ -ACL_FUNC_VISIBILITY aclError aclrtEventElapsedTime(float *ms, aclrtEvent start, aclrtEvent end); +ACL_FUNC_VISIBILITY aclError aclrtEventElapsedTime(float *ms, aclrtEvent startEvent, aclrtEvent endEvent); /** * @ingroup AscendCL @@ -731,6 +731,43 @@ ACL_FUNC_VISIBILITY aclError aclrtMemset(void *devPtr, size_t maxCount, int32_t ACL_FUNC_VISIBILITY aclError aclrtMemcpyAsync(void *dst, size_t destMax, const void *src, size_t count, aclrtMemcpyKind kind, aclrtStream stream); +/** + * @ingroup AscendCL + * @brief synchronous memory replication of two-dimensional matrix between host and device + * + * @param dst [IN] destination address pointer + * @param dpitch [IN] pitch of destination memory + * @param src [IN] source address pointer + * @param spitch [IN] pitch of source memory + * @param width [IN] width of matrix transfer + * @param height [IN] height of matrix transfer + * @param kind [IN] memcpy type + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtMemcpy2d(void *dst, size_t dpitch, const void *src, size_t spitch, size_t width, + size_t height, aclrtMemcpyKind kind); + +/** + * @ingroup AscendCL + * @brief asynchronous memory replication of two-dimensional matrix between host and device + * + * @param dst [IN] destination address pointer + * @param dpitch [IN] pitch of destination memory + * @param src [IN] source address pointer + * @param spitch [IN] pitch of source memory + * @param width [IN] width of matrix transfer + * @param height [IN] height of matrix transfer + * @param kind [IN] memcpy type + * @param stream [IN] asynchronized task stream + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtMemcpy2dAsync(void *dst, size_t dpitch, const void *src, size_t spitch, size_t width, + size_t height, aclrtMemcpyKind kind, aclrtStream stream); + /** * @ingroup AscendCL * @brief Asynchronous initialize memory diff --git a/inc/external/acl/acl_tdt.h b/inc/external/acl/acl_tdt.h index c357518d..d928a911 100644 --- a/inc/external/acl/acl_tdt.h +++ b/inc/external/acl/acl_tdt.h @@ -215,7 +215,7 @@ ACL_FUNC_VISIBILITY aclError acltdtStopChannel(acltdtChannelHandle *handle); * @brief Create the channel * * @param deviceId [IN] the device id - * @param name [IN] the channel's name + * @param name [IN] the name of channel * * @retval null for failed * @retval OtherValues success @@ -224,6 +224,22 @@ ACL_FUNC_VISIBILITY aclError acltdtStopChannel(acltdtChannelHandle *handle); */ ACL_FUNC_VISIBILITY acltdtChannelHandle *acltdtCreateChannel(uint32_t deviceId, const char *name); +/** + * @ingroup AscendCL + * @brief Create the channel with max size + * + * @param deviceId [IN] the device id + * @param name [IN] the name of channel + * @param capacity [IN] the capacity of channel + * + * @retval null for failed + * @retval OtherValues success + * + * @see acltdtDestroyChannel + */ +ACL_FUNC_VISIBILITY acltdtChannelHandle *acltdtCreateChannelWithCapacity(uint32_t deviceId, const char *name, + size_t capacity); + /** * @ingroup AscendCL * @brief Destroy the channel @@ -269,6 +285,19 @@ ACL_FUNC_VISIBILITY aclError acltdtSendTensor(const acltdtChannelHandle *handle, ACL_FUNC_VISIBILITY aclError acltdtReceiveTensor(const acltdtChannelHandle *handle, acltdtDataset *dataset, int32_t timeout); +/** + * @ingroup AscendCL + * @brief query the size of the channel + * + * @param handle [IN] pointer to the channel handle + * @param size [OUT] current size of this channel + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + */ +ACL_FUNC_VISIBILITY aclError acltdtQueryChannelSize(const acltdtChannelHandle *handle, size_t *size); + #ifdef __cplusplus } #endif diff --git a/inc/external/acl/acl_tdt_queue.h b/inc/external/acl/acl_tdt_queue.h new file mode 100644 index 00000000..95cfdb8c --- /dev/null +++ b/inc/external/acl/acl_tdt_queue.h @@ -0,0 +1,437 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef INC_EXTERNAL_ACL_ACL_TDT_QUEUE_H_ +#define INC_EXTERNAL_ACL_ACL_TDT_QUEUE_H_ + +#include "acl/acl_base.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ACL_TDT_QUEUE_PERMISSION_MANAGE 1 +#define ACL_TDT_QUEUE_PERMISSION_DEQUEUE 2 +#define ACL_TDT_QUEUE_PERMISSION_ENQUEUE 4 + +typedef void *acltdtBuf; +typedef struct tagMemQueueAttr acltdtQueueAttr; +typedef struct acltdtQueueRouteList acltdtQueueRouteList; +typedef struct acltdtQueueRouteQueryInfo acltdtQueueRouteQueryInfo; +typedef struct acltdtQueueRoute acltdtQueueRoute; + +typedef enum { ACL_TDT_QUEUE_NAME_PTR = 0, ACL_TDT_QUEUE_DEPTH_UINT32 } acltdtQueueAttrType; + +typedef enum { + ACL_TDT_QUEUE_ROUTE_SRC_UINT32 = 0, + ACL_TDT_QUEUE_ROUTE_DST_UINT32, + ACL_TDT_QUEUE_ROUTE_STATUS_INT32 +} acltdtQueueRouteParamType; + +typedef enum { + ACL_TDT_QUEUE_ROUTE_QUERY_SRC = 0, + ACL_TDT_QUEUE_ROUTE_QUERY_DST, + ACL_TDT_QUEUE_ROUTE_QUERY_SRC_AND_DST +} acltdtQueueRouteQueryMode; + +typedef enum { + ACL_TDT_QUEUE_ROUTE_QUERY_MODE_ENUM = 0, + ACL_TDT_QUEUE_ROUTE_QUERY_SRC_ID_UINT32, + ACL_TDT_QUEUE_ROUTE_QUERY_DST_ID_UINT32 +} acltdtQueueRouteQueryInfoParamType; + +/** + * @ingroup AscendCL + * @brief create queue + * + * @param attr [IN] pointer to the queue attr + * @param qid [OUT] pointer to the qid + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtDestroyQueue + */ +ACL_FUNC_VISIBILITY aclError acltdtCreateQueue(const acltdtQueueAttr *attr, uint32_t *qid); + +/** + * @ingroup AscendCL + * @brief destroy queue + * + * @param qid [IN] qid which to be destroyed + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtCreateQueue + */ +ACL_FUNC_VISIBILITY aclError acltdtDestroyQueue(uint32_t qid); + +/** + * @ingroup AscendCL + * @brief enqueue function + * + * @param qid [IN] qid + * @param buf [IN] acltdtBuf + * @param timeout [IN] timeout + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtDequeue + */ +ACL_FUNC_VISIBILITY aclError acltdtEnqueue(uint32_t qid, acltdtBuf buf, int32_t timeout); + +/** + * @ingroup AscendCL + * @brief dequeue function + * + * @param qid [IN] qid + * @param buf [OUT] pointer to the acltdtBuf + * @param timeout [IN] timeout + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtEnqueue + */ +ACL_FUNC_VISIBILITY aclError acltdtDequeue(uint32_t qid, acltdtBuf *buf, int32_t timeout); + +/** + * @ingroup AscendCL + * @brief grant queue to other process + * + * @param qid [IN] qid + * @param pid [IN] pid of dst process + * @param permission [IN] permission of queue + * @param timeout [IN] timeout + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see ACL_TDT_QUEUE_PERMISSION_MANAGE | ACL_TDT_QUEUE_PERMISSION_DEQUEUE | ACL_TDT_QUEUE_PERMISSION_ENQUEUE + */ +ACL_FUNC_VISIBILITY aclError acltdtGrantQueue(uint32_t qid, int32_t pid, uint32_t permission, int32_t timeout); + +/** + * @ingroup AscendCL + * @brief attach queue in current process + * + * @param qid [IN] qid + * @param timeout [IN] timeout + * @param permission [OUT] permission of queue + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtGrantQueue + */ +ACL_FUNC_VISIBILITY aclError acltdtAttachQueue(uint32_t qid, int32_t timeout, uint32_t *permission); + +/** + * @ingroup AscendCL + * @brief bind queue routes + * + * @param qRouteList [IN|OUT] pointer to the route list + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acltdtBindQueueRoutes(acltdtQueueRouteList *qRouteList); + +/** + * @ingroup AscendCL + * @brief unbind queue routes + * + * @param qRouteList [IN|OUT] pointer to the route list + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acltdtUnbindQueueRoutes(acltdtQueueRouteList *qRouteList); + +/** + * @ingroup AscendCL + * @brief query queue routes according to query mode + * + * @param queryInfo [IN] pointer to the queue route query info + * @param qRouteList [IN|OUT] pointer to the route list + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError acltdtQueryQueueRoutes(const acltdtQueueRouteQueryInfo *queryInfo, + acltdtQueueRouteList *qRouteList); + +/** + * @ingroup AscendCL + * @brief alloc acltdtBuf + * + * @param size [IN] alloc buf size + * @param buf [OUT] pointer to the acltdtBuf + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtFreeBuf + */ +ACL_FUNC_VISIBILITY aclError acltdtAllocBuf(size_t size, acltdtBuf *buf); + +/** + * @ingroup AscendCL + * @brief free acltdtBuf + * + * @param buf [IN] pointer to the acltdtBuf + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtAllocBuf + */ +ACL_FUNC_VISIBILITY aclError acltdtFreeBuf(acltdtBuf buf); + +/** + * @ingroup AscendCL + * @brief get data buf address + * + * @param buf [IN] acltdtBuf + * @param dataPtr [OUT] pointer to the data ptr which is acquired from acltdtBuf + * @param size [OUT] pointer to the size + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtAllocBuf + */ +ACL_FUNC_VISIBILITY aclError acltdtGetBufData(const acltdtBuf buf, void **dataPtr, size_t *size); + +/** + * @ingroup AscendCL + * @brief Create the queue attr + * + * @retval null for failed + * @retval OtherValues success + * + * @see acltdtDestroyQueueAttr + */ +ACL_FUNC_VISIBILITY acltdtQueueAttr *acltdtCreateQueueAttr(); + +/** + * @ingroup AscendCL + * @brief Destroy the queue attr + * + * @param attr [IN] pointer to the queue attr + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtCreateQueueAttr + */ +ACL_FUNC_VISIBILITY aclError acltdtDestroyQueueAttr(const acltdtQueueAttr *attr); + +/** + * @ingroup AscendCL + * @brief Set parameter for queue attr + * + * @param attr [IN|OUT] pointer to the queue attr + * @param type [IN] parameter type + * @param len [IN] parameter length + * @param param [IN] pointer to parameter value + * + * @retval ACL_SUCCESS for success, other for failure + * + * @see acltdtCreateQueueAttr + */ +ACL_FUNC_VISIBILITY aclError acltdtSetQueueAttr(acltdtQueueAttr *attr, acltdtQueueAttrType type, size_t len, + const void *param); + +/** + * @ingroup AscendCL + * + * @brief Get parameter for queue attr. + * + * @param attr [IN] pointer to the queue attr + * @param type [IN] parameter type + * @param len [IN] parameter length + * @param paramRetSize [OUT] pointer to parameter real length + * @param param [OUT] pointer to parameter value + * + * @retval ACL_SUCCESS for success, other for failure + * + * @see acltdtCreateQueueAttr + */ +ACL_FUNC_VISIBILITY aclError acltdtGetQueueAttr(const acltdtQueueAttr *attr, acltdtQueueAttrType type, size_t len, + size_t *paramRetSize, void *param); + +/** + * @ingroup AscendCL + * @brief Create the queue route + * + * @param srcId [IN] src id of queue route + * @param dstId [IN] dst id of queue route + * + * @retval null for failed + * @retval OtherValues success + * + * @see acltdtDestroyQueueRoute + */ +ACL_FUNC_VISIBILITY acltdtQueueRoute *acltdtCreateQueueRoute(uint32_t srcId, uint32_t dstId); + +/** + * @ingroup AscendCL + * @brief Destroy the queue attr + * + * @param route [IN] pointer to the queue route + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtCreateQueueRoute + */ +ACL_FUNC_VISIBILITY aclError acltdtDestroyQueueRoute(const acltdtQueueRoute *route); + +/** + * @ingroup AscendCL + * + * @brief Get parameter for queue route. + * + * @param route [IN] pointer to the queue route + * @param type [IN] parameter type + * @param len [IN] parameter length + * @param paramRetSize [OUT] pointer to parameter real length + * @param param [OUT] pointer to parameter value + * + * @retval ACL_SUCCESS for success, other for failure + * + * @see acltdtCreateQueueRoute + */ +ACL_FUNC_VISIBILITY aclError acltdtGetQueueRouteParam(const acltdtQueueRoute *route, acltdtQueueRouteParamType type, + size_t len, size_t *paramRetSize, void *param); + +/** + * @ingroup AscendCL + * @brief Create the queue route list + * + * @retval null for failed + * @retval OtherValues success + * + * @see acltdtDestroyQueueRouteList + */ +ACL_FUNC_VISIBILITY acltdtQueueRouteList *acltdtCreateQueueRouteList(); + +/** + * @ingroup AscendCL + * @brief Destroy the queue route list + * + * @param routeList [IN] pointer to the queue route list + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtCreateQueueRouteList + */ +ACL_FUNC_VISIBILITY aclError acltdtDestroyQueueRouteList(const acltdtQueueRouteList *routeList); + +/** + * @ingroup AscendCL + * @brief add queue route to the route list + * + * @param routeList [IN|OUT] pointer to the queue route list + * @param route [IN] pointer to the queue route + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtCreateQueueRouteList | acltdtCreateQueueRoute + * + */ +ACL_FUNC_VISIBILITY aclError acltdtAddQueueRoute(acltdtQueueRouteList *routeList, const acltdtQueueRoute *route); + +/** + * @ingroup AscendCL + * @brief get queue route from route list + * + * @param routeList [IN] pointer to the queue route list + * @param index [IN] index of queue route in route list + * @param route [IN|OUT] pointer to the queue route + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtCreateQueueRouteList | acltdtCreateQueueRoute + * + */ +ACL_FUNC_VISIBILITY aclError acltdtGetQueueRoute(const acltdtQueueRouteList *routeList, size_t index, + acltdtQueueRoute *route); + +/** + * @ingroup AscendCL + * @brief get queue route num from route list + * + * @param routeList [IN] pointer to the queue route list + * + * @retval the number of queue route + * + */ +ACL_FUNC_VISIBILITY size_t acltdtGetQueueRouteNum(const acltdtQueueRouteList *routeList); + +/** + * @ingroup AscendCL + * @brief Create the queue route query info + * + * @retval null for failed + * @retval OtherValues success + * + * @see acltdtDestroyQueueRouteQueryInfo + */ +ACL_FUNC_VISIBILITY acltdtQueueRouteQueryInfo *acltdtCreateQueueRouteQueryInfo(); + +/** + * @ingroup AscendCL + * @brief Destroy the queue route query info + * + * @param info [IN] pointer to the queue route info + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtCreateQueueRouteQueryInfo + * + */ +ACL_FUNC_VISIBILITY aclError acltdtDestroyQueueRouteQueryInfo(const acltdtQueueRouteQueryInfo *info); + +/** + * @ingroup AscendCL + * @brief Set parameter for queue route info + * + * @param attr [IN|OUT] pointer to the queue route info + * @param type [IN] parameter type + * @param len [IN] parameter length + * @param param [IN] pointer to parameter value + * + * @retval ACL_SUCCESS for success, other for failure + * + * @see acltdtCreateQueueRouteQueryInfo + */ +ACL_FUNC_VISIBILITY aclError acltdtSetQueueRouteQueryInfo(acltdtQueueRouteQueryInfo *param, + acltdtQueueRouteQueryInfoParamType type, size_t len, + const void *value); + +#ifdef __cplusplus +} +#endif + +#endif // INC_EXTERNAL_ACL_ACL_TDT_QUEUE_H_ \ No newline at end of file diff --git a/inc/external/acl/error_codes/rt_error_codes.h b/inc/external/acl/error_codes/rt_error_codes.h index 1c196c48..556652be 100644 --- a/inc/external/acl/error_codes/rt_error_codes.h +++ b/inc/external/acl/error_codes/rt_error_codes.h @@ -56,6 +56,10 @@ static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event res static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource +static const int32_t ACL_ERROR_RT_NO_CDQ_RESOURCE = 207011; // no cdq resource +static const int32_t ACL_ERROR_RT_OVER_LIMIT = 207012; // over limit +static const int32_t ACL_ERROR_RT_QUEUE_EMPTY = 207013; // queue is empty +static const int32_t ACL_ERROR_RT_QUEUE_FULL = 207014; // queue is full static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error diff --git a/inc/external/acl/ops/acl_dvpp.h b/inc/external/acl/ops/acl_dvpp.h index 5418ebd3..a536a23b 100644 --- a/inc/external/acl/ops/acl_dvpp.h +++ b/inc/external/acl/ops/acl_dvpp.h @@ -125,7 +125,7 @@ enum acldvppPixelFormat { enum acldvppStreamFormat { H265_MAIN_LEVEL = 0, H264_BASELINE_LEVEL, H264_MAIN_LEVEL, H264_HIGH_LEVEL }; // Supported Channel Mode -enum acldvppChannelMode { DVPP_CHNMODE_VPC = 1, DVPP_CHNMODE_JPEGD = 2, DVPP_CHNMODE_JPEGE = 4 }; +enum acldvppChannelMode { DVPP_CHNMODE_VPC = 1, DVPP_CHNMODE_JPEGD = 2, DVPP_CHNMODE_JPEGE = 4, DVPP_CHNMODE_PNGD = 8 }; // Supported Border Type enum acldvppBorderType { BORDER_CONSTANT = 0, BORDER_REPLICATE, BORDER_REFLECT, BORDER_REFLECT_101 }; diff --git a/inc/external/ge/ge_api_error_codes.h b/inc/external/ge/ge_api_error_codes.h index d0d7981e..2512de0a 100644 --- a/inc/external/ge/ge_api_error_codes.h +++ b/inc/external/ge/ge_api_error_codes.h @@ -72,17 +72,23 @@ class GE_FUNC_VISIBILITY StatusFactory { class GE_FUNC_VISIBILITY ErrorNoRegisterar { public: - ErrorNoRegisterar(uint32_t err, const std::string &desc) { StatusFactory::Instance()->RegisterErrorNo(err, desc); } - ErrorNoRegisterar(uint32_t err, const char *desc) { StatusFactory::Instance()->RegisterErrorNo(err, desc); } + ErrorNoRegisterar(uint32_t err, const std::string &desc) { + StatusFactory::Instance()->RegisterErrorNo(err, desc); + } + ErrorNoRegisterar(uint32_t err, const char *desc) { + StatusFactory::Instance()->RegisterErrorNo(err, desc); + } ~ErrorNoRegisterar() {} }; // Code compose(4 byte), runtime: 2 bit, type: 2 bit, level: 3 bit, sysid: 8 bit, modid: 5 bit, value: 12 bit -#define GE_ERRORNO(runtime, type, level, sysid, modid, name, value, desc) \ - constexpr ge::Status name = \ - ((0xFF & (static_cast(runtime))) << 30) | ((0xFF & (static_cast(type))) << 28) | \ - ((0xFF & (static_cast(level))) << 25) | ((0xFF & (static_cast(sysid))) << 17) | \ - ((0xFF & (static_cast(modid))) << 12) | (0x0FFF & (static_cast(value))); \ +#define GE_ERRORNO(runtime, type, level, sysid, modid, name, value, desc) \ + constexpr ge::Status name = (static_cast(0xFFU & (static_cast(runtime))) << 30) | \ + (static_cast(0xFFU & (static_cast(type))) << 28) | \ + (static_cast(0xFFU & (static_cast(level))) << 25) | \ + (static_cast(0xFFU & (static_cast(sysid))) << 17) | \ + (static_cast(0xFFU & (static_cast(modid))) << 12) | \ + (static_cast(0x0FFFU) & (static_cast(value))); \ const ErrorNoRegisterar g_##name##_errorno(name, desc); #define GE_ERRORNO_EXTERNAL(name, desc) const ErrorNoRegisterar g_##name##_errorno(name, desc); diff --git a/inc/external/ge/ge_api_types.h b/inc/external/ge/ge_api_types.h index ac821281..d2d5bf5d 100644 --- a/inc/external/ge/ge_api_types.h +++ b/inc/external/ge/ge_api_types.h @@ -28,6 +28,7 @@ namespace ge { // Option key: graph run mode const char *const OPTION_GRAPH_RUN_MODE = "ge.graphRunMode"; +const char *const OPTION_DEVICE_TYPE = "ge.deviceType"; // Option key: ome init const char *const OPTION_EXEC_SESSION_ID = "ge.exec.sessionId"; @@ -67,6 +68,7 @@ const char *const OPTION_EXEC_ENABLE_TAILING_OPTIMIZATION = "ge.exec.isTailingOp const char *const OPTION_EXEC_DYNAMIC_INPUT = "ge.exec.dynamicInput"; const char *const OPTION_EXEC_DYNAMIC_EXECUTE_MODE = "ge.exec.dynamicGraphExecuteMode"; const char *const OPTION_EXEC_DATA_INPUTS_SHAPE_RANGE = "ge.exec.dataInputsShapeRange"; +const char *const OPTION_EXEC_ENABLE_COPY_OUTPUT_ADDR = "ge.exec.enableCopyOutputAddr"; // Option key: memory init const char *const GRAPH_MEMORY_MAX_SIZE = "ge.graphMemoryMaxSize"; diff --git a/inc/external/ge/ge_ir_build.h b/inc/external/ge/ge_ir_build.h index 729685a9..cf543315 100644 --- a/inc/external/ge/ge_ir_build.h +++ b/inc/external/ge/ge_ir_build.h @@ -103,7 +103,7 @@ GE_FUNC_VISIBILITY graphStatus aclgrphBuildModel(const ge::Graph &graph, * @retval OtherValues Failure */ ATTRIBUTED_DEPRECATED(GE_FUNC_VISIBILITY graphStatus aclgrphSaveModel(const char *, const ModelBufferData &)) -GE_FUNC_VISIBILITY graphStatus aclgrphSaveModel(const string &output_file, const ModelBufferData &model); +GE_FUNC_VISIBILITY graphStatus aclgrphSaveModel(const std::string &output_file, const ModelBufferData &model); GE_FUNC_VISIBILITY graphStatus aclgrphSaveModel(const char *output_file, const ModelBufferData &model); diff --git a/inc/external/hccl/hccl_types.h b/inc/external/hccl/hccl_types.h index 0e832396..ea09fa4d 100644 --- a/inc/external/hccl/hccl_types.h +++ b/inc/external/hccl/hccl_types.h @@ -53,6 +53,7 @@ typedef enum { HCCL_E_PROFILING = 17, /**< call profiling api fail */ HCCL_E_CCE = 18, /**< call cce api fail */ HCCL_E_NETWORK = 19, /**< call network api fail */ + HCCL_E_AGAIN = 20, /**< try again */ HCCL_E_RESERVED /**< reserved */ } HcclResult; diff --git a/inc/external/runtime/rt_error_codes.h b/inc/external/runtime/rt_error_codes.h index ef7e2ec7..8966f738 100644 --- a/inc/external/runtime/rt_error_codes.h +++ b/inc/external/runtime/rt_error_codes.h @@ -58,6 +58,10 @@ static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream re static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource static const int32_t ACL_ERROR_RT_NO_CDQ_RESOURCE = 207011; // no cdq resource +static const int32_t ACL_ERROR_RT_OVER_LIMIT = 207012; // over limit +static const int32_t ACL_ERROR_RT_QUEUE_EMPTY = 207013; // queue is empty +static const int32_t ACL_ERROR_RT_QUEUE_FULL = 207014; // queue is full +static const int32_t ACL_ERROR_RT_REPEATED_INIT = 207015; // repeated init static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error diff --git a/inc/framework/common/ge_compiler_options.h b/inc/framework/common/ge_compiler_options.h index 5c947346..6876740e 100644 --- a/inc/framework/common/ge_compiler_options.h +++ b/inc/framework/common/ge_compiler_options.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/common/profiling/ge_profiling.h b/inc/framework/common/profiling/ge_profiling.h index e9b207af..0a7c9181 100644 --- a/inc/framework/common/profiling/ge_profiling.h +++ b/inc/framework/common/profiling/ge_profiling.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/common/profiling/ge_runner_profiling.h b/inc/framework/common/profiling/ge_runner_profiling.h index 27e19bce..1c594c5b 100644 --- a/inc/framework/common/profiling/ge_runner_profiling.h +++ b/inc/framework/common/profiling/ge_runner_profiling.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/common/taskdown_common.h b/inc/framework/common/taskdown_common.h index f2f731be..81a532dd 100644 --- a/inc/framework/common/taskdown_common.h +++ b/inc/framework/common/taskdown_common.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/memory/memory_api.h b/inc/framework/memory/memory_api.h index a316fd59..da36cdd6 100644 --- a/inc/framework/memory/memory_api.h +++ b/inc/framework/memory/memory_api.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/omg/ge_init.h b/inc/framework/omg/ge_init.h index 42fd8979..67ef1082 100644 --- a/inc/framework/omg/ge_init.h +++ b/inc/framework/omg/ge_init.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/omg/omg.h b/inc/framework/omg/omg.h index 37d9e26b..a5360bb3 100644 --- a/inc/framework/omg/omg.h +++ b/inc/framework/omg/omg.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/omg/parser/model_parser.h b/inc/framework/omg/parser/model_parser.h index 70444e0a..d311706d 100644 --- a/inc/framework/omg/parser/model_parser.h +++ b/inc/framework/omg/parser/model_parser.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/omg/parser/op_parser.h b/inc/framework/omg/parser/op_parser.h index 70bec218..7d02b257 100644 --- a/inc/framework/omg/parser/op_parser.h +++ b/inc/framework/omg/parser/op_parser.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/omg/parser/parser_api.h b/inc/framework/omg/parser/parser_api.h index 23df0177..a493e29f 100644 --- a/inc/framework/omg/parser/parser_api.h +++ b/inc/framework/omg/parser/parser_api.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/omg/parser/parser_factory.h b/inc/framework/omg/parser/parser_factory.h index 9d6590c0..06aaecb7 100644 --- a/inc/framework/omg/parser/parser_factory.h +++ b/inc/framework/omg/parser/parser_factory.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/inc/framework/omg/parser/weights_parser.h b/inc/framework/omg/parser/weights_parser.h index e4436044..a568f927 100644 --- a/inc/framework/omg/parser/weights_parser.h +++ b/inc/framework/omg/parser/weights_parser.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/metadef b/metadef index 60df4b39..7d777404 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit 60df4b39a6f639c21dd7deb220b93345451938f5 +Subproject commit 7d777404b3b7fe7daeaf00e566e431c6a05b040a diff --git a/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h b/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h index 7e0f94a8..2a10859c 100644 --- a/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h +++ b/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h @@ -17,6 +17,7 @@ #ifndef AICPU_OP_TYPE_LIST_H_ #define AICPU_OP_TYPE_LIST_H_ +extern "C" { enum OpKernelType { TF_KERNEL, CPU_KERNEL @@ -36,12 +37,6 @@ struct SysOpInfo { OpKernelType kernelsType; }; -struct OpParamInfo { - uint64_t num; - uint64_t dtypeList; - uint64_t formatList; -}; - struct SysOpCheckInfo { uint64_t opListNum; uint64_t offSetLen; @@ -57,4 +52,6 @@ struct SysOpCheckResp { uint64_t opParamInfoList; }; #pragma pack(pop) +} + #endif // AICPU_OP_TYPE_LIST_H_ diff --git a/third_party/fwkacllib/inc/hccl/base.h b/third_party/fwkacllib/inc/hccl/base.h index ffbf552b..aa43c82a 100644 --- a/third_party/fwkacllib/inc/hccl/base.h +++ b/third_party/fwkacllib/inc/hccl/base.h @@ -86,6 +86,47 @@ enum OriginalGraphShapeType { SHAPE_RESERVED /**< reserved */ }; +enum HcclEventType { + HCCL_EVENT_SEND_COMPLETION = 0, + HCCL_EVENT_RECV_REQUEST, + HCCL_EVENT_RECV_COMPLETION, + HCCL_EVENT_CONGESTION_RELIEF, + HCCL_EVENT_RESERVED /**< reserved */ +}; + +const u32 TAG_MAX_LEN = 127; // ×î´óµÄtag ³¤¶È +using TagAttr = struct TagAttrDef { + char name[TAG_MAX_LEN + 1]; // tag±êʶ + // tag±êʶµÄ½ÓÊÕÊý¾Ý£¬µ÷ÓÃÕßÊÇ·ñ»áÖ÷¶¯µ÷ÓýÓÊÕ½Ó¿Ú£¬0 = ·ñ, 1 = »á(Ô¤Áô£¬Ôݲ»Ö§³Ö)¡£ + // ¶ÔÓÚactiveRecv = 0£¬µ±½ÓÊÕ²àÊÕµ½Êý¾Ý»òÕß·¢ËÍÇëÇóʱ£¬Ö÷¶¯Í¨Öªµ÷ÓÃÕß¡£ + uint32_t activeRecv; + uint32_t sendCredit; // ÅäÖøÃtagÔÊÐíinflightµÄsend¸öÊý + uint32_t eventId; +}; + +using HcclEventMsg = struct HcclEventMsgDef { + HcclComm comm; + u32 peerRank; + u32 tag; + // 0:HCCL_SEND_COMPLETION; 1:HCCL_RECV_COMPLETION; 2:HCCL_RECV_REQUEST; 3:HCCL_CONGESTION_RELIEF + u32 hcclEventType; + union { + struct { + u32 reserver; + } sendCompletionItem; + struct { + u32 reserver; + } recvRequestItem; + struct { + u32 reserver; + } recvCompletionItem; + struct CongestionReliefItem { + u32 reserver; + } congestionReliefItem; + } desc; +}; + + /** * @brief stream handle. */ diff --git a/third_party/fwkacllib/inc/mmpa/mmpa_api.h b/third_party/fwkacllib/inc/mmpa/mmpa_api.h index f8d5ccf3..c48aaa63 100644 --- a/third_party/fwkacllib/inc/mmpa/mmpa_api.h +++ b/third_party/fwkacllib/inc/mmpa/mmpa_api.h @@ -40,7 +40,6 @@ #include #include #include -#include #include #include #include diff --git a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h index 3d196e41..46fb6e21 100644 --- a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h +++ b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h @@ -58,31 +58,31 @@ typedef long MM_LONG; typedef VOID *(*userProcFunc)(VOID *pulArg); typedef struct { - userProcFunc procFunc; // Callback function pointer - VOID *pulArg; // Callback function parameters + userProcFunc procFunc; // Callback function pointer + VOID *pulArg; // Callback function parameters } mmUserBlock_t; typedef struct { - const char *dli_fname; - void *dli_fbase; - const char *dli_sname; - void *dli_saddr; - size_t dli_size; /* ELF only */ - int dli_bind; /* ELF only */ - int dli_type; + const CHAR *dli_fname; + VOID *dli_fbase; + const CHAR *dli_sname; + VOID *dli_saddr; + size_t dli_size; /* ELF only */ + INT32 dli_bind; /* ELF only */ + INT32 dli_type; } mmDlInfo; typedef struct { - int wSecond; // Seconds. [0-60] (1 leap second) - int wMinute; // Minutes. [0-59] - int wHour; // Hours. [0-23] - int wDay; // Day. [1-31] - int wMonth; // Month. [1-12] - int wYear; // Year - int wDayOfWeek; // Day of week. [0-6] - int tm_yday; // Days in year.[0-365] - int tm_isdst; // DST. [-1/0/1] - long int wMilliseconds; // milliseconds + INT32 wSecond; // Seconds. [0-60] (1 leap second) + INT32 wMinute; // Minutes. [0-59] + INT32 wHour; // Hours. [0-23] + INT32 wDay; // Day. [1-31] + INT32 wMonth; // Month. [1-12] + INT32 wYear; // Year + INT32 wDayOfWeek; // Day of week. [0-6] + INT32 tm_yday; // Days in year.[0-365] + INT32 tm_isdst; // DST. [-1/0/1] + LONG wMilliseconds; // milliseconds } mmSystemTime_t; typedef sem_t mmSem_t; @@ -98,72 +98,72 @@ typedef ssize_t mmSsize_t; typedef size_t mmSize; // size typedef struct { - UINT32 createFlag; - INT32 oaFlag; + UINT32 createFlag; + INT32 oaFlag; } mmCreateFlag; typedef struct { - VOID *sendBuf; - INT32 sendLen; + VOID *sendBuf; + INT32 sendLen; } mmIovSegment; typedef struct in_addr mmInAddr; typedef struct { - VOID *inbuf; - INT32 inbufLen; - VOID *outbuf; - INT32 outbufLen; - mmOverLap *oa; + VOID *inbuf; + INT32 inbufLen; + VOID *outbuf; + INT32 outbufLen; + mmOverLap *oa; } mmIoctlBuf; typedef int mmAtomicType; typedef int mmAtomicType64; typedef enum { - pollTypeRead = 1, // pipe read - pollTypeRecv, // socket recv - pollTypeIoctl, // ioctl + pollTypeRead = 1, // pipe read + pollTypeRecv, // socket recv + pollTypeIoctl, // ioctl } mmPollType; typedef struct { - mmPollHandle handle; // The file descriptor or handle of poll is required - mmPollType pollType; // Operation type requiring poll + mmPollHandle handle; // The file descriptor or handle of poll is required + mmPollType pollType; // Operation type requiring poll // read or recv or ioctl - INT32 ioctlCode; // IOCTL operation code, dedicated to IOCTL - mmComPletionKey completionKey; // The default value is blank, which is used in windows + INT32 ioctlCode; // IOCTL operation code, dedicated to IOCTL + mmComPletionKey completionKey; // The default value is blank, which is used in windows // The data used to receive the difference between which handle is readable } mmPollfd; typedef struct { - VOID *priv; // User defined private content - mmPollHandle bufHandle; // Value of handle corresponding to buf - mmPollType bufType; // Data types polled to - VOID *buf; // Data used in poll - UINT32 bufLen; // Data length used in poll - UINT32 bufRes; // Actual return length + VOID *priv; // User defined private content + mmPollHandle bufHandle; // Value of handle corresponding to buf + mmPollType bufType; // Data types polled to + VOID *buf; // Data used in poll + UINT32 bufLen; // Data length used in poll + UINT32 bufRes; // Actual return length } mmPollData, *pmmPollData; typedef VOID (*mmPollBack)(pmmPollData); typedef struct { - INT32 tz_minuteswest; // How many minutes is it different from Greenwich - INT32 tz_dsttime; // type of DST correction + INT32 tz_minuteswest; // How many minutes is it different from Greenwich + INT32 tz_dsttime; // type of DST correction } mmTimezone; typedef struct { - LONG tv_sec; - LONG tv_usec; + LONG tv_sec; + LONG tv_usec; } mmTimeval; typedef struct { - MM_LONG tv_sec; - MM_LONG tv_nsec; + MM_LONG tv_sec; + MM_LONG tv_nsec; } mmTimespec; typedef struct { - ULONGLONG totalSize; - ULONGLONG freeSize; - ULONGLONG availSize; + ULONGLONG totalSize; + ULONGLONG freeSize; + ULONGLONG availSize; } mmDiskSize; #define mmTLS __thread @@ -174,40 +174,40 @@ typedef mode_t mmMode_t; typedef struct option mmStructOption; typedef struct { - char addr[MMPA_MACINFO_DEFAULT_SIZE]; // ex:aa-bb-cc-dd-ee-ff\0 + CHAR addr[MMPA_MACINFO_DEFAULT_SIZE]; // ex:aa-bb-cc-dd-ee-ff\0 } mmMacInfo; typedef struct { - char **argv; - INT32 argvCount; - char **envp; - INT32 envpCount; + CHAR **argv; + INT32 argvCount; + CHAR **envp; + INT32 envpCount; } mmArgvEnv; typedef struct { - char arch[MMPA_CPUDESC_DEFAULT_SIZE]; - char manufacturer[MMPA_CPUDESC_DEFAULT_SIZE]; // vendor - char version[MMPA_CPUDESC_DEFAULT_SIZE]; // modelname - INT32 frequency; // cpu frequency - INT32 maxFrequency; // max speed - INT32 ncores; // cpu cores - INT32 nthreads; // cpu thread count - INT32 ncounts; // logical cpu nums + CHAR arch[MMPA_CPUDESC_DEFAULT_SIZE]; + CHAR manufacturer[MMPA_CPUDESC_DEFAULT_SIZE]; // vendor + CHAR version[MMPA_CPUDESC_DEFAULT_SIZE]; // modelname + INT32 frequency; // cpu frequency + INT32 maxFrequency; // max speed + INT32 ncores; // cpu cores + INT32 nthreads; // cpu thread count + INT32 ncounts; // logical cpu nums } mmCpuDesc; typedef mode_t MODE; typedef struct { - INT32 detachFlag; // Determine whether to set separation property 0, not to separate 1 - INT32 priorityFlag; // Determine whether to set priority 0 and not set 1 - INT32 priority; // Priority value range to be set 1-99 - INT32 policyFlag; // Set scheduling policy or not 0 do not set 1 setting - INT32 policy; // Scheduling policy value value - // MMPA_THREAD_SCHED_RR - // MMPA_THREAD_SCHED_OTHER - // MMPA_THREAD_SCHED_FIFO - INT32 stackFlag; // Set stack size or not: 0 does not set 1 setting - UINT32 stackSize; // The stack size unit bytes to be set cannot be less than MMPA_THREAD_STACK_MIN + INT32 detachFlag; // Determine whether to set separation property 0, not to separate 1 + INT32 priorityFlag; // Determine whether to set priority 0 and not set 1 + INT32 priority; // Priority value range to be set 1-99 + INT32 policyFlag; // Set scheduling policy or not 0 do not set 1 setting + INT32 policy; // Scheduling policy value value + // MMPA_THREAD_SCHED_RR + // MMPA_THREAD_SCHED_OTHER + // MMPA_THREAD_SCHED_FIFO + INT32 stackFlag; // Set stack size or not: 0 does not set 1 setting + UINT32 stackSize; // The stack size unit bytes to be set cannot be less than MMPA_THREAD_STACK_MIN } mmThreadAttr; #ifdef __ANDROID__ @@ -326,8 +326,8 @@ MMPA_FUNC_VISIBILITY INT32 mmCondDestroy(mmCond *cond); MMPA_FUNC_VISIBILITY INT32 mmGetPid(); MMPA_FUNC_VISIBILITY INT32 mmGetTid(); MMPA_FUNC_VISIBILITY INT32 mmGetPidHandle(mmProcess *processHandle); -MMPA_FUNC_VISIBILITY INT32 mmGetLocalTime(mmSystemTime_t *sysTime); -MMPA_FUNC_VISIBILITY INT32 mmGetSystemTime(mmSystemTime_t *sysTime); +MMPA_FUNC_VISIBILITY INT32 mmGetLocalTime(mmSystemTime_t *sysTimePtr); +MMPA_FUNC_VISIBILITY INT32 mmGetSystemTime(mmSystemTime_t *sysTimePtr); MMPA_FUNC_VISIBILITY INT32 mmSemInit(mmSem_t *sem, UINT32 value); MMPA_FUNC_VISIBILITY INT32 mmSemWait(mmSem_t *sem); @@ -393,7 +393,7 @@ MMPA_FUNC_VISIBILITY mmSsize_t mmWritev(mmProcess fd, mmIovSegment *iov, INT32 i MMPA_FUNC_VISIBILITY VOID mmMb(); MMPA_FUNC_VISIBILITY INT32 mmInetAton(const CHAR *addrStr, mmInAddr *addr); -MMPA_FUNC_VISIBILITY mmProcess mmOpenFile(const CHAR *fileName, UINT32 access, mmCreateFlag fileFlag); +MMPA_FUNC_VISIBILITY mmProcess mmOpenFile(const CHAR *fileName, UINT32 accessFlag, mmCreateFlag fileFlag); MMPA_FUNC_VISIBILITY mmSsize_t mmReadFile(mmProcess fileId, VOID *buffer, INT32 len); MMPA_FUNC_VISIBILITY mmSsize_t mmWriteFile(mmProcess fileId, VOID *buffer, INT32 len); MMPA_FUNC_VISIBILITY INT32 mmCloseFile(mmProcess fileId); @@ -407,13 +407,13 @@ MMPA_FUNC_VISIBILITY mmAtomicType64 mmValueSub64(mmAtomicType64 *ptr, mmAtomicTy MMPA_FUNC_VISIBILITY INT32 mmCreateTaskWithDetach(mmThread *threadHandle, mmUserBlock_t *funcBlock); // The following 3 interfaces are to be deleted -MMPA_FUNC_VISIBILITY INT32 mmCreateNamedPipe(mmPipeHandle pipe[], CHAR *pipeName[], INT32 waitMode); -MMPA_FUNC_VISIBILITY INT32 mmOpenNamePipe(mmPipeHandle pipe[], CHAR *pipeName[], INT32 waitMode); +MMPA_FUNC_VISIBILITY INT32 mmCreateNamedPipe(mmPipeHandle pipeHandle[], CHAR *pipeName[], INT32 waitMode); +MMPA_FUNC_VISIBILITY INT32 mmOpenNamePipe(mmPipeHandle pipeHandle[], CHAR *pipeName[], INT32 waitMode); MMPA_FUNC_VISIBILITY VOID mmCloseNamedPipe(mmPipeHandle namedPipe[]); -MMPA_FUNC_VISIBILITY INT32 mmCreatePipe(mmPipeHandle pipe[], CHAR *pipeName[], UINT32 pipeCount, INT32 waitMode); -MMPA_FUNC_VISIBILITY INT32 mmOpenPipe(mmPipeHandle pipe[], CHAR *pipeName[], UINT32 pipeCount, INT32 waitMode); -MMPA_FUNC_VISIBILITY VOID mmClosePipe(mmPipeHandle pipe[], UINT32 pipeCount); +MMPA_FUNC_VISIBILITY INT32 mmCreatePipe(mmPipeHandle pipeHandle[], CHAR *pipeName[], UINT32 pipeCount, INT32 waitMode); +MMPA_FUNC_VISIBILITY INT32 mmOpenPipe(mmPipeHandle pipeHandle[], CHAR *pipeName[], UINT32 pipeCount, INT32 waitMode); +MMPA_FUNC_VISIBILITY VOID mmClosePipe(mmPipeHandle pipeHandle[], UINT32 pipeCount); // Poll related interface MMPA_FUNC_VISIBILITY mmCompletionHandle mmCreateCompletionPort(); @@ -467,10 +467,10 @@ MMPA_FUNC_VISIBILITY INT32 mmGetOptOpt(); MMPA_FUNC_VISIBILITY VOID mmSetOpOpt(INT32 mmOptOpt); MMPA_FUNC_VISIBILITY CHAR *mmGetOptArg(); MMPA_FUNC_VISIBILITY VOID mmSetOptArg(CHAR *mmOptArg); -MMPA_FUNC_VISIBILITY INT32 mmGetOpt(INT32 argc, char *const *argv, const char *opts); +MMPA_FUNC_VISIBILITY INT32 mmGetOpt(INT32 argc, CHAR *const *argv, const CHAR *opts); MMPA_FUNC_VISIBILITY INT32 mmGetOptLong(INT32 argc, - char *const *argv, - const char *opts, + CHAR *const *argv, + const CHAR *opts, const mmStructOption *longOpts, INT32 *longIndex); @@ -496,7 +496,7 @@ MMPA_FUNC_VISIBILITY INT32 mmSetEnv(const CHAR *name, const CHAR *value, INT32 o MMPA_FUNC_VISIBILITY CHAR *mmStrTokR(CHAR *str, const CHAR *delim, CHAR **saveptr); MMPA_FUNC_VISIBILITY CHAR *mmDirName(CHAR *path); MMPA_FUNC_VISIBILITY CHAR *mmBaseName(CHAR *path); -MMPA_FUNC_VISIBILITY INT32 mmGetDiskFreeSpace(const char *path, mmDiskSize *diskSize); +MMPA_FUNC_VISIBILITY INT32 mmGetDiskFreeSpace(const CHAR *path, mmDiskSize *diskSize); /* * Function: set the thread name created by mmcreatetask @@ -540,7 +540,7 @@ MMPA_FUNC_VISIBILITY INT32 mmGetCpuInfo(mmCpuDesc **cpuInfo, INT32 *count); MMPA_FUNC_VISIBILITY INT32 mmCpuInfoFree(mmCpuDesc *cpuInfo, INT32 count); MMPA_FUNC_VISIBILITY INT32 mmCreateProcess(const CHAR *fileName, const mmArgvEnv *env, - const char *stdoutRedirectFile, + const CHAR *stdoutRedirectFile, mmProcess *id); MMPA_FUNC_VISIBILITY INT32 mmCreateTaskWithThreadAttr(mmThread *threadHandle, diff --git a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h index b17234b8..699fe815 100644 --- a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h +++ b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h @@ -368,8 +368,8 @@ MMPA_FUNC_VISIBILITY INT32 mmCondDestroy(mmCond *cond); MMPA_FUNC_VISIBILITY INT32 mmGetPid(VOID); MMPA_FUNC_VISIBILITY INT32 mmGetTid(VOID); MMPA_FUNC_VISIBILITY INT32 mmGetPidHandle(mmProcess *processHandle); -MMPA_FUNC_VISIBILITY INT32 mmGetLocalTime(mmSystemTime_t *sysTime); -MMPA_FUNC_VISIBILITY INT32 mmGetSystemTime(mmSystemTime_t *sysTime); +MMPA_FUNC_VISIBILITY INT32 mmGetLocalTime(mmSystemTime_t *sysTimePtr); +MMPA_FUNC_VISIBILITY INT32 mmGetSystemTime(mmSystemTime_t *sysTimePtr); MMPA_FUNC_VISIBILITY INT32 mmSemInit(mmSem_t *sem, UINT32 value); MMPA_FUNC_VISIBILITY INT32 mmSemWait(mmSem_t *sem); MMPA_FUNC_VISIBILITY INT32 mmSemPost(mmSem_t *sem); @@ -431,7 +431,7 @@ MMPA_FUNC_VISIBILITY mmSsize_t mmWritev(mmSockHandle fd, mmIovSegment *iov, INT3 MMPA_FUNC_VISIBILITY VOID mmMb(); MMPA_FUNC_VISIBILITY INT32 mmInetAton(const CHAR *addrStr, mmInAddr *addr); -MMPA_FUNC_VISIBILITY mmProcess mmOpenFile(const CHAR *fileName, UINT32 access, mmCreateFlag fileFlag); +MMPA_FUNC_VISIBILITY mmProcess mmOpenFile(const CHAR *fileName, UINT32 accessFlag, mmCreateFlag fileFlag); MMPA_FUNC_VISIBILITY mmSsize_t mmReadFile(mmProcess fileId, VOID *buffer, INT32 len); MMPA_FUNC_VISIBILITY mmSsize_t mmWriteFile(mmProcess fileId, VOID *buffer, INT32 len); MMPA_FUNC_VISIBILITY INT32 mmCloseFile(mmProcess fileId); @@ -444,13 +444,13 @@ MMPA_FUNC_VISIBILITY mmAtomicType64 mmValueInc64(mmAtomicType64 *ptr, mmAtomicTy MMPA_FUNC_VISIBILITY mmAtomicType64 mmValueSub64(mmAtomicType64 *ptr, mmAtomicType64 value); MMPA_FUNC_VISIBILITY INT32 mmCreateTaskWithDetach(mmThread *threadHandle, mmUserBlock_t *funcBlock); -MMPA_FUNC_VISIBILITY INT32 mmCreateNamedPipe(mmPipeHandle pipe[], CHAR *pipeName[], INT32 waitMode); -MMPA_FUNC_VISIBILITY INT32 mmOpenNamePipe(mmPipeHandle pipe[], CHAR *pipeName[], INT32 waitMode); +MMPA_FUNC_VISIBILITY INT32 mmCreateNamedPipe(mmPipeHandle pipeHandle[], CHAR *pipeName[], INT32 waitMode); +MMPA_FUNC_VISIBILITY INT32 mmOpenNamePipe(mmPipeHandle pipeHandle[], CHAR *pipeName[], INT32 waitMode); MMPA_FUNC_VISIBILITY VOID mmCloseNamedPipe(mmPipeHandle namedPipe[]); -MMPA_FUNC_VISIBILITY INT32 mmCreatePipe(mmPipeHandle pipe[], CHAR *pipeName[], UINT32 pipeCount, INT32 waitMode); -MMPA_FUNC_VISIBILITY INT32 mmOpenPipe(mmPipeHandle pipe[], CHAR *pipeName[], UINT32 pipeCount, INT32 waitMode); -MMPA_FUNC_VISIBILITY VOID mmClosePipe(mmPipeHandle pipe[], UINT32 pipeCount); +MMPA_FUNC_VISIBILITY INT32 mmCreatePipe(mmPipeHandle pipeHandle[], CHAR *pipeName[], UINT32 pipeCount, INT32 waitMode); +MMPA_FUNC_VISIBILITY INT32 mmOpenPipe(mmPipeHandle pipeHandle[], CHAR *pipeName[], UINT32 pipeCount, INT32 waitMode); +MMPA_FUNC_VISIBILITY VOID mmClosePipe(mmPipeHandle pipeHandle[], UINT32 pipeCount); MMPA_FUNC_VISIBILITY mmCompletionHandle mmCreateCompletionPort(); MMPA_FUNC_VISIBILITY VOID mmCloseCompletionPort(mmCompletionHandle handle); diff --git a/third_party/fwkacllib/inc/ops/aipp.h b/third_party/fwkacllib/inc/ops/aipp.h index 86805f72..6db4d783 100644 --- a/third_party/fwkacllib/inc/ops/aipp.h +++ b/third_party/fwkacllib/inc/ops/aipp.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/all_ops.h b/third_party/fwkacllib/inc/ops/all_ops.h index b15f2292..b67ead37 100644 --- a/third_party/fwkacllib/inc/ops/all_ops.h +++ b/third_party/fwkacllib/inc/ops/all_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/array_ops.h b/third_party/fwkacllib/inc/ops/array_ops.h index 4b45f4cf..18028c19 100644 --- a/third_party/fwkacllib/inc/ops/array_ops.h +++ b/third_party/fwkacllib/inc/ops/array_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -701,6 +701,31 @@ REG_OP(Unsqueeze) .ATTR(axes, ListInt, {}) .OP_END_FACTORY_REG(Unsqueeze) +/** +*@brief Inserts a dimension of 1 into a tensor's shape. Only the tensor shape is changed, without changing the data. \n + +*@par Inputs: +*@li x: Original tensor. + +*@par Attributes: +*@li axes: List of ints indicating the dimensions to be inserted. \n + +*@par Outputs: +*y: Reshape tensor with same data as input. \n + +*@par Third-party framework compatibility +*Compatible with the Onnx operator Unsqueeze. + +*@par Restrictions: +* Warning: THIS FUNCTION IS DEPRECATED. Please use Unsqueeze instead. +*/ + +REG_OP(UnsqueezeV2) + .INPUT(x, TensorType::ALL()) + .OUTPUT(y, TensorType::ALL()) + .ATTR(axis, ListInt, {}) + .OP_END_FACTORY_REG(UnsqueezeV2) + /** *@brief Reshapes a tensor. Only the tensor shape is changed, without changing the data. \n @@ -753,6 +778,30 @@ REG_OP(Squeeze) .ATTR(axis, ListInt, {}) .OP_END_FACTORY_REG(Squeeze) +/** +*@brief Removes dimensions of size 1 from the shape of a tensor. \n + +*@par Inputs: +*x: A tensor. \n + +*@par Attributes: +*axis: An optional list of int32 or int64. If not specified, squeezes all dimensions of size 1. If specified, only squeezes the dimensions listed. It is an error to squeeze a dimension that is not 1. \n + +*@par Outputs: +*y: A tensor. \n + +*@par Third-party framework compatibility +*Compatible with the TensorFlow operator Squeeze. + +*@par Restrictions: +* Warning: THIS FUNCTION IS DEPRECATED. Please use Squeeze instead. +*/ +REG_OP(SqueezeV2) + .INPUT(x, TensorType::ALL()) + .OUTPUT(y, TensorType::ALL()) + .ATTR(axis, ListInt, {}) + .OP_END_FACTORY_REG(SqueezeV2) + /** *@brief Returns an integer representing the rank of input tensor. The rank of a tensor is the number of indices required to uniquely select each element of the tensor, that is, the dimension size of the tensor. \n @@ -1226,6 +1275,35 @@ REG_OP(NonZero) .ATTR(dtype, Type, DT_INT64) .OP_END_FACTORY_REG(NonZero) +/** +*@Returns a tensor containing the indices of all non-zero elements of input. \n + +*@par Inputs: +*x: A Tensor. Must be one of the following types: float16, float32, int32, int64. + +*@par Attributes: +* transpose: the output tensor will be transposed if true. \n + +*@par Outputs: +* value: A Tensor. Has the same type as "x" . \n +* index: A Tensor. The type is INT32, means index for input. \n +* count: A Scalar. The type is INT32, means count for non_zero ele in input. \n + +*@par Third-party framework compatibility +*Compatible with the PyTorch operator NonZeroWithValue. +*/ + +REG_OP(NonZeroWithValue) + .INPUT(x, TensorType({DT_DOUBLE, DT_FLOAT, DT_FLOAT16, DT_INT8, DT_UINT8, DT_INT16, \ + DT_UINT16, DT_INT32, DT_UINT32, DT_INT64, DT_UINT64, DT_BOOL})) + .OUTPUT(value, TensorType({DT_DOUBLE, DT_FLOAT, DT_FLOAT16, DT_INT8, DT_UINT8, DT_INT16, \ + DT_UINT16, DT_INT32, DT_UINT32, DT_INT64, DT_UINT64, DT_BOOL})) + .OUTPUT(index, TensorType({DT_INT32})) + .OUTPUT(count, TensorType({DT_INT32})) + .ATTR(transpose, Bool, false) + .ATTR(dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(NonZeroWithValue) + /** * @brief Expand the input tensor to a compatible shape. \n @@ -1258,24 +1336,53 @@ REG_OP(ExpandD) * Three inputs, including: * @li bucket_list: A 1-D tensor of type int32 with the value of ivf_counts and ivf_offset index. \n * @li ivf_counts: A 1-D tensor of type int32 with the value of ivf counts. \n -* @li ivf_offset: A 1-D tensor of type int32 with the value of ivf offset. \n +* @li ivf_offset: A 1-D tensor of type int32 or int64 with the value of ivf offset. \n * @par Attributes: * total_limit: A int64 type maximum value of the sum of ivf_counts corresponding to bucket_list. \n * @par Outputs: * @li buckets_limit: A 1-D tensor of type int32 with the sum <= total_limit. \n -* @li buckets_offset: A 1-D tensor of type int32 with the value of ivf_offset corresponding to bucket_list. \n +* @li buckets_offset: A 1-D tensor of type int32 or int64 with the value of ivf_offset corresponding to bucket_list. \n */ REG_OP(CalcBucketsLimitAndOffset) .INPUT(bucket_list, TensorType({DT_INT32})) .INPUT(ivf_counts, TensorType({DT_INT32})) - .INPUT(ivf_offset, TensorType({DT_INT32})) + .INPUT(ivf_offset, TensorType({DT_INT32, DT_INT64})) .OUTPUT(buckets_limit, TensorType({DT_INT32})) - .OUTPUT(buckets_offset, TensorType({DT_INT32})) + .OUTPUT(buckets_offset, TensorType({DT_INT32, DT_INT64})) .REQUIRED_ATTR(total_limit, Int) .OP_END_FACTORY_REG(CalcBucketsLimitAndOffset) +/** +*@brief Get dim number in tensordesc. \n + +*@par Inputs: +*x: A Tensor. \n + +*@par Outputs: +*y: A 1D tensor. The data type must be int32. \n +*/ +REG_OP(GetShape) + .DYNAMIC_INPUT(x, TensorType({DT_DOUBLE, DT_FLOAT, DT_FLOAT16, DT_INT8, DT_UINT8, DT_INT16, \ + DT_UINT16, DT_INT32, DT_UINT32, DT_INT64, DT_UINT64, DT_BOOL})) + .OUTPUT(y, TensorType({DT_INT32})) + .OP_END_FACTORY_REG(GetShape) + +/** +*@brief Update the tensor_desc of the output. \n + +* @par attributes: +* @li shape: A listInt contains the data to update. \n + +*@par outputs: +* y: a tensor_desc, type is int.\n +*/ +REG_OP(UpdateTensorDesc) + .OUTPUT(y, TensorType({DT_BOOL, DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT32, DT_UINT8, + DT_INT64, DT_UINT64, DT_INT16, DT_UINT16, DT_DOUBLE})) + .REQUIRED_ATTR(shape, ListInt) + .OP_END_FACTORY_REG(UpdateTensorDesc) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_ARRAY_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/audio_ops.h b/third_party/fwkacllib/inc/ops/audio_ops.h index f05135d1..d9883253 100644 --- a/third_party/fwkacllib/inc/ops/audio_ops.h +++ b/third_party/fwkacllib/inc/ops/audio_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h b/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h index d0800a08..9583eff9 100644 --- a/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h +++ b/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/batch_ops.h b/third_party/fwkacllib/inc/ops/batch_ops.h index ca4fe1db..4b78951d 100644 --- a/third_party/fwkacllib/inc/ops/batch_ops.h +++ b/third_party/fwkacllib/inc/ops/batch_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/bitwise_ops.h b/third_party/fwkacllib/inc/ops/bitwise_ops.h index dac78118..d032476d 100644 --- a/third_party/fwkacllib/inc/ops/bitwise_ops.h +++ b/third_party/fwkacllib/inc/ops/bitwise_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/boosted_trees_ops.h b/third_party/fwkacllib/inc/ops/boosted_trees_ops.h index 08e54824..550e8b7d 100644 --- a/third_party/fwkacllib/inc/ops/boosted_trees_ops.h +++ b/third_party/fwkacllib/inc/ops/boosted_trees_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h b/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h index 890c52ae..e20607bf 100644 --- a/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h +++ b/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/case_condition_ops.h b/third_party/fwkacllib/inc/ops/case_condition_ops.h index 85dba609..85064845 100644 --- a/third_party/fwkacllib/inc/ops/case_condition_ops.h +++ b/third_party/fwkacllib/inc/ops/case_condition_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/cluster.h b/third_party/fwkacllib/inc/ops/cluster.h new file mode 100644 index 00000000..f3242a13 --- /dev/null +++ b/third_party/fwkacllib/inc/ops/cluster.h @@ -0,0 +1,58 @@ +/** + * Copyright 2019-2020 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. + */ + +/*! + * \file cluster.h + * \brief + */ +#ifndef OPS_BUILT_IN_OP_PROTO_INC_CLUSTER_H_ +#define OPS_BUILT_IN_OP_PROTO_INC_CLUSTER_H_ + +#include "graph/operator_reg.h" +#include "graph/operator.h" + +namespace ge { +/** +* @brief Perform k-means clustering on a data matrix. \n + +* @par Inputs: +* Three required inputs and one optional inputs, including: \n +* @li x: A 2D tensor of data type float32. \n +* @li y: A 2D tensor of data type float32. \n +* @li sum_square_x: An optional 2D tensor of data type float32. \n +* @li sum_square_y: A 2D tensor of data type float32. \n + +* @par Attributes: +* use_actual_distance: Indicates whether to calculate the complete distance. \n + +* @par Outputs: +* @li segment_sum: A tensor of data type float32. \n +* @li segment_count: A tensor of data type float32. \n +* @li k_mean_total_sum: A tensor of data type float32. \n +*/ +REG_OP(KMeansCentroids) + .INPUT(x, TensorType({DT_FLOAT})) + .INPUT(y, TensorType({DT_FLOAT})) + .INPUT(sum_square_y, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(sum_square_x, TensorType({DT_FLOAT})) + .OUTPUT(segment_sum, TensorType({DT_FLOAT})) + .OUTPUT(segment_count, TensorType({DT_FLOAT})) + .OUTPUT(kmean_total_sum, TensorType({DT_FLOAT})) + .ATTR(use_actual_distance, Bool, false) + .OP_END_FACTORY_REG(KMeansCentroids) +} // namespace ge + +#endif // OPS_BUILT_IN_OP_PROTO_INC_CLUSTER_H_ diff --git a/third_party/fwkacllib/inc/ops/condtake_ops.h b/third_party/fwkacllib/inc/ops/condtake_ops.h index 029cffbf..5e91eb07 100644 --- a/third_party/fwkacllib/inc/ops/condtake_ops.h +++ b/third_party/fwkacllib/inc/ops/condtake_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/control_flow_ops.h b/third_party/fwkacllib/inc/ops/control_flow_ops.h index cd993599..53a213f7 100644 --- a/third_party/fwkacllib/inc/ops/control_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/control_flow_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h b/third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h index f52c90b0..79a64c2c 100644 --- a/third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h +++ b/third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/correlation.h b/third_party/fwkacllib/inc/ops/correlation.h index caebba50..c7262cbb 100644 --- a/third_party/fwkacllib/inc/ops/correlation.h +++ b/third_party/fwkacllib/inc/ops/correlation.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/ctc_ops.h b/third_party/fwkacllib/inc/ops/ctc_ops.h index 6e908091..7729432e 100644 --- a/third_party/fwkacllib/inc/ops/ctc_ops.h +++ b/third_party/fwkacllib/inc/ops/ctc_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/data_flow_ops.h b/third_party/fwkacllib/inc/ops/data_flow_ops.h index 32454d27..492a58ae 100644 --- a/third_party/fwkacllib/inc/ops/data_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/data_flow_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -2336,12 +2336,14 @@ REG_OP(CacheAllIndexToLocal) /** *@brief LRUCacheV2, aicore LRUCache. + *@par Inputs: *index_list: exchange index list *data: host data *cache: gm cache *tag: cache's tag *is_last_call: if is last call write all cache to data + *@par Outputs: *data: output data *cache: gm cache @@ -2349,8 +2351,11 @@ REG_OP(CacheAllIndexToLocal) *index_offset_list: index_offset_list *not_in_cache_index_list: output not in cache's index_list *not_in_cache_number: scalar + *@par Attributes: *pre_route_count: types of all outputs + +*@par Restrictions: *Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(LRUCacheV2) diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index bcf50058..4cb3d961 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -132,7 +132,7 @@ REG_OP(MinimumGrad) *dst_type: An required attribute of type int32, specifying the dst data type. \n *@par Outputs: -*y:A Tensor. Has the same type as x. +*y:A Tensor with same shape as x, and data type is specified by dst_type. */ REG_OP(Cast) .INPUT(x, TensorType({DT_BOOL, DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT32, DT_UINT8, @@ -3391,57 +3391,57 @@ REG_OP(TensorRedirect) .OP_END_FACTORY_REG(TensorRedirect) /** -* @brief Performs the element-wise division of tensor x2 by tensor x3, -* multiply the result by the scalar value and add it to tensor x1 +* @brief Performs the element-wise division of tensor x1 by tensor x2, +* multiply the result by the scalar value and add it to tensor input_data. * @par Inputs: * Four inputs, including: * @li input_data: A mutable input Tensor. Must be one of the following types: -* float16, float32. -* @li x1: A mutable input Tensor of the same type as x1. -* @li x2: A mutable input Tensor of the same type as x1. +* float16, float32, double, int64. +* @li x1: A mutable input Tensor of the same type as input_data. +* @li x2: A mutable input Tensor of the same type as input_data. * @li value: A mutable input Tensor. Must be one of the following types: -* float16, float32, int32. \n +* float16, float32, double, int64, int32. \n + * @par Outputs: -* y: A mutable Tensor. Has the same type as "x1". \n +* y: A mutable Tensor. Has the same type as input_data. \n * @par Third-party framework compatibility -* Compatible with the Pytorch operator Addcdiv. +* Compatible with the Pytorch operator Addcdiv(version-1.5.0). */ REG_OP(Addcdiv) - .INPUT(input_data, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(value, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT32})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(input_data, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT64})) + .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT64})) + .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT64})) + .INPUT(value, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT32, DT_DOUBLE, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT64})) .OP_END_FACTORY_REG(Addcdiv) /** -* @brief Performs the element-wise multiplication of tensor x2 by tensor x3, +* @brief Performs the element-wise multiplication of tensor x1 by tensor x2, * multiply the result by the scalar value and add it to tensor input_data - * @par Inputs: * Four inputs, including: * @li input_data: A mutable input Tensor. Must be one of the following types: -* float16, float32, int8, int32, uint8. -* @li x1: A mutable input Tensor of the same type as x1. -* @li x2: A mutable input Tensor of the same type as x1. -* @li value: A tensor which includes only one element of the same type as x1. \n +* float16, float32, double, int64, int8, int32, uint8. +* @li x1: A mutable input Tensor of the same type as input_data. +* @li x2: A mutable input Tensor of the same type as input_data. +* @li value: A tensor which includes only one element of the same type as input_data. \n * @par Outputs: -* y: A mutable output Tensor. Has the same type as "x1". \n +* y: A mutable output Tensor. Has the same type as input_data. \n * @par Third-party framework compatibility * Compatible with the Pytorch operator Addcmul. */ REG_OP(Addcmul) - .INPUT(input_data, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8 })) - .INPUT(x1, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8 })) - .INPUT(x2, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8 })) - .INPUT(value, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8 })) - .OUTPUT(y, TensorType({ DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8 })) + .INPUT(input_data, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8, DT_DOUBLE, DT_INT64})) + .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8, DT_DOUBLE, DT_INT64})) + .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8, DT_DOUBLE, DT_INT64})) + .INPUT(value, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8, DT_DOUBLE, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT8, DT_DOUBLE, DT_INT64})) .OP_END_FACTORY_REG(Addcmul) /** @@ -3508,8 +3508,8 @@ REG_OP(StrideAdd) * Compatible with the Pytorch equal operator. \n */ REG_OP(TensorEqual) - .INPUT(input_x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) - .INPUT(input_y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) + .INPUT(input_x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT64, DT_INT32, DT_INT8, DT_UINT8})) + .INPUT(input_y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT64, DT_INT32, DT_INT8, DT_UINT8})) .OUTPUT(output_z, TensorType({DT_BOOL})) .OP_END_FACTORY_REG(TensorEqual) diff --git a/third_party/fwkacllib/inc/ops/functional_ops.h b/third_party/fwkacllib/inc/ops/functional_ops.h index 7cfe39c4..e1fbe6b3 100644 --- a/third_party/fwkacllib/inc/ops/functional_ops.h +++ b/third_party/fwkacllib/inc/ops/functional_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/get_data_ops.h b/third_party/fwkacllib/inc/ops/get_data_ops.h index e5518ef8..33dc4f14 100644 --- a/third_party/fwkacllib/inc/ops/get_data_ops.h +++ b/third_party/fwkacllib/inc/ops/get_data_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/hcom_ops.h b/third_party/fwkacllib/inc/ops/hcom_ops.h index 497f6a68..6db276a9 100644 --- a/third_party/fwkacllib/inc/ops/hcom_ops.h +++ b/third_party/fwkacllib/inc/ops/hcom_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/hvd_ops.h b/third_party/fwkacllib/inc/ops/hvd_ops.h index 00299ef7..a49ec5ed 100644 --- a/third_party/fwkacllib/inc/ops/hvd_ops.h +++ b/third_party/fwkacllib/inc/ops/hvd_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/image_ops.h b/third_party/fwkacllib/inc/ops/image_ops.h index 2327e76e..319681e4 100644 --- a/third_party/fwkacllib/inc/ops/image_ops.h +++ b/third_party/fwkacllib/inc/ops/image_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -1848,14 +1848,51 @@ REG_OP(DenseImageWarpGrad) *Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(GridSampler2D) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(grid, TensorType({DT_FLOAT16, DT_FLOAT})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(grid, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) .ATTR(interpolation_mode, String, "bilinear") .ATTR(padding_mode, String, "zeros") .ATTR(align_corners, Bool, false) .OP_END_FACTORY_REG(GridSampler2D) +/** +*@brief Computes the gradients of GridSampler2D. + +*@par Inputs: +*@li grad: A 4-D Tensor with shape `[batch, channels, height, width]`. +*@li x: A 4-D Tensor with shape `[batch, channels, height, width]`. +*@li grid: flow field grid, 4-D Tensor with shape `[batch, height, width, 2]`. + +*@par Attributes: +*@li interpolation_mode: An optional string specifying the interpolation method. + Defaults to "bilinear". +*@li padding_mode: An optional string specifying the pad method. + Defaults to "zeros". +*@li align_corners: An optional bool. If "true", the centers of the corner + pixels of the input and output tensors are aligned. Defaults to false. + +*@par Outputs: +*dx: Returns 4-D Tensor with the same dtype and shape as `x`. +*dgrid: Returns 4-D Tensor with the same dtype and shape as `grid`. + +*@par Third-party framework compatibility +*Compatible with pytorch GridSampler2DGrad operator. + +*@par Restrictions: +*Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(GridSampler2DGrad) + .INPUT(grad, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(grid, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(dx, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(dgrid, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .ATTR(interpolation_mode, String, "bilinear") + .ATTR(padding_mode, String, "zeros") + .ATTR(align_corners, Bool, false) + .OP_END_FACTORY_REG(GridSampler2DGrad) + /** *@brief This operation unnormalize input Grid, which is usually gennerated by affine_grid. diff --git a/third_party/fwkacllib/inc/ops/index_to_addr_ops.h b/third_party/fwkacllib/inc/ops/index_to_addr_ops.h index 3af17a45..c6bbaaa8 100644 --- a/third_party/fwkacllib/inc/ops/index_to_addr_ops.h +++ b/third_party/fwkacllib/inc/ops/index_to_addr_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/internal_ops.h b/third_party/fwkacllib/inc/ops/internal_ops.h index bcc3f1c3..9dde14a5 100644 --- a/third_party/fwkacllib/inc/ops/internal_ops.h +++ b/third_party/fwkacllib/inc/ops/internal_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/linalg_ops.h b/third_party/fwkacllib/inc/ops/linalg_ops.h index f6cc8694..0f362d31 100644 --- a/third_party/fwkacllib/inc/ops/linalg_ops.h +++ b/third_party/fwkacllib/inc/ops/linalg_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -410,10 +410,10 @@ form square matrices. \n */ REG_OP(Svd) - .INPUT(x, TensorType({ DT_DOUBLE, DT_FLOAT })) - .OUTPUT(sigma, TensorType({ DT_DOUBLE, DT_FLOAT })) - .OUTPUT(u, TensorType({ DT_DOUBLE, DT_FLOAT })) - .OUTPUT(v, TensorType({ DT_DOUBLE, DT_FLOAT })) + .INPUT(x, TensorType({ DT_DOUBLE, DT_FLOAT, DT_COMPLEX64, DT_COMPLEX128 })) + .OUTPUT(sigma, TensorType({ DT_DOUBLE, DT_FLOAT, DT_COMPLEX64, DT_COMPLEX128 })) + .OUTPUT(u, TensorType({ DT_DOUBLE, DT_FLOAT, DT_COMPLEX64, DT_COMPLEX128 })) + .OUTPUT(v, TensorType({ DT_DOUBLE, DT_FLOAT, DT_COMPLEX64, DT_COMPLEX128 })) .ATTR(compute_uv, Bool, true) .ATTR(full_matrices, Bool, false) .OP_END_FACTORY_REG(Svd) diff --git a/third_party/fwkacllib/inc/ops/list_ops.h b/third_party/fwkacllib/inc/ops/list_ops.h index 0aa94e73..53024878 100644 --- a/third_party/fwkacllib/inc/ops/list_ops.h +++ b/third_party/fwkacllib/inc/ops/list_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/logging_ops.h b/third_party/fwkacllib/inc/ops/logging_ops.h index dd565657..a20370fd 100644 --- a/third_party/fwkacllib/inc/ops/logging_ops.h +++ b/third_party/fwkacllib/inc/ops/logging_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/lookup_ops.h b/third_party/fwkacllib/inc/ops/lookup_ops.h index b1fc254f..3fdc01fe 100644 --- a/third_party/fwkacllib/inc/ops/lookup_ops.h +++ b/third_party/fwkacllib/inc/ops/lookup_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/math_ops.h b/third_party/fwkacllib/inc/ops/math_ops.h index 6eb418d8..48867203 100644 --- a/third_party/fwkacllib/inc/ops/math_ops.h +++ b/third_party/fwkacllib/inc/ops/math_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -480,7 +480,7 @@ REG_OP(HistogramFixedWidth) .INPUT(range, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT64})) .INPUT(nbins, TensorType({DT_INT32})) .OUTPUT(y, TensorType({DT_INT32})) - .ATTR(dtype, String, "int32") + .ATTR(dtype, Int, 3) .OP_END_FACTORY_REG(HistogramFixedWidth) /** @@ -511,7 +511,7 @@ REG_OP(HistogramFixedWidthD) .INPUT(range, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT64})) .OUTPUT(y, TensorType({DT_INT32})) .REQUIRED_ATTR(nbins, Int) - .ATTR(dtype, String, "int32") + .ATTR(dtype, Int, 3) .OP_END_FACTORY_REG(HistogramFixedWidthD) /** @@ -938,6 +938,57 @@ REG_OP(LpNorm) .ATTR(epsilon, Float, 1e-12) .OP_END_FACTORY_REG(LpNorm) +/** +* @brief Computes LpNormReduce. + +* @par Inputs: +* x: An ND tensor of type float16, float32. \n +* +* @par Attributes: +* @li p: Int, "inf" or "-inf", default value is 2. +* @li axes: ListInt, {} means all axes will be computed. +* @li keepdim: Bool, default is false. +* @li epsilon: Float, default is 1e-12. \n + +* @par Outputs: +* y: An ND tensor of type float16, float32. The shape of y is depending +* on axes and keepdim. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator LpNormReduce. +*/ +REG_OP(LpNormReduce) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(p, Int, 2) + .ATTR(axes, ListInt, {}) + .ATTR(keepdim, Bool, false) + .ATTR(epsilon, Float, 1e-12) + .OP_END_FACTORY_REG(LpNormReduce) + +/** +* @brief Computes LpNormUpdate. + +* @par Inputs: +* x: An ND tensor of type float16, float32. \n +* +* @par Attributes: +* @li p: Int, "inf" or "-inf", default value is 2. +* @li epsilon: Float, default is 1e-12. \n + +* @par Outputs: +* y: An ND tensor of type float16, float32. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator LpNormUpdate. +*/ +REG_OP(LpNormUpdate) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(p, Int, 2) + .ATTR(epsilon, Float, 1e-12) + .OP_END_FACTORY_REG(LpNormUpdate) + /** * @brief get complex. diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index e82251bb..289a33a6 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -49,10 +49,10 @@ namespace ge { * Compatible with the TensorFlow operator BatchMatmul. */ REG_OP(MatMul) - .INPUT(x1, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) - .INPUT(x2, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) - .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .INPUT(x1, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_BF16})) + .INPUT(x2, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_BF16})) + .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_BF16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_BF16})) .ATTR(transpose_x1, Bool, false) .ATTR(transpose_x2, Bool, false) .OP_END_FACTORY_REG(MatMul) @@ -88,10 +88,10 @@ REG_OP(MatMul) * Compatible with the TensorFlow operator BatchMatmul. */ REG_OP(MatMulV2) - .INPUT(x1, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8, DT_INT4})) - .INPUT(x2, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8 DT_INT4})) - .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .INPUT(x1, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8, DT_INT4, DT_BF16})) + .INPUT(x2, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8, DT_INT4, DT_BF16})) + .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_BF16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_BF16})) .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8, DT_INT4})) .ATTR(transpose_x1, Bool, false) .ATTR(transpose_x2, Bool, false) @@ -531,6 +531,36 @@ REG_OP(ScatterAdd) .ATTR(use_locking, Bool, false) .OP_END_FACTORY_REG(ScatterAdd) +/** +*@brief Adds sparse "updates" to a variable reference . \n + +*@par Inputs: +* Three inputs, including: +*@li var: An ND Tensor . +*Must be one of the following types: float16, float32, int32, int8, uint8 + +*@li indices: An ND Tensor of type int32 or int64 + +*@li updates: An ND Tensor . +*Must be one of the following types: float16, float32, int32, int8, uint8 + +*@par Attributes: +* axis: An required int. The axis along which to index. \n + +*@par Outputs: +*var: A Tensor. Has the same type and format as input "var" . \n + +*@par Third-party framework compatibility +* Compatible with the pytorch operator ScatterAdd. +*/ +REG_OP(ScatterAddWithAxis) + .INPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .INPUT(indices, TensorType::IndexNumberType()) + .INPUT(updates, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .OUTPUT(var, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT32,DT_INT8,DT_UINT8})) + .REQUIRED_ATTR(axis, Int) + .OP_END_FACTORY_REG(ScatterAddWithAxis) + /** *@brief Divides a variable reference by sparse updates . \n @@ -1066,6 +1096,40 @@ REG_OP(MatrixSetDiagV2) .OUTPUT(output, TensorType::BasicType()) .OP_END_FACTORY_REG(MatrixSetDiagV2) +/** +*@brief Returns a batched matrix tensor with new batched diagonal values . \n + +*@par Inputs: +* Three inputs, including: +*@li input: "Rank `r+1`, where `r >= 1`. \n + +*@li diagonal: Rank `r` when `k` is an integer or `k[0] == k[1]`. Otherwise, it has rank `r+1`. \n + +*@li k: +*Diagonal offset(s). Positive value means superdiagonal, 0 refers to the main \n +*diagonal, and negative value means subdiagonals. `k` can be a single integer \n +*(for a single diagonal) or a pair of integers specifying the low and high ends \n +*of a matrix band. `k[0]` must not be larger than `k[1]`. \n + +*@par Attributes: +*@li align: An optional string. Defaults to RIGHT_LEFT. It is a string specifying \n +*how superdiagonals and subdiagonals should be aligned, respectively. \n +*other optional: LEFT_RIGHT, LEFT_LEFT, and RIGHT_RIGHT.\n + +*@par Outputs: +*output: Rank `r+1`, with `output.shape = input.shape` . \n + +*@par Third-party framework compatibility +* Compatible with the TensorFlow operator ScatterUpdate. +*/ +REG_OP(MatrixSetDiagV3) + .INPUT(input, TensorType::BasicType()) + .INPUT(diagonal, TensorType::BasicType()) + .INPUT(k, TensorType({DT_INT32})) + .OUTPUT(output, TensorType::BasicType()) + .ATTR(align, String, "RIGHT_LEFT") + .OP_END_FACTORY_REG(MatrixSetDiagV3) + /** *@brief Returns a batched diagonal tensor with given batched diagonal values . \n diff --git a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h index 9629976e..66d67551 100644 --- a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -114,7 +114,8 @@ Must be 5D if input "x" is with format NC1HWC0. Specifies the variance of "x". *@li reserve_space_1: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D if input "x" is with format NC1HWC0. Specifies the mean of "x" for gradient computation. Pass "None" to skip this output. *@li reserve_space_2: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. -Must be 5D if input "x" is with format NC1HWC0. Specifies the variance of "x" for gradient computation. Pass "None" to skip this output . \n +Must be 5D if input "x" is with format NC1HWC0. Specifies the variance of "x" for gradient computation. Pass "None" to skip this output . +*@li reserve_space_3: An optional Tensor of type float32. For compatibility with tensorflow, only has one useless element. \n *@attention Constraints: *@li If the operation is used for inference and outputs "reserve_space_1" and "reserve_space_2" are available, @@ -136,11 +137,35 @@ REG_OP(BatchNorm) .OUTPUT(batch_variance, TensorType({DT_FLOAT})) .OUTPUT(reserve_space_1, TensorType({DT_FLOAT})) .OUTPUT(reserve_space_2, TensorType({DT_FLOAT})) + .OUTPUT(reserve_space_3, TensorType({DT_FLOAT})) .ATTR(epsilon, Float, 0.0001) .ATTR(data_format, String, "NHWC") .ATTR(is_training, Bool, true) .OP_END_FACTORY_REG(BatchNorm) +/** +*@brief part of SyncBatchNormBackward . \n + +*@par Inputs: +* Three inputs, including: +*@li sum_dy: A Tensor. Must be one of the following types: float16, float32 . +*@li sum_dy_dx_pad: A Tensor. Must be one of the following types: float16, float32 . +*@li mean: A Tensor. Must be one of the following types: float16, float32 . +*@li invert_std: A Tensor. Must be one of the following types: float16, float32 . \n + +*@par Outputs: +*@li sum_dy_xmu: A Tensor. Has the same type and format as input "sum_dy" +*@li y: A Tensor. Has the same type and format as input "sum_dy" . \n +*/ +REG_OP(SyncBatchNormBackwardReduce) + .INPUT(sum_dy, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(sum_dy_dx_pad, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(mean, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(invert_std, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(sum_dy_xmu, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(SyncBatchNormBackwardReduce) + /** *@brief Performs batch normalization . \n @@ -260,7 +285,8 @@ REG_OP(BatchNormExt2) *@li x: A 4D or 5D Tensor of type float16 or float32, with format NHWC, NCHW, or NC1HWC0. *@li scale: A 4D or 5D Tensor of type float32, with format NHWC, NCHW, or NC1HWC0. *@li reserve_space_1: A 4D or 5D Tensor of type float32, with format NHWC, NCHW, or NC1HWC0. It is an output of BatchNorm. -*@li reserve_space_2: A 4D or 5D Tensor of type float32, with format NHWC, NCHW, or NC1HWC0. It is an output of BatchNorm . \n +*@li reserve_space_2: A 4D or 5D Tensor of type float32, with format NHWC, NCHW, or NC1HWC0. It is an output of BatchNorm . +*@li reserve_space_3: A 1D optional Tensor of type float32. It is an output of BatchNorm . \n *@par Attributes: *@li epsilon: An optional float32. Defaults to "0.0001". A small float number added to the variance of "x". @@ -287,6 +313,7 @@ REG_OP(BatchNormGrad) .INPUT(scale, TensorType({DT_FLOAT})) .INPUT(reserve_space_1, TensorType({DT_FLOAT})) .INPUT(reserve_space_2, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(reserve_space_3, TensorType({DT_FLOAT})) .OUTPUT(x_backprop, TensorType({DT_FLOAT16,DT_FLOAT})) .OUTPUT(scale_backprop, TensorType({DT_FLOAT})) .OUTPUT(offset_backprop, TensorType({DT_FLOAT})) diff --git a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h index ed7cb9b5..025f669c 100644 --- a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -269,10 +269,10 @@ REG_OP(DepthwiseConv2DBackpropInputD) *@par Inputs: *Two required inputs and two optional inputs, including: \n -* @li x: A 4D tensor of type float16 or int8, with shape [N, C, H, W] or [N, H, W, C] -* @li filter: A 4D tensor of type float16 or int8, with shape [H, W, C, K] +* @li x: A 4D tensor of type float16 or int8 or int4, with shape [N, C, H, W] or [N, H, W, C] +* @li filter: A 4D tensor of type float16 or int8 or int4, with shape [H, W, C, K] * @li bias: An optional tensor of type float16 or int32 -* @li offset_w: An optional float16 or int8, used for quantized inference +* @li offset_w: An optional float16 or int8 or int4, used for quantized inference * @par Attributes: * @li strides: A required list or tuple. The stride of the sliding window for @@ -312,10 +312,10 @@ REG_OP(DepthwiseConv2DBackpropInputD) * @li Compatible with the Caffe operator DepthwiseConv2D. */ REG_OP(DepthwiseConv2D) - .INPUT(x, TensorType({DT_FLOAT16, DT_INT8})) - .INPUT(filter, TensorType({DT_FLOAT16, DT_INT8})) + .INPUT(x, TensorType({DT_FLOAT16, DT_INT8, DT_INT4})) + .INPUT(filter, TensorType({DT_FLOAT16, DT_INT8, DT_INT4})) .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT16, DT_INT32})) - .OPTIONAL_INPUT(offset_w, TensorType({DT_FLOAT16, DT_INT8})) + .OPTIONAL_INPUT(offset_w, TensorType({DT_FLOAT16, DT_INT8, DT_INT4})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_INT32})) .REQUIRED_ATTR(strides, ListInt) .ATTR(dilations, ListInt, {1, 1, 1, 1}) @@ -369,16 +369,14 @@ REG_OP(BiasAddGrad) *\n * The following are the supported data types and data formats:\n *\n - | Tensor | out_bckprop | filter | y\n - ------------|-------------|---------|--------\n - | Data Type | float16 | float16 | float16\n - | |-------------|---------|--------\n - | | float32 | float32 | float32\n - | |-------------|---------|--------\n - | | float64 | float64 | float64\n - ------------|-------------|---------|--------\n - | Format | NCHW | NCHW | NCHW\n - | | NHWC | HWCN | NHWC\n + *\n + | Tensor | out_bckprop | filter | y |\n + |-----------|-------------|---------|--------|\n + | Data Type | float16 | float16 | float16|\n + | | float32 | float32 | float32|\n + | | float64 | float64 | float64|\n + | Format | NCHW | NCHW | NCHW |\n + | | NHWC | HWCN | NHWC |\n *\n * For float32 and float64 type, the actual calculation on the chip is based on * float16. @@ -400,30 +398,25 @@ REG_OP(BiasAddGrad) *\n * The following value range restrictions must be met:\n *\n - | Name | Field | Scope\n - -------------------|----------|--------------\n - | input_size | H | [1, 200000]\n - | | W | [1, 4096]\n - -------------------|----------|--------------\n - | Filter | H | [1, 255]\n - | | W | [1, 255]\n - -------------------|----------|--------------\n - | out_backprop | H*strideH| [1, 200000]\n - | | W*strideW| [1, 4096]\n - -------------------|----------|--------------\n - | y(fmap) | H | [1, 200000]\n - | | W | [1, 4096]\n - -------------------|----------|--------------\n - | Stride | H | [1, 63]\n - | | W | [1, 63]\n - -------------------|----------|--------------\n - | Padding | Top | [0, 255]\n - | | Bottom | [0, 255]\n - | | Left | [0, 255]\n - | | Right | [0, 255]\n - -------------------|----------|--------------\n - | Dilation | H | [1, 255]\n - | | W | [1, 255]\n + *\n + | Name | Field | Scope |\n + |------------------|----------|--------------|\n + | input_size | H | [1, 200000] |\n + | | W | [1, 4096] |\n + | Filter | H | [1, 255] |\n + | | W | [1, 255] |\n + | out_backprop | H*strideH| [1, 200000] |\n + | | W*strideW| [1, 4096] |\n + | y(fmap) | H | [1, 200000] |\n + | | W | [1, 4096] |\n + | Stride | H | [1, 63] |\n + | | W | [1, 63] |\n + | Padding | Top | [0, 255] |\n + | | Bottom | [0, 255] |\n + | | Left | [0, 255] |\n + | | Right | [0, 255] |\n + | Dilation | H | [1, 255] |\n + | | W | [1, 255] |\n *\n * In Ascend910, fmap or out_backprop's H and W not support 1 when @@ -495,9 +488,9 @@ REG_OP(Conv2DBackpropInput) * Warning: THIS FUNCTION IS DEPRECATED. Please use Conv2DBackpropInput instead. */ REG_OP(Conv2DBackpropInputD) - .INPUT(filter, TensorType({DT_FLOAT16, DT_INT8})) - .INPUT(out_backprop, TensorType({DT_FLOAT16, DT_INT8})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_INT32, DT_FLOAT32})) + .INPUT(filter, TensorType({DT_FLOAT16, DT_INT8, DT_BF16})) + .INPUT(out_backprop, TensorType({DT_FLOAT16, DT_INT8, DT_BF16})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_INT32, DT_FLOAT32, DT_BF16})) .REQUIRED_ATTR(input_size, ListInt) .REQUIRED_ATTR(strides, ListInt) .REQUIRED_ATTR(pads, ListInt) @@ -523,13 +516,12 @@ REG_OP(Conv2DBackpropInputD) *\n * The following are the supported data types and data formats:\n *\n - | Tensor | x | filter | bias | y\n - ------------|---------|---------|---------|--------\n - | Data Type | float16 | float16 | float16 | float16\n - | |---------|---------|---------|--------\n - | | int8 | int8 | int32 | int32\n - ------------|---------|---------|---------|--------\n - | Format | NCHW | NCHW | ND | NCHW\n + *\n + | Tensor | x | filter | bias | y |\n + |-----------|---------|---------|---------|--------|\n + | Data Type | float16 | float16 | float16 | float16|\n + | | int8 | int8 | int32 | int32 |\n + | Format | NCHW | NCHW | ND | NCHW |\n *\n * For int8, a dequant or requant operator must be followed. *\n @@ -553,29 +545,24 @@ REG_OP(Conv2DBackpropInputD) *\n * The following value range restrictions must be met:\n *\n - | Name | Field | Scope\n - -------------------|----------|--------------\n - | x (out_backprop) | H*strideH| [1, 200000]\n - | | W*strideW| [1, 4096]\n - -------------------|----------|--------------\n - | Filter | H | [1, 255]\n - | | W | [1, 255]\n - -------------------|----------|--------------\n - | y (fmap) | H | [1, 200000]\n - | | W | [1, 4096]\n - -------------------|----------|--------------\n - | Stride | H | [1, 63]\n - | | W | [1, 63]\n - -------------------|----------|--------------\n - | Padding | Top | [0, 255]\n - | | Bottom | [0, 255]\n - | | Left | [0, 255]\n - | | Right | [0, 255]\n - -------------------|----------|--------------\n - | Dilation | H | [1, 255]\n - | | W | [1, 255]\n - -------------------|----------|--------------\n - | Offset_x | | [-128, 127]\n + *\n + | Name | Field | Scope |\n + |------------------|----------|--------------|\n + | x (out_backprop) | H*strideH| [1, 200000] |\n + | | W*strideW| [1, 4096] |\n + | Filter | H | [1, 255] |\n + | | W | [1, 255] |\n + | y (fmap) | H | [1, 200000] |\n + | | W | [1, 4096] |\n + | Stride | H | [1, 63] |\n + | | W | [1, 63] |\n + | Padding | Top | [0, 255] |\n + | | Bottom | [0, 255] |\n + | | Left | [0, 255] |\n + | | Right | [0, 255] |\n + | Dilation | H | [1, 255] |\n + | | W | [1, 255] |\n + | Offset_x | | [-128, 127] |\n *\n * In Ascend910, fmap or out_backprop's H and W not support 1 when * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 @@ -631,16 +618,14 @@ REG_OP(Deconvolution) *\n * The following are the supported data types and data formats:\n *\n - | Tensor | x | out_backprop | y\n - ------------|---------|--------------|---------\n - | Data Type | float16 | float16 | float16\n - | |---------|--------------|---------\n - | | float32 | float32 | float32\n - | |---------|--------------|---------\n - | | float64 | float64 | float64\n - |-----------|---------|--------------|---------\n - | Format | NCHW | NCHW | NCHW\n - | | NHWC | NHWC | HWCN\n + *\n + | Tensor | x | out_backprop | y |\n + |-----------|---------|--------------|---------|\n + | Data Type | float16 | float16 | float16 |\n + | | float32 | float32 | float32 |\n + | | float64 | float64 | float64 |\n + | Format | NCHW | NCHW | NCHW |\n + | | NHWC | NHWC | HWCN |\n *\n * For float32 and float64 type of x and outbackprop, the actual calculation on the chip * is based on float16. @@ -662,30 +647,25 @@ REG_OP(Deconvolution) *\n * The following value range restrictions must be met:\n *\n - | Name | Field | Scope\n - -------------------|----------|--------------\n - | x(fmap) | H | [1, 200000]\n - | | W | [1, 4096]\n - -------------------|----------|--------------\n - | Filter Size | H | [1, 255]\n - | | W | [1, 255]\n - -------------------|----------|--------------\n - | out_backprop | H | [1, 200000]\n - | | W | [1, 4096]\n - -------------------|----------|--------------\n - | y | H | [1, 200000]\n - | | W | [1, 4096]\n - -------------------|----------|--------------\n - | Stride | H | [1, 63]\n - | | W | [1, 63]\n - -------------------|----------|--------------\n - | Padding | Top | [0, 255]\n - | | Bottom | [0, 255]\n - | | Left | [0, 255]\n - | | Right | [0, 255]\n - -------------------|----------|--------------\n - | Dilation | H | [1, 255]\n - | | W | [1, 255]\n + *\n + | Name | Field | Scope |\n + |------------------|----------|--------------|\n + | x(fmap) | H | [1, 200000] |\n + | | W | [1, 4096] |\n + | Filter Size | H | [1, 255] |\n + | | W | [1, 255] |\n + | out_backprop | H | [1, 200000] |\n + | | W | [1, 4096] |\n + | y | H | [1, 200000] |\n + | | W | [1, 4096] |\n + | Stride | H | [1, 63] |\n + | | W | [1, 63] |\n + | Padding | Top | [0, 255] |\n + | | Bottom | [0, 255] |\n + | | Left | [0, 255] |\n + | | Right | [0, 255] |\n + | Dilation | H | [1, 255] |\n + | | W | [1, 255] |\n *\n *@par Outputs: * y: A Tensor. Has the same type as x, has the same format as filter_size. @@ -853,11 +833,11 @@ REG_OP(Conv2DBackpropFilterD) *@li Compatible with the Caffe operator 2D "Convolution". */ REG_OP(Conv2D) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8})) - .INPUT(filter, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_BF16})) + .INPUT(filter, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT8, DT_BF16})) .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_BF16})) .REQUIRED_ATTR(strides, ListInt) .REQUIRED_ATTR(pads, ListInt) .ATTR(dilations, ListInt, {1, 1, 1, 1}) @@ -1441,14 +1421,13 @@ REG_OP(Conv3DTransposeD) *\n * The following are the supported data types and data formats:\n *\n - | Tensor | x | filter | bias | y\n - ------------|---------|---------|---------|--------\n - | Data Type | float16 | float16 | float16 | float16\n - | |---------|---------|---------|--------\n - | | int8 | int8 | int32 | int32\n - ------------|---------|---------|---------|--------\n - | Format | NCHW | NCHW | ND | NCHW\n - | | NHWC | HWCN | | NHWC\n + *\n + | Tensor | x | filter | bias | y |\n + |-----------|---------|---------|---------|--------|\n + | Data Type | float16 | float16 | float16 | float16|\n + | | int8 | int8 | int32 | int32 |\n + | Format | NCHW | NCHW | ND | NCHW |\n + | | NHWC | HWCN | | NHWC |\n *\n * For int8, a dequant or requant operator must be followed. *\n @@ -1476,32 +1455,26 @@ REG_OP(Conv3DTransposeD) *\n * The following value range restrictions must be met:\n *\n - | Name | Field | Scope\n - -------------------|----------|--------------\n - | input_size | H | [1, 200000]\n - | | W | [1, 4096]\n - -------------------|----------|--------------\n - | x (out_backprop) | H*strideH| [1, 200000]\n - | | W*strideW| [1, 4096]\n - -------------------|----------|--------------\n - | filter | H | [1, 255]\n - | | W | [1, 255]\n - -------------------|----------|--------------\n - | y (fmap) | H | [1, 200000]\n - | | W | [1, 4096]\n - -------------------|----------|--------------\n - | Stride | H | [1, 63]\n - | | W | [1, 63]\n - -------------------|----------|--------------\n - | Padding | Top | [0, 255]\n - | | Bottom | [0, 255]\n - | | Left | [0, 255]\n - | | Right | [0, 255]\n - -------------------|----------|--------------\n - | Dilation | H | [1, 255]\n - | | W | [1, 255]\n - -------------------|----------|--------------\n - | Offset_x | | [-128, 127]\n + *\n + | Name | Field | Scope |\n + |------------------|----------|--------------|\n + | input_size | H | [1, 200000] |\n + | | W | [1, 4096] |\n + | x (out_backprop) | H*strideH| [1, 200000] |\n + | | W*strideW| [1, 4096] |\n + | filter | H | [1, 255] |\n + | | W | [1, 255] |\n + | y (fmap) | H | [1, 200000] |\n + | | W | [1, 4096] |\n + | Stride | H | [1, 63] |\n + | | W | [1, 63] |\n + | Padding | Top | [0, 255] |\n + | | Bottom | [0, 255] |\n + | | Left | [0, 255] |\n + | | Right | [0, 255] |\n + | Dilation | H | [1, 255] |\n + | | W | [1, 255] |\n + | Offset_x | | [-128, 127] |\n *\n * In Ascend910, fmap or out_backprop's H and W not support 1 when * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 diff --git a/third_party/fwkacllib/inc/ops/nn_detect_ops.h b/third_party/fwkacllib/inc/ops/nn_detect_ops.h index 0011c72e..e960234e 100644 --- a/third_party/fwkacllib/inc/ops/nn_detect_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_detect_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -135,7 +135,8 @@ REG_OP(CheckValid) * the value "4" refers to "x0", "x1", "y0", and "y1" . \n *@par Attributes: -*mode: Computation mode, a character string with the value range of [iou, iof] . \n +*@li mode: Computation mode, a character string with the value range of [iou, iof] +*@li eps: An optional float, prevent division by 0, default value is 1.0 . \n *@par Outputs: *overlap: A 2D Tensor of type float16 or float32 with shape [M, N], specifying @@ -150,6 +151,7 @@ REG_OP(Iou) .INPUT(gtboxes, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(overlap, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(mode, String, "iou") + .ATTR(eps, Float, 1.0) .OP_END_FACTORY_REG(Iou) /** @@ -205,7 +207,8 @@ the value "5" indicates the indexes of images where the ROIs are located, "x0", *@li spatial_scale: A required attribute of type float, specifying the scaling ratio of "features" to the original image. *@li sample_num: An optional attribute of type int, specifying the horizontal and vertical sampling frequency of each output. If this attribute is set to "0", the sampling frequency is -equal to the rounded up value of "rois", which is a floating point number. Defaults to "2" . \n +equal to the rounded up value of "rois", which is a floating point number. Defaults to "2" . +*@li roi_end_mode: An optional attribute of type int, specifying the align mode .\n *@par Outputs: *xdiff: Gradient added to input "features". Has the same 5HD shape as input "features". @@ -220,6 +223,7 @@ REG_OP(ROIAlignGrad) .REQUIRED_ATTR(pooled_height, Int) .REQUIRED_ATTR(spatial_scale, Float) .ATTR(sample_num, Int, 2) + .ATTR(roi_end_mode, Int, 1) .OP_END_FACTORY_REG(ROIAlignGrad) /** @@ -579,6 +583,172 @@ REG_OP(Yolo) .ATTR(softmaxtree, Bool, false) .OP_END_FACTORY_REG(Yolo) +/** +*@brief Normalizes data. It is called Region on YOLO v2 and Yolo on YOLO v3 . \n + +*@par Inputs: +*x: An NCHW tensor of type float16 or float32. The data is with shape (N, boxes*(coords+obj+classes), H, W), +where, "obj" indicates the confidence of an object, and only one confidence is supported. Boxes are arranged +as xx...xyy...yww...whh...hbb...bc0c0..c0c1c1...c1......cncn...cn . \n + +*@par Attributes: +*@li boxes: A required int32, specifying the number of anchor boxes. Defaults to "5" for V2 or "3" for V3. +*@li coords: An int32, specifying the number of parameters required for locating an object. The value is fixed at "4", corresponding to (x,y,w,h). +*@li classes: An int32, specifying the number of prediction classes. Defaults to "80". The value range is [1, 1024]. +*@li yolo_version: A string, specifying the YOLO version, either "V2" or "V3".Defaults to "V3" +*@li softmax: A bool, specifying whether to perform softmax, valid only when "yolo_version = V2". Defaults to "false". +*@li background: A bool, specifying the operation types of the obj and classes, used in conjunction with "softmax" and valid only when "yolo_version = V2". Defaults to "false". +*@li softmaxtree: A bool, Fixed to False, defined in Lite, but not used. Defaults to "false" . \n + +*@par Outputs: +*@li coord_data: A float16 or float32 with shape [N, boxes*coords, ceilx(height*width*2+32, 32)/2], +* where "ceil" indicates that a detected box is aligned upwards with the second parameter. Specifies the coordinates of a detected box. +*@li obj_prob: A float16 or float32 with shape [N, ceilx(boxes*height*width *2+32, 32)/2], +* where "ceil" indicates that a detected box is aligned upwards with the second parameter. Specifies the confidence. +*@li classes_prob: A float16 or float32 with shape [N, classes, ceilx(boxes*height*width *2+32, 32)/2], +* where "ceil" indicates that a detected box is aligned upwards with the second parameter. Specifies the prediction classes . \n + +*@attention Constraints: +*@li This operator applies to YOLO v2,v3 and v5 networks. +*@li The succeeding layer of the Yolo operator must be operator Yolov5DetectionOutput. +*@par Third-party framework compatibility +* It is a custom operator. +*/ +REG_OP(YoloPreDetection) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(coord_data, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(obj_prob, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(classes_prob, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(boxes, Int, 3) + .ATTR(coords, Int, 4) + .ATTR(classes, Int, 80) + .ATTR(yolo_version, String, "V5") + .ATTR(softmax, Bool, false) + .ATTR(background, Bool, false) + .ATTR(softmaxtree, Bool, false) + .OP_END_FACTORY_REG(YoloPreDetection) + +/** +*@brief Performs YOLO V5 detection . \n + +*@par Inputs: +*Ten inputs, including: +*@li Operator Yolov5DetectionOutput takes the outputs of operator Yolo as its inputs. A Yolo operator has three outputs: "coords", "obj", and "class". \n +There are three Yolo operators at Yolov5DetectionOutput's preceding layer on Yolo v5. For details, see the description of operator Yolo. +*@li img_info: A float16 or float32, describing the image information including the required image height and width \n +* and the actual image height and width. + +*@par Attributes: +*@li biases: A required float. "biases = Number of Yolo operators at the preceding layer x 2 x boxes" +*@li boxes: A required int32, specifying the number of anchor boxes predicted for each Yolo layer. +*@li coords: Specifies the number of coordinate parameters. Must be 4. +*@li classes: A required int32, specifying the number of classes to be predicted. The value range is [1, 80]. +*@li relative: An optional bool. Defaults to and must be "true". +*@li obj_threshold: A required float, specifying the confidence threshold for box filtering, which is the output "obj" of operator Yolo). The value range is [0.0, 1.0]. + +*@li post_nms_topn: An optional int32. This attribute is reserved. +*@li score_threshold: A required float, specifying the class score threshold for box filtering, which is the output "class" of operator Yolo). The value range is [0.0, 1.0]. + +*@li iou_threshold: A required float, specifying the intersection-over-union (IOU) threshold for box filtering. The value range is [0.0, 1.0].\n + +*@li pre_nms_topn: An optional int, specifying the number of boxes for non-maximum suppression (NMS). Defaults to "512". + +*@par Outputs: +*@li boxout: A tensor of type float16 or float32 with shape [batch,6,post_nms_topn](out_box_dim == 3) or [batch, 6*post_nms_topn](out_box_dim == 2), +* In output shape, 6 means x1, y1, x2, y2, score, label(class). Output by the number of box_out_num. +*@li boxoutnum: A tensor of type int32 with shape [batch,8], specifying the number of output boxes. +* The output shape means only the first one of the 8 numbers is valid, the number of valid boxes in each batch, the maximum number of valid boxes in each batch is 1024 + +*@attention Constraints:\n +*@li This operator applies only to the YOLO v5 network. +*@li The preceding layer of operator Yolov5DetectionOutput must be three Yolo operators. + +*@see Yolo() +*@par Third-party framework compatibility +* It is a custom operator. It has no corresponding operator in Caffe. +*/ +REG_OP(YoloV5DetectionOutput) + .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(biases, ListFloat) + .ATTR(boxes, Int, 3) + .ATTR(coords, Int, 4) + .ATTR(classes, Int, 80) + .ATTR(relative, Bool, true) + .ATTR(obj_threshold, Float, 0.5) + .ATTR(post_nms_topn, Int, 512) + .ATTR(score_threshold, Float, 0.5) + .ATTR(iou_threshold, Float, 0.45) + .ATTR(pre_nms_topn, Int, 512) + .ATTR(N, Int, 10) + .ATTR(resize_origin_img_to_net, Bool, false) + .ATTR(out_box_dim, Int, 3) + .ATTR(alpha, Float, 2.0) + .OUTPUT(box_out, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(box_out_num, TensorType({DT_INT32})) + .OP_END_FACTORY_REG(YoloV5DetectionOutput) + +/** +*@brief Performs YOLO V5 detection. + +*@par Inputs: +*16 Input, including: +*@li The outputs of operator Yolo at the preceding layer (that is, three Yolo operators on YOLO v5) are used as the inputs of operator Yolov5DetectionOutput. +* A Yolo operator has three outputs: "coords", "obj", and "class". For details, see the description of operator Yolo. +*@li imginfo: A float16, describing the image information including the required image height and width +* and the actual image height and width. +*@li windex: A windex tensor with shape [height,weight]. Has the same type as the inputs. +* [[0,1,2...(weight-1)],[0,1,2...(w-1)]...[0,1,2...(weight-1)]] consisting of h groups of [0, 1, 2...(weight-1)] +* is formed for the three Yolo outputs, respectively .It's a dynamic input. \n + +*@li hindex: A hindex tensor with shape [height,weight]. Has the same type as the inputs. [[0,0...0],[1,1...1],[2,2...2]...[height-1,height-1...,height-1]] is formed for the three Yolo outputs, respectively . \n +*@par Attributes: +*@li biases: A required float32. "biases = Number of Yolo operators at the preceding layer x 2 x boxes" +*@li boxes: A required int32, specifying the number of anchor boxes predicted for each Yolo layer. +*@li coords: Specifies the number of coordinate parameters. Must be 4. +*@li classes: A required int32, specifying the number of classes to be predicted. The value range is [1, 80]. +*@li relative: An optional bool. Defaults to and must be "true". +*@li obj_threshold: A required float, specifying the confidence threshold for box filtering, which is the output "obj" of operator Yolo). The value range is [0.0, 1.0]. +*@li post_nms_topn: An optional int32. This attribute is reserved. +*@li score_threshold: A required float, specifying the class score threshold for box filtering, which is the output "class" of operator Yolo). The value range is [0.0, 1.0]. +*@li iou_threshold: A required float, specifying the intersection-over-union (IOU) threshold for box filtering. The value range is [0.0, 1.0]. +*@li pre_nms_topn: An optional int, specifying the number of boxes for non-maximum suppression (NMS). Defaults to "512". +* +*@par Outputs: +*@li boxout: A tensor of type float16 or float32 with shape [batch,6,post_nms_topn](out_box_dim == 3) or [batch, 6*post_nms_topn](out_box_dim == 2), +* describing the information of each output box. +* In output shape, 6 means x1, y1, x2, y2, score, label(class). Output by the number of box_out_num. +*@li boxoutnum: A tensor of type int32 with shape [batch,8], specifying the number of output boxes. +* The output shape means only the first one of the 8 numbers is valid, the number of valid boxes in each batch, the maximum number of valid boxes in each batch is 1024 +* +*@attention Constraints: +*@li This operator applies only to the YOLO v5 network. +*@li The preceding layer of operator Yolov5DetectionOutput must be three Yolo operators. +*@see Yolo() +*@par Third-party framework compatibility +* It is a custom operator. +*/ +REG_OP(YoloV5DetectionOutputD) + .DYNAMIC_INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .DYNAMIC_INPUT(windex, TensorType({DT_FLOAT16, DT_FLOAT})) + .DYNAMIC_INPUT(hindex, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(biases, ListFloat) + .ATTR(boxes, Int, 3) + .ATTR(coords, Int, 4) + .ATTR(classes, Int, 80) + .ATTR(relative, Bool, true) + .ATTR(obj_threshold, Float, 0.5) + .ATTR(post_nms_topn, Int, 512) + .ATTR(score_threshold, Float, 0.5) + .ATTR(iou_threshold, Float, 0.45) + .ATTR(pre_nms_topn, Int, 512) + .ATTR(N, Int, 10) + .ATTR(resize_origin_img_to_net, Bool, false) + .ATTR(out_box_dim, Int, 3) + .ATTR(alpha, Float, 2.0) + .OUTPUT(box_out, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(box_out_num, TensorType({DT_INT32})) + .OP_END_FACTORY_REG(YoloV5DetectionOutputD) + /** *@brief Performs YOLO V2 detection . \n diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index 9ce7abfd..d66c8948 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/nn_ops.h b/third_party/fwkacllib/inc/ops/nn_ops.h index 5b1a4dd0..a08b610b 100644 --- a/third_party/fwkacllib/inc/ops/nn_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h index ee599a76..978c480c 100644 --- a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/nn_training_ops.h b/third_party/fwkacllib/inc/ops/nn_training_ops.h index 9dd502cd..39234057 100644 --- a/third_party/fwkacllib/inc/ops/nn_training_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_training_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -2645,6 +2645,19 @@ REG_OP(SparseApplyAdadeltaD) REG_OP(AtomicAddrClean) .ATTR(automic_add_mem_size, ListInt, {}) .OP_END_FACTORY_REG(AtomicAddrClean) + +/** +*@brief Clean memory of workspace list . \n + +*@par Attributes: +* @li workspace_size: sizes of workspaces . \n + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(DynamicAtomicAddrClean) + .ATTR(automic_add_mem_size, ListInt, {}) + .OP_END_FACTORY_REG(DynamicAtomicAddrClean) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_TRAINING_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/no_op.h b/third_party/fwkacllib/inc/ops/no_op.h index b27b1fa0..7834591c 100644 --- a/third_party/fwkacllib/inc/ops/no_op.h +++ b/third_party/fwkacllib/inc/ops/no_op.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h index 067357de..a4f2fe80 100644 --- a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h +++ b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -58,6 +58,25 @@ REG_OP(HardSwish) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(HardSwish) +/** +*@brief Computes the gradient for the hard_swish of "x" . \n + +* @par Inputs: +*Two inputs, including: +* @li grad: A Tensor. Must be one of the following types: float16, float32 +* @li x: A Tensor of the same type as "grad" . \n + +*@par Outputs: +*y: A Tensor. Has the same type as "grad". +* @par Third-party framework compatibility +* Compatible with the Torch operator HardSwishGrad. +*/ +REG_OP(HardSwishGrad) + .INPUT(grad, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(HardSwishGrad) + /** *@brief Computes the for the Swish of "x" . \n @@ -80,6 +99,29 @@ REG_OP(Swish) .ATTR(scale, Float, 1.0) .OP_END_FACTORY_REG(Swish) +/** +*@brief Computes the gradient for the Swish of "x" . \n + +*@par Inputs: +*Three inputs, including: +* @li grad: A Tensor. Must be one of the following types: float16, float32 +* @li x: A Tensor of the same type as "grad". +* @li y: A Tensor of the same type as "grad" . \n +* @par Attributes: +* scale: A optional scalar. The data type is float . \n +*@par Outputs: +*grad_x: A Tensor. Has the same type as "grad". +*@par Third-party framework compatibility +*Compatible with the Torch operator SwishGrad +*/ +REG_OP(SwishGrad) + .INPUT(grad, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(grad_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(scale, Float, 1.0) + .OP_END_FACTORY_REG(SwishGrad) + /** *@brief Computes the gradient for the gelu of "x" . \n diff --git a/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h b/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h index f36d2935..8d7ef9f9 100644 --- a/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h +++ b/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/ocr_ops.h b/third_party/fwkacllib/inc/ops/ocr_ops.h new file mode 100644 index 00000000..639c34de --- /dev/null +++ b/third_party/fwkacllib/inc/ops/ocr_ops.h @@ -0,0 +1,268 @@ +/** + * Copyright 2019-2020 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. + */ + +/*! + * \file ocr_ops.h + * \brief + */ +#ifndef OPS_BUILT_IN_OP_PROTO_INC_OCR_OPS_H_ +#define OPS_BUILT_IN_OP_PROTO_INC_OCR_OPS_H_ + +#include "graph/operator_reg.h" + +namespace ge { +/** +*@brief batch input x acording to attr batch_size and enqueue. +*@par Inputs: +*@li x: A Tensor need to batch of type float16/float32/float64/int8/int32/int64/uint8/uint32/uint64. \n +*@li queue_id:A Tensor of type uint32, queue id. + +*@par Outputs: +*enqueue_count: A Tensor of type int64, enqueue tensor number. + +*@par Attributes: +*@li batch_size: An optional int. Batch size. +*@li queue_name: An optional string. Queue name. +*@li queue_depth: An optional int. Queue depth. +*@li pad_mode: An optional string from: '"REPLICATE", "ZERO"'. Defaults to +"REPLICATE". Pad mode. +*/ +REG_OP(BatchEnqueue) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, \ + DT_INT8, DT_INT32, DT_INT64, DT_UINT8, DT_UINT32, DT_UINT64})) + .OPTIONAL_INPUT(queue_id, TensorType({DT_UINT32})) + .OUTPUT(enqueue_count, TensorType({DT_INT32})) + .ATTR(batch_size, Int, 8) + .ATTR(queue_name, String, "") + .ATTR(queue_depth, Int, 100) + .ATTR(pad_mode, String, "REPLICATE") + .OP_END_FACTORY_REG(BatchEnqueue) + +/** +*@brief batch input x acording to attr batch_size and enqueue. +*@par Inputs: +*@li imgs_data: A Tensor of type uint8. Multi img data value. \n +*@li imgs_offset:A Tensor of type int32. Offset of every img data in input imgs_data. \n +*@li imgs_size:A Tensor of type int32. Shape of every img data. \n +*@li langs:A Tensor of type int32. Lang of every img data. \n +*@li langs_score:A Tensor of type int32. Lang score of every img data. \n + +*@par Outputs: +*@liimgs: A Tensor of type uint8. Multi imgs data after reconition pre handle. +*@liimgs_relation: A Tensor of type int32. Output imgs orders in input imgs. +*@liimgs_lang: A Tensor of type int32. Output batch imgs langs. + +*@par Attributes: +*@li batch_size: An optional int. Batch size. +*@li data_format: An optional string from: '"NHWC", "NCHW"'. Defaults to +"NHWC". Data format. +*@li pad_mode: An optional string from: '"REPLICATE", "ZERO"'. Defaults to +"REPLICATE". Pad mode. +*/ +REG_OP(OCRRecognitionPreHandle) + .INPUT(imgs_data, TensorType({DT_UINT8})) + .INPUT(imgs_offset, TensorType({DT_INT32})) + .INPUT(imgs_size, TensorType({DT_INT32})) + .INPUT(langs, TensorType({DT_INT32})) + .INPUT(langs_score, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(imgs, TensorType({DT_UINT8})) + .OUTPUT(imgs_relation, TensorType({DT_INT32})) + .OUTPUT(imgs_lang, TensorType({DT_INT32})) + .ATTR(batch_size, Int, 8) + .ATTR(data_format, String, "NHWC") + .ATTR(pad_mode, String, "REPLICATE") + .OP_END_FACTORY_REG(OCRRecognitionPreHandle) + +/** +*@brief ocr detection pre handle. +*@par Inputs: +*img: A Tensor of type uint8. img data value. \n + +*@par Outputs: +*@li resized_img: A Tensor of type uint8. Img after detection pre handle. +*@li h_scale: A Tensor of type float. H scale. +*@li w_scale: A Tensor of type float. W scale. + +*@par Attributes: +*data_format: An optional string from: '"NHWC", "NCHW"'. Defaults to +"NHWC". Data format. +*/ +REG_OP(OCRDetectionPreHandle) + .INPUT(img, TensorType({DT_UINT8})) + .OUTPUT(resized_img, TensorType({DT_UINT8})) + .OUTPUT(h_scale, TensorType({DT_FLOAT})) + .OUTPUT(w_scale, TensorType({DT_FLOAT})) + .ATTR(data_format, String, "NHWC") + .OP_END_FACTORY_REG(OCRDetectionPreHandle) + +/** +*@brief ocr identify prehandle. +*@par Inputs: +*@li imgs_data: A Tensor of type uint8. Multi img data value. \n +*@li imgs_offset:A Tensor of type int32. Offset of every img data in input imgs_data. \n +*@li imgs_size:A Tensor of type int32. Shape of every img data. \n + +*@par Outputs: +*resized_imgs: A Tensor of type uint8. Multi imgs after identify pre handle. + +*@par Attributes: +*@li size: An optional int. Size. +*@li data_format: An optional string from: '"NHWC", "NCHW"'. Defaults to +"NHWC". Data format. +*/ +REG_OP(OCRIdentifyPreHandle) + .INPUT(imgs_data, TensorType({DT_UINT8})) + .INPUT(imgs_offset, TensorType({DT_INT32})) + .INPUT(imgs_size, TensorType({DT_INT32})) + .OUTPUT(resized_imgs, TensorType({DT_UINT8})) + .ATTR(size, ListInt, {}) + .ATTR(data_format, String, "NHWC") + .OP_END_FACTORY_REG(OCRIdentifyPreHandle) + +/** +*@brief batch dilate polygons according to expand_scale. +*@par Inputs: +*@li polys_data: A Tensor of type int32. point data of every polygon. \n +*@li polys_offset:A Tensor of type int32. Offset of every polygon . \n +*@li polys_size:A Tensor of type int32. Size of every polygon. \n +*@li score:A Tensor of type float. Score of every point in image. \n +*@li min_border:A Tensor of type int32. Minimum width of each polygon. \n +*@li min_area_thr:A Tensor of type int32. Minimum area of each polygon. \n +*@li score_thr:A Tensor of type float. Minimum confidence score of each polygon. \n +*@li expands_cale:A Tensor of type float. Polygon expansion multiple. \n + +*@par Outputs: +*@li dilated_polys_data: A Tensor of type int32. Point data of every dilated polygon. \n +*@li dilated_polys_offset: A Tensor of type int32. Offset of every dilated polygon . \n +*@li dilated_polys_size: A Tensor of type int32. Size of every dilated polygon. \n +*/ +REG_OP(BatchDilatePolys) + .INPUT(polys_data, TensorType({DT_INT32})) + .INPUT(polys_offset, TensorType({DT_INT32})) + .INPUT(polys_size, TensorType({DT_INT32})) + .INPUT(score, TensorType({DT_FLOAT})) + .INPUT(min_border, TensorType({DT_INT32})) + .INPUT(min_area_thr, TensorType({DT_INT32})) + .INPUT(score_thr, TensorType({DT_FLOAT})) + .INPUT(expands_cale, TensorType({DT_FLOAT})) + .OUTPUT(dilated_polys_data, TensorType({DT_INT32})) + .OUTPUT(dilated_polys_offset, TensorType({DT_INT32})) + .OUTPUT(dilated_polys_size, TensorType({DT_INT32})) + .OP_END_FACTORY_REG(BatchDilatePolys) + +/** +*@brief find contours acording to img. +*@par Inputs: +*@li img: A Tensor of type uint8. Img data value. \n + +*@par Outputs: +*@li polys_data: A Tensor of type int32. Point data of every contours. \n +*@li polys_offset:A Tensor of type int32. Offset of every contours . \n +*@li polys_size:A Tensor of type int32. Size of every contours. \n +*/ +REG_OP(OCRFindContours) + .INPUT(img, TensorType({DT_UINT8})) + .OUTPUT(polys_data, TensorType({DT_INT32})) + .OUTPUT(polys_offset, TensorType({DT_INT32})) + .OUTPUT(polys_size, TensorType({DT_INT32})) + .ATTR(value_mode, Int, 0) + .OP_END_FACTORY_REG(OCRFindContours) + +/** +*@brief dequeue data acording to queue_id and queue_name. +*@par Inputs: +*@li queue_id:An Tensor of type uint32, queue id. \n + +*@par Outputs: +*data: A Tensor of type RealNumberType, dequeue tensor. \n + +*@par Attributes: +*@li output_type: A required type. dequeue data type. +*@li output_shape: A required listint. dequeue data shape. +*@li queue_name: An optional string. Queue name. \n +*/ +REG_OP(Dequeue) + .OPTIONAL_INPUT(queue_id, TensorType({DT_UINT32})) + .OUTPUT(data, TensorType::RealNumberType()) + .REQUIRED_ATTR(output_type, Type) + .REQUIRED_ATTR(output_shape, ListInt) + .ATTR(queue_name, String, "") + .OP_END_FACTORY_REG(Dequeue); + +/** +*@brief ocr detection post handle. +*@par Inputs: +*@li img: A Tensor of type uint8. original image data. +*@li polys_data: A Tensor of type int32. point data of every poly. +*@li polys_offset:A Tensor of type int32. Offset of every poly. +*@li polys_size:A Tensor of type int32. Size of every poly. \n + +*@par Outputs: +*@li imgs_data: A Tensor of type int32. imgs_data of original image. +*@li imgs_offset: A Tensor of type int32. Offset of every imgs data. +*@li imgs_size: A Tensor of type int32. Shape of every imgs data. +*@li rect_points: A Tensor of type int32. Rect points of every imgs. \n + +*@par Attributes: +*@li data_format: An optional string from: '"NHWC", "NCHW"'. Defaults to +"NHWC". Data format. +*/ +REG_OP(OCRDetectionPostHandle) + .INPUT(img, TensorType({DT_UINT8})) + .INPUT(polys_data, TensorType({DT_INT32})) + .INPUT(polys_offset, TensorType({DT_INT32})) + .INPUT(polys_size, TensorType({DT_INT32})) + .OUTPUT(imgs_data, TensorType({DT_UINT8})) + .OUTPUT(imgs_offset, TensorType({DT_INT32})) + .OUTPUT(imgs_size, TensorType({DT_INT32})) + .OUTPUT(rect_points, TensorType({DT_INT32})) + .ATTR(data_format, String, "NHWC") + .OP_END_FACTORY_REG(OCRDetectionPostHandle); + +/** +*@brief resize and clip polys. +*@par Inputs: +*@li polys_data: A Tensor of type int32. point data of every poly. +*@li polys_offset:A Tensor of type int32. Offset of every poly . +*@li polys_size:A Tensor of type int32. Size of every poly. +*@li img_h:A Tensor of type int32. Height of original image. +*@li img_w:A Tensor of type int32. Width of original image. +*@li h_scale:A Tensor of type float. Expand scale of height. +*@li w_scale:A Tensor of type float. Expand scale of width. \n + +*@par Outputs: +*@li clipped_polys_data: A Tensor of type int32. point data of every clipped poly. \n +*@li clipped_polys_offset: A Tensor of type int32. Offset of every clipped poly . \n +*@li clipped_polys_size: A Tensor of type int32. Size of every clipped poly. \n +*/ +REG_OP(ResizeAndClipPolys) + .INPUT(polys_data, TensorType({DT_INT32})) + .INPUT(polys_offset, TensorType({DT_INT32})) + .INPUT(polys_size, TensorType({DT_INT32})) + .INPUT(img_h, TensorType({DT_INT32})) + .INPUT(img_w, TensorType({DT_INT32})) + .INPUT(h_scale, TensorType({DT_FLOAT})) + .INPUT(w_scale, TensorType({DT_FLOAT})) + .OUTPUT(clipped_polys_data, TensorType({DT_INT32})) + .OUTPUT(clipped_polys_offset, TensorType({DT_INT32})) + .OUTPUT(clipped_polys_size, TensorType({DT_INT32})) + .OP_END_FACTORY_REG(ResizeAndClipPolys); + + +} // namespace ge + + +#endif // OPS_BUILT_IN_OP_PROTO_INC_OCR_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/outfeed_ops.h b/third_party/fwkacllib/inc/ops/outfeed_ops.h index 53b9d701..e0b783bc 100644 --- a/third_party/fwkacllib/inc/ops/outfeed_ops.h +++ b/third_party/fwkacllib/inc/ops/outfeed_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/pad_ops.h b/third_party/fwkacllib/inc/ops/pad_ops.h index 9d0e7a62..a9a3b0f0 100644 --- a/third_party/fwkacllib/inc/ops/pad_ops.h +++ b/third_party/fwkacllib/inc/ops/pad_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -274,6 +274,38 @@ REG_OP(PadV3) .ATTR(mode, String, "constant") .ATTR(paddings_contiguous, Bool, true) .OP_END_FACTORY_REG(PadV3) + + /** +*@brief Cal the grad of Pads. + +*@par Inputs: +*Two inputs, including: +* @li x: A Tensor. Must be one of the following types: float16, float32, double, int32, +* uint8, int16, int8, complex64, int64, qint8, quint8, qint32, qint16, quint16, uint16, +* complex128, uint32, uint64. +* @li paddings: A Tensor of type int32 or int64. + +*@par Attributes: +* @li mode: An optional string, Defaults to "reflect", indicates paddings mode, +* support "reflect", "edge" +* @li paddings_contiguous: An optional bool value, Defaults to true. +* If true, paddings is arranged as [[begin0, end0], [begin1, end1], ...] +* If false, paddings is arranged as [[begin0, begin1], ..., [end0, end1], ...] + +*@par Outputs: +*y: A Tensor of the same type as "x". + +*@par Third-party framework compatibility: +* Compatible with ONNX operator PadGrad. +*/ + +REG_OP(PadV3Grad) + .INPUT(x, TensorType::BasicType()) + .INPUT(paddings, TensorType::IndexNumberType()) + .OUTPUT(y, TensorType::BasicType()) + .ATTR(mode, String, "reflect") + .ATTR(paddings_contiguous, Bool, true) + .OP_END_FACTORY_REG(PadV3Grad) /** *@brief Pads a tensor. diff --git a/third_party/fwkacllib/inc/ops/parsing_ops.h b/third_party/fwkacllib/inc/ops/parsing_ops.h index e578997c..03024f96 100644 --- a/third_party/fwkacllib/inc/ops/parsing_ops.h +++ b/third_party/fwkacllib/inc/ops/parsing_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/quantize_ops.h b/third_party/fwkacllib/inc/ops/quantize_ops.h index 0ed46e80..e4b1075b 100644 --- a/third_party/fwkacllib/inc/ops/quantize_ops.h +++ b/third_party/fwkacllib/inc/ops/quantize_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -85,7 +85,7 @@ REG_OP(Quantize) *@brief Quantizes the input . \n *@par Inputs: -*x: An NC1HWC0 tensor of type float16 or float32, specifying the input . \n +*x: An tensor of type float16 or float32, specifying the input . \n *@par Attributes: *@li scale: A required float32, specifying the scaling ratio. @@ -96,7 +96,7 @@ REG_OP(Quantize) *@li dst_type: A optional int32, specifying the output data type. Defaults to "DT_INT8" . \n *@par Outputs: -*y: The quantized output tensor of type int8 or int4 and with format NC1HWC0 . \n +*y: The quantized output tensor of type int8 or int4. \n *@par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. @@ -115,8 +115,8 @@ REG_OP(AscendQuant) *@brief Dequantizes the input . \n *@par Inputs: -*@li x: An NC1HWC0 tensor of type int32, specifying the input. -*@li deq_scale: An NC1HWC0 tensor of type float16 or uint64, specifying the scaling ratio . \n +*@li x: An tensor of type int32, specifying the input. +*@li deq_scale: An tensor of type float16 or uint64, specifying the scaling ratio . \n *@par Attributes: *@li sqrt_mode: A optional bool, specifying whether to perform square root on "scale", either "True" or "False". Defaults to "False". @@ -124,7 +124,7 @@ REG_OP(AscendQuant) *@li dtype: A optional int32, specifying the output data type. Defaults to "DT_FLOAT" . \n *@par Outputs: -*y: The dequantized output tensor of type float16 or float32 and with format NC1HWC0 . \n +*y: The dequantized output tensor of type float16 or float32. \n *@par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. @@ -142,7 +142,7 @@ REG_OP(AscendDequant) *@brief Anti quantizes the input . \n *@par Inputs: -*x: An NC1HWC0 tensor of type int8, specifying the input . \n +*x: An tensor of type int8, specifying the input . \n *@par Attributes: *@li scale: A required float32 scale. @@ -151,7 +151,7 @@ REG_OP(AscendDequant) *@li sqrt_mode: A optional bool, specifying whether to perform square root on "scale", either "True" or "False". Defaults to "False" . \n *@par Outputs: -*y: The dequantized output tensor of type float16 or float32 and with format NC1HWC0 . \n +*y: The dequantized output tensor of type float16 or float32. \n *@par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. @@ -169,15 +169,15 @@ REG_OP(AscendAntiQuant) *@brief Dequantizes the input of int16 . \n *@par Inputs: -*@li x0: An NC1HWC0 tensor of type int32, specifying the input. -*@li deq_scale: An NC1HWC0 tensor of type uint64, specifying the scaling ratio. -*@li x1: An NC1HWC0 tensor of type int16, specifying the input . \n +*@li x0: An tensor of type int32, specifying the input. +*@li deq_scale: An tensor of type uint64, specifying the scaling ratio. +*@li x1: An tensor of type int16, specifying the input . \n *@par Attributes: *relu_flag: A optional bool, specifying whether to perform ReLU, either "True" or "False". Defaults to "False" . \n *@par Outputs: -*y: The dequantized output tensor of type int16 and with format NC1HWC0 . \n +*y: The dequantized output tensor of type int16. \n *@par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. @@ -194,14 +194,14 @@ REG_OP(AscendDequantS16) *@brief Requantizes the input . \n *@par Inputs: -*@li x: An NC1HWC0 tensor of type int32, specifying the input. -*@li req_scale: An NC1HWC0 tensor of type uint64, specifying the scaling ratio . \n +*@li x: An tensor of type int32, specifying the input. +*@li req_scale: An tensor of type uint64, specifying the scaling ratio . \n *@par Attributes: *relu_flag: A optional bool, specifying whether to perform ReLU, either "True" or "False". Defaults to "False" . \n *@par Outputs: -*y: The dequantized output tensor of type int8 and with format NC1HWC0 . \n +*y: The dequantized output tensor of type int8. \n *@par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. @@ -217,17 +217,17 @@ REG_OP(AscendRequant) *@brief Requantizes the input of int16 . \n *@par Inputs: -*@li x0: An NC1HWC0 tensor of type int16, specifying the input. -*@li req_scale: An NC1HWC0 tensor of type uint64, specifying the scaling ratio. -*@li x1: An NC1HWC0 tensor of type int16 . \n +*@li x0: An tensor of type int16, specifying the input. +*@li req_scale: An tensor of type uint64, specifying the scaling ratio. +*@li x1: An tensor of type int16 . \n *@par Attributes: *@li dual_output: A optional bool, specifying whether to perform dual ouput, either "True" or "False". Defaults to "False". *@li relu_flag: A optional bool, specifying whether to perform ReLU, either "True" or "False". Defaults to "False" . \n *@par Outputs: -*@li y0: The dequantized output tensor of type int8 and with format NC1HWC0. -*@li y1: The dequantized output tensor of type int16 and with format NC1HWC0 . \n +*@li y0: The dequantized output tensor of type int8. +*@li y1: The dequantized output tensor of type int16. \n *@par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. diff --git a/third_party/fwkacllib/inc/ops/ragged_array_ops.h b/third_party/fwkacllib/inc/ops/ragged_array_ops.h index 5af2dd74..9d116760 100644 --- a/third_party/fwkacllib/inc/ops/ragged_array_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_array_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h b/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h index ceaa64e4..2e253ed4 100644 --- a/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/ragged_math_ops.h b/third_party/fwkacllib/inc/ops/ragged_math_ops.h index 4376437f..b2caa0be 100644 --- a/third_party/fwkacllib/inc/ops/ragged_math_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_math_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/random_ops.h b/third_party/fwkacllib/inc/ops/random_ops.h index 66f9b65f..28fbb7f2 100644 --- a/third_party/fwkacllib/inc/ops/random_ops.h +++ b/third_party/fwkacllib/inc/ops/random_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -685,6 +685,24 @@ REG_OP(Uniform) .ATTR(from, Float, 0.0) .ATTR(to, Float, 1.0) .OP_END_FACTORY_REG(Uniform) -} // namespace ge +/** +*@brief Outputs integers consisting of 0 and 1, used for lstm etc. \n +*@par Inputs +* @li time_step: A tensor with data type int64. 0-D. +* @li batch_size: A tensor with data type int64. 0-D. + +*@par Outputs: +*y: A Tensor. Has the type float16 or float, 2-D, [time_step,batch_size]. \n + +*@attention Constraints: +* Compatible with the Caffe operator ContinuationIndicator. +*/ + +REG_OP(ContinuationIndicator) + .REQUIRED_ATTR(time_step, Int) + .REQUIRED_ATTR(batch_size, Int) + .OUTPUT(y, TensorType({DT_FLOAT})) + .OP_END_FACTORY_REG(ContinuationIndicator) +} // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_RANDOM_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/reduce_ops.h b/third_party/fwkacllib/inc/ops/reduce_ops.h index 1578ba59..e8c14b1a 100644 --- a/third_party/fwkacllib/inc/ops/reduce_ops.h +++ b/third_party/fwkacllib/inc/ops/reduce_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -185,7 +185,7 @@ REG_OP(BN3DTrainingReduceGrad) *@li This operator is a BatchNorm fusion operator for updating the moving averages for training. *This operator is used in conjunction with BNTrainingUpdate. -*@li For Ascend 310, the result accuracy fails to reach 1‰ due to the square +*@li For Ascend 310, the result accuracy fails to reach 1/1000 due to the square * root instruction. */ REG_OP(BNTrainingUpdate) @@ -238,7 +238,7 @@ REG_OP(BNTrainingUpdate) *@li This operator is a BatchNorm fusion operator for updating the moving averages for training. *This operator is used in conjunction with BN3DTrainingUpdate. -*@li For Ascend 310, the result accuracy fails to reach 1‰ due to the square +*@li For Ascend 310, the result accuracy fails to reach 1/1000 due to the square * root instruction. */ REG_OP(BN3DTrainingUpdate) @@ -277,7 +277,7 @@ REG_OP(BN3DTrainingUpdate) *y: A 5D Tensor of type float16 or float32 for the normalized "x" . \n *@attention Constraints: -*For Ascend 310, the result accuracy fails to reach 1‰ due to the square root +*For Ascend 310, the result accuracy fails to reach 1/1000 due to the square root * instruction. */ REG_OP(BNInfer) @@ -313,7 +313,7 @@ assignmoving average . \n *@attention Constraints: *This operator is used in conjunction with BNTrainingReduce. -For Ascend 310, the result accuracy fails to reach 1‰ due to the square root instruction. +For Ascend 310, the result accuracy fails to reach 1/1000 due to the square root instruction. */ REG_OP(BNTrainingUpdateV2) .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -351,7 +351,7 @@ assign moving average . \n *@attention Constraints: *@li This operator is used in conjunction with BNTrainingReduce. -*@li For Ascend 310, the result accuracy fails to reach 1‰ due to the square root instruction. +*@li For Ascend 310, the result accuracy fails to reach 1/1000 due to the square root instruction. */ REG_OP(BNTrainingUpdateV3) .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -1189,7 +1189,7 @@ for the updated variance. *@attention Constraints: *@li This operator is a InstanceNorm fusion operator for updating the moving averages for training. * This operator is used in conjunction with GNTrainingUpdate. -*@li For Ascend 310, the result accuracy fails to reach 1‰ due to the square root instruction. +*@li For Ascend 310, the result accuracy fails to reach 1/1000 due to the square root instruction. */ REG_OP(GNTrainingUpdate) .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -1275,7 +1275,7 @@ REG_OP(ReduceStd) * @par Attributes: -* Three Attributes, including: +* Five Attributes, including: * @li dim: An optional listint, Defaults to "None". \n * @li unbiased: An optional bool. Defaults to "True". * If "True", Use Bessel Correction. @@ -1283,9 +1283,14 @@ REG_OP(ReduceStd) * @li keepdim: An optional bool. Defaults to "False". * If "True", Keep the original tensor dimension. * If "False", Do not keep the original tensor dimension. \n +* @li invert: An optional bool, Defaults to "False". +* If "True", the output is inverse of variance. +* If "False", the output is variance. +* @li epsilon: An optional floar, Defaults to 0.001. +* Prevent division by 0. * @par Outputs: -* @li y: A Tensor. It's the std of X. Has the same type as "x". +* @li y: A Tensor. It's the variance of X or reciprocal of vaiance of X. Has the same type as "x". * @par Third-party framework compatibility * Compatible with the Pytorch operator ReduceStdWithMean. @@ -1297,6 +1302,8 @@ REG_OP(ReduceStdWithMean) .ATTR(dim, ListInt, {}) .ATTR(unbiased, Bool, true) .ATTR(keepdim, Bool, false) + .ATTR(invert, Bool, false) + .ATTR(epsilon, Float, 0.001) .OP_END_FACTORY_REG(ReduceStdWithMean) } //namespace ge diff --git a/third_party/fwkacllib/inc/ops/resource_variable_ops.h b/third_party/fwkacllib/inc/ops/resource_variable_ops.h index 156f2f34..a5d7f9c3 100644 --- a/third_party/fwkacllib/inc/ops/resource_variable_ops.h +++ b/third_party/fwkacllib/inc/ops/resource_variable_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/rnn.h b/third_party/fwkacllib/inc/ops/rnn.h index cc0bff00..691f1e9f 100644 --- a/third_party/fwkacllib/inc/ops/rnn.h +++ b/third_party/fwkacllib/inc/ops/rnn.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -822,7 +822,7 @@ REG_OP(DynamicGRU) *@li weight_hidden:Must be one of the following types: float16. The format must be FRACTAL_Z. *@li bias_input:Must be one of the following types: float16, float32. The format must be ND. *@li bias_hidden:Must be one of the following types: float16, float32. The format must be ND. -*@li seq_length:Must be one of the following types: int32. The format must be ND. +*@li seq_length:Must be one of the following types: float16 in FRACTAL_NZ and int32 in ND. *@li init_h:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@par Attributes: @@ -852,7 +852,7 @@ REG_OP(DynamicGRUV2) .INPUT(weight_hidden, TensorType({DT_FLOAT16})) .OPTIONAL_INPUT(bias_input, TensorType({DT_FLOAT16, DT_FLOAT})) .OPTIONAL_INPUT(bias_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) - .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32})) + .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32, DT_FLOAT16})) .OPTIONAL_INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(output_h, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -880,7 +880,7 @@ REG_OP(DynamicGRUV2) *@li x_weight_input:Must be one of the following types: float32. The format must be FRACTAL_NZ. *@li weight_hidden:Must be one of the following types: float16. The format must be FRACTAL_Z. *@li bias_hidden:Must be one of the following types: float16, float32. The format must be ND. -*@li seq_length:Must be one of the following types: int32. The format must be ND. +*@li seq_length:Must be one of the following types: float16 in FRACTAL_NZ and int32 in ND. *@li init_h:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. *@par Attributes: @@ -913,7 +913,7 @@ REG_OP(DynamicGRUV2Hidden) .INPUT(x_weight_input, TensorType({DT_FLOAT32})) .INPUT(weight_hidden, TensorType({DT_FLOAT16})) .OPTIONAL_INPUT(bias_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) - .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32})) + .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32, DT_FLOAT16})) .OPTIONAL_INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(output_h, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -1049,6 +1049,50 @@ REG_OP(GRUV2HiddenGradCell) .ATTR(gate_order, String, "zrh") .OP_END_FACTORY_REG(GRUV2HiddenGradCell) +/** +*@brief: DynamicGRUCellGrad calculation. +*@par Inputs: +*ten inputs: \n +*@li dh_pre_t:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li update:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li reset:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li new:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ.+ +*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li t_state:A 1D Tensor. Must be one of the following types: int32. The format must be ND. + +*@par Attributes: +*gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. + +*@par Outputs: +*three outputs: \n +*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dgate_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dnt_x:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(DynamicGRUCellGrad) + .INPUT(dh_pre_t, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(h, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(dy, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(dh, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(update, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(reset, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(new, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(hidden_new, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(t_state, TensorType({DT_INT32, DT_INT32})) + .OUTPUT(dh_prev, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dgate_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dnt_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(gate_order, String, "zrh") + .OP_END_FACTORY_REG(DynamicGRUCellGrad) + /** * @brief Calculates the reversed outputs of the function "embedding". \n @@ -1137,8 +1181,8 @@ REG_OP(CommonLSTM) * * @par Inputs: * @li seq_length: A 1D Tensor. Must be one of the following types: int32. Record the current length of each batch. [batch_size]. - * @li b: A 1D Tensor. Must be one of the following types: fp16/fp32. Record the hidden_size. [4 * hidden_size]. * @li x: A 3D Tensor. Must be one of the following types: fp16/fp32. Record the num_step/batch_size/input_size. [num_step, batch_size, input_size]. + * @li hidden_size: An optional attribute of type int32. pass the hidden_size. \n * * @par Outputs: * seq_mask: A 3D Tensor. Must be one of the following types: fp16/fp32. with the shape of [num_step, batch_size, hidden_size]. And has the same type as "b" \n @@ -1148,8 +1192,8 @@ REG_OP(CommonLSTM) */ REG_OP(RnnGenMaskV2) .INPUT(seq_length, TensorType({DT_INT32})) - .INPUT(b, TensorType({{DT_FLOAT16, DT_FLOAT})) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(hidden_size, Int) .OUTPUT(seq_mask, TensorType({DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(RnnGenMaskV2) diff --git a/third_party/fwkacllib/inc/ops/rpn_ops.h b/third_party/fwkacllib/inc/ops/rpn_ops.h index 850b3e5a..90707602 100644 --- a/third_party/fwkacllib/inc/ops/rpn_ops.h +++ b/third_party/fwkacllib/inc/ops/rpn_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/save_ops.h b/third_party/fwkacllib/inc/ops/save_ops.h index 5ce6c2e0..0ce473b7 100644 --- a/third_party/fwkacllib/inc/ops/save_ops.h +++ b/third_party/fwkacllib/inc/ops/save_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/sdca_ops.h b/third_party/fwkacllib/inc/ops/sdca_ops.h index 601b360b..e8f3e6b6 100644 --- a/third_party/fwkacllib/inc/ops/sdca_ops.h +++ b/third_party/fwkacllib/inc/ops/sdca_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/selection_ops.h b/third_party/fwkacllib/inc/ops/selection_ops.h index 7f7c4fc8..8812a14f 100644 --- a/third_party/fwkacllib/inc/ops/selection_ops.h +++ b/third_party/fwkacllib/inc/ops/selection_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -904,8 +904,10 @@ REG_OP(SliceDV2) * @li indices: A Tensor of type int32, specifying the indices of sorted data . \n * @attention Constraints: -* @li k =< 5120 +* @li k =< 4096 * @li Size of the last dimension =< 1458176 +* @li k =< 2048 under lhisi version +* @li Size of the last dimension =< 1040000 under lhisi version * @li sorted = true * @li It's unstable sorted indices on the platform of Ascend310 @@ -1306,8 +1308,7 @@ REG_OP(CumprodD) *@par Inputs: * Two inputs, including: -*@li x: A Tensor. Must be one of the following types: float32, float64, int32, uint8, int16, int8, -* complex64, int64, qint8, quint8, qint32, uint16, complex128, float16, uint32, uint64. +*@li x: A Tensor. Must be one of the following types: float32, int32, uint8, int8, float16. *@li axis A Tensor of type int32 or int64. Range is [-rank(x),rank(x)). Defaults to "0". * *@par Attributes: @@ -1333,8 +1334,7 @@ REG_OP(Cumsum) * *@par Inputs: * One input: -*x: A Tensor. Must be one of the following types: float32, float64, int32, uint8, int16, int8, -* complex64, int64, qint8, quint8, qint32, uint16, complex128, float16, uint32, uint64. +*x: A Tensor. Must be one of the following types: float32, int32, uint8, int8, float16. * *@par Attributes: *@li axis A Tensor of type int32 or int64. Range is [-rank(x),rank(x)). Defaults to "0". @@ -2408,6 +2408,40 @@ REG_OP(TopKPQDistanceMerge) .OUTPUT(topk_index, TensorType({DT_INT32})) .REQUIRED_ATTR(k, Int) .OP_END_FACTORY_REG(TopKPQDistanceMerge) + +/** +*@brief Extracts a strided slice of a tensor. Roughly speaking, this op + extracts a slice of size (end-begin)/stride from the given input tensor. + Starting at the location specified by begin the slice continues by + adding stride to the index until all dimensions are not less than end. + +*@par Inputs: +*Four inputs, including: +* @li x: A Tensor. Must be one of the following types: float32, float64, int32, uint8, int16, int8, +* complex64, int64, qint8, quint8, qint32, qint16, quint16, uint16, +* complex128, float16, uint32, uint64. +* @li begin: A Tensor of type int32 or int64, for the index of the first value to select . \n + +* @li end: A Tensor of type int32 or int64, for the index of the last value to select . \n + +* @li strides: A Tensor of type int32 or int64, for the increment . \n + +* @li axes: A Tensor of type int32 or int64, for the increment . \n + +*@par Outputs: +*y: A Tensor. Has the same type as "x" . \n + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(StridedSliceV3) + .INPUT(x, TensorType::BasicType()) + .INPUT(begin, TensorType::IndexNumberType()) + .INPUT(end, TensorType::IndexNumberType()) + .OPTIONAL_INPUT(axes, TensorType::IndexNumberType()) + .OPTIONAL_INPUT(strides, TensorType::IndexNumberType()) + .OUTPUT(y, TensorType::BasicType()) + .OP_END_FACTORY_REG(StridedSliceV3) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_SELECTION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/set_ops.h b/third_party/fwkacllib/inc/ops/set_ops.h index 04e04f1b..1d02fa15 100644 --- a/third_party/fwkacllib/inc/ops/set_ops.h +++ b/third_party/fwkacllib/inc/ops/set_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/slice_write_ops.h b/third_party/fwkacllib/inc/ops/slice_write_ops.h index 0c161b2d..994f197c 100644 --- a/third_party/fwkacllib/inc/ops/slice_write_ops.h +++ b/third_party/fwkacllib/inc/ops/slice_write_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/sparse_ops.h b/third_party/fwkacllib/inc/ops/sparse_ops.h index 8eb7b521..d9fb4d0a 100644 --- a/third_party/fwkacllib/inc/ops/sparse_ops.h +++ b/third_party/fwkacllib/inc/ops/sparse_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/spectral_ops.h b/third_party/fwkacllib/inc/ops/spectral_ops.h index ab9e1dec..d17cbfdd 100644 --- a/third_party/fwkacllib/inc/ops/spectral_ops.h +++ b/third_party/fwkacllib/inc/ops/spectral_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/split_combination_ops.h b/third_party/fwkacllib/inc/ops/split_combination_ops.h index 98d4d111..cba8e648 100644 --- a/third_party/fwkacllib/inc/ops/split_combination_ops.h +++ b/third_party/fwkacllib/inc/ops/split_combination_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -298,8 +298,8 @@ REG_OP(ConcatD) * Compatible with the TensorFlow operator Concat. */ REG_OP(Concat) - .DYNAMIC_INPUT(x, TensorType::BasicType()) .INPUT(concat_dim, TensorType::IndexNumberType()) + .DYNAMIC_INPUT(x, TensorType::BasicType()) .OUTPUT(y, TensorType::BasicType()) .ATTR(N, Int, 1) .OP_END_FACTORY_REG(Concat) diff --git a/third_party/fwkacllib/inc/ops/state_ops.h b/third_party/fwkacllib/inc/ops/state_ops.h index d1ec00b5..49029317 100644 --- a/third_party/fwkacllib/inc/ops/state_ops.h +++ b/third_party/fwkacllib/inc/ops/state_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/stateful_random_ops.h b/third_party/fwkacllib/inc/ops/stateful_random_ops.h index f4eb763c..a3d18922 100644 --- a/third_party/fwkacllib/inc/ops/stateful_random_ops.h +++ b/third_party/fwkacllib/inc/ops/stateful_random_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/stateless_random_ops.h b/third_party/fwkacllib/inc/ops/stateless_random_ops.h index ff9daaa3..dad3c379 100644 --- a/third_party/fwkacllib/inc/ops/stateless_random_ops.h +++ b/third_party/fwkacllib/inc/ops/stateless_random_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/string_ops.h b/third_party/fwkacllib/inc/ops/string_ops.h index a78d63a1..a2699315 100644 --- a/third_party/fwkacllib/inc/ops/string_ops.h +++ b/third_party/fwkacllib/inc/ops/string_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/swap_co_ops.h b/third_party/fwkacllib/inc/ops/swap_co_ops.h index 6e8eaac3..a1bf4f8b 100644 --- a/third_party/fwkacllib/inc/ops/swap_co_ops.h +++ b/third_party/fwkacllib/inc/ops/swap_co_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/target_crop_and_resize.h b/third_party/fwkacllib/inc/ops/target_crop_and_resize.h index 9bef1d7b..9c61f2c9 100644 --- a/third_party/fwkacllib/inc/ops/target_crop_and_resize.h +++ b/third_party/fwkacllib/inc/ops/target_crop_and_resize.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/ops/transformation_ops.h b/third_party/fwkacllib/inc/ops/transformation_ops.h index 3560db11..775dd4a9 100644 --- a/third_party/fwkacllib/inc/ops/transformation_ops.h +++ b/third_party/fwkacllib/inc/ops/transformation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -368,8 +368,9 @@ REG_OP(SpaceToDepth) * complex128, uint32, uint64 *@par Attributes: -*Two attributes, including: +*Three attributes, including: * @li block_size: An int >= 2, specifying the size of the spatial block. +* @li mode: An optional string, specifying the mode. Defaults to "DCR". * @li data_format: An optional string, specifying the data format. Defaults to "NHWC" . \n *@par Outputs: @@ -382,6 +383,7 @@ REG_OP(DepthToSpace) .INPUT(x, TensorType::BasicType()) .OUTPUT(y, TensorType::BasicType()) .REQUIRED_ATTR(block_size, Int) + .ATTR(mode, String, "DCR") .ATTR(data_format, String, "NHWC") .OP_END_FACTORY_REG(DepthToSpace) @@ -845,7 +847,11 @@ with the same setting for this option. Default: False \n selected indices from the boxes tensor, where M <= max_output_size. \n *@attention Constraints: -*Input theta must be float16 or float, output_size must be int32 type . \n +*Input theta must be float16 or float, output_size must be int32 type . +The current implementation of AffineGrid operator AiCore adopts +BatchMatMul's FP16 fusion operator scheme, and the accuracy will +decrease when the theta range exceeds [-10,10].If the model requires +high accuracy of AffineGrid, it is recommended to use AICPU. \n *@par Third-party framework compatibility *Compatible with Pytorch affine_grid operator. diff --git a/third_party/fwkacllib/inc/ops/vector_search.h b/third_party/fwkacllib/inc/ops/vector_search.h index e3099511..8c1d0a2e 100644 --- a/third_party/fwkacllib/inc/ops/vector_search.h +++ b/third_party/fwkacllib/inc/ops/vector_search.h @@ -1,5 +1,5 @@ /** - * Copyright 2021 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -34,7 +34,11 @@ namespace ge { * @li bucket_list: A Tensor. Must be one of the following types: int32, int64. * * @par Outputs: -* @li adc_tables: A Tensor. Must be one of the following types: float16, float32. +* adc_tables: A Tensor. Must be one of the following types: float16, float32. +* +* @par Attributes: +* distance_type: The string indicates the distance type of ADC tables. Examples: `"l2sqr", "inner_product"`. +The default value is "l2sqr". */ REG_OP(GenADC) .INPUT(query, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -42,7 +46,89 @@ REG_OP(GenADC) .INPUT(centroids, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(bucket_list, TensorType({DT_INT32, DT_INT64})) .OUTPUT(adc_tables, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(distance_type, String, "l2sqr") .OP_END_FACTORY_REG(GenADC) + +/** +* @brief Finds values and indices of the "k" largest or least elements for the last dimension. \n +* +* @par Inputs: +* Dynamin inputs, including: +* @li actual_count: A Tensor of type int32, the actual number of pq_distance. +* @li pq_distance: A Tensor, Will be updated after calculation. Must be one of the following types: float32, float16. +* @li grouped_extreme_distance: A Tensor, the extremum in each group. Must be one of the following types: float32, float16. +* @li pq_index: A Tensor of type int32, index corresponding to pq_distance. +* @li pq_ivf: A Tensor of type int32 , the bucket number corresponding to pq_distance. +* +* @par Attributes: +* @li order: A string, indicates the sorting method of topk_pq_distance. \n +* @li k: Int, k maximum or minimum values. \n +* @li group_size: Int, the group size of the extremum. \n +* +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(TopKPQDistance) + .DYNAMIC_INPUT(actual_count, TensorType({DT_INT32})) + .DYNAMIC_INPUT(pq_distance, TensorType({DT_FLOAT16, DT_FLOAT})) + .DYNAMIC_INPUT(grouped_extreme_distance, TensorType({DT_FLOAT16, DT_FLOAT})) + .DYNAMIC_INPUT(pq_ivf, TensorType({DT_INT32})) + .DYNAMIC_INPUT(pq_index, TensorType({DT_INT32})) + .OUTPUT(topk_distance, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(topk_ivf, TensorType({DT_INT32})) + .OUTPUT(topk_index, TensorType({DT_INT32})) + .ATTR(order, String, "ASC") + .ATTR(k, Int, 0) + .ATTR(group_size, Int, 0) + .OP_END_FACTORY_REG(TopKPQDistance) + +/** +* @brief Calculate PQ distance. \n +* +* @par Inputs: +* Six inputs, including: +* @li ivf: A Tensor, dtype is uint8. +* @li bucket_list: A Tensor, dtype is int32. +* @li bucket_base_distance: A Tensor, dtype is float16. +* @li bucket_limits: A Tensor, dtype is int32. +* @li bucket_offsets: A Tensor, dtype is int32. +* @li adc_tables: A Tensor. dtype is float16. \n +* +* @par Outputs: +* Five outputs, including: +* @li actual_count: A Tensor, dtype is int32, the first element means the length of processed ivf. +* @li pq_distance: A Tensor, dtype is float16. +* @li grouped_extreme_distance: A Tensor, dtype is float16. +* @li pq_ivf: A Tensor, dtype is int32. +* @li pq_index: A Tensor, dtype is int32. \n +* +* @par Attributes: +* Five attributes, including: +* @li group_size: A Scalar, indicates the group size when compute grouped_extreme_distance. +* @li total_limit: A Scalar, indicates the total length of the outputs. +* @li extreme_mode: A Scalar, indicates the type of extremum, 0 means minimum, and 1 means maximum. +* @li split_count: A Scalar. +* @li split_index: A Scalar. \n +* +*/ +REG_OP(ScanPQCodes) + .INPUT(ivf, TensorType({DT_UINT8})) + .INPUT(bucket_list, TensorType({DT_INT32, DT_INT64})) + .INPUT(bucket_base_distance, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(bucket_limits, TensorType({DT_INT32})) + .INPUT(bucket_offsets, TensorType({DT_INT64})) + .INPUT(adc_tables, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(actual_count, TensorType({DT_INT32})) + .OUTPUT(pq_distance, TensorType({DT_FLOAT16})) + .OUTPUT(grouped_extreme_distance, TensorType({DT_FLOAT16})) + .OUTPUT(pq_ivf, TensorType({DT_INT32})) + .OUTPUT(pq_index, TensorType({DT_INT32})) + .REQUIRED_ATTR(total_limit, Int) + .ATTR(group_size, Int, 64) + .ATTR(extreme_mode, Int, 0) + .ATTR(split_count, Int, 1) + .ATTR(split_index, Int, 0) + .OP_END_FACTORY_REG(ScanPQCodes) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_VECTOR_SEARCH_H_ diff --git a/third_party/fwkacllib/inc/ops/warp_perspective_ops.h b/third_party/fwkacllib/inc/ops/warp_perspective_ops.h index 8ef69d8b..e19cbd7c 100644 --- a/third_party/fwkacllib/inc/ops/warp_perspective_ops.h +++ b/third_party/fwkacllib/inc/ops/warp_perspective_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. diff --git a/third_party/fwkacllib/inc/runtime/base.h b/third_party/fwkacllib/inc/runtime/base.h index fc2cd038..9e95a8b9 100644 --- a/third_party/fwkacllib/inc/runtime/base.h +++ b/third_party/fwkacllib/inc/runtime/base.h @@ -1,18 +1,18 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ #ifndef __CCE_RUNTIME_BASE_H__ #define __CCE_RUNTIME_BASE_H__ @@ -36,13 +36,25 @@ extern "C" { typedef int32_t rtError_t; static const int32_t RT_ERROR_NONE = 0; // success +#ifndef char_t +typedef char char_t; +#endif + +#ifndef float32_t +typedef float float32_t; +#endif + +#ifndef float64_t +typedef double float64_t; +#endif + /** * @ingroup dvrt_base * @brief device mode. */ typedef enum tagRtDeviceMode { RT_DEVICE_MODE_SINGLE_DIE = 0, - RT_DEVICE_MODE_MULTI_DIE = 1, + RT_DEVICE_MODE_MULTI_DIE, RT_DEVICE_MODE_RESERVED } rtDeviceMode; @@ -166,19 +178,19 @@ typedef enum { * @ingroup profiling_base * @brief runtime handle. */ -RTS_API rtError_t rtSetProfDirEx(const char *profDir, const char *address, const char *jobCtx); +RTS_API rtError_t rtSetProfDirEx(const char_t *profDir, const char_t *address, const char_t *jobCtx); /** * @ingroup profiling_base * @brief init profiler object. */ -RTS_API rtError_t rtProfilerInit(const char *profDir, const char *address, const char *jobCtx); +RTS_API rtError_t rtProfilerInit(const char_t *profDir, const char_t *address, const char_t *jobCtx); /** * @ingroup profiling_base * @brief config rts profiler. */ -RTS_API rtError_t rtProfilerConfig(uint16_t type); +RTS_API rtError_t rtProfilerConfig(uint16_t profConfig); /** * @ingroup profiling_base @@ -249,18 +261,6 @@ RTS_API rtError_t rtProfSetProSwitch(void *data, uint32_t len); */ RTS_API rtError_t rtProfRegisterCtrlCallback(uint32_t moduleId, rtProfCtrlHandle callback); -/** - * @ingroup dvrt_base - * @brief Returns the last error from a runtime call. - */ -RTS_API rtError_t rtGetLastError(); - -/** - * @ingroup dvrt_base - * @brief Returns the last error from a runtime call. - */ -RTS_API rtError_t rtPeekAtLastError(); - /** * @ingroup dvrt_base * @brief register callback for error code @@ -285,7 +285,7 @@ RTS_API rtError_t rtSetTaskFailCallback(rtTaskFailCallback callback); * @param [out] NA * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtRegDeviceStateCallback(const char *regName, rtDeviceStateCallback callback); +RTS_API rtError_t rtRegDeviceStateCallback(const char_t *regName, rtDeviceStateCallback callback); /** * @ingroup dvrt_base @@ -295,7 +295,7 @@ RTS_API rtError_t rtRegDeviceStateCallback(const char *regName, rtDeviceStateCal * @param [out] NA * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtRegTaskFailCallbackByModule(const char *moduleName, rtTaskFailCallback callback); +RTS_API rtError_t rtRegTaskFailCallbackByModule(const char_t *moduleName, rtTaskFailCallback callback); /** * @ingroup dvrt_base @@ -373,7 +373,7 @@ RTS_API rtError_t rtLabelGoto(rtLabel_t label, rtStream_t stream); * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtNameLabel(rtLabel_t label, const char *name); +RTS_API rtError_t rtNameLabel(rtLabel_t label, const char_t *name); /** * @ingroup dvrt_base diff --git a/third_party/fwkacllib/inc/runtime/config.h b/third_party/fwkacllib/inc/runtime/config.h index 76836e7b..64ab1497 100644 --- a/third_party/fwkacllib/inc/runtime/config.h +++ b/third_party/fwkacllib/inc/runtime/config.h @@ -1,21 +1,21 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ -#ifndef __CCE_RUNTIME_CONFIG_H__ -#define __CCE_RUNTIME_CONFIG_H__ +#ifndef CCE_RUNTIME_CONFIG_H +#define CCE_RUNTIME_CONFIG_H #include "base.h" @@ -23,28 +23,28 @@ extern "C" { #endif -#define PLAT_COMBINE(arch, chip, ver) ((arch << 16) | (chip << 8) | (ver)) -#define PLAT_GET_ARCH(type) ((type >> 16) & 0xffff) -#define PLAT_GET_CHIP(type) ((type >> 8) & 0xff) -#define PLAT_GET_VER(type) (type & 0xff) +#define PLAT_COMBINE(arch, chip, ver) (((arch) << 16U) | ((chip) << 8U) | (ver)) +#define PLAT_GET_ARCH(type) (((type) >> 16U) & 0xffffU) +#define PLAT_GET_CHIP(type) (((type) >> 8U) & 0xffU) +#define PLAT_GET_VER(type) ((type) & 0xffU) typedef enum tagRtArchType { ARCH_BEGIN = 0, ARCH_V100 = ARCH_BEGIN, - ARCH_V200, - ARCH_END, + ARCH_V200 = 1, + ARCH_END = 2, } rtArchType_t; typedef enum tagRtChipType { CHIP_BEGIN = 0, CHIP_MINI = CHIP_BEGIN, - CHIP_CLOUD, - CHIP_MDC, - CHIP_LHISI, - CHIP_DC, - CHIP_CLOUD_V2, - CHIP_NO_DEVICE, - CHIP_END, + CHIP_CLOUD = 1, + CHIP_MDC = 2, + CHIP_LHISI = 3, + CHIP_DC = 4, + CHIP_CLOUD_V2 = 5, + CHIP_NO_DEVICE = 6, + CHIP_END = 7, } rtChipType_t; typedef enum tagRtAicpuScheType { @@ -59,29 +59,32 @@ typedef enum tagRtDeviceCapabilityType { RT_SCHEDULE_HARDWARE, // HWTS Schedule RT_AICPU_BLOCKING_OP_NOT_SUPPORT, RT_AICPU_BLOCKING_OP_SUPPORT, // 1910/1980/1951 ts support AICPU blocking operation + RT_MODE_NO_FFTS, // no ffts + RT_MODE_FFTS, // 1981 get ffts work mode, ffts + RT_MODE_FFTS_PLUS, // 1981 get ffts work mode, ffts plus } rtDeviceCapabilityType; typedef enum tagRtVersion { VER_BEGIN = 0, VER_NA = VER_BEGIN, - VER_ES, - VER_CS, - VER_SD3403, - VER_END, + VER_ES = 1, + VER_CS = 2, + VER_SD3403 = 3, + VER_END = 4, } rtVersion_t; /* match rtChipType_t */ typedef enum tagRtPlatformType { PLATFORM_BEGIN = 0, PLATFORM_MINI_V1 = PLATFORM_BEGIN, - PLATFORM_CLOUD_V1, - PLATFORM_MINI_V2, - PLATFORM_LHISI_ES, - PLATFORM_LHISI_CS, - PLATFORM_DC, - PLATFORM_CLOUD_V2, - PLATFORM_LHISI_SD3403, - PLATFORM_END, + PLATFORM_CLOUD_V1 = 1, + PLATFORM_MINI_V2 = 2, + PLATFORM_LHISI_ES = 3, + PLATFORM_LHISI_CS = 4, + PLATFORM_DC = 5, + PLATFORM_CLOUD_V2 = 6, + PLATFORM_LHISI_SD3403 = 7, + PLATFORM_END = 8, } rtPlatformType_t; typedef enum tagRtCubeFracMKNFp16 { @@ -240,4 +243,4 @@ RTS_API rtError_t rtSetOpExecuteTimeOut(uint32_t timeout); } #endif -#endif // __CCE_RUNTIME_STREAM_H__ +#endif // CCE_RUNTIME_CONFIG_H \ No newline at end of file diff --git a/third_party/fwkacllib/inc/runtime/context.h b/third_party/fwkacllib/inc/runtime/context.h index bb6bf111..bc8dda52 100644 --- a/third_party/fwkacllib/inc/runtime/context.h +++ b/third_party/fwkacllib/inc/runtime/context.h @@ -1,21 +1,21 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ -#ifndef __CCE_RUNTIME_CONTEXT_H__ -#define __CCE_RUNTIME_CONTEXT_H__ +#ifndef CCE_RUNTIME_CONTEXT_H +#define CCE_RUNTIME_CONTEXT_H #include "base.h" @@ -173,4 +173,4 @@ RTS_API rtError_t rtSetCtxINFMode(bool mode); #endif -#endif // __CCE_RUNTIME_CONTEXT_H__ +#endif // CCE_RUNTIME_CONTEXT_H \ No newline at end of file diff --git a/third_party/fwkacllib/inc/runtime/dev.h b/third_party/fwkacllib/inc/runtime/dev.h index 3d3da22e..f6777262 100644 --- a/third_party/fwkacllib/inc/runtime/dev.h +++ b/third_party/fwkacllib/inc/runtime/dev.h @@ -1,21 +1,21 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ -#ifndef __CCE_RUNTIME_DEVICE_H__ -#define __CCE_RUNTIME_DEVICE_H__ +#ifndef CCE_RUNTIME_DEVICE_H +#define CCE_RUNTIME_DEVICE_H #include "base.h" @@ -23,8 +23,9 @@ extern "C" { #endif -#define RT_CAPABILITY_SUPPORT (0x1) -#define RT_CAPABILITY_NOT_SUPPORT (0x0) +#define RT_CAPABILITY_SUPPORT (0x1U) +#define RT_CAPABILITY_NOT_SUPPORT (0x0U) +#define MEMORY_INFO_TS_4G_LIMITED (0x0) // for compatibility typedef struct tagRTDeviceInfo { uint8_t env_type; // 0: FPGA 1: EMU 2: ESL @@ -45,27 +46,28 @@ typedef struct tagRTDeviceInfo { typedef enum tagRtRunMode { RT_RUN_MODE_OFFLINE = 0, - RT_RUN_MODE_ONLINE = 1, - RT_RUN_MODE_AICPU_SCHED = 2, + RT_RUN_MODE_ONLINE, + RT_RUN_MODE_AICPU_SCHED, RT_RUN_MODE_RESERVED } rtRunMode; typedef enum tagRtAicpuDeployType { AICPU_DEPLOY_CROSS_OS = 0x0, - AICPU_DEPLOY_CROSS_PROCESS = 0x1, - AICPU_DEPLOY_CROSS_THREAD = 0x2, + AICPU_DEPLOY_CROSS_PROCESS, + AICPU_DEPLOY_CROSS_THREAD, AICPU_DEPLOY_RESERVED } rtAicpuDeployType_t; typedef enum tagRtFeatureType { FEATURE_TYPE_MEMCPY = 0, - FEATURE_TYPE_MEMORY = 1, + FEATURE_TYPE_MEMORY, FEATURE_TYPE_RSV } rtFeatureType_t; typedef enum tagRtDeviceFeatureType { FEATURE_TYPE_SCHE, FEATURE_TYPE_BLOCKING_OPERATOR, + FEATURE_TYPE_FFTS_MODE, FEATURE_TYPE_END, } rtDeviceFeatureType_t; @@ -75,7 +77,7 @@ typedef enum tagMemcpyInfo { } rtMemcpyInfo_t; typedef enum tagMemoryInfo { - MEMORY_INFO_TS_4G_LIMITED = 0, + MEMORY_INFO_TS_LIMITED = 0, MEMORY_INFO_RSV } rtMemoryInfo_t; @@ -90,6 +92,15 @@ typedef enum tagRtDeviceModuleType { RT_MODULE_TYPE_VECTOR_CORE, /**< VECTOR CORE info*/ } rtDeviceModuleType_t; +// used for rtGetDevMsg callback function +typedef void (*rtGetMsgCallback)(const char_t *msg, uint32_t len); + +typedef enum tagGetDevMsgType { + RT_GET_DEV_ERROR_MSG = 0, + RT_GET_DEV_RUNNING_STREAM_SNAPSHOT_MSG, + RT_GET_DEV_MSG_RESERVE +} rtGetDevMsgType_t; + /** * @ingroup dvrt_dev * @brief get total device number. @@ -353,14 +364,14 @@ RTS_API rtError_t rtGetAicpuDeploy(rtAicpuDeployType_t *deployType); * @brief set chipType * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtSetSocVersion(const char *version); +RTS_API rtError_t rtSetSocVersion(const char_t *version); /** * @ingroup dvrt_dev * @brief get chipType * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtGetSocVersion(char *version, const uint32_t maxLen); +RTS_API rtError_t rtGetSocVersion(char_t *version, const uint32_t maxLen); /** * @ingroup dvrt_dev @@ -408,8 +419,17 @@ RTS_API rtError_t rtSetDeviceWithoutTsd(int32_t device); */ RTS_API rtError_t rtDeviceResetWithoutTsd(int32_t device); +/** + * @ingroup dvrt_dev + * @brief get device message + * @param [in] rtGetDevMsgType_t getMsgType:msg type + * @param [in] GetMsgCallback callback:acl callback function + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtGetDevMsg(rtGetDevMsgType_t getMsgType, rtGetMsgCallback callback); #if defined(__cplusplus) } #endif -#endif // __CCE_RUNTIME_DEVICE_H__ +#endif // CCE_RUNTIME_DEVICE_H diff --git a/third_party/fwkacllib/inc/runtime/dvfsprofile.h b/third_party/fwkacllib/inc/runtime/dvfsprofile.h index 33e2f4c1..c610bbb6 100644 --- a/third_party/fwkacllib/inc/runtime/dvfsprofile.h +++ b/third_party/fwkacllib/inc/runtime/dvfsprofile.h @@ -1,21 +1,21 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ -#ifndef __CCE_RUNTIME_DVFSPROFILE_H__ -#define __CCE_RUNTIME_DVFSPROFILE_H__ +#ifndef CCE_RUNTIME_DVFSPROFILE_H +#define CCE_RUNTIME_DVFSPROFILE_H #include "base.h" @@ -60,4 +60,4 @@ RTS_API rtError_t rtGetDvfsProfile(DvfsProfileMode *pmode); } #endif -#endif // __CCE_RUNTIME_PROFILE_H__ +#endif // CCE_RUNTIME_DVFSPROFILE_H \ No newline at end of file diff --git a/third_party/fwkacllib/inc/runtime/event.h b/third_party/fwkacllib/inc/runtime/event.h index 81b635c3..f6141d42 100644 --- a/third_party/fwkacllib/inc/runtime/event.h +++ b/third_party/fwkacllib/inc/runtime/event.h @@ -1,21 +1,21 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ -#ifndef __CCE_RUNTIME_EVENT_H__ -#define __CCE_RUNTIME_EVENT_H__ +#ifndef CCE_RUNTIME_EVENT_H +#define CCE_RUNTIME_EVENT_H #include "base.h" @@ -33,8 +33,8 @@ typedef enum rtEventWaitStatus { * @ingroup event_flags * @brief event op bit flags */ -#define RT_EVENT_DEFAULT (0x0E) -#define RT_EVENT_WITH_FLAG (0x0B) +#define RT_EVENT_DEFAULT (0x0EU) +#define RT_EVENT_WITH_FLAG (0x0BU) #define RT_EVENT_DDSYNC_NS 0x01U #define RT_EVENT_STREAM_MARK 0x02U @@ -133,7 +133,7 @@ RTS_API rtError_t rtEventQueryWaitStatus(rtEvent_t event, rtEventWaitStatus_t *s * @param [in] end ending event * @return RT_ERROR_NONE for ok, errno for failed */ -RTS_API rtError_t rtEventElapsedTime(float *time, rtEvent_t start, rtEvent_t end); +RTS_API rtError_t rtEventElapsedTime(float32_t *time, rtEvent_t start, rtEvent_t end); /** * @ingroup dvrt_event @@ -153,7 +153,7 @@ RTS_API rtError_t rtEventGetTimeStamp(uint64_t *time, rtEvent_t event); * @return RT_ERROR_INVALID_VALUE for error input of event, name * @return RT_ERROR_DRV_ERR for driver error */ -RTS_API rtError_t rtNameEvent(rtEvent_t event, const char *name); +RTS_API rtError_t rtNameEvent(rtEvent_t event, const char_t *name); /** * @ingroup dvrt_event @@ -200,14 +200,14 @@ RTS_API rtError_t rtNotifyWait(rtNotify_t notify, rtStream_t stream); /** * @ingroup dvrt_event * @brief Wait for a notify with time out - * @param [in] notify_ notify to be wait - * @param [in] stream_ input stream + * @param [in] notify notify to be wait + * @param [in] stream input stream * @param [in] timeOut input timeOut * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input * @return RT_ERROR_STREAM_CONTEXT for stream is not in current ctx */ -RTS_API rtError_t rtNotifyWaitWithTimeOut(rtNotify_t notify_, rtStream_t stream_, uint32_t timeOut); +RTS_API rtError_t rtNotifyWaitWithTimeOut(rtNotify_t notify, rtStream_t stream, uint32_t timeOut); /** * @ingroup dvrt_event @@ -217,7 +217,7 @@ RTS_API rtError_t rtNotifyWaitWithTimeOut(rtNotify_t notify_, rtStream_t stream_ * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtNameNotify(rtNotify_t notify, const char *name); +RTS_API rtError_t rtNameNotify(rtNotify_t notify, const char_t *name); /** * @ingroup dvrt_event @@ -237,7 +237,7 @@ RTS_API rtError_t rtGetNotifyID(rtNotify_t notify, uint32_t *notifyId); * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input of */ -RTS_API rtError_t rtIpcSetNotifyName(rtNotify_t notify, char *name, uint32_t len); +RTS_API rtError_t rtIpcSetNotifyName(rtNotify_t notify, char_t *name, uint32_t len); /** * @ingroup dvrt_event @@ -247,7 +247,7 @@ RTS_API rtError_t rtIpcSetNotifyName(rtNotify_t notify, char *name, uint32_t len * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtIpcOpenNotify(rtNotify_t *notify, const char *name); +RTS_API rtError_t rtIpcOpenNotify(rtNotify_t *notify, const char_t *name); /** * @ingroup dvrt_event @@ -270,10 +270,10 @@ RTS_API rtError_t rtNotifyGetAddrOffset(rtNotify_t notify, uint64_t *devAddrOffs * @return RT_ERROR_INVALID_VALUE for error input * @return RT_ERROR_DRV_ERR for driver error */ -RTS_API rtError_t rtSetIpcNotifyPid(const char *name, int32_t pid[], int num); +RTS_API rtError_t rtSetIpcNotifyPid(const char_t *name, int32_t pid[], int32_t num); #if defined(__cplusplus) } #endif -#endif // __CCE_RUNTIME_EVENT_H__ +#endif // CCE_RUNTIME_EVENT_H diff --git a/third_party/fwkacllib/inc/runtime/kernel.h b/third_party/fwkacllib/inc/runtime/kernel.h index f33b51d3..8c556e3a 100644 --- a/third_party/fwkacllib/inc/runtime/kernel.h +++ b/third_party/fwkacllib/inc/runtime/kernel.h @@ -1,21 +1,21 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ -#ifndef __CCE_RUNTIME_KERNEL_H__ -#define __CCE_RUNTIME_KERNEL_H__ +#ifndef CCE_RUNTIME_KERNEL_H +#define CCE_RUNTIME_KERNEL_H #include "base.h" #include "stream.h" @@ -116,9 +116,9 @@ typedef struct rtKernelInfo { * @brief op name */ typedef struct rtKernelLaunchNames { - const char *soName; // defined for so name - const char *kernelName; // defined for kernel type name - const char *opName; // defined for operator name + const char_t *soName; // defined for so name + const char_t *kernelName; // defined for kernel type name + const char_t *opName; // defined for operator name } rtKernelLaunchNames_t; /** @@ -131,7 +131,10 @@ typedef struct tagRtArgsWithTiling { uint32_t argsSizeWithoutTiling; // input + output + tiling addr size uint16_t tilingAddrOffset; // tiling addr offset uint16_t tilingDataOffset; // tiling data offset - uint16_t reserved[2]; + uint16_t hostInputAddrOffset; // index of host_memory input in inputs_addrs list + uint16_t hostInputDataOffset; // host_mem input data offset + bool hasHostMemInput; // has host_memory input data in args or not: ture or false + uint8_t reserved[7]; } rtArgsWithTiling_t; /** @@ -141,7 +144,7 @@ typedef struct tagRtArgsWithTiling { typedef enum tagRtDumpKind { RT_DATA_DUMP_KIND_INVALID = -1, RT_DATA_DUMP_KIND_DUMP = 0, - RT_DATA_DUMP_KIND_RESERVED + RT_DATA_DUMP_KIND_RESERVED = 1, } rtDumpKind_t; /** @@ -160,72 +163,72 @@ typedef void (*rtCallback_t)(void *fnData); * @ingroup rt_kernel * @brief magic number of plain binary for aicore */ -#define RT_DEV_BINARY_MAGIC_PLAIN 0xabceed50 +#define RT_DEV_BINARY_MAGIC_PLAIN 0xabceed50U /** * @ingroup rt_kernel * @brief magic number of plain binary for aicpu */ -#define RT_DEV_BINARY_MAGIC_PLAIN_AICPU 0xabceed51 +#define RT_DEV_BINARY_MAGIC_PLAIN_AICPU 0xabceed51U /** * @ingroup rt_kernel * @brief magic number of plain binary for aivector */ -#define RT_DEV_BINARY_MAGIC_PLAIN_AIVEC 0xabceed52 +#define RT_DEV_BINARY_MAGIC_PLAIN_AIVEC 0xabceed52U /** * @ingroup rt_kernel * @brief magic number of elf binary for aicore */ -#define RT_DEV_BINARY_MAGIC_ELF 0x43554245 +#define RT_DEV_BINARY_MAGIC_ELF 0x43554245U /** * @ingroup rt_kernel * @brief magic number of elf binary for aicpu */ -#define RT_DEV_BINARY_MAGIC_ELF_AICPU 0x41415243 +#define RT_DEV_BINARY_MAGIC_ELF_AICPU 0x41415243U /** * @ingroup rt_kernel * @brief magic number of elf binary for aivector */ -#define RT_DEV_BINARY_MAGIC_ELF_AIVEC 0x41415246 +#define RT_DEV_BINARY_MAGIC_ELF_AIVEC 0x41415246U /** * @ingroup rt_kernel * @brief magic number of elf binary for aicube */ -#define RT_DEV_BINARY_MAGIC_ELF_AICUBE 0x41494343 +#define RT_DEV_BINARY_MAGIC_ELF_AICUBE 0x41494343U /** * @ingroup rt_kernel_flags * @brief kernel op bit flags */ -#define RT_KERNEL_DEFAULT (0x00) -#define RT_KERNEL_CONVERT (0x01) -#define RT_KERNEL_DUMPFLAG (0x02) -#define RT_FUSION_KERNEL_DUMPFLAG (0x04) -#define RT_KERNEL_CUSTOM_AICPU (0x08) +#define RT_KERNEL_DEFAULT (0x00U) +#define RT_KERNEL_CONVERT (0x01U) +#define RT_KERNEL_DUMPFLAG (0x02U) +#define RT_FUSION_KERNEL_DUMPFLAG (0x04U) +#define RT_KERNEL_CUSTOM_AICPU (0x08U) // STARS topic scheduler sqe : topic_type -#define RT_KERNEL_DEVICE_FIRST (0x10) -#define RT_KERNEL_HOST_ONLY (0x20) -#define RT_KERNEL_HOST_FIRST (0x40) +#define RT_KERNEL_DEVICE_FIRST (0x10U) +#define RT_KERNEL_HOST_ONLY (0x20U) +#define RT_KERNEL_HOST_FIRST (0x40U) /** * @ingroup rt_kernel * @brief kernel mode **/ -#define RT_DEFAULT_KERNEL_MODE (0x00) -#define RT_NORMAL_KERNEL_MODE (0x01) -#define RT_ALL_KERNEL_MODE (0x02) +#define RT_DEFAULT_KERNEL_MODE (0x00U) +#define RT_NORMAL_KERNEL_MODE (0x01U) +#define RT_ALL_KERNEL_MODE (0x02U) /** * @ingroup rt_kernel * @brief kernel L1 Fusion Dump bit flags */ -#define RT_DDR_ADDR (0x0) +#define RT_DDR_ADDR (0x0U) /** * @ingroup rt_kernel @@ -273,7 +276,7 @@ RTS_API rtError_t rtDevBinaryUnRegister(void *handle); * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtMetadataRegister(void *handle, const char *metadata); +RTS_API rtError_t rtMetadataRegister(void *handle, const char_t *metadata); /** * @ingroup rt_kernel @@ -296,7 +299,7 @@ RTS_API rtError_t rtDependencyRegister(void *mHandle, void *sHandle); * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtFunctionRegister(void *binHandle, const void *stubFunc, const char *stubName, const void *devFunc, +RTS_API rtError_t rtFunctionRegister(void *binHandle, const void *stubFunc, const char_t *stubName, const void *devFunc, uint32_t funcMode); /** @@ -307,7 +310,7 @@ RTS_API rtError_t rtFunctionRegister(void *binHandle, const void *stubFunc, cons * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtGetFunctionByName(const char *stubName, void **stubFunc); +RTS_API rtError_t rtGetFunctionByName(const char_t *stubName, void **stubFunc); /** * @ingroup rt_kernel @@ -325,7 +328,7 @@ RTS_API rtError_t rtGetAddrByFun(const void *stubFunc, void **addr); * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtQueryFunctionRegistered(const char *stubName); +RTS_API rtError_t rtQueryFunctionRegistered(const char_t *stubName); /** * @ingroup rt_kernel @@ -410,7 +413,7 @@ RTS_API rtError_t rtKernelLaunchEx(void *args, uint32_t argsSize, uint32_t flags * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtKernelLaunchFwk(const char *opName, void *args, uint32_t argsSize, uint32_t flags, +RTS_API rtError_t rtKernelLaunchFwk(const char_t *opName, void *args, uint32_t argsSize, uint32_t flags, rtStream_t rtStream); /** @@ -672,7 +675,7 @@ RTS_API rtError_t rtStopMDCProfiler(void *addr); * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtKernelLaunchWithTiling(const void *stubFunc, uint32_t blockDim, - rtArgsWithTiling_t *argsInfo, rtSmDesc_t *smDesc, rtStream_t stream_); + rtArgsWithTiling_t *argsInfo, rtSmDesc_t *smDesc, rtStream_t stream); /** * @ingroup rt_kernel @@ -688,11 +691,11 @@ RTS_API rtError_t rtKernelLaunchWithTiling(const void *stubFunc, uint32_t blockD * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtKernelLaunchWithHandleAndTiling(void *handle, const void *devFunc, uint32_t blockDim, - rtArgsWithTiling_t *argsInfo, rtSmDesc_t *smDesc, rtStream_t stream_, const void* kernelInfo); + rtArgsWithTiling_t *argsInfo, rtSmDesc_t *smDesc, rtStream_t stream, const void* kernelInfo); #if defined(__cplusplus) } #endif -#endif // __CCE_RUNTIME_KERNEL_H__ +#endif // CCE_RUNTIME_KERNEL_H diff --git a/third_party/fwkacllib/inc/runtime/mem.h b/third_party/fwkacllib/inc/runtime/mem.h index b049e762..971f0cb0 100644 --- a/third_party/fwkacllib/inc/runtime/mem.h +++ b/third_party/fwkacllib/inc/runtime/mem.h @@ -1,25 +1,23 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ -#ifndef __CCE_RUNTIME_MEM_H__ -#define __CCE_RUNTIME_MEM_H__ +#ifndef CCE_RUNTIME_MEM_H +#define CCE_RUNTIME_MEM_H -/*lint -e7*/ #include -/*lint +e7*/ #include "base.h" #include "config.h" #include "stream.h" @@ -32,43 +30,43 @@ extern "C" { * @ingroup dvrt_mem * @brief memory type */ -#define RT_MEMORY_DEFAULT ((uint32_t)0x0) // default memory on device -#define RT_MEMORY_HBM ((uint32_t)0x2) // HBM memory on device -#define RT_MEMORY_RDMA_HBM ((uint32_t)0x3) // RDMA-HBM memory on device -#define RT_MEMORY_DDR ((uint32_t)0x4) // DDR memory on device -#define RT_MEMORY_SPM ((uint32_t)0x8) // shared physical memory on device -#define RT_MEMORY_P2P_HBM ((uint32_t)0x10) // HBM memory on other 4P device -#define RT_MEMORY_P2P_DDR ((uint32_t)0x11) // DDR memory on other device -#define RT_MEMORY_DDR_NC ((uint32_t)0x20) // DDR memory of non-cache -#define RT_MEMORY_TS_4G ((uint32_t)0x40) -#define RT_MEMORY_TS ((uint32_t)0x80) -#define RT_MEMORY_RESERVED ((uint32_t)0x100) +#define RT_MEMORY_DEFAULT (0x0U) // default memory on device +#define RT_MEMORY_HBM (0x2U) // HBM memory on device +#define RT_MEMORY_RDMA_HBM (0x3U) // RDMA-HBM memory on device +#define RT_MEMORY_DDR (0x4U) // DDR memory on device +#define RT_MEMORY_SPM (0x8U) // shared physical memory on device +#define RT_MEMORY_P2P_HBM (0x10U) // HBM memory on other 4P device +#define RT_MEMORY_P2P_DDR (0x11U) // DDR memory on other device +#define RT_MEMORY_DDR_NC (0x20U) // DDR memory of non-cache +#define RT_MEMORY_TS (0x40U) // Used for Ts memory +#define RT_MEMORY_TS_4G (0x40U) // Used for Ts memory(only 1951) +#define RT_MEMORY_RESERVED (0x100U) -#define RT_MEMORY_L1 ((uint32_t)0x1<<16) -#define RT_MEMORY_L2 ((uint32_t)0x1<<17) +#define RT_MEMORY_L1 (0x1U << 16U) +#define RT_MEMORY_L2 (0x1U << 17U) /** * @ingroup dvrt_mem * @brief memory info type */ -#define RT_MEM_INFO_TYPE_DDR_SIZE ((uint32_t)0x1) -#define RT_MEM_INFO_TYPE_HBM_SIZE ((uint32_t)0x2) -#define RT_MEM_INFO_TYPE_DDR_P2P_SIZE ((uint32_t)0x3) -#define RT_MEM_INFO_TYPE_HBM_P2P_SIZE ((uint32_t)0x4) +#define RT_MEM_INFO_TYPE_DDR_SIZE (0x1U) +#define RT_MEM_INFO_TYPE_HBM_SIZE (0x2U) +#define RT_MEM_INFO_TYPE_DDR_P2P_SIZE (0x3U) +#define RT_MEM_INFO_TYPE_HBM_P2P_SIZE (0x4U) /** * @ingroup dvrt_mem * @brief memory Policy */ -#define RT_MEMORY_POLICY_NONE ((uint32_t)0x0) // Malloc mem prior hage page, then default page -#define RT_MEMORY_POLICY_HUGE_PAGE_FIRST ((uint32_t)0x1 << 10) // Malloc mem prior hage page, then default page -#define RT_MEMORY_POLICY_HUGE_PAGE_ONLY ((uint32_t)0x1 << 11) // Malloc mem only use hage page -#define RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY ((uint32_t)0x1 << 12) // Malloc mem only use default page -#define RT_MEMORY_POLICY_HUGE_PAGE_FIRST_P2P ((uint32_t)0x1 << 13) // Malloc mem prior hage page, then default page, use for p2p -#define RT_MEMORY_POLICY_HUGE_PAGE_ONLY_P2P ((uint32_t)0x1 << 14) // Malloc mem only use hage page, use for p2p -#define RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY_P2P ((uint32_t)0x1 << 15) // Malloc mem only use default page, use for p2p +#define RT_MEMORY_POLICY_NONE (0x0U) // Malloc mem prior huge page, then default page +#define RT_MEMORY_POLICY_HUGE_PAGE_FIRST (0x1U << 10U) // Malloc mem prior huge page, then default page +#define RT_MEMORY_POLICY_HUGE_PAGE_ONLY (0x1U << 11U) // Malloc mem only use huge page +#define RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY (0x1U << 12U) // Malloc mem only use default page +#define RT_MEMORY_POLICY_HUGE_PAGE_FIRST_P2P (0x1U << 13U) // Malloc mem prior huge page, then default page, for p2p +#define RT_MEMORY_POLICY_HUGE_PAGE_ONLY_P2P (0x1U << 14U) // Malloc mem only use huge page, use for p2p +#define RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY_P2P (0x1U << 15U) // Malloc mem only use default page, use for p2p -#define MEM_ALLOC_TYPE_BIT ((uint32_t)0x3FF) // mem type bit in <0, 9> +#define MEM_ALLOC_TYPE_BIT (0x3FFU) // mem type bit in <0, 9> /** * @ingroup dvrt_mem @@ -80,10 +78,10 @@ typedef uint32_t rtMemType_t; * @ingroup dvrt_mem * @brief memory advise type */ -#define RT_MEMORY_ADVISE_EXE (0x02) -#define RT_MEMORY_ADVISE_THP (0x04) -#define RT_MEMORY_ADVISE_PLE (0x08) -#define RT_MEMORY_ADVISE_PIN (0x16) +#define RT_MEMORY_ADVISE_EXE (0x02U) +#define RT_MEMORY_ADVISE_THP (0x04U) +#define RT_MEMORY_ADVISE_PLE (0x08U) +#define RT_MEMORY_ADVISE_PIN (0x16U) /** * @ingroup dvrt_mem @@ -119,7 +117,7 @@ typedef enum tagRtRecudeKind { RT_MEMCPY_SDMA_AUTOMATIC_MAX = 11, RT_MEMCPY_SDMA_AUTOMATIC_MIN = 12, RT_MEMCPY_SDMA_AUTOMATIC_EQUAL = 13, - RT_RECUDE_KIND_END + RT_RECUDE_KIND_END = 14, } rtRecudeKind_t; typedef enum tagRtDataType { @@ -134,7 +132,7 @@ typedef enum tagRtDataType { RT_DATA_TYPE_UINT8 = 8, // uint8 RT_DATA_TYPE_UINT16= 9, // uint16 RT_DATA_TYPE_UINT32= 10,// uint32 - RT_DATA_TYPE_END + RT_DATA_TYPE_END = 11, } rtDataType_t; /** @@ -191,21 +189,21 @@ typedef struct tagRtPointerAttributes { typedef struct rtMallocHostSharedMemoryIn { - const char *name; + const char_t *name; const uint64_t size; uint32_t flag; } rtMallocHostSharedMemoryIn; typedef struct rtMallocHostSharedMemoryOut { - int fd; + int32_t fd; void *ptr; void *devPtr; } rtMallocHostSharedMemoryOut; typedef struct rtFreeHostSharedMemoryIn { - const char *name; + const char_t *name; const uint64_t size; - int fd; + int32_t fd; void *ptr; void *devPtr; } rtFreeHostSharedMemoryIn; @@ -310,6 +308,18 @@ RTS_API rtError_t rtMemAllocManaged(void **ptr, uint64_t size, uint32_t flag); * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtMemFreeManaged(void *ptr); + +/** + * @ingroup dvrt_mem + * @brief Specifies how memory is use + * @param [in] devPtr memory pointer + * @param [in] size memory size + * @param [in] advise reserved, set to 1 + * @return RT_ERROR_NONE for ok + * @return others for error + */ +RTS_API rtError_t rtMemAdvise(void *devPtr, uint64_t size, uint32_t advise); + /** * @ingroup dvrt_mem * @brief alloc cached device memory @@ -382,6 +392,39 @@ RTS_API rtError_t rtMemcpyAsync(void *dst, uint64_t destMax, const void *src, ui RTS_API rtError_t rtReduceAsync(void *dst, uint64_t destMax, const void *src, uint64_t count, rtRecudeKind_t kind, rtDataType_t type, rtStream_t stream); +/** + * @ingroup dvrt_mem + * @brief synchronized memcpy2D + * @param [in] dst destination address pointer + * @param [in] dstPitch pitch of destination memory + * @param [in] src source address pointer + * @param [in] srcPitch pitch of source memory + * @param [in] width width of matrix transfer + * @param [in] height height of matrix transfer + * @param [in] kind memcpy type + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtMemcpy2d(void *dst, uint64_t dstPitch, const void *src, uint64_t srcPitch, uint64_t width, + uint64_t height, rtMemcpyKind_t kind); + +/** + * @ingroup dvrt_mem + * @brief asynchronized memcpy2D + * @param [in] dst destination address pointer + * @param [in] dstPitch length of destination address memory + * @param [in] src source address pointer + * @param [in] srcPitch length of destination address memory + * @param [in] width width of matrix transfer + * @param [in] height height of matrix transfer + * @param [in] kind memcpy type + * @param [in] stream asynchronized task stream + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtMemcpy2dAsync(void *dst, uint64_t dstPitch, const void *src, uint64_t srcPitch, uint64_t width, + uint64_t height, rtMemcpyKind_t kind, rtStream_t stream); + /** * @ingroup dvrt_mem * @brief query memory size @@ -429,22 +472,22 @@ RTS_API rtError_t rtMemsetAsync(void *ptr, uint64_t destMax, uint32_t value, uin /** * @ingroup dvrt_mem * @brief get current device memory total and free - * @param [out] free - * @param [out] total + * @param [out] freeSize + * @param [out] totalSize * @return RT_ERROR_NONE for ok, errno for failed * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtMemGetInfo(size_t *free, size_t *total); +RTS_API rtError_t rtMemGetInfo(size_t *freeSize, size_t *totalSize); /** * @ingroup dvrt_mem * @brief get current device memory total and free * @param [in] memInfoType - * @param [out] free - * @param [out] total + * @param [out] freeSize + * @param [out] totalSize * @return RT_ERROR_NONE for ok, errno for failed */ -RTS_API rtError_t rtMemGetInfoEx(rtMemInfoType_t memInfoType, size_t *free, size_t *total); +RTS_API rtError_t rtMemGetInfoEx(rtMemInfoType_t memInfoType, size_t *freeSize, size_t *totalSize); /** * @ingroup dvrt_mem @@ -477,7 +520,7 @@ RTS_API rtError_t rtPointerGetAttributes(rtPointerAttributes_t *attributes, cons * @return RT_ERROR_INVALID_VALUE for error input * @return RT_ERROR_DRV_ERR for driver error */ -RTS_API rtError_t rtIpcSetMemoryName(const void *ptr, uint64_t byteCount, char *name, uint32_t len); +RTS_API rtError_t rtIpcSetMemoryName(const void *ptr, uint64_t byteCount, char_t *name, uint32_t len); /** * @ingroup dvrt_mem @@ -487,7 +530,7 @@ RTS_API rtError_t rtIpcSetMemoryName(const void *ptr, uint64_t byteCount, char * * @return RT_ERROR_INVALID_VALUE for error input * @return RT_ERROR_DRV_ERR for driver error */ -RTS_API rtError_t rtIpcDestroyMemoryName(const char *name); +RTS_API rtError_t rtIpcDestroyMemoryName(const char_t *name); /** * @ingroup dvrt_mem @@ -498,7 +541,7 @@ RTS_API rtError_t rtIpcDestroyMemoryName(const char *name); * @return RT_ERROR_INVALID_VALUE for error input * @return RT_ERROR_DRV_ERR for driver error */ -RTS_API rtError_t rtIpcOpenMemory(void **ptr, const char *name); +RTS_API rtError_t rtIpcOpenMemory(void **ptr, const char_t *name); /** * @ingroup dvrt_mem @@ -533,7 +576,7 @@ RTS_API rtError_t rtRDMASend(uint32_t index, uint32_t wqeIndex, rtStream_t strea * @return RT_ERROR_INVALID_VALUE for error input * @return RT_ERROR_DRV_ERR for driver error */ -RTS_API rtError_t rtSetIpcMemPid(const char *name, int32_t pid[], int num); +RTS_API rtError_t rtSetIpcMemPid(const char_t *name, int32_t pid[], int num); /** * @ingroup dvrt_mem @@ -551,4 +594,4 @@ RTS_API rtError_t rtRDMADBSend(uint32_t dbIndex, uint64_t dbInfo, rtStream_t str } #endif -#endif // __CCE_RUNTIME_MEM_H__ +#endif // CCE_RUNTIME_MEM_H diff --git a/third_party/fwkacllib/inc/runtime/rt.h b/third_party/fwkacllib/inc/runtime/rt.h index 6c2f5318..519ccd40 100644 --- a/third_party/fwkacllib/inc/runtime/rt.h +++ b/third_party/fwkacllib/inc/runtime/rt.h @@ -1,21 +1,21 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ -#ifndef __CCE_RUNTIME_RT_H__ -#define __CCE_RUNTIME_RT_H__ +#ifndef CCE_RUNTIME_RT_H +#define CCE_RUNTIME_RT_H #include "base.h" #include "config.h" @@ -32,4 +32,4 @@ #include "rt_ffts_plus.h" #include "rt_dfx.h" -#endif // __CCE_RUNTIME_RT_H__ +#endif // CCE_RUNTIME_RT_H \ No newline at end of file diff --git a/third_party/fwkacllib/inc/runtime/rt_dfx.h b/third_party/fwkacllib/inc/runtime/rt_dfx.h index d5927575..7e0bc280 100644 --- a/third_party/fwkacllib/inc/runtime/rt_dfx.h +++ b/third_party/fwkacllib/inc/runtime/rt_dfx.h @@ -1,6 +1,17 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. - * Description: dfx interface +/** + * Copyright 2019-2020 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. */ #ifndef CCE_RUNTIME_RT_DFX_H @@ -26,7 +37,7 @@ extern "C" { * @return RT_ERROR_NONE for ok * @return other failed */ -RTS_API rtError_t rtSetTaskTag(const char *taskTag); +RTS_API rtError_t rtSetTaskTag(const char_t *taskTag); #if defined(__cplusplus) } diff --git a/third_party/fwkacllib/inc/runtime/rt_ffts.h b/third_party/fwkacllib/inc/runtime/rt_ffts.h index f2809218..ded78d25 100644 --- a/third_party/fwkacllib/inc/runtime/rt_ffts.h +++ b/third_party/fwkacllib/inc/runtime/rt_ffts.h @@ -1,10 +1,21 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. - * Description: ffts interface +/** + * Copyright 2019-2020 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. */ -#ifndef __CCE_RUNTIME_FFTS_H -#define __CCE_RUNTIME_FFTS_H +#ifndef CCE_RUNTIME_RT_FFTS_H +#define CCE_RUNTIME_RT_FFTS_H #include "base.h" @@ -33,7 +44,7 @@ typedef enum tagFftsSubTaskType { RT_FFTS_SUB_TASK_TYPE_MIX_AIC = 6, RT_FFTS_SUB_TASK_TYPE_MIX_AIV = 7, RT_FFTS_SUB_TASK_TYPE_SDMA = 8, - RT_FFTS_SUB_TASK_TYPE_RESERVED, + RT_FFTS_SUB_TASK_TYPE_RESERVED = 9, } rtFftsSubTaskType_t; typedef struct tagManualThreadDmuInfo { @@ -64,7 +75,7 @@ typedef struct tagManualThreadAicAivInfo { // num: thread0_prefetch_dmu_descriptor_index – prefetch_once_dmu_descriptor_index uint16_t threadPrefetchDmuIdx[RT_FFTS_MAX_MANUAL_THREAD_NUM]; // max valid is threadDim uint16_t threadBlkDim[RT_FFTS_MAX_MANUAL_THREAD_NUM]; - const char *threadTaskFuncStub[RT_FFTS_MAX_MANUAL_THREAD_NUM]; + const char_t *threadTaskFuncStub[RT_FFTS_MAX_MANUAL_THREAD_NUM]; rtManualThreadDmuInfo_t *prefetchList; // dmu desc 0-64k, length is the last threadPrefetchDmuIdx[threadDim-1] rtManualThreadDependency_t srcDepTbl[RT_FFTS_MAX_TICKET_CACHE_PER_SUBTASK]; @@ -91,8 +102,8 @@ typedef struct tagAutoThreadAicAivInfo { uint16_t tailBlkDim; uint16_t nonTailBlkDim; - const char *nonTailTaskFuncStub; - const char *tailTaskFuncStub; + const char_t *nonTailTaskFuncStub; + const char_t *tailTaskFuncStub; // for prefetch, valid num is prefetchEnableBitmap bit count. // if prefetchEnableBitmap='00010011', need prefetch number is 3, srcPrefetch is only 0, 1, 2 is valid @@ -177,8 +188,11 @@ typedef struct tagFftsTaskInfo { } rtFftsTaskInfo_t; RTS_API rtError_t rtFftsTaskLaunch(rtFftsTaskInfo_t *fftsTaskInfo, rtStream_t stream); +RTS_API rtError_t rtGetC2cCtrlAddr(uint64_t *addr, uint32_t *len); + +RTS_API rtError_t rtFftsTaskLaunchWithFlag(rtFftsTaskInfo_t *fftsTaskInfo, rtStream_t stream, uint32_t flag); #if defined(__cplusplus) } #endif -#endif // __CCE_RUNTIME_FFTS_H +#endif // CCE_RUNTIME_RT_FFTS_H \ No newline at end of file diff --git a/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h b/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h index 61eee9f3..53f3e60a 100644 --- a/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h +++ b/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h @@ -1,10 +1,21 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. - * Description: ffts plus interface +/** + * Copyright 2019-2020 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. */ -#ifndef __CCE_RUNTIME_FFTS_PLUS_H -#define __CCE_RUNTIME_FFTS_PLUS_H +#ifndef CCE_RUNTIME_RT_FFTS_PLUS_H +#define CCE_RUNTIME_RT_FFTS_PLUS_H #include "base.h" #include "rt_ffts_plus_define.h" @@ -26,9 +37,13 @@ typedef struct tagFftsPlusTaskInfo { #pragma pack(pop) RTS_API rtError_t rtGetAddrAndPrefCntWithHandle(void *handle, const void *devFunc, void **addr, uint32_t *prefetchCnt); + RTS_API rtError_t rtFftsPlusTaskLaunch(rtFftsPlusTaskInfo_t *fftsPlusTaskInfo, rtStream_t stream); +RTS_API rtError_t rtFftsPlusTaskLaunchWithFlag(rtFftsPlusTaskInfo_t *fftsPlusTaskInfo, rtStream_t stream, + uint32_t flag); + #if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) } #endif -#endif // __CCE_RUNTIME_FFTS_H +#endif // CCE_RUNTIME_RT_FFTS_PLUS_H \ No newline at end of file diff --git a/third_party/fwkacllib/inc/runtime/rt_ffts_plus_define.h b/third_party/fwkacllib/inc/runtime/rt_ffts_plus_define.h index 9887b943..8956e009 100644 --- a/third_party/fwkacllib/inc/runtime/rt_ffts_plus_define.h +++ b/third_party/fwkacllib/inc/runtime/rt_ffts_plus_define.h @@ -1,10 +1,21 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. - * Description: the definition of ffts plus +/** + * Copyright 2019-2020 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. */ -#ifndef __CCE_RUNTIME_FFTS_PLUS_DEFINE_H -#define __CCE_RUNTIME_FFTS_PLUS_DEFINE_H +#ifndef CCE_RUNTIME_RT_FFTS_PLUS_DEFINE_H +#define CCE_RUNTIME_RT_FFTS_PLUS_DEFINE_H #include "base.h" @@ -30,7 +41,7 @@ typedef enum tagFftsPlusHwType { RT_HW_CTX_TYPE_WRITEBACK_DATA = 11, RT_HW_CTX_TYPE_AICPU = 12, RT_HW_CTX_TYPE_LOAD = 13, - RT_HW_CTX_TYPE_MAX, + RT_HW_CTX_TYPE_MAX = 14, } rtFftsPlusHwType_t; // hardware context type @@ -40,7 +51,8 @@ typedef enum tagFftsPlusSoftType { RT_SOFT_CTX_TYPE_AT_START = 3, RT_SOFT_CTX_TYPE_AT_END = 4, RT_SOFT_CTX_TYPE_LABEL = 5, - RT_SOFT_CTX_TYPE_MAX, + RT_SOFT_CTX_PERSISTENT_CACHE = 6, + RT_SOFT_CTX_TYPE_MAX = 7, } rtFftsPlusSoftType_t; typedef enum tagFftsPlusContextType { @@ -61,6 +73,7 @@ typedef enum tagFftsPlusContextType { RT_CTX_TYPE_AT_START = 0x0300, RT_CTX_TYPE_AT_END = 0x0400, RT_CTX_TYPE_LABEL = 0x0500, + RT_CTX_TYPE_PERSISTENT_CACHE = 0x0600, }rtFftsPlusContextType_t; // condition type @@ -71,7 +84,7 @@ typedef enum tagFftsPlusCondType { RT_COND_TYPE_GREATER_OR_EQUAL = 3, RT_COND_TYPE_LESS = 4, RT_COND_TYPE_LESS_OR_EQUAL = 5, - RT_COND_TYPE_MAX, + RT_COND_TYPE_MAX = 6, } rtFftsPlusCondType_t; // the definition of ffts plus context @@ -505,7 +518,7 @@ typedef struct tagFftsPlusAtStartCtx { uint16_t threadIdInit; uint16_t threadWindowSize; // 80-127 - uint16_t res9[12]; + uint32_t res9[12]; } rtFftsPlusAtStartCtx_t; // at end context @@ -707,9 +720,35 @@ typedef struct tagFftsPlusCondSwitchCtx { uint32_t cmpValue2; } rtFftsPlusCondSwitchCtx_t; +// ffts plus persistent cache context +typedef struct tagFftsPlusPersistentCacheCtx { + // 0- 3bytes + uint16_t contextType; + uint8_t successorNum; + uint8_t res1 : 7; + uint8_t aten : 1; + // 4-7 + uint8_t res2[2]; + uint8_t predCntInit; + uint8_t predCnt; + // 8-11 + uint8_t res3[4]; + // 12-63 + uint16_t successorList[RT_CTX_SUCCESSOR_NUM]; + // 64-67 + uint8_t persistentEnable : 1; + uint8_t res4 : 7; + uint8_t res5; + uint16_t persistentSize; + // 68-71 + uint32_t persistentId; + // 72-127 + uint32_t res6[14]; +} rtFftsPlusPersistentCacheCtx_t; + #pragma pack(pop) #if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) } #endif -#endif // __CCE_RUNTIME_FFTS_PLUS_DEFINE_H +#endif // CCE_RUNTIME_RT_FFTS_PLUS_DEFINE_H \ No newline at end of file diff --git a/third_party/fwkacllib/inc/runtime/rt_model.h b/third_party/fwkacllib/inc/runtime/rt_model.h index d0ffe9c8..9486639d 100644 --- a/third_party/fwkacllib/inc/runtime/rt_model.h +++ b/third_party/fwkacllib/inc/runtime/rt_model.h @@ -1,21 +1,21 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ -#ifndef __CCE_RUNTIME_MODEL_H__ -#define __CCE_RUNTIME_MODEL_H__ +#ifndef CCE_RUNTIME_RT_MODEL_H +#define CCE_RUNTIME_RT_MODEL_H #include "base.h" @@ -42,7 +42,7 @@ typedef enum tagModelTaskType { RT_MODEL_TASK_NOTIFY_WAIT, RT_MODEL_TASK_REDUCE_ASYNC, RT_MODEL_TASK_RDMA_SEND, - RT_MODEL_TASK_EVENT_RESET = 18, + RT_MODEL_TASK_EVENT_RESET, RT_MODEL_TASK_MODEL_END_GRAPH, RT_MODEL_TASK_STREAM_SWITCH_N, RT_MODEL_TASK_RDMA_DB_SEND, @@ -66,16 +66,16 @@ typedef enum tagModelQueueFlag { RT_MODEL_OUTPUT_QUEUE = 1 } rtModelQueueFlag_t; -#define EXECUTOR_NONE ((uint32_t)0x0) -#define EXECUTOR_TS ((uint32_t)0x01) -#define EXECUTOR_AICPU ((uint32_t)0x02) +#define EXECUTOR_NONE (0x0U) +#define EXECUTOR_TS (0x01U) +#define EXECUTOR_AICPU (0x02U) /* * @ingroup rt_model * @brief debug flag for kernel exception dump */ -#define RT_DEBUG_FLAG_AICORE_OVERFLOW (0x1 << 0) -#define RT_DEBUG_FLAG_ATOMIC_ADD_OVERFLOW (0x1 << 1) +#define RT_DEBUG_FLAG_AICORE_OVERFLOW (0x1U << 0U) +#define RT_DEBUG_FLAG_ATOMIC_ADD_OVERFLOW (0x1U << 1U) /** * @ingroup @@ -125,7 +125,7 @@ typedef struct tagKernelTaskInfo { uint16_t argsCount; uint16_t argsSize; uint16_t reserved; - char *stubFunc; + char_t *stubFunc; uint8_t *smDesc; uint8_t *args; uint16_t *argsOffset; @@ -392,12 +392,12 @@ RTS_API rtError_t rtModelExecute(rtModel_t model, rtStream_t stream, uint32_t fl * @ingroup rt_model * @brief get model the last persist task id * @param [in] model model to execute - * @param [out] taskid last task id of the model - * @param [out] streamid last steam id of the model + * @param [out] taskId last task id of the model + * @param [out] streamId last steam id of the model * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtModelGetTaskId(rtModel_t model, uint32_t *taskid, uint32_t *streamid); +RTS_API rtError_t rtModelGetTaskId(rtModel_t model, uint32_t *taskId, uint32_t *streamId); /** * @ingroup rt_model @@ -495,4 +495,4 @@ RTS_API rtError_t rtDebugUnRegister(rtModel_t model); } #endif -#endif // __CCE_RUNTIME_MODEL_H__ +#endif // CCE_RUNTIME_RT_MODEL_H \ No newline at end of file diff --git a/third_party/fwkacllib/inc/runtime/rt_stars.h b/third_party/fwkacllib/inc/runtime/rt_stars.h index 016c352a..857006b5 100644 --- a/third_party/fwkacllib/inc/runtime/rt_stars.h +++ b/third_party/fwkacllib/inc/runtime/rt_stars.h @@ -1,10 +1,21 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. - * Description: +/** + * Copyright 2019-2020 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. */ -#ifndef __CCE_RUNTIME_STARS_H -#define __CCE_RUNTIME_STARS_H +#ifndef CCE_RUNTIME_RT_STARS_H +#define CCE_RUNTIME_RT_STARS_H #include "base.h" @@ -32,7 +43,7 @@ RTS_API rtError_t rtStarsTaskLaunch(const void *taskSqe, uint32_t sqeLen, rtStre * @param [in] queName cdq name * @return RT_ERROR_NONE for ok, ACL_ERROR_RT_NO_CDQ_RESOURCE for no cdq resources */ -RTS_API rtError_t rtCdqCreate(uint32_t batchNum, uint32_t batchSize, const char *queName); +RTS_API rtError_t rtCdqCreate(uint32_t batchNum, uint32_t batchSize, const char_t *queName); /** * @ingroup rt_stars @@ -40,7 +51,7 @@ RTS_API rtError_t rtCdqCreate(uint32_t batchNum, uint32_t batchSize, const char * @param [in] queName cdq name * @return RT_ERROR_NONE for ok, others failed */ -RTS_API rtError_t rtCdqDestroy(const char *queName); +RTS_API rtError_t rtCdqDestroy(const char_t *queName); /** * @ingroup rt_stars @@ -50,7 +61,7 @@ RTS_API rtError_t rtCdqDestroy(const char *queName); * @param [out] batchId batch index * @return RT_ERROR_NONE for ok, ACL_ERROR_RT_WAIT_TIMEOUT for timeout */ -RTS_API rtError_t rtCdqAllocBatch(const char *queName, int32_t timeout, uint32_t *batchId); +RTS_API rtError_t rtCdqAllocBatch(const char_t *queName, int32_t timeout, uint32_t *batchId); /** * @ingroup rt_stars @@ -63,7 +74,7 @@ RTS_API rtError_t rtCdqAllocBatch(const char *queName, int32_t timeout, uint32_t * @param [in] stream launch task on the stream * @return RT_ERROR_NONE for ok, others failed */ -RTS_API rtError_t rtCdqEnQueue(const char *queName, uint32_t cdqeIndex, void *data, uint32_t dataSize, +RTS_API rtError_t rtCdqEnQueue(const char_t *queName, uint32_t cdqeIndex, void *data, uint32_t dataSize, rtStream_t stream); /** @@ -77,11 +88,11 @@ RTS_API rtError_t rtCdqEnQueue(const char *queName, uint32_t cdqeIndex, void *da * @param [in] stream launch task on the stream * @return RT_ERROR_NONE for ok, others failed */ -RTS_API rtError_t rtCdqEnQueuePtrMode(const char *queName, uint32_t cdqeIndex, const void *ptrAddr, +RTS_API rtError_t rtCdqEnQueuePtrMode(const char_t *queName, uint32_t cdqeIndex, const void *ptrAddr, rtStream_t stream); #if defined(__cplusplus) } #endif -#endif // __CCE_RUNTIME_STARS_H +#endif // CCE_RUNTIME_RT_STARS_H \ No newline at end of file diff --git a/third_party/fwkacllib/inc/runtime/rt_stars_define.h b/third_party/fwkacllib/inc/runtime/rt_stars_define.h index d77a8a8e..861af80b 100644 --- a/third_party/fwkacllib/inc/runtime/rt_stars_define.h +++ b/third_party/fwkacllib/inc/runtime/rt_stars_define.h @@ -1,10 +1,21 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. - * Description: the definition of stars +/** + * Copyright 2019-2020 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. */ -#ifndef __CCE_RUNTIME_STARS_DEFINE__H -#define __CCE_RUNTIME_STARS_DEFINE__H +#ifndef CCE_RUNTIME_RT_STARS_DEFINE_H +#define CCE_RUNTIME_RT_STARS_DEFINE_H #include "base.h" @@ -88,4 +99,4 @@ typedef struct tagFftsPlusSqe { #if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) } #endif -#endif // __CCE_RUNTIME_STARS_DEFINE__H \ No newline at end of file +#endif // CCE_RUNTIME_RT_STARS_DEFINE_H \ No newline at end of file diff --git a/third_party/fwkacllib/inc/runtime/stream.h b/third_party/fwkacllib/inc/runtime/stream.h index 3a078e99..a7ca9ebb 100644 --- a/third_party/fwkacllib/inc/runtime/stream.h +++ b/third_party/fwkacllib/inc/runtime/stream.h @@ -1,21 +1,21 @@ /** - * Copyright 2020 Huawei Technologies Co., Ltd - + * Copyright 2019-2020 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. -*/ + */ -#ifndef __CCE_RUNTIME_STREAM_H__ -#define __CCE_RUNTIME_STREAM_H__ +#ifndef CCE_RUNTIME_STREAM_H +#define CCE_RUNTIME_STREAM_H #include "base.h" #include "event.h" @@ -28,27 +28,27 @@ extern "C" { * @ingroup stream_flags * @brief stream op bit flags */ -#define RT_STREAM_DEFAULT (0x00) -#define RT_STREAM_PERSISTENT (0x01) -#define RT_STREAM_FORCE_COPY (0x02) -#define RT_STREAM_HUGE (0x04) -#define RT_STREAM_AICPU (0x08) -#define RT_STREAM_FORBIDDEN_DEFAULT (0x10) -#define RT_STREAM_HEAD (0x20) -#define RT_STREAM_PRIMARY_DEFAULT (0x40) -#define RT_STREAM_PRIMARY_FIRST_DEFAULT (0x80) +#define RT_STREAM_DEFAULT (0x00U) +#define RT_STREAM_PERSISTENT (0x01U) +#define RT_STREAM_FORCE_COPY (0x02U) +#define RT_STREAM_HUGE (0x04U) +#define RT_STREAM_AICPU (0x08U) +#define RT_STREAM_FORBIDDEN_DEFAULT (0x10U) +#define RT_STREAM_HEAD (0x20U) +#define RT_STREAM_PRIMARY_DEFAULT (0x40U) +#define RT_STREAM_PRIMARY_FIRST_DEFAULT (0x80U) /** * @ingroup stream_type * @brief stream type */ -#define RT_NORMAL_STREAM (0x00) -#define RT_HUGE_STREAM (0x01) +#define RT_NORMAL_STREAM (0x00U) +#define RT_HUGE_STREAM (0x01U) /** * priority level default value when create a stream */ -#define RT_STREAM_PRIORITY_DEFAULT (0) +#define RT_STREAM_PRIORITY_DEFAULT (0U) /** * @ingroup dvrt_stream @@ -137,7 +137,7 @@ RTS_API rtError_t rtGetMaxStreamAndTask(uint32_t streamType, uint32_t *maxStrCou * @return RT_ERROR_NONE for complete * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtNameStream(rtStream_t stream, const char *name); +RTS_API rtError_t rtNameStream(rtStream_t stream, const char_t *name); /** * @ingroup dvrt_stream @@ -215,4 +215,4 @@ RTS_API rtError_t rtDebugUnRegisterForStream(rtStream_t stream); } #endif -#endif // __CCE_RUNTIME_STREAM_H__ +#endif // CCE_RUNTIME_STREAM_H \ No newline at end of file diff --git a/third_party/fwkacllib/inc/toolchain/plog.h b/third_party/fwkacllib/inc/toolchain/plog.h index 6134c3e6..8dd8d403 100644 --- a/third_party/fwkacllib/inc/toolchain/plog.h +++ b/third_party/fwkacllib/inc/toolchain/plog.h @@ -44,14 +44,14 @@ extern "C" { * @brief DlogReportInitialize: init log in service process before all device setting. * @return: 0: SUCCEED, others: FAILED */ -DLL_EXPORT int DlogReportInitialize(); +DLL_EXPORT int DlogReportInitialize(void); /** * @ingroup plog * @brief DlogReportFinalize: release log resource in service process after all device reset. * @return: 0: SUCCEED, others: FAILED */ -DLL_EXPORT int DlogReportFinalize(); +DLL_EXPORT int DlogReportFinalize(void); #ifdef __cplusplus } diff --git a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h index d65aac83..0bc63385 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h +++ b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h @@ -22,18 +22,7 @@ #define PROF_TASK_TIME 0x00000002 #define PROF_AICORE_METRICS 0x00000004 #define PROF_AICPU_TRACE 0x00000008 -#define PROF_MODEL_EXECUTE 0x00000010 -#define PROF_RUNTIME_API 0x00000020 -#define PROF_RUNTIME_TRACE 0x00000040 -#define PROF_SCHEDULE_TIMELINE 0x00000080 -#define PROF_SCHEDULE_TRACE 0x00000100 -#define PROF_AIVECTORCORE_METRICS 0x00000200 -#define PROF_SUBTASK_TIME 0x00000400 - -#define PROF_TRAINING_TRACE 0x00000800 -#define PROF_HCCL_TRACE 0x00001000 - -#define PROF_TASK_TRACE 0x00001852 +#define PROF_L2CACHE 0x00000010 // system profilinig switch #define PROF_CPU 0x00010000 @@ -44,6 +33,19 @@ #define PROF_SYS_AICORE_SAMPLE 0x00200000 #define PROF_AIVECTORCORE_SAMPLE 0x00400000 +#define PROF_MODEL_EXECUTE 0x0000001000000 +#define PROF_RUNTIME_API 0x0000002000000 +#define PROF_RUNTIME_TRACE 0x0000004000000 +#define PROF_SCHEDULE_TIMELINE 0x0000008000000 +#define PROF_SCHEDULE_TRACE 0x0000010000000 +#define PROF_AIVECTORCORE_METRICS 0x0000020000000 +#define PROF_SUBTASK_TIME 0x0000040000000 + +#define PROF_TRAINING_TRACE 0x0000080000000 +#define PROF_HCCL_TRACE 0x0000100000000 + +#define PROF_TASK_TRACE 0x0000185000002 + #define PROF_MODEL_LOAD 0x8000000000000000 // DataTypeConfig MASK @@ -51,16 +53,7 @@ #define PROF_TASK_TIME_MASK 0x00000002 #define PROF_AICORE_METRICS_MASK 0x00000004 #define PROF_AICPU_TRACE_MASK 0x00000008 -#define PROF_MODEL_EXECUTE_MASK 0x00000010 -#define PROF_RUNTIME_API_MASK 0x00000020 -#define PROF_RUNTIME_TRACE_MASK 0x00000040 -#define PROF_SCHEDULE_TIMELINE_MASK 0x00000080 -#define PROF_SCHEDULE_TRACE_MASK 0x00000100 -#define PROF_AIVECTORCORE_METRICS_MASK 0x00000200 -#define PROF_SUBTASK_TIME_MASK 0x00000400 - -#define PROF_TRAINING_TRACE_MASK 0x00000800 -#define PROF_HCCL_TRACE_MASK 0x00001000 +#define PROF_L2CACHE_MASK 0x00000010 // system profilinig mask #define PROF_CPU_MASK 0x00010000 @@ -71,20 +64,27 @@ #define PROF_SYS_AICORE_SAMPLE_MASK 0x00200000 #define PROF_AIVECTORCORE_SAMPLE_MASK 0x00400000 -#define PROF_MODEL_LOAD_MASK 0x8000000000000000 +#define PROF_MODEL_EXECUTE_MASK 0x0000001000000 +#define PROF_RUNTIME_API_MASK 0x0000002000000 +#define PROF_RUNTIME_TRACE_MASK 0x0000004000000 +#define PROF_SCHEDULE_TIMELINE_MASK 0x0000008000000 +#define PROF_SCHEDULE_TRACE_MASK 0x0000010000000 +#define PROF_AIVECTORCORE_METRICS_MASK 0x0000020000000 +#define PROF_SUBTASK_TIME_MASK 0x0000040000000 -#ifndef OS_TYPE -#define OS_TYPE 0 -#endif // OS_TYPE +#define PROF_TRAINING_TRACE_MASK 0x0000080000000 +#define PROF_HCCL_TRACE_MASK 0x0000100000000 + +#define PROF_MODEL_LOAD_MASK 0x8000000000000000 -#if (OS_TYPE != LINUX) +#if (defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)) #define MSVP_PROF_API __declspec(dllexport) #else #define MSVP_PROF_API __attribute__((visibility("default"))) #endif #include -#include +#include namespace Msprofiler { namespace Api { @@ -106,7 +106,7 @@ extern "C" { MSVP_PROF_API uint64_t ProfGetOpExecutionTime(const void *data, uint32_t len, uint32_t index); -typedef uint32_t Status; +typedef int32_t Status; typedef struct aclprofSubscribeConfig aclprofSubscribeConfig1; /// /// @ingroup AscendCL diff --git a/third_party/fwkacllib/inc/toolchain/prof_callback.h b/third_party/fwkacllib/inc/toolchain/prof_callback.h index e6ac64bf..cb531417 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_callback.h +++ b/third_party/fwkacllib/inc/toolchain/prof_callback.h @@ -1,5 +1,5 @@ /** - * Copyright 2020-2020 Huawei Technologies Co., Ltd + * Copyright 2019-2020 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. @@ -12,9 +12,6 @@ * 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. - * - * @file prof_callback.h - * @brief declaraion of profiling callbacks */ #ifndef MSPROFILER_PROF_CALLBACK_H_ @@ -24,7 +21,7 @@ extern "C" { #endif // __cplusplus -#if (OS_TYPE != LINUX) +#if (defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)) #define MSVP_PROF_API __declspec(dllexport) #else #define MSVP_PROF_API __attribute__((visibility("default"))) diff --git a/third_party/fwkacllib/inc/toolchain/prof_reporter.h b/third_party/fwkacllib/inc/toolchain/prof_reporter.h index d5ed7569..f0747833 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_reporter.h +++ b/third_party/fwkacllib/inc/toolchain/prof_reporter.h @@ -16,11 +16,8 @@ #ifndef MSPROF_ENGINE_PROF_REPORTER_H_ #define MSPROF_ENGINE_PROF_REPORTER_H_ -#ifndef OS_TYPE -#define OS_TYPE 0 -#endif // OS_TYPE -#if (OS_TYPE != LINUX) +#if (defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)) #define MSVP_PROF_API __declspec(dllexport) #else #define MSVP_PROF_API __attribute__((visibility("default"))) From 0d2dfa274852b0015c58df5474588c6714bdd5ca Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Sat, 6 Nov 2021 11:46:52 +0800 Subject: [PATCH 40/59] fix missing hearders --- inc/framework/common/aicpu_op.h | 2 +- inc/framework/common/debug/ge_log.h | 90 ++++--- inc/framework/common/debug/log.h | 151 ++++++------ inc/framework/common/fmk_error_codes.h | 2 +- inc/framework/common/fmk_types.h | 2 +- inc/framework/common/ge_compiler_options.h | 2 +- inc/framework/common/ge_format_util.h | 4 +- inc/framework/common/ge_inner_error_codes.h | 44 ++-- inc/framework/common/ge_types.h | 43 ++-- inc/framework/common/gflags_util.h | 2 +- inc/framework/common/helper/model_helper.h | 12 +- inc/framework/common/helper/om_file_helper.h | 14 +- inc/framework/common/l2_cache_optimize.h | 25 +- inc/framework/common/op/attr_value_util.h | 4 +- inc/framework/common/op/ge_op_utils.h | 20 +- inc/framework/common/op/op_parser_util.h | 8 +- inc/framework/common/op_types.h | 10 +- inc/framework/common/profiling/ge_profiling.h | 4 +- .../common/profiling/ge_runner_profiling.h | 2 +- inc/framework/common/scope_guard.h | 15 +- inc/framework/common/string_util.h | 8 +- inc/framework/common/taskdown_common.h | 2 +- inc/framework/common/types.h | 211 +--------------- inc/framework/common/util.h | 229 +++++++++--------- inc/framework/engine/dnnengine.h | 29 ++- inc/framework/executor/ge_executor.h | 8 +- inc/framework/generator/ge_generator.h | 46 ++-- inc/framework/generator/generator_api.h | 187 -------------- inc/framework/memory/memory_api.h | 6 +- inc/framework/memory/memory_assigner.h | 6 +- inc/framework/omg/ge_init.h | 4 +- inc/framework/omg/model_tool.h | 2 +- inc/framework/omg/omg.h | 11 +- inc/framework/omg/omg_inner_types.h | 5 +- inc/framework/omg/omg_types.h | 2 +- inc/framework/omg/parser/model_parser.h | 2 +- inc/framework/omg/parser/op_parser.h | 4 +- inc/framework/omg/parser/parser_api.h | 4 +- inc/framework/omg/parser/parser_factory.h | 2 +- inc/framework/omg/parser/parser_inner_ctx.h | 2 +- inc/framework/omg/parser/parser_types.h | 4 +- inc/framework/omg/parser/weights_parser.h | 2 +- inc/framework/omg/version.h | 8 +- 43 files changed, 465 insertions(+), 775 deletions(-) delete mode 100644 inc/framework/generator/generator_api.h diff --git a/inc/framework/common/aicpu_op.h b/inc/framework/common/aicpu_op.h index 850ceca3..773d42fd 100644 --- a/inc/framework/common/aicpu_op.h +++ b/inc/framework/common/aicpu_op.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/inc/framework/common/debug/ge_log.h b/inc/framework/common/debug/ge_log.h index 3e646440..dbd6f875 100644 --- a/inc/framework/common/debug/ge_log.h +++ b/inc/framework/common/debug/ge_log.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ extern "C" { #endif -#define GE_MODULE_NAME static_cast(GE) +#define GE_MODULE_NAME static_cast(GE) // trace status of log enum TraceStatus { TRACE_INIT = 0, TRACE_RUNNING, TRACE_WAITING, TRACE_STOP }; @@ -51,43 +51,61 @@ class GE_FUNC_VISIBILITY GeLog { }; inline bool IsLogEnable(int module_name, int log_level) { - int32_t enable = CheckLogLevel(module_name, log_level); + const int32_t enable = CheckLogLevel(module_name, log_level); // 1:enable, 0:disable return (enable == 1); } -#define GELOGE(ERROR_CODE, fmt, ...) \ - dlog_error(GE_MODULE_NAME, "%lu %s: ErrorNo: %d(%s) %s" fmt, GeLog::GetTid(), __FUNCTION__, ERROR_CODE, \ - ((GE_GET_ERRORNO_STR(ERROR_CODE)).c_str()), ErrorManager::GetInstance().GetLogHeader().c_str(), \ - ##__VA_ARGS__) -#define GELOGW(fmt, ...) \ - if (IsLogEnable(GE_MODULE_NAME, DLOG_WARN)) \ - dlog_warn(GE_MODULE_NAME, "%lu %s:" fmt, GeLog::GetTid(), __FUNCTION__, ##__VA_ARGS__) -#define GELOGI(fmt, ...) \ - if (IsLogEnable(GE_MODULE_NAME, DLOG_INFO)) \ - dlog_info(GE_MODULE_NAME, "%lu %s:" fmt, GeLog::GetTid(), __FUNCTION__, ##__VA_ARGS__) -#define GELOGD(fmt, ...) \ - if (IsLogEnable(GE_MODULE_NAME, DLOG_DEBUG)) \ - dlog_debug(GE_MODULE_NAME, "%lu %s:" fmt, GeLog::GetTid(), __FUNCTION__, ##__VA_ARGS__) - -#define GEEVENT(fmt, ...) dlog_event(GE_MODULE_NAME, "%lu %s:" fmt, GeLog::GetTid(), __FUNCTION__, ##__VA_ARGS__) - -#define GELOGT(VALUE, fmt, ...) \ - do { \ - TraceStatus stat = VALUE; \ - const char *const TraceStatStr[] = {"INIT", "RUNNING", "WAITING", "STOP"}; \ - int idx = static_cast(stat); \ - char *k = const_cast("status"); \ - char *v = const_cast(TraceStatStr[idx]); \ - KeyValue kv = {k, v}; \ - DlogWithKV(static_cast(GE_MODULE_NAME), DLOG_TRACE, &kv, 1, "%lu %s:" fmt, GeLog::GetTid(), __FUNCTION__, \ - ##__VA_ARGS__); \ - } while (0) - -#define GE_LOG_ERROR(MOD_NAME, ERROR_CODE, fmt, ...) \ - dlog_error(MOD_NAME, "%lu %s: ErrorNo: %d(%s) %s" fmt, GeLog::GetTid(), __FUNCTION__, ERROR_CODE, \ - ((GE_GET_ERRORNO_STR(ERROR_CODE)).c_str()), ErrorManager::GetInstance().GetLogHeader().c_str(), \ - ##__VA_ARGS__) +#define GELOGE(ERROR_CODE, fmt, ...) \ + do { \ + dlog_error(GE_MODULE_NAME, "%lu %s: ErrorNo: %u(%s) %s" fmt, GeLog::GetTid(), &__FUNCTION__[0], ERROR_CODE, \ + ((GE_GET_ERRORNO_STR(ERROR_CODE)).c_str()), ErrorManager::GetInstance().GetLogHeader().c_str(), \ + ##__VA_ARGS__); \ + } while (false) + +#define GELOGW(fmt, ...) \ + do { \ + if (IsLogEnable(GE_MODULE_NAME, DLOG_WARN)) { \ + dlog_warn(GE_MODULE_NAME, "%lu %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \ + } \ + } while (false) + +#define GELOGI(fmt, ...) \ + do { \ + if (IsLogEnable(GE_MODULE_NAME, DLOG_INFO)) { \ + dlog_info(GE_MODULE_NAME, "%lu %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \ + } \ + } while (false) + +#define GELOGD(fmt, ...) \ + do { \ + if (IsLogEnable(GE_MODULE_NAME, DLOG_DEBUG)) { \ + dlog_debug(GE_MODULE_NAME, "%lu %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \ + } \ + } while (false) + +#define GEEVENT(fmt, ...) \ + do { \ + dlog_event(GE_MODULE_NAME, "%lu %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \ + } while (false) + +#define GELOGT(VALUE, fmt, ...) \ + do { \ + TraceStatus stat = VALUE; \ + const char *const TraceStatStr[] = {"INIT", "RUNNING", "WAITING", "STOP"}; \ + const int32_t idx = static_cast(stat); \ + char *k = const_cast("status"); \ + char *v = const_cast(TraceStatStr[idx]); \ + KeyValue kv = {k, v}; \ + DlogWithKV(GE_MODULE_NAME, DLOG_TRACE, &kv, 1, "%lu %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \ + } while (false) + +#define GE_LOG_ERROR(MOD_NAME, ERROR_CODE, fmt, ...) \ + do { \ + dlog_error(MOD_NAME, "%lu %s: ErrorNo: %u(%s) %s" fmt, GeLog::GetTid(), &__FUNCTION__[0], ERROR_CODE, \ + ((GE_GET_ERRORNO_STR(ERROR_CODE)).c_str()), ErrorManager::GetInstance().GetLogHeader().c_str(), \ + ##__VA_ARGS__); \ + } while (false) // print memory when it is greater than 1KB. #define GE_PRINT_DYNAMIC_MEMORY(FUNC, PURPOSE, SIZE) \ @@ -95,7 +113,7 @@ inline bool IsLogEnable(int module_name, int log_level) { if ((SIZE) > 1024) { \ GELOGI("MallocMemory, func=%s, size=%zu, purpose=%s", (#FUNC), static_cast(SIZE), (PURPOSE)); \ } \ - } while (0); + } while (false) #ifdef __cplusplus } #endif diff --git a/inc/framework/common/debug/log.h b/inc/framework/common/debug/log.h index f06faa1b..3b11ce57 100644 --- a/inc/framework/common/debug/log.h +++ b/inc/framework/common/debug/log.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,14 +19,11 @@ #include #include -#include -#include "runtime/rt.h" -#include "common/string_util.h" -#include "common/util.h" -#include "common/util/error_manager/error_manager.h" +#include "framework/common/string_util.h" +#include "framework/common/util.h" #include "framework/common/debug/ge_log.h" -#include "ge/ge_api_error_codes.h" +#include "external/ge/ge_api_error_codes.h" #if !defined(__ANDROID__) && !defined(ANDROID) #define DOMI_LOGE(fmt, ...) GE_LOG_ERROR(GE_MODULE_NAME, ge::FAILED, fmt, ##__VA_ARGS__) @@ -52,82 +49,82 @@ GELOGW(__VA_ARGS__); \ } -#define GE_LOGE_IF(condition, ...) \ - if ((condition)) { \ - DOMI_LOGE(__VA_ARGS__); \ +#define GE_LOGE_IF(condition, ...) \ + if ((condition)) { \ + GELOGE(ge::FAILED, __VA_ARGS__); \ } // If expr is not SUCCESS, print the log and return the same value -#define GE_CHK_STATUS_RET(expr, ...) \ - do { \ - const ge::Status _status = (expr); \ - if (_status != ge::SUCCESS) { \ - DOMI_LOGE(__VA_ARGS__); \ - return _status; \ - } \ - } while (0); +#define GE_CHK_STATUS_RET(expr, ...) \ + do { \ + const ge::Status _chk_status = (expr); \ + if (_chk_status != ge::SUCCESS) { \ + GELOGE(ge::FAILED, __VA_ARGS__); \ + return _chk_status; \ + } \ + } while (false) // If expr is not SUCCESS, print the log and do not execute return -#define GE_CHK_STATUS(expr, ...) \ - do { \ - const ge::Status _status = (expr); \ - if (_status != ge::SUCCESS) { \ - DOMI_LOGE(__VA_ARGS__); \ - } \ - } while (0); +#define GE_CHK_STATUS(expr, ...) \ + do { \ + const ge::Status _chk_status = (expr); \ + if (_chk_status != ge::SUCCESS) { \ + GELOGE(ge::FAILED, __VA_ARGS__); \ + } \ + } while (false) // If expr is not SUCCESS, return the same value -#define GE_CHK_STATUS_RET_NOLOG(expr) \ - do { \ - const ge::Status _status = (expr); \ - if (_status != ge::SUCCESS) { \ - return _status; \ - } \ - } while (0); +#define GE_CHK_STATUS_RET_NOLOG(expr) \ + do { \ + const ge::Status _chk_status = (expr); \ + if (_chk_status != ge::SUCCESS) { \ + return _chk_status; \ + } \ + } while (false) // If expr is not GRAPH_SUCCESS, print the log and return FAILED #define GE_CHK_GRAPH_STATUS_RET(expr, ...) \ do { \ if ((expr) != ge::GRAPH_SUCCESS) { \ REPORT_CALL_ERROR("E19999", "Operator graph failed"); \ - DOMI_LOGE(__VA_ARGS__); \ + GELOGE(ge::FAILED, __VA_ARGS__); \ return FAILED; \ } \ - } while (0); + } while (false) // If expr is not SUCCESS, print the log and execute a custom statement -#define GE_CHK_STATUS_EXEC(expr, exec_expr, ...) \ - do { \ - const ge::Status _status = (expr); \ - GE_CHK_BOOL_EXEC(_status == SUCCESS, exec_expr, __VA_ARGS__); \ - } while (0); +#define GE_CHK_STATUS_EXEC(expr, exec_expr, ...) \ + do { \ + const ge::Status _chk_status = (expr); \ + GE_CHK_BOOL_EXEC(_chk_status == SUCCESS, exec_expr, __VA_ARGS__); \ + } while (false) // If expr is not true, print the log and return the specified status #define GE_CHK_BOOL_RET_STATUS(expr, _status, ...) \ do { \ - bool b = (expr); \ + const bool b = (expr); \ if (!b) { \ REPORT_INNER_ERROR("E19999", __VA_ARGS__); \ GELOGE(_status, __VA_ARGS__); \ return _status; \ } \ - } while (0); + } while (false) // If expr is not true, print the log and return the specified status #define GE_CHK_BOOL_RET_STATUS_NOLOG(expr, _status, ...) \ do { \ - bool b = (expr); \ + const bool b = (expr); \ if (!b) { \ return _status; \ } \ - } while (0); + } while (false) // If expr is not true, print the log and execute a custom statement #define GE_CHK_BOOL_EXEC(expr, exec_expr, ...) \ { \ - bool b = (expr); \ + const bool b = (expr); \ if (!b) { \ - DOMI_LOGE(__VA_ARGS__); \ + GELOGE(ge::FAILED, __VA_ARGS__); \ exec_expr; \ } \ } @@ -135,7 +132,7 @@ // If expr is not true, print the log and execute a custom statement #define GE_CHK_BOOL_EXEC_WARN(expr, exec_expr, ...) \ { \ - bool b = (expr); \ + const bool b = (expr); \ if (!b) { \ GELOGW(__VA_ARGS__); \ exec_expr; \ @@ -144,7 +141,7 @@ // If expr is not true, print the log and execute a custom statement #define GE_CHK_BOOL_EXEC_INFO(expr, exec_expr, ...) \ { \ - bool b = (expr); \ + const bool b = (expr); \ if (!b) { \ GELOGI(__VA_ARGS__); \ exec_expr; \ @@ -154,7 +151,7 @@ // If expr is not true, print the log and execute a custom statement #define GE_CHK_BOOL_TRUE_EXEC_INFO(expr, exec_expr, ...) \ { \ - bool b = (expr); \ + const bool b = (expr); \ if (b) { \ GELOGI(__VA_ARGS__); \ exec_expr; \ @@ -164,16 +161,16 @@ // If expr is true, print logs and execute custom statements #define GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(expr, exec_expr, ...) \ { \ - bool b = (expr); \ + const bool b = (expr); \ if (b) { \ - DOMI_LOGE(__VA_ARGS__); \ + GELOGE(ge::FAILED, __VA_ARGS__); \ exec_expr; \ } \ } // If expr is true, print the Information log and execute a custom statement #define GE_CHK_TRUE_EXEC_INFO(expr, exec_expr, ...) \ { \ - bool b = (expr); \ + const bool b = (expr); \ if (b) { \ GELOGI(__VA_ARGS__); \ exec_expr; \ @@ -183,9 +180,9 @@ // If expr is not SUCCESS, print the log and execute the expression + return #define GE_CHK_BOOL_TRUE_RET_VOID(expr, exec_expr, ...) \ { \ - bool b = (expr); \ + const bool b = (expr); \ if (b) { \ - DOMI_LOGE(__VA_ARGS__); \ + GELOGE(ge::FAILED, __VA_ARGS__); \ exec_expr; \ return; \ } \ @@ -194,10 +191,10 @@ // If expr is not SUCCESS, print the log and execute the expression + return _status #define GE_CHK_BOOL_TRUE_EXEC_RET_STATUS(expr, _status, exec_expr, ...) \ { \ - bool b = (expr); \ + const bool b = (expr); \ if (b) { \ REPORT_INNER_ERROR("E19999", __VA_ARGS__); \ - DOMI_LOGE(__VA_ARGS__); \ + GELOGE(ge::FAILED, __VA_ARGS__); \ exec_expr; \ return _status; \ } \ @@ -206,7 +203,7 @@ // If expr is not true, execute a custom statement #define GE_CHK_BOOL_EXEC_NOLOG(expr, exec_expr) \ { \ - bool b = (expr); \ + const bool b = (expr); \ if (!b) { \ exec_expr; \ } \ @@ -214,34 +211,34 @@ // -----------------runtime related macro definitions------------------------------- // If expr is not RT_ERROR_NONE, print the log -#define GE_CHK_RT(expr) \ - do { \ - rtError_t _rt_ret = (expr); \ - if (_rt_ret != RT_ERROR_NONE) { \ - DOMI_LOGE("Call rt api failed, ret: 0x%X", _rt_ret); \ - } \ - } while (0); +#define GE_CHK_RT(expr) \ + do { \ + const rtError_t _rt_ret = (expr); \ + if (_rt_ret != RT_ERROR_NONE) { \ + GELOGE(ge::FAILED, "Call rt api failed, ret: 0x%X", _rt_ret); \ + } \ + } while (false) // If expr is not RT_ERROR_NONE, print the log and execute the exec_expr expression -#define GE_CHK_RT_EXEC(expr, exec_expr) \ - { \ - rtError_t _rt_ret = (expr); \ - if (_rt_ret != RT_ERROR_NONE) { \ - DOMI_LOGE("Call rt api failed, ret: 0x%X", _rt_ret); \ - exec_expr; \ - } \ - } +#define GE_CHK_RT_EXEC(expr, exec_expr) \ + do { \ + const rtError_t _rt_ret = (expr); \ + if (_rt_ret != RT_ERROR_NONE) { \ + GELOGE(ge::FAILED, "Call rt api failed, ret: 0x%X", _rt_ret); \ + exec_expr; \ + } \ + } while (false) // If expr is not RT_ERROR_NONE, print the log and return #define GE_CHK_RT_RET(expr) \ do { \ - rtError_t _rt_ret = (expr); \ + const rtError_t _rt_ret = (expr); \ if (_rt_ret != RT_ERROR_NONE) { \ REPORT_CALL_ERROR("E19999", "Call %s fail, ret: 0x%X", #expr, _rt_ret); \ - DOMI_LOGE("Call rt api failed, ret: 0x%X", _rt_ret); \ + GELOGE(ge::FAILED, "Call rt api failed, ret: 0x%X", _rt_ret); \ return RT_ERROR_TO_GE_STATUS(_rt_ret); \ } \ - } while (0); + } while (false) // If expr is true, execute exec_expr without printing logs #define GE_IF_BOOL_EXEC(expr, exec_expr) \ @@ -256,7 +253,7 @@ try { \ exec_expr0; \ } catch (const std::bad_alloc &) { \ - DOMI_LOGE("Make shared failed"); \ + GELOGE(ge::FAILED, "Make shared failed"); \ exec_expr1; \ } @@ -274,13 +271,13 @@ #define GE_CHK_LOG_AND_ERRORMSG(expr, _status, errormsg) \ do { \ - bool b = (expr); \ + const bool b = (expr); \ if (!b) { \ GELOGE(_status, "%s", errormsg); \ ErrorManager::GetInstance().ATCReportErrMessage("E19021", {"reason"}, {errormsg}); \ return _status; \ } \ - } while (0) + } while (false) template GE_FUNC_VISIBILITY std::string FmtToStr(const T &t) { diff --git a/inc/framework/common/fmk_error_codes.h b/inc/framework/common/fmk_error_codes.h index 188809bd..139785ae 100644 --- a/inc/framework/common/fmk_error_codes.h +++ b/inc/framework/common/fmk_error_codes.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/inc/framework/common/fmk_types.h b/inc/framework/common/fmk_types.h index f84390da..906e2a69 100644 --- a/inc/framework/common/fmk_types.h +++ b/inc/framework/common/fmk_types.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/inc/framework/common/ge_compiler_options.h b/inc/framework/common/ge_compiler_options.h index 6876740e..075c9403 100644 --- a/inc/framework/common/ge_compiler_options.h +++ b/inc/framework/common/ge_compiler_options.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/inc/framework/common/ge_format_util.h b/inc/framework/common/ge_format_util.h index dfceefb8..3c621576 100644 --- a/inc/framework/common/ge_format_util.h +++ b/inc/framework/common/ge_format_util.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,7 @@ #include -#include "common/ge_inner_error_codes.h" +#include "framework/common/ge_inner_error_codes.h" #include "graph/tensor.h" namespace ge { diff --git a/inc/framework/common/ge_inner_error_codes.h b/inc/framework/common/ge_inner_error_codes.h index 3697a526..9e9b5d1d 100644 --- a/inc/framework/common/ge_inner_error_codes.h +++ b/inc/framework/common/ge_inner_error_codes.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -61,29 +61,29 @@ enum ErrorLevel { CRITICAL_LEVEL = 0b100, }; -// Each module defines error codes using the following macros +// Each module defines error codes using the following macros, name can not be modified to (name) #define GE_ERRORNO_COMMON(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, COMMON_MODULE, name, value, desc) + GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, COMMON_MODULE, name, (value), (desc)) #define GE_ERRORNO_CLIENT(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, CLIENT_MODULE, name, value, desc) + GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, CLIENT_MODULE, name, (value), (desc)) #define GE_ERRORNO_INIT(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, INIT_MODULE, name, value, desc) + GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, INIT_MODULE, name, (value), (desc)) #define GE_ERRORNO_SESSION(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, SESSION_MODULE, name, value, desc) + GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, SESSION_MODULE, name, (value), (desc)) #define GE_ERRORNO_GRAPH(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, GRAPH_MODULE, name, value, desc) + GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, GRAPH_MODULE, name, (value), (desc)) #define GE_ERRORNO_ENGINE(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, ENGINE_MODULE, name, value, desc) + GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, ENGINE_MODULE, name, (value), (desc)) #define GE_ERRORNO_OPS(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, OPS_MODULE, name, value, desc) + GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, OPS_MODULE, name, (value), (desc)) #define GE_ERRORNO_PLUGIN(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, PLUGIN_MODULE, name, value, desc) + GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, PLUGIN_MODULE, name, (value), (desc)) #define GE_ERRORNO_RUNTIME(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, RUNTIME_MODULE, name, value, desc) + GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, RUNTIME_MODULE, name, (value), (desc)) #define GE_ERRORNO_EXECUTOR(name, value, desc) \ - GE_ERRORNO(RT_DEVICE, ERROR_CODE, COMMON_LEVEL, SYSID_GE, EXECUTOR_MODULE, name, value, desc) + GE_ERRORNO(RT_DEVICE, ERROR_CODE, COMMON_LEVEL, SYSID_GE, EXECUTOR_MODULE, name, (value), (desc)) #define GE_ERRORNO_GENERATOR(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, GENERATOR_MODULE, name, value, desc) + GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, GENERATOR_MODULE, name, (value), (desc)) // Get error code description #define GE_GET_ERRORNO_STR(value) ge::StatusFactory::Instance()->GetErrDesc(value) @@ -125,13 +125,13 @@ GE_ERRORNO_CLIENT(GE_CLI_GE_ALREADY_INITIALIZED, 10, "GE is already initialized. GE_ERRORNO_CLIENT(GE_CLI_GE_NOT_INITIALIZED, 11, "GE is not yet initialized or is finalized."); // 1343229963 // Init module error code definition -GE_ERRORNO_INIT(GE_MULTI_INIT, 0, "Multiple initializations are not supported."); // 1343234048 -GE_ERRORNO_INIT(GE_FINALIZE_NOT_INIT, 1, "Finalize is not allowed before initialization."); // 1343234049 -GE_ERRORNO_INIT(GE_MULTI_FINALIZE, 2, "Multiple finalizations are not supported."); // 1343234050 -GE_ERRORNO_INIT(GE_PROF_MULTI_INIT, 3, "Multiple profiling initializations are not supported."); // 1343234051 -GE_ERRORNO_INIT(GE_PROF_NOT_INIT, 4, "Profing initializations have not been done."); // 1343234052 +GE_ERRORNO_INIT(GE_MULTI_INIT, 0, "Multiple initializations are not supported."); // 1343234048 +GE_ERRORNO_INIT(GE_FINALIZE_NOT_INIT, 1, "Finalize is not allowed before initialization."); // 1343234049 +GE_ERRORNO_INIT(GE_MULTI_FINALIZE, 2, "Multiple finalizations are not supported."); // 1343234050 +GE_ERRORNO_INIT(GE_PROF_MULTI_INIT, 3, "Multiple profiling initializations are not supported."); // 1343234051 +GE_ERRORNO_INIT(GE_PROF_NOT_INIT, 4, "Profing initializations have not been done."); // 1343234052 GE_ERRORNO_INIT(GE_PROF_MODE_CONFLICT, 5, - "Profiling command mode which is preferred is running, the api mode will not work."); // 1343234053 + "Profiling command mode which is preferred is running, the api mode will not work."); // 1343234053 // Session module error code definition GE_ERRORNO_SESSION(GE_SESS_INIT_FAILED, 0, "Failed to initialize session."); // 1343238144 @@ -216,8 +216,8 @@ GE_ERRORNO_ENGINE(GE_ENG_FINALIZE_FAILED, 1, "Engine finalize failed."); GE_ERRORNO_ENGINE(GE_ENG_MEMTYPE_ERROR, 2, "Memory type HBM is necessary when engine is in device"); // 1343246338 // Optimize errocode -GE_ERRORNO_GRAPH(TO_BE_DELETED, 63, "The node of the graph to be deleted."); // 1343242303 -GE_ERRORNO_GRAPH(NOT_CHANGED, 64, "The node of the graph no changed."); // 1343242304 +GE_ERRORNO_GRAPH(TO_BE_DELETED, 63, "The node of the graph to be deleted."); // 1343242303 +GE_ERRORNO_GRAPH(NOT_CHANGED, 64, "The node of the graph no changed."); // 1343242304 // Ops module error code definition GE_ERRORNO_OPS(GE_OPS_KERNEL_STORE_INIT_FAILED, 0, "Failed to initialize OpsKernelInfoStore."); // 1343250432 @@ -313,7 +313,7 @@ GE_ERRORNO_GENERATOR(GE_GENERATOR_GRAPH_MANAGER_BUILD_GRAPH_FAILED, 3, "Graph ma GE_ERRORNO_GENERATOR(GE_GENERATOR_GRAPH_MANAGER_FINALIZE_FAILED, 4, "Graph manager finalize failed."); GE_ERRORNO_GENERATOR(GE_GENERATOR_GRAPH_MANAGER_SAVE_MODEL_FAILED, 5, "Graph manager save model failed."); -#define RT_ERROR_TO_GE_STATUS(RT_ERROR) static_cast(RT_ERROR) +#define RT_ERROR_TO_GE_STATUS(RT_ERROR) static_cast(RT_ERROR) } // namespace ge #endif // INC_FRAMEWORK_COMMON_GE_INNER_ERROR_CODES_H_ diff --git a/inc/framework/common/ge_types.h b/inc/framework/common/ge_types.h index 83d01c1f..dcfb4961 100644 --- a/inc/framework/common/ge_types.h +++ b/inc/framework/common/ge_types.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,13 +17,13 @@ #ifndef INC_FRAMEWORK_COMMON_GE_TYPES_H_ #define INC_FRAMEWORK_COMMON_GE_TYPES_H_ -#include +#include #include #include #include "framework/common/fmk_error_codes.h" -#include "ge/ge_api_error_codes.h" +#include "external/ge/ge_api_error_codes.h" #include "external/graph/types.h" #include "external/ge/ge_api_types.h" @@ -60,6 +60,7 @@ const char *const GE_OPTION_EXEC_PLACEMENT = "ge.exec.placement"; const std::string kTaskTypeAicore = "AI_CORE"; const std::string kTaskTypeAicpu = "AI_CPU"; const std::string kTaskTypeInvalid = "TASK_TYPE_INVALID"; +const std::string kTaskTypeFftsPlus = "FFTS_PLUS"; // dynamic execute mode const char *const kLazyRecompile = "lazy_recompile"; @@ -70,11 +71,11 @@ struct DataBuffer { void *data; // Data address uint64_t length; // Data length bool isDataSupportMemShare = false; - uint32_t placement = 0; - DataBuffer(void *dataIn, uint64_t len, bool isSupportMemShare, uint32_t placement = 0) - : data(dataIn), length(len), isDataSupportMemShare(isSupportMemShare), placement(placement) {} + uint32_t placement = 0U; + DataBuffer(void *data_in, uint64_t data_len, bool is_support_mem_share, uint32_t placement = 0U) + : data(data_in), length(data_len), isDataSupportMemShare(is_support_mem_share), placement(placement) {} - DataBuffer() : data(nullptr), length(0), isDataSupportMemShare(false) {} + DataBuffer() : data(nullptr), length(0U), isDataSupportMemShare(false) {} }; /// @@ -86,7 +87,7 @@ struct InputData { uint32_t timestamp; // Data creation time uint32_t timeout; // Processing timeout uint32_t model_id; // Model ID required for data processing - uint64_t request_id = 0; // Request ID + uint64_t request_id = 0U; // Request ID std::vector blobs; // Actual input data, currently only supports one input bool is_dynamic_batch = false; // Whether is dynamic batch size scene, default:false std::string batch_label; // Gear used for current inference in dynamic batch scene @@ -202,7 +203,7 @@ struct AippConfigInfo { // The structure of offline Modeldata struct ModelData { void *model_data = nullptr; // Model binary data start addr - uint32_t model_len = 0; // Model binary data length + uint32_t model_len = 0U; // Model binary data length int32_t priority = 0; // Model priority std::string key; // Key path for encrypt model, Empty for unencrypt std::string om_name; // om file name, used for data dump @@ -210,12 +211,12 @@ struct ModelData { // The definition of Model information struct ModelInfo { - uint32_t version = 0; + uint32_t version = 0U; std::string name; - bool is_encrypt = 0; // 0:unencrypt, 1:encrypt + bool is_encrypt = false; // 0:unencrypt, 1:encrypt std::vector input_desc; std::vector output_desc; - uint8_t reserved[3] = {0}; // 3-byte reserved field + uint8_t reserved[3] = {0U}; // 3-byte reserved field }; // Asynchronous callback interface, implemented by the caller @@ -231,8 +232,10 @@ class GE_FUNC_VISIBILITY ModelListener { virtual Status OnComputeDone(uint32_t model_id, uint32_t data_index, uint32_t result_code, std::vector &outputs) = 0; + virtual void SetCallback(const RunAsyncCallback &callback){}; + virtual uint32_t GetResultCode() { - return 0; + return 0U; }; virtual Status ResetResult() { @@ -276,13 +279,23 @@ struct TaskDescInfo { std::vector output_format; std::vector> output_shape; std::vector output_data_type; + uint32_t context_id; }; struct OpDescInfo { std::string op_name; std::string op_type; - uint32_t task_id; - uint32_t stream_id; + uint32_t task_id = 0U; + uint32_t stream_id = 0U; + uint32_t imply_type = 0U; + uint32_t block_dim = 0U; + std::string op_file_path; + std::string dev_func; + std::string tvm_magic; + uint32_t tiling_key = 0U; + std::string tiling_data; + std::string node_info; + std::vector workspace_bytes; std::vector input_format; std::vector> input_shape; std::vector input_data_type; diff --git a/inc/framework/common/gflags_util.h b/inc/framework/common/gflags_util.h index 6e9ea41b..5d374261 100644 --- a/inc/framework/common/gflags_util.h +++ b/inc/framework/common/gflags_util.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/inc/framework/common/helper/model_helper.h b/inc/framework/common/helper/model_helper.h index 2a63291c..b3cf19a4 100644 --- a/inc/framework/common/helper/model_helper.h +++ b/inc/framework/common/helper/model_helper.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,11 +20,11 @@ #include #include -#include "common/fmk_types.h" -#include "common/helper/om_file_helper.h" +#include "framework/common/fmk_types.h" +#include "framework/common/helper/om_file_helper.h" #include "common/model/ge_model.h" #include "common/model/ge_root_model.h" -#include "common/types.h" +#include "framework/common/types.h" #include "graph/model.h" namespace ge { @@ -35,8 +35,8 @@ class GE_FUNC_VISIBILITY ModelHelper { Status SaveToOmModel(const GeModelPtr &ge_model, const SaveParam &save_param, const std::string &output_file, ge::ModelBufferData &model); - Status SaveToOmRootModel(const GeRootModelPtr &ge_root_model, const SaveParam &save_param, const string &output_file, - ModelBufferData &model, bool is_unknown_shape); + Status SaveToOmRootModel(const GeRootModelPtr &ge_root_model, const SaveParam &save_param, + const std::string &output_file, ModelBufferData &model, bool is_unknown_shape); Status SaveOriginalGraphToOmModel(const ge::Graph &graph, const std::string &output_file); Status LoadModel(const ge::ModelData &model_data); Status LoadRootModel(const ge::ModelData &model_data); diff --git a/inc/framework/common/helper/om_file_helper.h b/inc/framework/common/helper/om_file_helper.h index 34509b39..45d61395 100644 --- a/inc/framework/common/helper/om_file_helper.h +++ b/inc/framework/common/helper/om_file_helper.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -65,7 +65,7 @@ class GE_FUNC_VISIBILITY OmFileLoadHelper { OmFileContext context_; - vector model_contexts_; + std::vector model_contexts_; private: Status CheckModelValid(const ge::ModelData &model) const; @@ -79,9 +79,13 @@ class GE_FUNC_VISIBILITY OmFileLoadHelper { class GE_FUNC_VISIBILITY OmFileSaveHelper { public: - ModelFileHeader &GetModelFileHeader() { return model_header_; } + ModelFileHeader &GetModelFileHeader() { + return model_header_; + } - uint32_t GetModelDataSize() const { return context_.model_data_len_; } + uint32_t GetModelDataSize() const { + return context_.model_data_len_; + } ModelPartitionTable *GetPartitionTable(); @@ -96,7 +100,7 @@ class GE_FUNC_VISIBILITY OmFileSaveHelper { Status SaveModelToFile(const char *output_file, ge::ModelBufferData &model, bool is_offline = true); - vector model_contexts_; + std::vector model_contexts_; ModelFileHeader model_header_; OmFileContext context_; diff --git a/inc/framework/common/l2_cache_optimize.h b/inc/framework/common/l2_cache_optimize.h index e3606582..39bc1d13 100644 --- a/inc/framework/common/l2_cache_optimize.h +++ b/inc/framework/common/l2_cache_optimize.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,15 +17,15 @@ #ifndef INC_FRAMEWORK_COMMON_L2_CACHE_OPTIMIZE_H_ #define INC_FRAMEWORK_COMMON_L2_CACHE_OPTIMIZE_H_ -#include +#include #include #include #include #include -#include "common/types.h" -#include "common/util.h" +#include "framework/common/types.h" +#include "framework/common/util.h" #include "graph/compute_graph.h" using std::vector; @@ -53,7 +53,7 @@ enum MemType { INPUT_TENSOR, OUTPUT_TENSOR, WEIGHT, WORKSPACE }; // Memory usage information < node, type, number > struct NodeInfo { - string nodeName; + std::string nodeName; MemType memType; size_t index; }; @@ -81,26 +81,27 @@ class GE_FUNC_VISIBILITY L2CacheOptimize { ge::ComputeGraphPtr graph_; // Save RC block information list - vector weightRCs; - vector opRCs; + std::vector weightRCs; + std::vector opRCs; // Extract RC information generated by FE from compiled graph void RetirveRCinfo(); // Take the maximum common divisor of RC values for the duplicate address - void Merge(vector &blocks); + void Merge(std::vector &blocks); // The RC information is aligned with the 2m address - void Align(vector &blocks); + void Align(std::vector &blocks); // Weight of l2loss operator, output of gradient aggregation output, RC value set to 0 - void HandleOutputZeroRC(RCType type, ge::NodePtr node, vector &outputList, vector &blocks); + void HandleOutputZeroRC(RCType type, ge::NodePtr node, std::vector &outputList, + std::vector &blocks); // Processing operator input Tensor's RC - void HandOPInput(ge::NodePtr node, vector &inputList, vector &blocks); + void HandOPInput(ge::NodePtr node, std::vector &inputList, std::vector &blocks); // Processing operator output Tensor's RC - void HandOPoutput(ge::NodePtr node, vector &outputList, vector &blocks); + void HandOPoutput(ge::NodePtr node, std::vector &outputList, std::vector &blocks); // maximum common divisor uint32_t Measure(uint32_t x, uint32_t y) { diff --git a/inc/framework/common/op/attr_value_util.h b/inc/framework/common/op/attr_value_util.h index 28d48c1d..cc4e0fcf 100644 --- a/inc/framework/common/op/attr_value_util.h +++ b/inc/framework/common/op/attr_value_util.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -169,6 +169,6 @@ GE_FUNC_VISIBILITY bool GetAttrDefListValue(const std::string &key, int idx, int GE_FUNC_VISIBILITY bool GetAttrDefListValue(const std::string &key, int idx, uint32_t *value, const AttrDefMap &attr); GE_FUNC_VISIBILITY bool GetAttrDefListValue(const std::string &key, int idx, float *value, const AttrDefMap &attr); GE_FUNC_VISIBILITY bool GetAttrDefListValue(const std::string &key, int idx, double *value, const AttrDefMap &attr); -} +} // namespace ge #endif // INC_FRAMEWORK_COMMON_OP_ATTR_VALUE_UTIL_H_ diff --git a/inc/framework/common/op/ge_op_utils.h b/inc/framework/common/op/ge_op_utils.h index bc965d13..1d12c05b 100644 --- a/inc/framework/common/op/ge_op_utils.h +++ b/inc/framework/common/op/ge_op_utils.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,10 +20,10 @@ #include #include -#include "common/op/attr_value_util.h" +#include "framework/common/op/attr_value_util.h" #include "register/register_types.h" #include "register/register_error_codes.h" -#include "common/util.h" +#include "framework/common/util.h" #include "graph/attr_value.h" #include "graph/ge_tensor.h" #include "graph/node.h" @@ -95,7 +95,7 @@ class GE_FUNC_VISIBILITY OpUtils { /// @param [out] aipp_params aipp parameters /// @return enum of tagCCAippInputFormat /// - static Status ConvertAippParams(const GeAttrValue::NamedAttrs &aipp_attr, domi::AippOpParams *aipp_params); + static Status ConvertAippParams(const NamedAttrs &aipp_attr, domi::AippOpParams *aipp_params); static Status TransferDim(const std::vector &dim, std::vector &dim_vector); template static void SliceData(const std::vector &input, int64_t chunk_size, std::vector &output, @@ -134,12 +134,12 @@ class GE_FUNC_VISIBILITY OpUtils { /// static void TransDataKCHW2HWCK(const void *input, int64_t K, int64_t C, int64_t H, int64_t W, void *output); - static vector GetWeights(const ge::Node &node); - static vector GetWeights(ge::ConstNodePtr node); - static vector MutableWeights(const ge::Node &node); - static vector MutableWeights(const ge::NodePtr node); - static Status SetWeights(ge::Node &node, const vector &weights); - static Status SetWeights(ge::NodePtr node, const vector &weights); + static std::vector GetWeights(const ge::Node &node); + static std::vector GetWeights(ge::ConstNodePtr node); + static std::vector MutableWeights(const ge::Node &node); + static std::vector MutableWeights(const ge::NodePtr node); + static Status SetWeights(ge::Node &node, const std::vector &weights); + static Status SetWeights(ge::NodePtr node, const std::vector &weights); static Status GetShapeDataFromConstTensor(const ConstGeTensorPtr &tensor, DataType type, std::vector &dims); private: diff --git a/inc/framework/common/op/op_parser_util.h b/inc/framework/common/op/op_parser_util.h index 43254ca9..12ce6980 100644 --- a/inc/framework/common/op/op_parser_util.h +++ b/inc/framework/common/op/op_parser_util.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,9 +17,9 @@ #ifndef INC_FRAMEWORK_COMMON_OP_OP_PARSER_UTIL_H_ #define INC_FRAMEWORK_COMMON_OP_OP_PARSER_UTIL_H_ -#include -#include -#include +#include +#include +#include namespace ge { // general diff --git a/inc/framework/common/op_types.h b/inc/framework/common/op_types.h index fa41c1b6..4e4d4dda 100644 --- a/inc/framework/common/op_types.h +++ b/inc/framework/common/op_types.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,9 @@ class GE_FUNC_VISIBILITY OpTypeContainer { } ~OpTypeContainer() = default; - void Register(const std::string &op_type) { op_type_list_.insert(op_type); } + void Register(const std::string &op_type) { + op_type_list_.insert(op_type); + } bool IsExisting(const std::string &op_type) { auto iter_find = op_type_list_.find(op_type); @@ -45,7 +47,9 @@ class GE_FUNC_VISIBILITY OpTypeContainer { class GE_FUNC_VISIBILITY OpTypeRegistrar { public: - explicit OpTypeRegistrar(const std::string &op_type) { OpTypeContainer::Instance()->Register(op_type); } + explicit OpTypeRegistrar(const std::string &op_type) { + OpTypeContainer::Instance()->Register(op_type); + } ~OpTypeRegistrar() {} }; diff --git a/inc/framework/common/profiling/ge_profiling.h b/inc/framework/common/profiling/ge_profiling.h index 0a7c9181..f0ecc5d1 100644 --- a/inc/framework/common/profiling/ge_profiling.h +++ b/inc/framework/common/profiling/ge_profiling.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ #ifndef INC_FRAMEWORK_COMMON_GE_PROFILING_H_ #define INC_FRAMEWORK_COMMON_GE_PROFILING_H_ -#include "ge/ge_api_error_codes.h" +#include "external/ge/ge_api_error_codes.h" #include "runtime/base.h" /// diff --git a/inc/framework/common/profiling/ge_runner_profiling.h b/inc/framework/common/profiling/ge_runner_profiling.h index 1c594c5b..b0a666ce 100644 --- a/inc/framework/common/profiling/ge_runner_profiling.h +++ b/inc/framework/common/profiling/ge_runner_profiling.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/inc/framework/common/scope_guard.h b/inc/framework/common/scope_guard.h index 62ae4b6d..4ec4cfa7 100644 --- a/inc/framework/common/scope_guard.h +++ b/inc/framework/common/scope_guard.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,7 +25,9 @@ /// MAKE_GUARD([&] { Release Resource 1 }) /// Acquire Resource 2 // MAKE_GUARD([&] { Release Resource 2 }) -#define GE_MAKE_GUARD(var, callback) ScopeGuard make_guard_##var(callback) +#define GE_MAKE_GUARD(var, callback) const ScopeGuard const_guard_##var(callback) + +#define GE_DISMISSABLE_GUARD(var, callback) ScopeGuard make_guard_##var(callback) #define GE_DISMISS_GUARD(var) make_guard_##var.Dismiss() namespace ge { @@ -42,13 +44,16 @@ class GE_FUNC_VISIBILITY ScopeGuard { if (on_exit_scope_ != nullptr) { try { on_exit_scope_(); - } catch (std::bad_function_call &e) { } - catch (...) { } + } catch (std::bad_function_call &e) { + } catch (...) { + } } } } - void Dismiss() { dismissed_ = true; } + void Dismiss() { + dismissed_ = true; + } private: std::function on_exit_scope_; diff --git a/inc/framework/common/string_util.h b/inc/framework/common/string_util.h index 677b1971..4d808e2e 100644 --- a/inc/framework/common/string_util.h +++ b/inc/framework/common/string_util.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -54,7 +54,7 @@ class GE_FUNC_VISIBILITY StringUtils { // lint -esym(551,*) static std::string &Rtrim(std::string &s) { /*lint !e618*/ #if __cplusplus >= 201103L - (void)s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) { return std::isspace(c) == 0; })); + (void)s.erase(std::find_if(s.rbegin(), s.rend(), [](int c) { return std::isspace(c) == 0; }).base(), s.end()); #else (void)s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); #endif @@ -78,8 +78,8 @@ class GE_FUNC_VISIBILITY StringUtils { /// @param [in] delim separator /// @return string array after segmentation /// - static std::vector Split(const std::string &str, char delim) { - std::vector elems; + static std::vector> Split(const std::string &str, char delim) { + std::vector> elems; if (str.empty()) { elems.emplace_back(""); diff --git a/inc/framework/common/taskdown_common.h b/inc/framework/common/taskdown_common.h index 81a532dd..1417677c 100644 --- a/inc/framework/common/taskdown_common.h +++ b/inc/framework/common/taskdown_common.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/inc/framework/common/types.h b/inc/framework/common/types.h index 811d5eed..053a3423 100644 --- a/inc/framework/common/types.h +++ b/inc/framework/common/types.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,8 +17,8 @@ #ifndef INC_FRAMEWORK_COMMON_TYPES_H_ #define INC_FRAMEWORK_COMMON_TYPES_H_ -#include -#include +#include +#include #include #include #include @@ -31,14 +31,6 @@ #include "framework/common/op_types.h" #include "register/register_types.h" -#if !defined(__ANDROID__) && !defined(ANDROID) -#define DOMI_DYNAMIC_CAST static_cast -#define DOMI_DYNAMIC_POINTER_CAST std::static_pointer_cast -#else -#define DOMI_DYNAMIC_CAST static_cast -#define DOMI_DYNAMIC_POINTER_CAST std::static_pointer_cast -#endif - namespace ge { // dump FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string DUMP_MODEL; @@ -51,24 +43,10 @@ FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string OP_DEB FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string OP_DEBUG_ATOMIC; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string OP_DEBUG_ALL; -// Supported public properties name -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string PROP_OME_START_TIME; // Start time -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string PROP_OME_DUMP_PATH; // Dump path -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string PROP_OME_LOG_PATH; // Log path - // Profile-related constants -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t CCE_PROFILE_ON; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t CCE_PROFILE_OFF; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string OME_PROFILE; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string CCE_PROFILE; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string RTS_PROFILE; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string PROFILER_JOBCTX; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string PROFILER_TARGET_PATH; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string RTS_PROFILE_PATH; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string PROFILE_STOP_KEY; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string PROFILE_STOP_VALUE; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::map PROFILE_COMPONENT_MAP; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string PROFILE_CONFIG; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string PROFILE_MODEL_ID; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string MODEL_ATTR_TASKS; @@ -76,14 +54,7 @@ FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string MODEL_ FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string MODEL_ATTR_TASK_GEN_WEIGHT_ADDR; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string MODEL_ATTR_FUSION_MODEL_DEF; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const int MODEL_MAX_SIZE; // Max size of 2 GB minus 1 byte. -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint64_t FILE_HEADER_MAX_SIZE; // Max size of 3 GB. - -#if !defined(__ANDROID__) && !defined(ANDROID) FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint64_t ALLOC_MEMORY_MAX_SIZE; // Max size of 8 GB. -#else -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint64_t ALLOC_MEMORY_MAX_SIZE; // Max size of 512M. -#endif template static std::pair flip_pair(const std::pair &p) { @@ -167,6 +138,8 @@ REGISTER_OPTYPE_DECLARE(SLICED, "SliceD"); REGISTER_OPTYPE_DECLARE(FLOORDIV, "FloorDiv"); REGISTER_OPTYPE_DECLARE(SQUEEZE, "Squeeze"); REGISTER_OPTYPE_DECLARE(UNSQUEEZE, "Unsqueeze"); +REGISTER_OPTYPE_DECLARE(SQUEEZEV2, "SqueezeV2"); +REGISTER_OPTYPE_DECLARE(UNSQUEEZEV2, "UnsqueezeV2"); REGISTER_OPTYPE_DECLARE(STRIDEDSLICE, "StridedSlice"); REGISTER_OPTYPE_DECLARE(RANGE, "Range"); REGISTER_OPTYPE_DECLARE(RPNPROPOSALS, "GenerateRpnProposals"); @@ -339,6 +312,8 @@ REGISTER_OPTYPE_DECLARE(PLACEHOLDER, "PlaceHolder"); REGISTER_OPTYPE_DECLARE(END, "End"); REGISTER_OPTYPE_DECLARE(BASICLSTMCELL, "BasicLSTMCell"); REGISTER_OPTYPE_DECLARE(GETNEXT, "GetNext"); +REGISTER_OPTYPE_DECLARE(ITERATOR, "Iterator"); +REGISTER_OPTYPE_DECLARE(ITERATORV2, "IteratorV2"); REGISTER_OPTYPE_DECLARE(INITDATA, "InitData"); REGISTER_OPTYPE_DECLARE(TRANSSHAPE, "TransShape") REGISTER_OPTYPE_DECLARE(REFIDENTITY, "RefIdentity"); @@ -616,34 +591,6 @@ static constexpr uint32_t MODEL_FILE_CHECKSUM_LENGTH = 64; /// static constexpr uint32_t MODEL_FILE_RESERVED_LENGTH = 75; -/// -/// @ingroup domi_omg -/// @brief INPUT node type -/// -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string INPUT_TYPE; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string DUMMY_DATA; - -/// -/// @ingroup domi_omg -/// @brief AIPP flag, indicating the aipp conv operator -/// -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string AIPP_CONV_FLAG; - -/// -/// @ingroup domi_omg -/// @brief AIPP flag, indicating the aipp data operator -/// -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string AIPP_DATA_FLAG; - -// flag of the Data operator, indicating that the input will be input to the dynamic AIPP operator -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string INPUT_TO_DYNAMIC_AIPP; - -// records the W dimension of the model input corresponding to the dynamic AIPP -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string AIPP_RELATED_DATA_DIM_W; - -// H dimension of the model input corresponding to the dynamic AIPP -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string AIPP_RELATED_DATA_DIM_H; - // DATA node type FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string DATA_TYPE; @@ -655,10 +602,6 @@ FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string FRAMEW // DATA node type FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string ANN_DATA_TYPE; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string ANN_NETOUTPUT_TYPE; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string ANN_DEPTHCONV_TYPE; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string ANN_CONV_TYPE; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string ANN_FC_TYPE; // convolution node type FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string NODE_NAME_NET_OUTPUT; @@ -667,161 +610,31 @@ FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string NODE_N FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string NODE_NAME_OP_DEBUG; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string OP_TYPE_OP_DEBUG; -// convolution node type -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string OP_TYPE_CONVOLUTION; -// adds a convolutional node name for the hard AIPP -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string AIPP_CONV_OP_NAME; // delimiter of operator configuration items FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string OP_CONF_DELIMITER; -// op attr name -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string ATTR_NAME_VALUE1; - -// op attr name, used to 6d_2_4d C channel -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string ATTR_NAME_INPUT_CVALUE; - -// op attr name -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string ATTR_NAME_VALUE1; - -// alpha default value -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const float ALPHA_DEFAULT_VALUE; - -// beta default value -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const float BETA_DEFAULT_VALUE; - -// coef default value -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const float COEF_DEFAULT_VALUE; - -// coef value of Relu6 -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const float RELU6_COEF; - -// stride default value -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t STRIDE_DEFAULT_VALUE; - -// pad default value -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t PAD_DEFAULT_VALUE; - -// dilation default value -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const int DILATION_DEFAULT_VALUE; - -// kernel default value -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t KERNEL_DEFAULT_VALUE; - -// default conv Group Size -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t DEFAULT_CONV_GROUP; - -// default deconv adj -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t DEFAULT_DECONV_ADJ; - -// indicate num 1 -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t NUM_ONE; - // dim default size value static const int32_t DIM_DEFAULT_SIZE = 4; -// the shape of c must be the mutiply of 16 for depthwise -static const uint32_t DEPTHWISE_DIM_C_BASE_NUM = 16; - -// C1HWNCoC0 dim size -static const int32_t DIM_C1HWNCoC0_SIZE = 6; -// C1HWNCoC0 C0 value -static const int C1HWCOC_C0_VALUE = 16; -// spatial default dim size -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const int32_t SPATIAL_DIM_DEFAULT_SIZE; - // dim extension default value FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const int32_t DIM_DEFAULT_VALUE; -// the first item in the weight list of opdef is filter -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const int32_t WEIGHT_FILTER_INDEX; - -// the second item in the weight list of opdef is bias. -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const int32_t WEIGHT_BIAS_INDEX; - -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const int32_t TENSOR_ND_SUPPORT_SIZE; - // default NCHW index FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t NCHW_DIM_N; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t NCHW_DIM_C; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t NCHW_DIM_H; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t NCHW_DIM_W; -// default C1HWNCoC0 index -static const uint32_t C1HWNCoC0_DIM_C1 = 0; -static const uint32_t C1HWNCoC0_DIM_H = 1; -static const uint32_t C1HWNCoC0_DIM_W = 2; -static const uint32_t C1HWNCoC0_DIM_N = 3; -static const uint32_t C1HWNCoC0_DIM_Co = 4; -static const uint32_t C1HWNCoC0_DIM_C0 = 5; - -// default KCHW index -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t KCHW_DIM_K; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t KCHW_DIM_C; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t KCHW_DIM_H; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t KCHW_DIM_W; - -// default HWCK index -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t HWCK_DIM_H; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t HWCK_DIM_W; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t HWCK_DIM_C; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t HWCK_DIM_K; - // default NHWC index FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t NHWC_DIM_N; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t NHWC_DIM_H; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t NHWC_DIM_W; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t NHWC_DIM_C; -// default CHWN index -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t CHWN_DIM_N; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t CHWN_DIM_C; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t CHWN_DIM_H; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t CHWN_DIM_W; - -// default CHW index -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t CHW_DIM_C; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t CHW_DIM_H; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t CHW_DIM_W; - -// default HWC index -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t HWC_DIM_H; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t HWC_DIM_W; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t HWC_DIM_C; -// default Pad index -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t PAD_H_HEAD; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t PAD_H_TAIL; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t PAD_W_HEAD; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t PAD_W_TAIL; - -// default window index -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t WINDOW_H; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t WINDOW_W; - -// default stride index -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t STRIDE_H; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t STRIDE_W; - -// default dilation index -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t DILATION_H; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t DILATION_W; - -// the num of XRBG channel -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t XRGB_CHN_NUM; - -// default tensor format -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const int DEFAULT_FORMAT; - -// default global pooling -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const bool DEFAULT_GLOBAL_POOLING; - FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t MODEL_VERSION; // model version 1.0 -// Number of inputs of the Eltwise operator -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const int ELTWISE_MIN_INPUT_SIZE; - // flowctrl FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string NODE_NAME_STREAM_SWITCH; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string NODE_NAME_STREAM_ACTIVE; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string NODE_NAME_FLOWCTRL_LOOP_PER_ITER; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string NODE_NAME_FLOWCTRL_LOOP_COND; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string NODE_NAME_FLOWCTRL_LOOP_INCREMENT; @@ -833,9 +646,8 @@ FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t TRUE_STRE FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t STREAM_SWITCH_INPUT_NUM; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string NODE_NAME_GLOBAL_STEP; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string NODE_NAME_GLOBAL_STEP_ASSIGNADD; -static const int PLATFORM_VERSION_LEN = 20; +static const uint32_t PLATFORM_VERSION_LEN = 20; // Definition of the file header of the model file struct ModelFileHeader { @@ -860,11 +672,6 @@ struct ModelFileHeader { static constexpr uint8_t TARGET_TYPE_LTTE_8BIT = 0; static constexpr uint8_t TARGET_TYPE_MINI_8BIT = 1; -static constexpr uint8_t TARGET_TYPE_TINY_8BIT = 2; - -static constexpr int32_t PARTITION_TYPE_MODEL_DEF = 0; -static constexpr int32_t PARTITION_TYPE_WEIGHTS = 1; -static constexpr int32_t PARTITION_TYPE_TASK_INFO = 2; // number of partitions in the current model static constexpr uint32_t PARTITION_SIZE = 5; @@ -884,8 +691,6 @@ struct ModelPartitionTable { #define SIZE_OF_MODEL_PARTITION_TABLE(table) (sizeof(ModelPartitionTable) + sizeof(ModelPartitionMemInfo) * (table).num) -static constexpr int32_t PTHREAD_CREAT_SUCCESS = 0; // pthread_creat success - // Filter format typedef enum tagDomiFilterFormat { DOMI_FILTER_KCHW, // KCHW diff --git a/inc/framework/common/util.h b/inc/framework/common/util.h index a3989b9d..c854e016 100644 --- a/inc/framework/common/util.h +++ b/inc/framework/common/util.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,30 +17,28 @@ #ifndef INC_FRAMEWORK_COMMON_UTIL_H_ #define INC_FRAMEWORK_COMMON_UTIL_H_ -#include -#include -#include +#include +#include #include #include #include -#include "framework/common/debug/ge_log.h" +#include #include "framework/common/debug/log.h" #include "framework/common/scope_guard.h" #include "framework/common/ge_inner_error_codes.h" -#include "mmpa/mmpa_api.h" -#define GE_CHECK_POSITIVE_SIZE_RANGE(size) \ - do { \ - if (size <= 0) { \ - DOMI_LOGE("param[%s] is not a positive number", #size); \ - return PARAM_INVALID; \ - } \ - } while (0) +#define GE_CHECK_POSITIVE_SIZE_RANGE(size) \ + do { \ + if (size <= 0) { \ + GELOGE(ge::FAILED, "param[%s] is not a positive number", #size); \ + return PARAM_INVALID; \ + } \ + } while (false) #define CHECK_FALSE_EXEC(expr, exec_expr, ...) \ { \ - bool b = (expr); \ + const bool b = (expr); \ if (!b) { \ exec_expr; \ } \ @@ -59,131 +57,133 @@ }); // For propagating errors when calling a function. -#define GE_RETURN_IF_ERROR(expr) \ - do { \ - const ::ge::Status _status = (expr); \ - if (_status) return _status; \ - } while (0) +#define GE_RETURN_IF_ERROR(expr) \ + do { \ + const ge::Status _chk_status = (expr); \ + if (_chk_status != ge::SUCCESS) { \ + return _chk_status; \ + } \ + } while (false) #define GE_RETURN_WITH_LOG_IF_ERROR(expr, ...) \ do { \ - const ::ge::Status _status = (expr); \ - if (_status) { \ - DOMI_LOGE(__VA_ARGS__); \ - return _status; \ + const ge::Status _chk_status = (expr); \ + if (_chk_status != ge::SUCCESS) { \ + GELOGE(ge::FAILED, __VA_ARGS__); \ + return _chk_status; \ } \ - } while (0) + } while (false) // check whether the parameter is true. If it is, return FAILED and record the error log #define GE_RETURN_WITH_LOG_IF_TRUE(condition, ...) \ do { \ if (condition) { \ - DOMI_LOGE(__VA_ARGS__); \ + GELOGE(ge::FAILED, __VA_ARGS__); \ return ge::FAILED; \ } \ - } while (0) + } while (false) // Check if the parameter is false. If yes, return FAILED and record the error log #define GE_RETURN_WITH_LOG_IF_FALSE(condition, ...) \ do { \ - bool _condition = (condition); \ + const bool _condition = (condition); \ if (!_condition) { \ - DOMI_LOGE(__VA_ARGS__); \ + GELOGE(ge::FAILED, __VA_ARGS__); \ return ge::FAILED; \ } \ - } while (0) + } while (false) // Checks whether the parameter is true. If so, returns PARAM_INVALID and records the error log #define GE_RT_PARAM_INVALID_WITH_LOG_IF_TRUE(condition, ...) \ do { \ if (condition) { \ - DOMI_LOGE(__VA_ARGS__); \ + GELOGE(ge::FAILED, __VA_ARGS__); \ return ge::PARAM_INVALID; \ } \ - } while (0) + } while (false) // Check if the parameter is false. If yes, return PARAM_INVALID and record the error log #define GE_RT_PARAM_INVALID_WITH_LOG_IF_FALSE(condition, ...) \ do { \ - bool _condition = (condition); \ + const bool _condition = (condition); \ if (!_condition) { \ - DOMI_LOGE(__VA_ARGS__); \ + GELOGE(ge::FAILED, __VA_ARGS__); \ return ge::PARAM_INVALID; \ } \ - } while (0) + } while (false) // Check if the parameter is null. If yes, return PARAM_INVALID and record the error #define GE_CHECK_NOTNULL(val) \ do { \ if (val == nullptr) { \ REPORT_INNER_ERROR("E19999", "Param:%s is nullptr, check invalid", #val); \ - DOMI_LOGE("[Check][Param:%s]null is invalid.", #val); \ + GELOGE(ge::FAILED, "[Check][Param:%s]null is invalid.", #val); \ return ge::PARAM_INVALID; \ } \ - } while (0) + } while (false) // Check if the parameter is null. If yes, just return and record the error -#define GE_CHECK_NOTNULL_JUST_RETURN(val) \ - do { \ - if (val == nullptr) { \ - DOMI_LOGE("param[%s] must not be null.", #val); \ - return; \ - } \ - } while (0) +#define GE_CHECK_NOTNULL_JUST_RETURN(val) \ + do { \ + if (val == nullptr) { \ + GELOGE(ge::FAILED, "param[%s] must not be null.", #val); \ + return; \ + } \ + } while (false) // Check whether the parameter is null. If so, execute the exec_expr expression and record the error log -#define GE_CHECK_NOTNULL_EXEC(val, exec_expr) \ - do { \ - if (val == nullptr) { \ - DOMI_LOGE("param[%s] must not be null.", #val); \ - exec_expr; \ - } \ - } while (0) +#define GE_CHECK_NOTNULL_EXEC(val, exec_expr) \ + do { \ + if (val == nullptr) { \ + GELOGE(ge::FAILED, "param[%s] must not be null.", #val); \ + exec_expr; \ + } \ + } while (false) // Check whether the parameter is null. If yes, return directly and record the error log -#define GE_RT_VOID_CHECK_NOTNULL(val) \ - do { \ - if (val == nullptr) { \ - DOMI_LOGE("param[%s] must not be null.", #val); \ - return; \ - } \ - } while (0) +#define GE_RT_VOID_CHECK_NOTNULL(val) \ + do { \ + if (val == nullptr) { \ + GELOGE(ge::FAILED, "param[%s] must not be null.", #val); \ + return; \ + } \ + } while (false) // Check if the parameter is null. If yes, return false and record the error log -#define GE_RT_FALSE_CHECK_NOTNULL(val) \ - do { \ - if (val == nullptr) { \ - DOMI_LOGE("param[%s] must not be null.", #val); \ - return false; \ - } \ - } while (0) +#define GE_RT_FALSE_CHECK_NOTNULL(val) \ + do { \ + if (val == nullptr) { \ + GELOGE(ge::FAILED, "param[%s] must not be null.", #val); \ + return false; \ + } \ + } while (false) // Check if the parameter is out of bounds -#define GE_CHECK_SIZE(size) \ - do { \ - if (size == 0) { \ - DOMI_LOGE("param[%s] is out of range", #size); \ - return ge::PARAM_INVALID; \ - } \ - } while (0) +#define GE_CHECK_SIZE(size) \ + do { \ + if (size == 0) { \ + GELOGE(ge::FAILED, "param[%s] is out of range", #size); \ + return ge::PARAM_INVALID; \ + } \ + } while (false) // Check if the value on the left is greater than or equal to the value on the right -#define GE_CHECK_GE(lhs, rhs) \ - do { \ - if (lhs < rhs) { \ - DOMI_LOGE("param[%s] is less than[%s]", #lhs, #rhs); \ - return ge::PARAM_INVALID; \ - } \ - } while (0) +#define GE_CHECK_GE(lhs, rhs) \ + do { \ + if (lhs < rhs) { \ + GELOGE(ge::FAILED, "param[%s] is less than[%s]", #lhs, #rhs); \ + return ge::PARAM_INVALID; \ + } \ + } while (false) // Check if the value on the left is less than or equal to the value on the right -#define GE_CHECK_LE(lhs, rhs) \ - do { \ - if (lhs > rhs) { \ - DOMI_LOGE("param[%s] is greater than[%s]", #lhs, #rhs); \ - return ge::PARAM_INVALID; \ - } \ - } while (0) +#define GE_CHECK_LE(lhs, rhs) \ + do { \ + if (lhs > rhs) { \ + GELOGE(ge::FAILED, "param[%s] is greater than[%s]", #lhs, #rhs); \ + return ge::PARAM_INVALID; \ + } \ + } while (false) #define GE_DELETE_NEW_SINGLE(var) \ do { \ @@ -191,7 +191,7 @@ delete var; \ var = nullptr; \ } \ - } while (0) + } while (false) #define GE_DELETE_NEW_ARRAY(var) \ do { \ @@ -199,18 +199,18 @@ delete[] var; \ var = nullptr; \ } \ - } while (0) + } while (false) #define GE_FREE_RT_LOG(addr) \ do { \ if (addr != nullptr) { \ - rtError_t error = rtFree(addr); \ + const rtError_t error = rtFree(addr); \ if (error != RT_ERROR_NONE) { \ GELOGE(RT_FAILED, "Call rtFree failed, error: %#x", error); \ } \ addr = nullptr; \ } \ - } while (0) + } while (false) /** * @ingroup domi_common @@ -226,12 +226,6 @@ static constexpr int32_t OM_PROTO_VERSION = 2; namespace ge { using google::protobuf::Message; -/// -/// @ingroup domi_common -/// @brief Maximum file path length -/// -const int32_t DOMI_MAX_PATH_LEN = 256; - /// /// @ingroup domi_common /// @brief Reads the proto structure from an array. @@ -253,8 +247,6 @@ GE_FUNC_VISIBILITY bool ReadProtoFromArray(const void *data, int size, Message * /// GE_FUNC_VISIBILITY bool ReadProtoFromText(const char *file, google::protobuf::Message *message); -GE_FUNC_VISIBILITY bool ReadProtoFromMem(const char *data, int size, google::protobuf::Message *message); - /// /// @ingroup: domi_common /// @brief: get length of file @@ -306,10 +298,10 @@ GE_FUNC_VISIBILITY std::string ToString(std::vector &v) { ss << x; ss << ", "; } - std::string strRet = - ss.str().substr(0, ss.str().length() - 2); // Delete the two extra characters at the end of the line. - strRet += "]"; - return strRet; + // Delete the two extra characters at the end of the line. + std::string str = ss.str().substr(0U, ss.str().length() - 2U); + str += "]"; + return str; } /// @@ -326,10 +318,29 @@ GE_FUNC_VISIBILITY std::string ToString(const google::protobuf::RepeatedField ss << x; ss << ", "; } - std::string strRet = - ss.str().substr(0, ss.str().length() - 2); // Delete the two extra characters at the end of the line. - strRet += "]"; - return strRet; + // Delete the two extra characters at the end of the line. + std::string str = ss.str().substr(0U, ss.str().length() - 2U); + str += "]"; + return str; +} + +/// +/// @ingroup ge_ir_utils +/// @brief RepeatedPtrField->String +/// @param [in] const rpd_field RepeatedPtrField +/// @return String +/// +template +GE_FUNC_VISIBILITY std::string ToString(const google::protobuf::RepeatedPtrField &rpd_ptr_field) { + std::stringstream ss; + ss << "["; + for (const T &x : rpd_ptr_field) { + ss << x; + ss << ", "; + } + std::string str_ret = ss.str().substr(0U, ss.str().length() - 2U); + str_ret += "]"; + return str_ret; } /// @@ -392,14 +403,6 @@ GE_FUNC_VISIBILITY bool CheckOutputPathValid(const std::string &file_path, const /// GE_FUNC_VISIBILITY bool ValidateStr(const std::string &filePath, const std::string &mode); -/// -/// @ingroup domi_common -/// @brief Check whether the file is normal file. -/// @param [in] file_path file path -/// @param [out] result -/// -GE_FUNC_VISIBILITY bool IsValidFile(const char *file_path); - /// /// @ingroup domi_common /// @brief Check path invalid diff --git a/inc/framework/engine/dnnengine.h b/inc/framework/engine/dnnengine.h index 8a0f3b65..84d5705a 100644 --- a/inc/framework/engine/dnnengine.h +++ b/inc/framework/engine/dnnengine.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,8 +21,8 @@ #include #include -#include "common/ge_inner_error_codes.h" -#include "common/ge_types.h" +#include "framework/common/ge_inner_error_codes.h" +#include "framework/common/ge_types.h" #include "graph/types.h" namespace ge { @@ -43,14 +43,31 @@ struct DNNEngineAttribute { // If engine input format must be specific, set this attribute, else set FORMAT_RESERVED Format engine_input_format; Format engine_output_format; + bool atomic_engine_flag; }; class GE_FUNC_VISIBILITY DNNEngine { public: + DNNEngine() = default; + explicit DNNEngine(const DNNEngineAttribute &attrs) { + engine_attribute_ = attrs; + } virtual ~DNNEngine() = default; - virtual Status Initialize(const std::map &options) = 0; - virtual Status Finalize() = 0; - virtual void GetAttributes(DNNEngineAttribute &attr) const = 0; + Status Initialize(const std::map &options) { + return SUCCESS; + } + Status Finalize() { + return SUCCESS; + } + void GetAttributes(DNNEngineAttribute &attr) const { + attr = engine_attribute_; + } + bool IsAtomic() const { + return engine_attribute_.atomic_engine_flag; + } + + protected: + DNNEngineAttribute engine_attribute_; }; } // namespace ge diff --git a/inc/framework/executor/ge_executor.h b/inc/framework/executor/ge_executor.h index ce7c82ac..c5df77df 100644 --- a/inc/framework/executor/ge_executor.h +++ b/inc/framework/executor/ge_executor.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,9 +22,9 @@ #include #include "common/dynamic_aipp.h" -#include "common/ge_inner_error_codes.h" -#include "common/ge_types.h" -#include "common/types.h" +#include "framework/common/ge_inner_error_codes.h" +#include "framework/common/ge_types.h" +#include "framework/common/types.h" #include "graph/tensor.h" #include "graph/ge_tensor.h" #include "runtime/base.h" diff --git a/inc/framework/generator/ge_generator.h b/inc/framework/generator/ge_generator.h index 5da5a593..b746dbac 100644 --- a/inc/framework/generator/ge_generator.h +++ b/inc/framework/generator/ge_generator.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,26 +21,29 @@ #include #include #include -#include "ge/ge_ir_build.h" -#include "common/ge_inner_error_codes.h" -#include "common/ge_types.h" +#include "external/ge/ge_ir_build.h" +#include "framework/common/ge_inner_error_codes.h" +#include "framework/common/ge_types.h" #include "graph/ge_tensor.h" #include "graph/graph.h" #include "graph/op_desc.h" #include "graph/detail/attributes_holder.h" -#include "omg/omg_inner_types.h" +#include "framework/omg/omg_inner_types.h" namespace ge { class GeRootModel; class GE_FUNC_VISIBILITY GeGenerator { public: + using InOutTensorRef = std::pair &, const std::vector &>; static GeGenerator &GetInstance() { static GeGenerator Instance; return Instance; } GeGenerator() = default; - ~GeGenerator() { (void)Finalize(); } + ~GeGenerator() { + (void)Finalize(); + } GeGenerator(const GeGenerator &) = delete; @@ -54,7 +57,7 @@ class GE_FUNC_VISIBILITY GeGenerator { Status GenerateOfflineModel(const Graph &graph, const std::string &file_name_prefix, const std::vector &inputs = std::vector()); - Status GenerateOnlineModel(const Graph &graph, const vector &inputs, ge::ModelBufferData &model); + Status GenerateOnlineModel(const Graph &graph, const std::vector &inputs, ge::ModelBufferData &model); Status GenerateInfershapeGraph(const Graph &graph); @@ -81,10 +84,12 @@ class GE_FUNC_VISIBILITY GeGenerator { /// @param [in] compile_flag: op build flag, accurate build is 0, fuzz build is 1 /// @param [out] model_buff: model buff of op. /// @return SUCCESS or FAILED - Status BuildSingleOpModel(OpDescPtr &op_desc, const vector &inputs, const vector &outputs, - OpEngineType engine_type, ModelBufferData &model_buff); - Status BuildSingleOpModel(OpDescPtr &op_desc, const vector &inputs, const vector &outputs, - OpEngineType engine_type, int32_t compile_flag, ModelBufferData &model_buff); + Status BuildSingleOpModel(OpDescPtr &op_desc, const std::vector &inputs, + const std::vector &outputs, OpEngineType engine_type, + ModelBufferData &model_buff); + Status BuildSingleOpModel(OpDescPtr &op_desc, const std::vector &inputs, + const std::vector &outputs, OpEngineType engine_type, int32_t compile_flag, + ModelBufferData &model_buff); /// /// @ingroup ge /// @brief: Build single Op into model buff. @@ -94,22 +99,27 @@ class GE_FUNC_VISIBILITY GeGenerator { /// @param [in] graph_name: graph name. /// @param [out] graph: graph of single op. /// @return SUCCESS or FAILED - Status BuildSingleOpGraph(OpDescPtr &op_desc, const vector &inputs, const vector &outputs, - std::string graph_name, Graph &graph); + Status BuildSingleOpGraph(OpDescPtr &op_desc, const InOutTensorRef &inputs_outputs, std::string graph_name, + Graph &graph, std::vector> &inputs_name_type); private: - Status GenerateModel(const Graph &graph, const string &file_name_prefix, const vector &inputs, + Status GenerateModel(const Graph &graph, const std::string &file_name_prefix, const std::vector &inputs, ge::ModelBufferData &model, bool is_offline = true); - Status BuildSingleOp(OpDescPtr &op_desc, const vector &inputs, const vector &outputs, - const string &model_file_name, OpEngineType engine_type, ModelBufferData &model_buff, + Status BuildSingleOp(OpDescPtr &op_desc, const std::vector &inputs, const std::vector &outputs, + const std::string &model_file_name, OpEngineType engine_type, ModelBufferData &model_buff, bool is_offline = true, int32_t compile_flag = 0); bool CheckNoAicore(const ComputeGraphPtr &graph); - void RemoveConst(const vector &inputs, vector &outputs); - Status CheckForSingleOp(OpDescPtr &op_desc, const vector &inputs, const vector &outputs); + void RemoveConst(const std::vector &inputs, std::vector &outputs); + Status CheckForSingleOp(OpDescPtr &op_desc, const std::vector &inputs, + const std::vector &outputs); Status InferFormatForSingleOp(OpDescPtr &op_desc, Graph &graph); using GeRootModelPtr = std::shared_ptr; Status SetModelNameForDump(const GeRootModelPtr &ge_root_model); + Status CreateGeneralizedBuildAttrs(const GeRootModelPtr &ge_root_model, const std::vector &inputs, + const std::vector &outputs, + const std::vector> &inputs_name_type, + std::vector &generalized_build_attrs); class Impl; diff --git a/inc/framework/generator/generator_api.h b/inc/framework/generator/generator_api.h deleted file mode 100644 index 56b83a20..00000000 --- a/inc/framework/generator/generator_api.h +++ /dev/null @@ -1,187 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef INC_FRAMEWORK_GENERATOR_GENERATOR_API_H_ -#define INC_FRAMEWORK_GENERATOR_GENERATOR_API_H_ - -#if defined(_MSC_VER) -#ifdef FUNC_VISIBILITY -#define GE_FUNC_VISIBILITY _declspec(dllexport) -#else -#define GE_FUNC_VISIBILITY -#endif -#else -#ifdef FUNC_VISIBILITY -#define GE_FUNC_VISIBILITY __attribute__((visibility("default"))) -#else -#define GE_FUNC_VISIBILITY -#endif -#endif - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef uint32_t Status_t; - -typedef void *OpAttr_t; -typedef void *OpTensor_t; - -/// -/// @ingroup ge -/// @brief Generate offline model for the op. -/// @param [in] op_type: type name of the op. -/// @param [in] in_tensor: input description array (created by OpTensorCreate). -/// @param [in] in_num: number of in_tensor. -/// @param [in] out_tensor: output description array (created by OpTensorCreate). -/// @param [in] out_num: number of out_tensor. -/// @param [in] attr: the attributes of the op (created by OpAttrCreate). -/// @param [in] om_file: file name for the om to save. -/// @return 0 for success / others for fail -/// -GE_FUNC_VISIBILITY extern Status_t OpTaskGernerator(const char *op_type, const OpTensor_t *in_tensor, int in_num, - const OpTensor_t *out_tensor, int out_num, const OpAttr_t attr, - const char *om_file); - -/// -/// @ingroup ge -/// @brief Create Tensor Description. -/// @param [in] format: tensor format of the data. -/// @param [in] datatype: tensor type of the data. -/// @param [in] shape: tensor shape array. -/// @param [in] num: number of shape. -/// @return OpTensor_t for success / nullptr for failure -/// -GE_FUNC_VISIBILITY extern OpTensor_t OpTensorCreate(int format, int datatype, const int64_t *shape, int num); - -/// -/// @ingroup ge -/// @brief Destroy Tensor Description. -/// @param [in] OpTensor_t tensor: created by OpTensorCreate. -/// @param [out] none -/// @return 0 for success / others for failure. -/// -GE_FUNC_VISIBILITY extern Status_t OpTensorDestroy(OpTensor_t tensor); - -/// -/// @ingroup ge -/// @brief Create an attribute holder. -/// @param [in] none -/// @param [out] none -/// @return OpAttr_t for success / nullptr for failure. -/// -GE_FUNC_VISIBILITY extern OpAttr_t OpAttrCreate(); - -/// -/// @ingroup ge -/// @brief Destroy Attribute holder. -/// @param [in] OpAttr_t attr: created by OpAttrCreate. -/// @param [out] none -/// @return 0 for success / others for failure. -/// -GE_FUNC_VISIBILITY extern Status_t OpAttrDestroy(OpAttr_t attr); - -/// -/// @ingroup ge -/// @brief Set a boolean attribute to the attribute holder. -/// @param [in] attr: attribute holder (created by OpAttrCreate). -/// @param [in] name: attribute name (can`t be nullptr, end with '\0'). -/// @param [in] value: attributed value. -/// @return 0 for success / others for failure. -/// -GE_FUNC_VISIBILITY extern Status_t SetAttrBool(OpAttr_t attr, const char *name, bool value); - -/// -/// @ingroup ge -/// @brief Set an integer attribute to the attribute holder. -/// @param [in] attr: attribute holder (created by OpAttrCreate). -/// @param [in] name: attribute name (can`t be nullptr, end with '\0'). -/// @param [in] value: attribute value. -/// @return 0 for success / others for failure. -/// -GE_FUNC_VISIBILITY extern Status_t SetAttrInt(OpAttr_t attr, const char *name, int64_t value); - -/// -/// @ingroup ge -/// @brief Set a float attribute to the attribute holder. -/// @param [in] attr: attribute holder (created by OpAttrCreate). -/// @param [in] name: attribute name (can`t be nullptr, end with '\0'). -/// @param [in] value: attribute value. -/// @return 0 for success / others for failure. -/// -GE_FUNC_VISIBILITY extern Status_t SetAttrFloat(OpAttr_t attr, const char *name, float value); - -/// -/// @ingroup ge -/// @brief Set a string attribute to the attribute holder. -/// @param [in] attr: attribute holder (created by OpAttrCreate). -/// @param [in] name: attribute name (can`t be nullptr, end with '\0'). -/// @param [in] value: attribute value (can`t be nullptr, end with '\0'). -/// @return 0 for success / others for failure. -/// -GE_FUNC_VISIBILITY extern Status_t SetAttrString(OpAttr_t attr, const char *name, const char *value); - -/// -/// @ingroup ge -/// @brief Set a boolean array attribute to the attribute holder. -/// @param [in] attr: attribute holder (created by OpAttrCreate). -/// @param [in] name: attribute name (can`t be nullptr, end with '\0'). -/// @param [in] value: attribute value array. -/// @param [in] num: number of value array. -/// @return 0 for success / others for failure. -/// -GE_FUNC_VISIBILITY extern Status_t SetAttrBoolList(OpAttr_t attr, const char *name, const bool *value, int num); - -/// -/// @ingroup ge -/// @brief Set an integer array attribute to the attribute holder. -/// @param [in] attr: attribute holder (created by OpAttrCreate). -/// @param [in] name: attribute name (can`t be nullptr, end with '\0'). -/// @param [in] value: attribute value array. -/// @param [in] num: number of value array. -/// @return 0 for success / others for failure. -/// -GE_FUNC_VISIBILITY extern Status_t SetAttrIntList(OpAttr_t attr, const char *name, const int64_t *value, int num); - -/// -/// @ingroup ge -/// @brief Set a float array attribute to the attribute holder. -/// @param [in] attr: attribute holder (created by OpAttrCreate). -/// @param [in] name: attribute name (can`t be nullptr, end with '\0'). -/// @param [in] value: attribute value array. -/// @param [in] num: number of value array. -/// @return 0 for success / others for failure. -/// -GE_FUNC_VISIBILITY extern Status_t SetAttrFloatList(OpAttr_t attr, const char *name, const float *value, int num); - -/// -/// @ingroup ge -/// @brief Set a string array attribute to the attribute holder. -/// @param [in] attr: attribute holder (created by OpAttrCreate). -/// @param [in] name: attribute name (can`t be nullptr, end with '\0'). -/// @param [in] value: attribute value array (each value can`t be nullptr, end with '\0'). -/// @param [in] num: number of value array. -/// @return 0 for success / others for failure. -/// -GE_FUNC_VISIBILITY extern Status_t SetAttrStringList(OpAttr_t attr, const char *name, const char **value, int num); - -#ifdef __cplusplus -} -#endif - -#endif // INC_FRAMEWORK_GENERATOR_GENERATOR_API_H_ diff --git a/inc/framework/memory/memory_api.h b/inc/framework/memory/memory_api.h index da36cdd6..a04a1ebe 100644 --- a/inc/framework/memory/memory_api.h +++ b/inc/framework/memory/memory_api.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,8 +20,8 @@ #include #include -#include "ge/ge_api_error_codes.h" -#include "graph//types.h" +#include "external/ge/ge_api_error_codes.h" +#include "graph/types.h" #include "runtime/mem.h" namespace ge { diff --git a/inc/framework/memory/memory_assigner.h b/inc/framework/memory/memory_assigner.h index 173cc64e..1ccbd785 100644 --- a/inc/framework/memory/memory_assigner.h +++ b/inc/framework/memory/memory_assigner.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,7 @@ #include -#include "common/ge_inner_error_codes.h" +#include "framework/common/ge_inner_error_codes.h" #include "graph/node.h" namespace ge { @@ -33,7 +33,7 @@ class GE_FUNC_VISIBILITY MemoryAssigner { MemoryAssigner &operator=(const MemoryAssigner &) = delete; - Status AssignMemory(bool is_loop_graph, map &mem_offset, size_t &zero_copy_mem_size); + Status AssignMemory(bool is_loop_graph, std::map &mem_offset, size_t &zero_copy_mem_size); private: ge::ComputeGraphPtr compute_graph_; diff --git a/inc/framework/omg/ge_init.h b/inc/framework/omg/ge_init.h index 67ef1082..a2fe6fc9 100644 --- a/inc/framework/omg/ge_init.h +++ b/inc/framework/omg/ge_init.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ #define INC_FRAMEWORK_OMG_GE_INIT_H_ #include #include -#include "common/ge_inner_error_codes.h" +#include "framework/common/ge_inner_error_codes.h" namespace ge { class GE_FUNC_VISIBILITY GEInit { diff --git a/inc/framework/omg/model_tool.h b/inc/framework/omg/model_tool.h index 8c425823..24554e65 100644 --- a/inc/framework/omg/model_tool.h +++ b/inc/framework/omg/model_tool.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/inc/framework/omg/omg.h b/inc/framework/omg/omg.h index a5360bb3..029b7a24 100644 --- a/inc/framework/omg/omg.h +++ b/inc/framework/omg/omg.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -43,8 +43,8 @@ namespace ge { * @brief init omg context * @return void */ -GE_FUNC_VISIBILITY Status InitDomiOmgContext(const string &input_shape, const string &input_format, - const string &net_format, bool is_dynamic_input); +GE_FUNC_VISIBILITY Status InitDomiOmgContext(const std::string &input_shape, const std::string &input_format, + const std::string &net_format, bool is_dynamic_input); /** * @ingroup domi_omg @@ -61,7 +61,7 @@ GE_FUNC_VISIBILITY Status InitDomiOmgContext(const string &input_shape, const st * @param [in] atc_params multiply atc params * @return Status result code */ -GE_FUNC_VISIBILITY Status ParseGraph(ge::Graph &graph, const std::map &atc_params, +GE_FUNC_VISIBILITY Status ParseGraph(ge::Graph &graph, const std::map &atc_params, const char *model_file, const char *weights_file, domi::FrameworkType type, const char *op_conf = nullptr, const char *target = nullptr, RunMode run_mode = GEN_OM_MODEL, bool is_dynamic_input = false); @@ -91,7 +91,8 @@ GE_FUNC_VISIBILITY Status ConvertFwkModelToJson(domi::FrameworkType framework, c GE_FUNC_VISIBILITY void GetGroupName(ge::proto::ModelDef &model); -GE_FUNC_VISIBILITY void FindParserSo(const string &path, vector &fileList, string &caffe_parser_path); +GE_FUNC_VISIBILITY void FindParserSo(const std::string &path, std::vector &fileList, + std::string &caffe_parser_path); GE_FUNC_VISIBILITY Status DumpInfershapeJson(const ge::Graph &graph, const char *json_file); diff --git a/inc/framework/omg/omg_inner_types.h b/inc/framework/omg/omg_inner_types.h index a3621d8b..3f7b5db1 100644 --- a/inc/framework/omg/omg_inner_types.h +++ b/inc/framework/omg/omg_inner_types.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -120,14 +120,13 @@ struct OmgContext { std::string dynamic_image_size; std::string dynamic_dims; std::string dynamic_node_type; - std::vector> user_real_input_dims; - std::vector cur_dynamic_dims; bool need_multi_batch = false; std::vector data_nodes; std::vector getnext_nosink_nodes; bool fuzz_compile_flag = false; std::string atc_cmdline; bool user_attr_index_valid = false; + bool is_online_model = false; }; } // namespace ge diff --git a/inc/framework/omg/omg_types.h b/inc/framework/omg/omg_types.h index 771a53a4..8ec2a49b 100644 --- a/inc/framework/omg/omg_types.h +++ b/inc/framework/omg/omg_types.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/inc/framework/omg/parser/model_parser.h b/inc/framework/omg/parser/model_parser.h index d311706d..b6ebd8a8 100644 --- a/inc/framework/omg/parser/model_parser.h +++ b/inc/framework/omg/parser/model_parser.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/inc/framework/omg/parser/op_parser.h b/inc/framework/omg/parser/op_parser.h index 7d02b257..760b41f5 100644 --- a/inc/framework/omg/parser/op_parser.h +++ b/inc/framework/omg/parser/op_parser.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,7 @@ #include #include "framework/omg/parser/parser_types.h" -#include "omg/omg_inner_types.h" +#include "framework/omg/omg_inner_types.h" #include "proto/om.pb.h" #include "graph/ge_tensor.h" #include "graph/op_desc.h" diff --git a/inc/framework/omg/parser/parser_api.h b/inc/framework/omg/parser/parser_api.h index a493e29f..26c9e051 100644 --- a/inc/framework/omg/parser/parser_api.h +++ b/inc/framework/omg/parser/parser_api.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,7 +20,7 @@ #include #include #include -#include "ge/ge_api_error_codes.h" +#include "external/ge/ge_api_error_codes.h" namespace ge { // Initialize parser diff --git a/inc/framework/omg/parser/parser_factory.h b/inc/framework/omg/parser/parser_factory.h index 06aaecb7..5b505d52 100644 --- a/inc/framework/omg/parser/parser_factory.h +++ b/inc/framework/omg/parser/parser_factory.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/inc/framework/omg/parser/parser_inner_ctx.h b/inc/framework/omg/parser/parser_inner_ctx.h index 5de54704..fd559468 100644 --- a/inc/framework/omg/parser/parser_inner_ctx.h +++ b/inc/framework/omg/parser/parser_inner_ctx.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/inc/framework/omg/parser/parser_types.h b/inc/framework/omg/parser/parser_types.h index f3b7f00a..a2452c65 100644 --- a/inc/framework/omg/parser/parser_types.h +++ b/inc/framework/omg/parser/parser_types.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -17,7 +17,7 @@ #ifndef PARSER_COMMON_TYPES_H_ #define PARSER_COMMON_TYPES_H_ -#include +#include #include #include "register/register_types.h" diff --git a/inc/framework/omg/parser/weights_parser.h b/inc/framework/omg/parser/weights_parser.h index a568f927..c231fd41 100644 --- a/inc/framework/omg/parser/weights_parser.h +++ b/inc/framework/omg/parser/weights_parser.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/inc/framework/omg/version.h b/inc/framework/omg/version.h index 4facba0d..156fbc5c 100644 --- a/inc/framework/omg/version.h +++ b/inc/framework/omg/version.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,8 +22,8 @@ #include #include -#include "common/debug/log.h" -#include "common/string_util.h" +#include "framework/common/debug/log.h" +#include "framework/common/string_util.h" #include "framework/common/debug/ge_log.h" namespace ge { @@ -33,7 +33,7 @@ class GE_FUNC_VISIBILITY PlatformVersionManager { ~PlatformVersionManager() = delete; static Status GetPlatformVersion(std::string &ver) { ver = "1.11.z"; - std::vector version_splits = StringUtils::Split(ver, '.'); + const std::vector version_splits = StringUtils::Split(ver, '.'); GE_IF_BOOL_EXEC(version_splits.size() < 3, GELOGW("Read platform version error!"); return FAILED;); GELOGI("Read current platform version: %s.", ver.c_str()); From 60cbe0c4d5a11f32aa9be6981812679c90e79b6f Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Thu, 18 Nov 2021 16:01:24 +0800 Subject: [PATCH 41/59] upgrade Ascend package 18 Nov 21 --- inc/external/acl/error_codes/rt_error_codes.h | 1 + inc/framework/common/ge_types.h | 1 + metadef | 2 +- .../inc/external/runtime/rt_error_codes.h | 9 ++- third_party/fwkacllib/inc/ops/array_ops.h | 52 ++++++++------- third_party/fwkacllib/inc/ops/image_ops.h | 21 +++++- .../fwkacllib/inc/ops/nn_batch_norm_ops.h | 36 ++++++++-- third_party/fwkacllib/inc/ops/ocr_ops.h | 4 +- third_party/fwkacllib/inc/ops/reduce_ops.h | 21 ++++++ third_party/fwkacllib/inc/ops/vector_search.h | 66 ++++++++++++++++++- third_party/fwkacllib/inc/runtime/base.h | 6 +- third_party/fwkacllib/inc/runtime/config.h | 12 +++- third_party/fwkacllib/inc/runtime/dev.h | 11 +++- third_party/fwkacllib/inc/runtime/kernel.h | 16 +++-- third_party/fwkacllib/inc/runtime/mem.h | 2 +- third_party/fwkacllib/inc/runtime/rt.h | 3 +- .../fwkacllib/inc/toolchain/prof_acl_api.h | 12 ++-- 17 files changed, 217 insertions(+), 58 deletions(-) diff --git a/inc/external/acl/error_codes/rt_error_codes.h b/inc/external/acl/error_codes/rt_error_codes.h index 556652be..abfa30db 100644 --- a/inc/external/acl/error_codes/rt_error_codes.h +++ b/inc/external/acl/error_codes/rt_error_codes.h @@ -60,6 +60,7 @@ static const int32_t ACL_ERROR_RT_NO_CDQ_RESOURCE = 207011; // no cdq resou static const int32_t ACL_ERROR_RT_OVER_LIMIT = 207012; // over limit static const int32_t ACL_ERROR_RT_QUEUE_EMPTY = 207013; // queue is empty static const int32_t ACL_ERROR_RT_QUEUE_FULL = 207014; // queue is full +static const int32_t ACL_ERROR_RT_REPEATED_INIT = 207015; // repeated init static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error diff --git a/inc/framework/common/ge_types.h b/inc/framework/common/ge_types.h index dcfb4961..060a7bf0 100644 --- a/inc/framework/common/ge_types.h +++ b/inc/framework/common/ge_types.h @@ -293,6 +293,7 @@ struct OpDescInfo { std::string dev_func; std::string tvm_magic; uint32_t tiling_key = 0U; + uintptr_t args = 0U; std::string tiling_data; std::string node_info; std::vector workspace_bytes; diff --git a/metadef b/metadef index 7d777404..fe47d04d 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit 7d777404b3b7fe7daeaf00e566e431c6a05b040a +Subproject commit fe47d04d75170006fc0d28538dec49a2da426ceb diff --git a/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h b/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h index c5423d36..09ce1f65 100644 --- a/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h +++ b/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h @@ -58,6 +58,10 @@ static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no str static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource static const int32_t ACL_ERROR_RT_NO_CDQ_RESOURCE = 207011; // no cdq resource +static const int32_t ACL_ERROR_RT_OVER_LIMIT = 207012; // over limit +static const int32_t ACL_ERROR_RT_QUEUE_EMPTY = 207013; // queue is empty +static const int32_t ACL_ERROR_RT_QUEUE_FULL = 207014; // queue is full +static const int32_t ACL_ERROR_RT_REPEATED_INIT = 207015; // repeated init static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error @@ -97,6 +101,10 @@ static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception static const int32_t ACL_ERROR_RT_CDQ_BATCH_ABNORMAL = 507037; // cdq alloc batch abnormal +static const int32_t ACL_ERROR_RT_DIE_MODE_CHANGE_ERROR = 507038; // can not change die mode +static const int32_t ACL_ERROR_RT_DIE_SET_ERROR = 507039; // single die mode can not set die +static const int32_t ACL_ERROR_RT_INVALID_DIEID = 507040; // invalid die id +static const int32_t ACL_ERROR_RT_DIE_MODE_NOT_SET = 507041; // die mode not set static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error @@ -105,5 +113,4 @@ static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc di #ifdef __cplusplus } #endif - #endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/third_party/fwkacllib/inc/ops/array_ops.h b/third_party/fwkacllib/inc/ops/array_ops.h index 18028c19..c02537cd 100644 --- a/third_party/fwkacllib/inc/ops/array_ops.h +++ b/third_party/fwkacllib/inc/ops/array_ops.h @@ -497,6 +497,25 @@ REG_OP(Constant) .ATTR(value, Tensor, Tensor()) .OP_END_FACTORY_REG(Constant) +/** +*@brief Creates a file constant tensor, The operator is used to process the very large weight which is store in file. \n + +*@par Attributes: +*file_id: A string, used to record file id. \n +*shape: data shape. \n +*dtype: data type. \n + +*@par Outputs: +*y: The FileConstant tensor. \n +*/ +REG_OP(FileConstant) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT16, DT_UINT16, \ + DT_UINT8, DT_INT32, DT_INT64, DT_UINT32, DT_UINT64, DT_BOOL, DT_DOUBLE})) + .REQUIRED_ATTR(file_id, String) + .REQUIRED_ATTR(shape, ListInt) + .REQUIRED_ATTR(dtype, Type) + .OP_END_FACTORY_REG(FileConstant) + /** *@brief Returns a copy of the input tensor. \n @@ -1329,31 +1348,6 @@ REG_OP(ExpandD) .REQUIRED_ATTR(shape, ListInt) .OP_END_FACTORY_REG(ExpandD) -/** -* @brief Calculate buckets limit and offset. \n - -* @par Inputs: -* Three inputs, including: -* @li bucket_list: A 1-D tensor of type int32 with the value of ivf_counts and ivf_offset index. \n -* @li ivf_counts: A 1-D tensor of type int32 with the value of ivf counts. \n -* @li ivf_offset: A 1-D tensor of type int32 or int64 with the value of ivf offset. \n - -* @par Attributes: -* total_limit: A int64 type maximum value of the sum of ivf_counts corresponding to bucket_list. \n - -* @par Outputs: -* @li buckets_limit: A 1-D tensor of type int32 with the sum <= total_limit. \n -* @li buckets_offset: A 1-D tensor of type int32 or int64 with the value of ivf_offset corresponding to bucket_list. \n -*/ -REG_OP(CalcBucketsLimitAndOffset) - .INPUT(bucket_list, TensorType({DT_INT32})) - .INPUT(ivf_counts, TensorType({DT_INT32})) - .INPUT(ivf_offset, TensorType({DT_INT32, DT_INT64})) - .OUTPUT(buckets_limit, TensorType({DT_INT32})) - .OUTPUT(buckets_offset, TensorType({DT_INT32, DT_INT64})) - .REQUIRED_ATTR(total_limit, Int) - .OP_END_FACTORY_REG(CalcBucketsLimitAndOffset) - /** *@brief Get dim number in tensordesc. \n @@ -1362,6 +1356,9 @@ REG_OP(CalcBucketsLimitAndOffset) *@par Outputs: *y: A 1D tensor. The data type must be int32. \n + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(GetShape) .DYNAMIC_INPUT(x, TensorType({DT_DOUBLE, DT_FLOAT, DT_FLOAT16, DT_INT8, DT_UINT8, DT_INT16, \ @@ -1377,8 +1374,13 @@ REG_OP(GetShape) *@par outputs: * y: a tensor_desc, type is int.\n + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(UpdateTensorDesc) + .INPUT(x, TensorType({DT_BOOL, DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT32, DT_UINT8, + DT_INT64, DT_UINT64, DT_INT16, DT_UINT16, DT_DOUBLE})) .OUTPUT(y, TensorType({DT_BOOL, DT_FLOAT16, DT_FLOAT, DT_INT8, DT_INT32, DT_UINT32, DT_UINT8, DT_INT64, DT_UINT64, DT_INT16, DT_UINT16, DT_DOUBLE})) .REQUIRED_ATTR(shape, ListInt) diff --git a/third_party/fwkacllib/inc/ops/image_ops.h b/third_party/fwkacllib/inc/ops/image_ops.h index 319681e4..e771d67c 100644 --- a/third_party/fwkacllib/inc/ops/image_ops.h +++ b/third_party/fwkacllib/inc/ops/image_ops.h @@ -585,6 +585,14 @@ REG_OP(ResizeNearestNeighborV2GradD) *@li original_image: A Tensor. 4-D shape. Must set the format, supported format list ["NCHW, NHWC"] channels], The image tensor that was resized . \n +*@par Attributes: +*@li size: An optional listint. Defaults to {}. +*@par Attributes: +*@li ori_image_size: An optional listint. Defaults to {}. +*@par Attributes: +*@li src_start_w: An optional int. Defaults to 0. +*@par Attributes: +*@li dst_start_w: An optional int. Defaults to 0. *@par Attributes: *@li align_corners: An optional bool. Defaults to False. If true, the centers of the 4 corner pixels of the input and grad tensors are aligned. Defaults to @@ -606,6 +614,10 @@ REG_OP(ResizeBilinearV2Grad) .INPUT(grads, TensorType({DT_FLOAT})) .INPUT(original_image, TensorType::FloatingDataType()) .OUTPUT(y, TensorType({DT_FLOAT})) + .ATTR(size, ListInt, {}) + .ATTR(ori_image_size, ListInt, {}) + .ATTR(src_start_w, Int, 0) + .ATTR(dst_start_w, Int, 0) .ATTR(align_corners, Bool, false) .ATTR(half_pixel_centers, Bool, false) .OP_END_FACTORY_REG(ResizeBilinearV2Grad) @@ -624,7 +636,10 @@ size for the images . \n output tensors are aligned, preserving the values at the corner pixels. Defaults to false . * @li half_pixel_centers: An optional bool. Defaults to False . \n - +*@li ori_image_size: An optional listint. Defaults to {}. +*@li split_size: An optional listint. Defaults to {}. +*@li src_start_w: An optional int. Defaults to 0. +*@li dst_start_w: An optional int. Defaults to 0. *@par Outputs: *y: 4-D with shape [batch, new_height, new_width, channels] . \n @@ -640,6 +655,10 @@ REG_OP(ResizeBilinearV2) DT_INT32, DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) .INPUT(size, TensorType({DT_INT32})) .OUTPUT(y, TensorType({DT_FLOAT})) + .ATTR(ori_image_size, ListInt, {}) + .ATTR(split_size, ListInt, {}) + .ATTR(src_start_w, Int, 0) + .ATTR(dst_start_w, Int, 0) .ATTR(align_corners, Bool, false) .ATTR(half_pixel_centers, Bool, false) .OP_END_FACTORY_REG(ResizeBilinearV2) diff --git a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h index 66d67551..ccafa01f 100644 --- a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h @@ -113,9 +113,7 @@ if input "x" is with format NC1HWC0. Specifies the mean of "x". Must be 5D if input "x" is with format NC1HWC0. Specifies the variance of "x". *@li reserve_space_1: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D if input "x" is with format NC1HWC0. Specifies the mean of "x" for gradient computation. Pass "None" to skip this output. -*@li reserve_space_2: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. -Must be 5D if input "x" is with format NC1HWC0. Specifies the variance of "x" for gradient computation. Pass "None" to skip this output . -*@li reserve_space_3: An optional Tensor of type float32. For compatibility with tensorflow, only has one useless element. \n +*@li reserve_space_2: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. \n *@attention Constraints: *@li If the operation is used for inference and outputs "reserve_space_1" and "reserve_space_2" are available, @@ -137,7 +135,6 @@ REG_OP(BatchNorm) .OUTPUT(batch_variance, TensorType({DT_FLOAT})) .OUTPUT(reserve_space_1, TensorType({DT_FLOAT})) .OUTPUT(reserve_space_2, TensorType({DT_FLOAT})) - .OUTPUT(reserve_space_3, TensorType({DT_FLOAT})) .ATTR(epsilon, Float, 0.0001) .ATTR(data_format, String, "NHWC") .ATTR(is_training, Bool, true) @@ -166,6 +163,33 @@ REG_OP(SyncBatchNormBackwardReduce) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(SyncBatchNormBackwardReduce) +/** +*@brief part of SyncBatchNormBackward . \n + +*@par Inputs: +* Three inputs, including: +*@li grad_output: A Tensor. Must be one of the following types: float16, float32 . +*@li save_input: A Tensor. Must be one of the following types: float16, float32 . +*@li mean: A Tensor. Must be one of the following types: float16, float32 . +*@li invstd: A Tensor. Must be one of the following types: float16, float32 . +*@li weight: A Tensor. Must be one of the following types: float16, float32 . +*@li mean_dy: A Tensor. Must be one of the following types: float16, float32 . +*@li mean_dy_xmu: A Tensor. Must be one of the following types: float16, float32 . \n + +*@par Outputs: +*@li grad_input: A Tensor. Has the same type and format as input "grad_output" . \n +*/ +REG_OP(SyncBatchNormBackwardElemt) + .INPUT(grad_output, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(save_input, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(mean, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(invstd, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(weight, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(mean_dy, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(mean_dy_xmu, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(grad_input, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(SyncBatchNormBackwardElemt) + /** *@brief Performs batch normalization . \n @@ -285,8 +309,7 @@ REG_OP(BatchNormExt2) *@li x: A 4D or 5D Tensor of type float16 or float32, with format NHWC, NCHW, or NC1HWC0. *@li scale: A 4D or 5D Tensor of type float32, with format NHWC, NCHW, or NC1HWC0. *@li reserve_space_1: A 4D or 5D Tensor of type float32, with format NHWC, NCHW, or NC1HWC0. It is an output of BatchNorm. -*@li reserve_space_2: A 4D or 5D Tensor of type float32, with format NHWC, NCHW, or NC1HWC0. It is an output of BatchNorm . -*@li reserve_space_3: A 1D optional Tensor of type float32. It is an output of BatchNorm . \n +*@li reserve_space_2: A 4D or 5D Tensor of type float32, with format NHWC, NCHW, or NC1HWC0. It is an output of BatchNorm . \n *@par Attributes: *@li epsilon: An optional float32. Defaults to "0.0001". A small float number added to the variance of "x". @@ -313,7 +336,6 @@ REG_OP(BatchNormGrad) .INPUT(scale, TensorType({DT_FLOAT})) .INPUT(reserve_space_1, TensorType({DT_FLOAT})) .INPUT(reserve_space_2, TensorType({DT_FLOAT})) - .OPTIONAL_INPUT(reserve_space_3, TensorType({DT_FLOAT})) .OUTPUT(x_backprop, TensorType({DT_FLOAT16,DT_FLOAT})) .OUTPUT(scale_backprop, TensorType({DT_FLOAT})) .OUTPUT(offset_backprop, TensorType({DT_FLOAT})) diff --git a/third_party/fwkacllib/inc/ops/ocr_ops.h b/third_party/fwkacllib/inc/ops/ocr_ops.h index 639c34de..baab5af2 100644 --- a/third_party/fwkacllib/inc/ops/ocr_ops.h +++ b/third_party/fwkacllib/inc/ops/ocr_ops.h @@ -128,7 +128,7 @@ REG_OP(OCRIdentifyPreHandle) .INPUT(imgs_offset, TensorType({DT_INT32})) .INPUT(imgs_size, TensorType({DT_INT32})) .OUTPUT(resized_imgs, TensorType({DT_UINT8})) - .ATTR(size, ListInt, {}) + .REQUIRED_ATTR(size, ListInt) .ATTR(data_format, String, "NHWC") .OP_END_FACTORY_REG(OCRIdentifyPreHandle) @@ -247,6 +247,7 @@ REG_OP(OCRDetectionPostHandle) *@li clipped_polys_data: A Tensor of type int32. point data of every clipped poly. \n *@li clipped_polys_offset: A Tensor of type int32. Offset of every clipped poly . \n *@li clipped_polys_size: A Tensor of type int32. Size of every clipped poly. \n +*@li clipped_polys_num: A Tensor of type int32. Number of clipped polys. \n */ REG_OP(ResizeAndClipPolys) .INPUT(polys_data, TensorType({DT_INT32})) @@ -259,6 +260,7 @@ REG_OP(ResizeAndClipPolys) .OUTPUT(clipped_polys_data, TensorType({DT_INT32})) .OUTPUT(clipped_polys_offset, TensorType({DT_INT32})) .OUTPUT(clipped_polys_size, TensorType({DT_INT32})) + .OUTPUT(clipped_polys_num, TensorType({DT_INT32})) .OP_END_FACTORY_REG(ResizeAndClipPolys); diff --git a/third_party/fwkacllib/inc/ops/reduce_ops.h b/third_party/fwkacllib/inc/ops/reduce_ops.h index e8c14b1a..4e4c74af 100644 --- a/third_party/fwkacllib/inc/ops/reduce_ops.h +++ b/third_party/fwkacllib/inc/ops/reduce_ops.h @@ -1305,6 +1305,27 @@ REG_OP(ReduceStdWithMean) .ATTR(invert, Bool, false) .ATTR(epsilon, Float, 0.001) .OP_END_FACTORY_REG(ReduceStdWithMean) + +/** +*@brief Performs reduced batch normalization . \n + +*@par Inputs: +*x: A 5D Tensor of type float16 or float32, with format NC1HWC0 . \n + +*@par Outputs: +*@li mean: A Tensor of type float32 for SUM reduced "x". +*@li variance: A Tensor of type float32 for square sum reduced "x" . \n + +*@par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(ReduceMeanVariance) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(mean, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(variance, TensorType({DT_FLOAT16,DT_FLOAT})) + .ATTR(axes, ListInt, {}) + .ATTR(keep_dims, Bool, true) + .OP_END_FACTORY_REG(ReduceMeanVariance) } //namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_REDUCE_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/vector_search.h b/third_party/fwkacllib/inc/ops/vector_search.h index 8c1d0a2e..8f2201af 100644 --- a/third_party/fwkacllib/inc/ops/vector_search.h +++ b/third_party/fwkacllib/inc/ops/vector_search.h @@ -78,8 +78,8 @@ REG_OP(TopKPQDistance) .OUTPUT(topk_ivf, TensorType({DT_INT32})) .OUTPUT(topk_index, TensorType({DT_INT32})) .ATTR(order, String, "ASC") - .ATTR(k, Int, 0) - .ATTR(group_size, Int, 0) + .REQUIRED_ATTR(k, Int) + .REQUIRED_ATTR(group_size, Int) .OP_END_FACTORY_REG(TopKPQDistance) /** @@ -129,6 +129,68 @@ REG_OP(ScanPQCodes) .ATTR(split_count, Int, 1) .ATTR(split_index, Int, 0) .OP_END_FACTORY_REG(ScanPQCodes) + +/** +* @brief Calculate buckets limit and offset. \n + +* @par Inputs: +* Three inputs, including: +* @li bucket_list: A 1-D tensor of type int32 with the value of ivf_counts and ivf_offset index. \n +* @li ivf_counts: A 1-D tensor of type int32 with the value of ivf counts. \n +* @li ivf_offset: A 1-D tensor of type int32 or int64 with the value of ivf offset. \n + +* @par Attributes: +* total_limit: A int64 type maximum value of the sum of ivf_counts corresponding to bucket_list. \n + +* @par Outputs: +* @li buckets_limit: A 1-D tensor of type int32 with the sum <= total_limit. \n +* @li buckets_offset: A 1-D tensor of type int32 or int64 with the value of ivf_offset corresponding to bucket_list. \n +*/ +REG_OP(CalcBucketsLimitAndOffset) + .INPUT(bucket_list, TensorType({DT_INT32})) + .INPUT(ivf_counts, TensorType({DT_INT32})) + .INPUT(ivf_offset, TensorType({DT_INT32, DT_INT64})) + .OUTPUT(buckets_limit, TensorType({DT_INT32})) + .OUTPUT(buckets_offset, TensorType({DT_INT32, DT_INT64})) + .REQUIRED_ATTR(total_limit, Int) + .OP_END_FACTORY_REG(CalcBucketsLimitAndOffset) + +/** +* @brief Calculate ProdVirialSeA. \n +* +* @par Inputs: +* Five inputs, including: +* @li net_deriv: A Tensor. Must be one of the following types: float16, float32, float64. +* @li in_deriv: A Tensor. Must be one of the following types: float16, float32, float64. +* @li rij: A Tensor. Must be one of the following types: float16, float32, float64. +* @li nlist: A Tensor. dtype is int32. +* @li natoms: A Tensor. dtype is int32. \n +* +* @par Outputs: +* Two outputs, including: +* @li virial: A Tensor. Must be one of the following types: float16, float32, float64. +* @li atom_virial: A Tensor. Must be one of the following types: float16, float32, float64. \n +* +* @par Attributes: +* Two attributes, including: +* @li n_a_sel: A Scalar. +* @li n_r_sel: A Scalar. \n +* +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(ProdVirialSeA) + .INPUT(net_deriv, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(in_deriv, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(rij, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(nlist, TensorType({DT_INT32})) + .INPUT(natoms, TensorType({DT_INT32})) + .OUTPUT(virial, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(atom_virial, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .REQUIRED_ATTR(n_a_sel, Int) + .REQUIRED_ATTR(n_r_sel, Int) + .ATTR(nall, Int, 28328) + .OP_END_FACTORY_REG(ProdVirialSeA) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_VECTOR_SEARCH_H_ diff --git a/third_party/fwkacllib/inc/runtime/base.h b/third_party/fwkacllib/inc/runtime/base.h index 9e95a8b9..39301554 100644 --- a/third_party/fwkacllib/inc/runtime/base.h +++ b/third_party/fwkacllib/inc/runtime/base.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef __CCE_RUNTIME_BASE_H__ -#define __CCE_RUNTIME_BASE_H__ +#ifndef CCE_RUNTIME_BASE_H +#define CCE_RUNTIME_BASE_H #include #include "toolchain/prof_callback.h" @@ -443,4 +443,4 @@ RTS_API rtError_t rtGetTaskIdAndStreamID(uint32_t *taskId, uint32_t *streamId); } #endif -#endif // __CCE_RUNTIME_BASE_H__ +#endif // CCE_RUNTIME_BASE_H \ No newline at end of file diff --git a/third_party/fwkacllib/inc/runtime/config.h b/third_party/fwkacllib/inc/runtime/config.h index 64ab1497..f9e6a49e 100644 --- a/third_party/fwkacllib/inc/runtime/config.h +++ b/third_party/fwkacllib/inc/runtime/config.h @@ -239,8 +239,18 @@ RTS_API rtError_t rtSetOpWaitTimeOut(uint32_t timeout); */ RTS_API rtError_t rtSetOpExecuteTimeOut(uint32_t timeout); +/** + * @ingroup + * @brief get is Heterogenous. + * @param [out] heterogenous=1 Heterogenous Mode: read isHeterogenous=1 in ini file. + * @param [out] heterogenous=0 NOT Heterogenous Mode: + * 1:not found ini file, 2:error when reading ini, 3:Heterogenous value is not 1 + * @return RT_ERROR_NONE for ok + */ +RTS_API rtError_t rtGetIsHeterogenous(int32_t *heterogenous); + #if defined(__cplusplus) } #endif -#endif // CCE_RUNTIME_CONFIG_H \ No newline at end of file +#endif // CCE_RUNTIME_CONFIG_H diff --git a/third_party/fwkacllib/inc/runtime/dev.h b/third_party/fwkacllib/inc/runtime/dev.h index f6777262..75d01f36 100644 --- a/third_party/fwkacllib/inc/runtime/dev.h +++ b/third_party/fwkacllib/inc/runtime/dev.h @@ -25,7 +25,7 @@ extern "C" { #define RT_CAPABILITY_SUPPORT (0x1U) #define RT_CAPABILITY_NOT_SUPPORT (0x0U) -#define MEMORY_INFO_TS_4G_LIMITED (0x0) // for compatibility +#define MEMORY_INFO_TS_4G_LIMITED (0x0U) // for compatibility typedef struct tagRTDeviceInfo { uint8_t env_type; // 0: FPGA 1: EMU 2: ESL @@ -171,6 +171,15 @@ RTS_API rtError_t rtSetDevice(int32_t device); */ RTS_API rtError_t rtSetDeviceV2(int32_t device, rtDeviceMode deviceMode); +/** + * @ingroup dvrt_dev + * @brief get deviceMode + * @param [out] deviceMode the device mode + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtGetDeviceMode(rtDeviceMode *deviceMode); + /** * @ingroup dvrt_dev * @brief set target die for current thread diff --git a/third_party/fwkacllib/inc/runtime/kernel.h b/third_party/fwkacllib/inc/runtime/kernel.h index 8c556e3a..2bd7f284 100644 --- a/third_party/fwkacllib/inc/runtime/kernel.h +++ b/third_party/fwkacllib/inc/runtime/kernel.h @@ -133,8 +133,11 @@ typedef struct tagRtArgsWithTiling { uint16_t tilingDataOffset; // tiling data offset uint16_t hostInputAddrOffset; // index of host_memory input in inputs_addrs list uint16_t hostInputDataOffset; // host_mem input data offset - bool hasHostMemInput; // has host_memory input data in args or not: ture or false - uint8_t reserved[7]; + uint8_t hasHostMemInput; // has host_memory input data in args or not: 0 means no host_memory input data, + // others means has host_memory input data. + uint8_t isNoNeedH2DCopy; // is no need host to device copy: 0 means need H2D copy, + // others means doesn't need H2D copy. + uint8_t reserved[6]; } rtArgsWithTiling_t; /** @@ -299,8 +302,8 @@ RTS_API rtError_t rtDependencyRegister(void *mHandle, void *sHandle); * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtFunctionRegister(void *binHandle, const void *stubFunc, const char_t *stubName, const void *devFunc, - uint32_t funcMode); +RTS_API rtError_t rtFunctionRegister(void *binHandle, const void *stubFunc, const char_t *stubName, + const void *devFunc, uint32_t funcMode); /** * @ingroup rt_kernel @@ -371,8 +374,9 @@ RTS_API rtError_t rtKernelLaunch(const void *stubFunc, uint32_t blockDim, void * * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtKernelLaunchWithHandle(void *handle, const void *devFunc, uint32_t blockDim, void *args, uint32_t argsSize, - rtSmDesc_t *smDesc, rtStream_t stream_, const void *kernelInfo); +RTS_API rtError_t rtKernelLaunchWithHandle(void *handle, const void *devFunc, uint32_t blockDim, + void *args, uint32_t argsSize, rtSmDesc_t *smDesc, rtStream_t stream_, + const void *kernelInfo); /** * @ingroup rt_kernel diff --git a/third_party/fwkacllib/inc/runtime/mem.h b/third_party/fwkacllib/inc/runtime/mem.h index 971f0cb0..d095ef0c 100644 --- a/third_party/fwkacllib/inc/runtime/mem.h +++ b/third_party/fwkacllib/inc/runtime/mem.h @@ -576,7 +576,7 @@ RTS_API rtError_t rtRDMASend(uint32_t index, uint32_t wqeIndex, rtStream_t strea * @return RT_ERROR_INVALID_VALUE for error input * @return RT_ERROR_DRV_ERR for driver error */ -RTS_API rtError_t rtSetIpcMemPid(const char_t *name, int32_t pid[], int num); +RTS_API rtError_t rtSetIpcMemPid(const char_t *name, int32_t pid[], int32_t num); /** * @ingroup dvrt_mem diff --git a/third_party/fwkacllib/inc/runtime/rt.h b/third_party/fwkacllib/inc/runtime/rt.h index 519ccd40..8c3e339f 100644 --- a/third_party/fwkacllib/inc/runtime/rt.h +++ b/third_party/fwkacllib/inc/runtime/rt.h @@ -31,5 +31,6 @@ #include "rt_ffts.h" #include "rt_ffts_plus.h" #include "rt_dfx.h" +#include "rt_mem_queue.h" -#endif // CCE_RUNTIME_RT_H \ No newline at end of file +#endif // CCE_RUNTIME_RT_H diff --git a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h index 0bc63385..80f4baab 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h +++ b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h @@ -23,6 +23,8 @@ #define PROF_AICORE_METRICS 0x00000004 #define PROF_AICPU_TRACE 0x00000008 #define PROF_L2CACHE 0x00000010 +#define PROF_HCCL_TRACE 0x00000020 +#define PROF_TRAINING_TRACE 0x00000040 // system profilinig switch #define PROF_CPU 0x00010000 @@ -41,10 +43,7 @@ #define PROF_AIVECTORCORE_METRICS 0x0000020000000 #define PROF_SUBTASK_TIME 0x0000040000000 -#define PROF_TRAINING_TRACE 0x0000080000000 -#define PROF_HCCL_TRACE 0x0000100000000 - -#define PROF_TASK_TRACE 0x0000185000002 +#define PROF_TASK_TRACE 0x0000005000062 #define PROF_MODEL_LOAD 0x8000000000000000 @@ -54,6 +53,8 @@ #define PROF_AICORE_METRICS_MASK 0x00000004 #define PROF_AICPU_TRACE_MASK 0x00000008 #define PROF_L2CACHE_MASK 0x00000010 +#define PROF_HCCL_TRACE_MASK 0x00000020 +#define PROF_TRAINING_TRACE_MASK 0x00000040 // system profilinig mask #define PROF_CPU_MASK 0x00010000 @@ -72,9 +73,6 @@ #define PROF_AIVECTORCORE_METRICS_MASK 0x0000020000000 #define PROF_SUBTASK_TIME_MASK 0x0000040000000 -#define PROF_TRAINING_TRACE_MASK 0x0000080000000 -#define PROF_HCCL_TRACE_MASK 0x0000100000000 - #define PROF_MODEL_LOAD_MASK 0x8000000000000000 #if (defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)) From ee529b48a3da63bdaca93dcaefe2a8a33d3c340d Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Fri, 19 Nov 2021 11:00:17 +0800 Subject: [PATCH 42/59] fix missing headers --- .../fwkacllib/inc/runtime/rt_mem_queue.h | 577 ++++++++++++++++++ 1 file changed, 577 insertions(+) create mode 100644 third_party/fwkacllib/inc/runtime/rt_mem_queue.h diff --git a/third_party/fwkacllib/inc/runtime/rt_mem_queue.h b/third_party/fwkacllib/inc/runtime/rt_mem_queue.h new file mode 100644 index 00000000..c6f56064 --- /dev/null +++ b/third_party/fwkacllib/inc/runtime/rt_mem_queue.h @@ -0,0 +1,577 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + * Description: mbuf and queue interface + */ + +#ifndef CCE_RUNTIME_RT_MEM_QUEUE_H +#define CCE_RUNTIME_RT_MEM_QUEUE_H + +#include "base.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +#define RT_MQ_MAX_NAME_LEN 128 // same as driver's +#define RT_MQ_DEPTH_MIN 2U +#define RT_MQ_MODE_PUSH 1 +#define RT_MQ_MODE_PULL 2 +#define RT_MQ_MODE_DEFAULT RT_MQ_MODE_PUSH +#define RT_EVENT_SUMMARY_RSV 4 +#define RT_EVENT_MAX_MSG_LEN 128 + +typedef struct tagMemQueueInfo { + int32_t id; + int32_t size; + uint32_t depth; + int32_t status; +} rtMemQueueInfo_t; + +typedef struct tagMemQueueAttr { + char_t name[RT_MQ_MAX_NAME_LEN]; + uint32_t depth; + uint32_t workMode; + uint32_t flowCtrlDropTime; + bool flowCtrlFlag; + bool overWriteFlag; +} rtMemQueueAttr_t; + +typedef struct tagMemQueueShareAttr { + uint32_t manage : 1; + uint32_t read : 1; + uint32_t write : 1; + uint32_t rsv : 29; +} rtMemQueueShareAttr_t; + +typedef struct tagMemQueueBuffInfo { + void *addr; + size_t len; +} rtMemQueueBuffInfo; + +typedef struct tagMemQueueBuff { + void *contextAddr; + size_t contextLen; + rtMemQueueBuffInfo *buffInfo; + uint32_t buffCount; +} rtMemQueueBuff_t; + + +typedef enum tagMemQueueQueryCmd { + RT_MQ_QUERY_QUE_ATTR_OF_CUR_PROC = 0, // input is qid(4bytes), output is rtMemQueueShareAttr_t + RT_MQ_QUERY_QUES_OF_CUR_PROC = 1, + RT_MQ_QUERY_CMD_MAX = 2 +} rtMemQueueQueryCmd_t; + +#define RT_MQ_EVENT_QS_MSG 27 // same as driver's + +#define RT_MQ_SCHED_PRIORITY_LEVEL0 0 // same as driver's +#define RT_MQ_SCHED_PRIORITY_LEVEL1 1 +#define RT_MQ_SCHED_PRIORITY_LEVEL2 2 +#define RT_MQ_SCHED_PRIORITY_LEVEL3 3 +#define RT_MQ_SCHED_PRIORITY_LEVEL4 4 +#define RT_MQ_SCHED_PRIORITY_LEVEL5 5 +#define RT_MQ_SCHED_PRIORITY_LEVEL6 6 +#define RT_MQ_SCHED_PRIORITY_LEVEL7 7 + +/* Events can be released between different systems. This parameter specifies the destination type of events + to be released. The destination type is defined based on the CPU type of the destination system. */ +#define RT_MQ_DST_ENGINE_ACPU_DEVICE 0 // device AICPU, same as driver's +#define RT_MQ_DST_ENGINE_ACPU_HOST 1 // Host AICPU +#define RT_MQ_DST_ENGINE_CCPU_DEVICE 2 // device CtrlCPU +#define RT_MQ_DST_ENGINE_CCPU_HOST 3 // Host CtrlCPU +#define RT_MQ_DST_ENGINE_DCPU_DEVICE 4 // device DataCPU +#define RT_MQ_DST_ENGINE_TS_CPU 5 // device TS CPU +#define RT_MQ_DST_ENGINE_DVPP_CPU 6 // device DVPP CPU + +#define RT_MQ_SCHED_EVENT_QS_MSG 25 // same as driver's EVENT_QS_MSG + +/* When the destination engine is AICPU, select a policy. + ONLY: The command is executed only on the local AICPU. + FIRST: The local AICPU is preferentially executed. If the local AICPU is busy, the remote AICPU can be used. */ +#define RT_SCHEDULE_POLICY_ONLY 0 // same as driver's schedule_policy +#define RT_SCHEDULE_POLICY_FIRST 1 // same as driver's schedule_policy + + +typedef struct tagEschedEventSummary { + int32_t pid; // dst PID + uint32_t grpId; + int32_t eventId; // only RT_MQ_SCHED_EVENT_QS_MSG is supported + uint32_t subeventId; + uint32_t msgLen; + char_t *msg; + uint32_t dstEngine; // dst system cpu type + int32_t policy; // RT_SCHEDULE_POLICY_ONLY or RT_SCHEDULE_POLICY_FIRST +} rtEschedEventSummary_t; + +typedef struct tagEschedEventReply { + char_t *buf; + uint32_t bufLen; + uint32_t replyLen; // output, ack msg len, same with msgLen in halEschedAckEvent +} rtEschedEventReply_t; + +#define RT_DEV_PROCESS_CP1 0 +#define RT_DEV_PROCESS_CP2 1 +#define RT_DEV_PROCESS_DEV_ONLY 2 +#define RT_DEV_PROCESS_QS 3 +#define RT_DEV_PROCESS_SIGN_LENGTH 49 + +typedef struct tagBindHostpidInfo { + int32_t hostPid; + uint32_t vfid; + uint32_t chipId; + int32_t cpType; // type of custom-process, see RT_DEV_PROCESS_XXX +} rtBindHostpidInfo_t; + +#define RT_MEM_BUFF_MAX_CFG_NUM 64 + +typedef struct { + uint32_t cfgId; // cfg id, start from 0 + uint32_t totalSize; // one zone total size + uint32_t blkSize; // blk size, 2^n (0, 2M] + uint32_t maxBufSize; // max size can alloc from zone + uint32_t pageType; // page type, small page / huge page + int32_t elasticEnable; // elastic enable + int32_t elasticRate; + int32_t elasticRateMax; + int32_t elasticHighLevel; + int32_t elasticLowLevel; +} rtMemZoneCfg_t; + +typedef struct { + rtMemZoneCfg_t cfg[RT_MEM_BUFF_MAX_CFG_NUM]; +}rtMemBuffCfg_t; + +typedef enum rt_queue_work_mode { + RT_QUEUE_MODE_PUSH = 1, + RT_QUEUE_MODE_PULL, +} RT_QUEUE_WORK_MODE; + +typedef void *rtMbufPtr_t; + +typedef enum rtEventIdType { + RT_EVENT_RANDOM_KERNEL, /* Random operator event */ + RT_EVENT_DVPP_MSG, /* operator events commited by DVPP */ + RT_EVENT_FR_MSG, /* operator events commited by Feature retrieves */ + RT_EVENT_TS_HWTS_KERNEL, /* operator events commited by ts/hwts */ + RT_EVENT_AICPU_MSG, /* aicpu activates its own stream events */ + RT_EVENT_TS_CTRL_MSG, /* controls message events of TS */ + RT_EVENT_QUEUE_ENQUEUE, /* entry event of Queue(consumer) */ + RT_EVENT_QUEUE_FULL_TO_NOT_FULL, /* full to non-full events of Queue(producers) */ + RT_EVENT_QUEUE_EMPTY_TO_NOT_EMPTY, /* empty to non-empty event of Queue(consumer) */ + RT_EVENT_TDT_ENQUEUE, /* data entry event of TDT */ + RT_EVENT_TIMER, /* ros timer */ + RT_EVENT_HCFI_SCHED_MSG, /* scheduling events of HCFI */ + RT_EVENT_HCFI_EXEC_MSG, /* performs the event of HCFI */ + RT_EVENT_ROS_MSG_LEVEL0, + RT_EVENT_ROS_MSG_LEVEL1, + RT_EVENT_ROS_MSG_LEVEL2, + RT_EVENT_ACPU_MSG_TYPE0, + RT_EVENT_ACPU_MSG_TYPE1, + RT_EVENT_ACPU_MSG_TYPE2, + RT_EVENT_CCPU_CTRL_MSG, + RT_EVENT_SPLIT_KERNEL, + RT_EVENT_DVPP_MPI_MSG, + RT_EVENT_CDQ_MSG, + /* Add a new event here */ + RT_EVENT_TEST, /* Reserve for test */ + RT_EVENT_MAX_NUM +} rtEventIdType_t; + +typedef enum rtGroupType { + /* Bound to a AICPU, multiple threads can be woken up simultaneously within a group */ + RT_GRP_TYPE_BIND_DP_CPU = 1, + RT_GRP_TYPE_BIND_CP_CPU, /* Bind to the control CPU */ + RT_GRP_TYPE_BIND_DP_CPU_EXCLUSIVE /* Bound to a AICPU, intra-group threads are mutex awakened */ +} rtGroupType_t; + +/** + * @ingroup rt_mem_queue + * @brief init queue schedule + * @param [in] device the logical device id + * @param [in] grpName the name of group, can be nullptr + * @return RT_ERROR_NONE for ok + */ +RTS_API rtError_t rtMemQueueInitQS(int32_t device, const char* grpName); + +/** + * @ingroup rt_mem_queue + * @brief create mbuf queue + * @param [in] device the logical device id + * @param [in] rtMemQueueAttr attribute of queue + * @param [out] qid queue id + * @return RT_ERROR_NONE for ok + */ +RTS_API rtError_t rtMemQueueCreate(int32_t device, const rtMemQueueAttr_t *queueAttr, uint32_t *qid); + +/** + * @ingroup rt_mem_queue + * @brief destroy mbuf queue + * @param [in] device the logical device id + * @param [in] qid queue id + * @return RT_ERROR_NONE for ok + */ +RTS_API rtError_t rtMemQueueDestroy(int32_t device, uint32_t qid); + +/** + * @ingroup rt_mem_queue + * @brief destroy mbuf queue init + * @param [in] device the logical device id + * @return RT_ERROR_NONE for ok + */ +RTS_API rtError_t rtMemQueueInit(int32_t device); + +/** + * @ingroup rt_mem_queue + * @brief enqueu mbuf + * @param [in] device the logical device id + * @param [in] qid queue id + * @param [in] mbuf enqueue mbuf + * @return RT_ERROR_NONE for ok + */ +RTS_API rtError_t rtMemQueueEnQueue(int32_t device, uint32_t qid, void *mbuf); + + +/** + * @ingroup rt_mem_queue + * @brief enqueu mbuf + * @param [in] device the logical device id + * @param [in] qid queue id + * @param [out] mbuf dequeue mbuf + * @return RT_ERROR_NONE for ok + */ +RTS_API rtError_t rtMemQueueDeQueue(int32_t device, uint32_t qid, void **mbuf); + +/** + * @ingroup rt_mem_queue + * @brief enqueu peek + * @param [in] device the logical device id + * @param [in] qid queue id + * @param [out] bufLen length of mbuf in queue + * @param [in] timeout peek timeout (ms), -1: wait all the time until peeking success + * @return RT_ERROR_NONE for ok + */ +RTS_API rtError_t rtMemQueuePeek(int32_t device, uint32_t qid, size_t *bufLen, int32_t timeout); + +/** + * @ingroup rt_mem_queue + * @brief enqueu buff + * @param [in] device the logical device id + * @param [in] qid queue id + * @param [in] inBuf enqueue buff + * @param [in] timeout enqueue timeout (ms), -1: wait all the time until enqueue success + * @return RT_ERROR_NONE for ok + */ +RTS_API rtError_t rtMemQueueEnQueueBuff(int32_t device, uint32_t qid, rtMemQueueBuff_t *inBuf, int32_t timeout); + +/** + * @ingroup rt_mem_queue + * @brief enqueu buff + * @param [in] device the logical device id + * @param [in] qid queue id + * @param [out] outBuf dequeue buff + * @param [in] timeout dequeue timeout (ms), -1: wait all the time until dequeue success + * @return RT_ERROR_NONE for ok + */ +RTS_API rtError_t rtMemQueueDeQueueBuff(int32_t device, uint32_t qid, rtMemQueueBuff_t *outBuf, int32_t timeout); + +/** + * @ingroup rt_mem_queue + * @brief query current queue info + * @param [in] device the logical device id + * @param [in] qid queue id + * @param [out] queueInfo current queue info + * @return RT_ERROR_NONE for ok + */ +RTS_API rtError_t rtMemQueueQueryInfo(int32_t device, uint32_t qid, rtMemQueueInfo_t *queueInfo); + +/** +* @ingroup rt_mem_queue +* @brief query queue status +* @param [in] device: the logical device id +* @param [in] cmd: query cmd +* @param [in] inBuff: input buff +* @param [in] inLen: the length of input +* @param [in|out] outBuff: output buff +* @param [in|out] outLen: the length of output +* @return RT_ERROR_NONE for ok +*/ +RTS_API rtError_t rtMemQueueQuery(int32_t device, rtMemQueueQueryCmd_t cmd, const void *inBuff, uint32_t inLen, + void *outBuff, uint32_t *outLen); + +/** +* @ingroup rt_mem_queue +* @brief grant queue +* @param [in] device: logic devid +* @param [in] qid: queue id +* @param [in] pid: pid +* @param [in] attr: queue share attr +* @return RT_ERROR_NONE for ok +*/ +RTS_API rtError_t rtMemQueueGrant(int32_t device, uint32_t qid, int32_t pid, rtMemQueueShareAttr_t *attr); + +/** +* @ingroup rt_mem_queue +* @brief attach queue +* @param [in] device: logic devid +* @param [in] qid: queue id +* @param [in] timeOut: timeOut +* @return RT_ERROR_NONE for ok +*/ +RTS_API rtError_t rtMemQueueAttach(int32_t device, uint32_t qid, int32_t timeOut); + +/** +* @ingroup rt_mem_queue +* @brief Commit the event to a specific process +* @param [in] device: logic devid +* @param [in] event: event summary info +* @param [out] ack: event reply info +* @return RT_ERROR_NONE for ok +*/ +RTS_API rtError_t rtEschedSubmitEventSync(int32_t device, rtEschedEventSummary_t *event, + rtEschedEventReply_t *ack); + +/** +* @ingroup rt_mem_queue +* @brief query device proccess id +* @param [in] info: see struct rtBindHostpidInfo_t +* @param [out] devPid: device proccess id +* @return RT_ERROR_NONE for ok +*/ +RTS_API rtError_t rtQueryDevPid(rtBindHostpidInfo_t *info, int32_t *devPid); + +/** +* @ingroup rt_mem_queue +* @brief device buff init +* @param [in] cfg, init cfg +* @return RT_ERROR_NONE for ok +*/ +RTS_API rtError_t rtMbufInit(rtMemBuffCfg_t *cfg); + +/** +* @ingroup rt_mem_queue +* @brief alloc buff +* @param [out] buff: buff addr alloced +* @param [in] size: The amount of memory space requested +* @return RT_ERROR_NONE for ok +*/ +RTS_API rtError_t rtMbufAlloc(rtMbufPtr_t *mbuf, uint64_t size); + +/** +* @ingroup rt_mem_queue +* @brief free buff +* @param [in] buff: buff addr to be freed +* @return RT_ERROR_NONE for ok +*/ +RTS_API rtError_t rtMbufFree(rtMbufPtr_t mbuf); + +/** +* @ingroup rt_mem_queue +* @brief get Data addr of Mbuf +* @param [in] mbuf: Mbuf addr +* @param [out] buf: Mbuf data addr +* @return RT_ERROR_NONE for ok +*/ +RTS_API rtError_t rtMbufGetBuffAddr(rtMbufPtr_t mbuf, void **buf); + +/** +* @ingroup rt_mem_queue +* @brief get total Buffer size of Mbuf +* @param [in] mbuf: Mbuf addr +* @param [out] totalSize: total buffer size of Mbuf +* @return RT_ERROR_NONE for ok +*/ +RTS_API rtError_t rtMbufGetBuffSize(rtMbufPtr_t mbuf, uint64_t *totalSize); + +/** +* @ingroup rt_mem_queue +* @brief Get the address and length of its user_data from the specified Mbuf +* @param [in] mbuf: Mbuf addr +* @param [out] priv: address of its user_data +* @param [out] size: length of its user_data +* @return RT_ERROR_NONE for ok +*/ +RTS_API rtError_t rtMbufGetPrivInfo (rtMbufPtr_t mbuf, void **priv, uint64_t *size); + +// mem group +typedef struct { + uint64_t maxMemSize; // max buf size in grp, in KB. = 0 means no limit +} rtMemGrpConfig_t; + +typedef struct { + uint32_t admin : 1; // admin permission, can add other proc to grp + uint32_t read : 1; // read only permission + uint32_t write : 1; // read and write permission + uint32_t alloc : 1; // alloc permission (have read and write permission) + uint32_t rsv : 28; +} rtMemGrpShareAttr_t; + +#define RT_MEM_GRP_QUERY_GROUPS_OF_PROCESS 1 // query process all grp + +typedef struct { + int32_t pid; +} rtMemGrpQueryByProc_t; // cmd: GRP_QUERY_GROUPS_OF_PROCESS + +typedef union { + rtMemGrpQueryByProc_t grpQueryByProc; // cmd: GRP_QUERY_GROUPS_OF_PROCESS +} rtMemGrpQueryInput_t; + +#define RT_MEM_GRP_NAME_LEN 32 // it must be same as driver define BUFF_GRP_NAME_LEN + +typedef struct { + char_t groupName[RT_MEM_GRP_NAME_LEN]; // group name + rtMemGrpShareAttr_t attr; // process in group attribute +} rtMemGrpOfProc_t; // cmd: GRP_QUERY_GROUPS_OF_PROCESS + +typedef struct { + rtMemGrpOfProc_t *groupsOfProc; // cmd: GRP_QUERY_GROUPS_OF_PROCESS + size_t maxNum; // max number of result + size_t resultNum; // if the number of results exceeds 'maxNum', only 'maxNum' results are filled in buffer +} rtMemGrpQueryOutput_t; + +/** +* @ingroup rt_mem_queue +* @brief create mem group +* @attention null +* @param [in] name, group name +* @param [in] cfg, group cfg +* @return 0 for success, others for fail +*/ +RTS_API rtError_t rtMemGrpCreate(const char_t *name, const rtMemGrpConfig_t *cfg); + +/** +* @ingroup rt_mem_queue +* @brief add process to group +* @param [in] name, group name +* @param [in] pid, process id +* @param [in] attr, process permission in group +* @return 0 for success, others for fail +*/ +RTS_API rtError_t rtMemGrpAddProc(const char_t *name, int32_t pid, const rtMemGrpShareAttr_t *attr); + +/** +* @ingroup rt_mem_queue +* @brief attach proccess to check permission in group +* @param [in] name, group name +* @param [in] timeout, time out ms +* @return 0 for success, others for fail +*/ +RTS_API rtError_t rtMemGrpAttach(const char_t *name, int32_t timeout); + +/** +* @ingroup rt_mem_queue +* @brief buff group query +* @param [in] cmd, cmd type +* @param [in] input, query input +* @param [in|out] output, query output +* @return 0 for success, others for fail +*/ +RTS_API rtError_t rtMemGrpQuery(int32_t cmd, const rtMemGrpQueryInput_t *input, rtMemGrpQueryOutput_t *output); + +/** +* @ingroup rt_mem_queue +* @brief buff group query +* @param [in] device, cdevice id +* @param [in] name, group name +* @param [out] qid, queue id +* @return 0 for success, others for fail +*/ +RTS_API rtError_t rtMemQueueGetQidByName(int32_t device, const char *name, uint32_t *qId); + +/** +* @ingroup rt_mem_queue +* @brief esched attach device +* @param [in] device, device id +* @return 0 for success, others for fail +*/ +RTS_API rtError_t rtEschedAttachDevice(int32_t device); + +/** +* @ingroup rt_mem_queue +* @brief esched dettach device +* @param [in] device, device id +* @return 0 for success, others for fail +*/ +RTS_API rtError_t rtEschedDettachDevice(int32_t device); + +/** +* @ingroup rt_mem_queue +* @brief esched wait event +* @param [in] device, device id +* @param [in] grpId, group id +* @param [in] threadId, thread id +* @param [in] timeout +* @param [in] event +* @return 0 for success, others for fail +*/ +RTS_API rtError_t rtEschedWaitEvent(int32_t device, uint32_t grpId, uint32_t threadId, + int timeout, rtEschedEventSummary_t *event); + +/** +* @ingroup rt_mem_queue +* @brief esched create group +* @param [in] device, device id +* @param [in] grpId, group id +* @param [in] type, group type +* @return 0 for success, others for fail +*/ +RTS_API rtError_t rtEschedCreateGrp(int32_t device, uint32_t grpId, rtGroupType_t type); + +/** +* @ingroup rt_mem_queue +* @brief esched submit event +* @param [in] device, device id +* @param [in] event +* @return 0 for success, others for fail +*/ +RTS_API rtError_t rtEschedSubmitEvent(int32_t device, rtEschedEventSummary_t *event); + +/** +* @ingroup rt_mem_queue +* @brief esched submit event +* @param [in] device, device id +* @param [in] grpId, group id +* @param [in] threadId, thread id +* @param [in] eventBitmap +* @return 0 for success, others for fail +*/ +RTS_API rtError_t rtEschedSubscribeEvent(int32_t device, uint32_t grpId, uint32_t threadId, uint64_t eventBitmap); + +/** +* @ingroup rtEschedAckEvent +* @brief esched ack event +* @param [in] device, device id +* @param [in] eventId, event type +* @param [in] subeventId, sub event type +* @param [in] msg, message info +* @param [in] len, message length +* @return 0 for success, others for fail +*/ +RTS_API rtError_t rtEschedAckEvent(int32_t device, rtEventIdType_t eventId, + uint32_t subeventId, char *msg, uint32_t len); + +/** +* @ingroup rtQueueSubF2NFEvent +* @brief full to not full event +* @param [in] device, device id +* @param [in] qid, queue id +* @param [in] groupId, group id +* @return 0 for success, others for fail +*/ +RTS_API rtError_t rtQueueSubF2NFEvent(int32_t device, uint32_t qId, uint32_t groupId); + +/** +* @ingroup rtQueueSubscribe +* @brief queue subscribe +* @param [in] device, device id +* @param [in] qid, queue id +* @param [in] groupId, group id +* @param [in] type + +* @return 0 for success, others for fail +*/ +RTS_API rtError_t rtQueueSubscribe(int32_t device, uint32_t qId, uint32_t groupId, int type); + +#if defined(__cplusplus) +} +#endif +#endif // CCE_RUNTIME_RT_MEM_QUEUE_H From 3177d9efab4fd7ae0c7514a182e2c6ba8c1cde69 Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Wed, 24 Nov 2021 09:33:26 +0800 Subject: [PATCH 43/59] add missing headers --- .../inc/toolchain/adx_datadump_callback.h | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 third_party/fwkacllib/inc/toolchain/adx_datadump_callback.h diff --git a/third_party/fwkacllib/inc/toolchain/adx_datadump_callback.h b/third_party/fwkacllib/inc/toolchain/adx_datadump_callback.h new file mode 100644 index 00000000..36c51a90 --- /dev/null +++ b/third_party/fwkacllib/inc/toolchain/adx_datadump_callback.h @@ -0,0 +1,35 @@ +/** + * Copyright 2019-2021 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. + */ + +#ifndef ADX_DATADUMP_CALLBACK_H +#define ADX_DATADUMP_CALLBACK_H +#include +namespace Adx { + const uint32_t MAX_FILE_PATH_LENGTH = 4096; + struct DumpChunk { + char fileName[MAX_FILE_PATH_LENGTH]; + uint32_t bufLen; + uint32_t isLastChunk; + int64_t offset; + int32_t flag; + uint8_t dataBuf[0]; + }; + + int AdxRegDumpProcessCallBack(int (* const messageCallback) (const Adx::DumpChunk *, int)); + void AdxUnRegDumpProcessCallBack(); +} + +#endif ADX_DATADUMP_CALLBACK_H \ No newline at end of file From d5f1f797a3cc2075e11df152e703a679a8b09207 Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Wed, 24 Nov 2021 11:02:51 +0800 Subject: [PATCH 44/59] fix endif --- third_party/fwkacllib/inc/toolchain/adx_datadump_callback.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/fwkacllib/inc/toolchain/adx_datadump_callback.h b/third_party/fwkacllib/inc/toolchain/adx_datadump_callback.h index 36c51a90..e2391f72 100644 --- a/third_party/fwkacllib/inc/toolchain/adx_datadump_callback.h +++ b/third_party/fwkacllib/inc/toolchain/adx_datadump_callback.h @@ -32,4 +32,4 @@ namespace Adx { void AdxUnRegDumpProcessCallBack(); } -#endif ADX_DATADUMP_CALLBACK_H \ No newline at end of file +#endif // ADX_DATADUMP_CALLBACK_H \ No newline at end of file From c1b7f6ecdefd44a20b8e27fa1442c51087a0135a Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Thu, 2 Dec 2021 11:38:12 +0800 Subject: [PATCH 45/59] upgrade Ascend package 2 Dec 21 --- inc/external/acl/acl_base.h | 9 +- inc/external/acl/acl_tdt_queue.h | 46 +- inc/external/acl/ops/acl_dvpp.h | 18 +- inc/external/ge/ge_api.h | 16 +- inc/external/ge/ge_api_error_codes.h | 31 +- inc/external/ge/ge_api_types.h | 5 +- inc/external/ge/ge_error_codes.h | 65 +- inc/external/ge/ge_ir_build.h | 13 +- inc/framework/common/debug/ge_log.h | 16 +- inc/framework/common/debug/log.h | 82 +- inc/framework/common/file_constant_util.h | 60 + inc/framework/common/fmk_error_codes.h | 18 +- inc/framework/common/ge_format_util.h | 2 +- inc/framework/common/ge_inner_error_codes.h | 5 +- inc/framework/common/ge_types.h | 45 +- inc/framework/common/helper/model_helper.h | 61 +- inc/framework/common/op/attr_value_util.h | 10 +- inc/framework/common/op/ge_op_utils.h | 18 +- inc/framework/common/op/op_parser_util.h | 42 +- inc/framework/common/string_util.h | 9 +- inc/framework/common/taskdown_common.h | 2 +- inc/framework/common/types.h | 3 + inc/framework/common/util.h | 10 +- inc/framework/generator/ge_generator.h | 12 +- inc/framework/omg/parser/model_parser.h | 24 +- inc/framework/omg/parser/op_parser.h | 8 +- inc/framework/omg/parser/parser_api.h | 1 - inc/framework/omg/parser/parser_factory.h | 4 +- inc/framework/omg/parser/parser_inner_ctx.h | 1 - inc/framework/omg/parser/weights_parser.h | 3 +- metadef | 2 +- third_party/fwkacllib/inc/cce/aicpu_engine.h | 63 - .../fwkacllib/inc/cce/aicpu_engine_struct.h | 56 - third_party/fwkacllib/inc/cce/blas_struct.h | 31 - third_party/fwkacllib/inc/cce/cce.h | 101 - third_party/fwkacllib/inc/cce/cce_def.hpp | 152 - .../fwkacllib/inc/cce/common/attr_list.hpp | 82 - .../fwkacllib/inc/cce/common/catch.hpp | 95 - third_party/fwkacllib/inc/cce/compiler_stub.h | 36 - third_party/fwkacllib/inc/cce/customize.h | 60 - third_party/fwkacllib/inc/cce/dnn.h | 23 - third_party/fwkacllib/inc/cce/dnn_base.h | 676 --- .../fwkacllib/inc/cce/dnn_base_def.hpp | 994 ---- third_party/fwkacllib/inc/cce/dnn_op.h | 4838 ----------------- third_party/fwkacllib/inc/cce/dnn_struct.hpp | 23 - .../fwkacllib/inc/cce/dnn_struct_base.hpp | 894 --- .../fwkacllib/inc/cce/fwk_adpt_struct.h | 155 - .../fwkacllib/inc/cce/l2fusion_struct.hpp | 56 - .../inc/cce/optimizer/fusion_engine.h | 65 - third_party/fwkacllib/inc/cce/taskdown_api.h | 54 - .../fwkacllib/inc/cce/taskdown_common.hpp | 108 - third_party/fwkacllib/inc/ops/aipp.h | 2 +- third_party/fwkacllib/inc/ops/all_ops.h | 3 +- third_party/fwkacllib/inc/ops/array_ops.h | 21 +- third_party/fwkacllib/inc/ops/audio_ops.h | 2 +- .../fwkacllib/inc/ops/avg_pool_1d_ops.h | 2 +- third_party/fwkacllib/inc/ops/batch_ops.h | 2 +- third_party/fwkacllib/inc/ops/bitwise_ops.h | 2 +- .../fwkacllib/inc/ops/boosted_trees_ops.h | 2 +- .../inc/ops/candidate_sampling_ops.h | 2 +- .../fwkacllib/inc/ops/case_condition_ops.h | 2 +- third_party/fwkacllib/inc/ops/cluster.h | 2 +- third_party/fwkacllib/inc/ops/condtake_ops.h | 2 +- .../fwkacllib/inc/ops/control_flow_ops.h | 2 +- .../inc/ops/coordinates_1d_to_2d_ops.h | 2 +- third_party/fwkacllib/inc/ops/correlation.h | 2 +- third_party/fwkacllib/inc/ops/ctc_ops.h | 2 +- third_party/fwkacllib/inc/ops/data_flow_ops.h | 21 +- third_party/fwkacllib/inc/ops/deep_md.h | 59 + .../inc/ops/elewise_calculation_ops.h | 2 +- .../fwkacllib/inc/ops/functional_ops.h | 2 +- third_party/fwkacllib/inc/ops/get_data_ops.h | 2 +- third_party/fwkacllib/inc/ops/hcom_ops.h | 2 +- third_party/fwkacllib/inc/ops/hvd_ops.h | 2 +- third_party/fwkacllib/inc/ops/image_ops.h | 84 +- .../fwkacllib/inc/ops/index_to_addr_ops.h | 2 +- third_party/fwkacllib/inc/ops/internal_ops.h | 2 +- third_party/fwkacllib/inc/ops/linalg_ops.h | 2 +- third_party/fwkacllib/inc/ops/list_ops.h | 2 +- third_party/fwkacllib/inc/ops/logging_ops.h | 2 +- third_party/fwkacllib/inc/ops/lookup_ops.h | 2 +- third_party/fwkacllib/inc/ops/math_ops.h | 4 +- .../inc/ops/matrix_calculation_ops.h | 2 +- .../fwkacllib/inc/ops/nn_batch_norm_ops.h | 10 +- .../fwkacllib/inc/ops/nn_calculation_ops.h | 6 +- third_party/fwkacllib/inc/ops/nn_detect_ops.h | 31 +- third_party/fwkacllib/inc/ops/nn_norm_ops.h | 2 +- third_party/fwkacllib/inc/ops/nn_ops.h | 2 +- .../fwkacllib/inc/ops/nn_pooling_ops.h | 2 +- .../fwkacllib/inc/ops/nn_training_ops.h | 2 +- third_party/fwkacllib/inc/ops/no_op.h | 2 +- .../fwkacllib/inc/ops/nonlinear_fuc_ops.h | 30 +- .../fwkacllib/inc/ops/npu_loss_scale_ops.h | 2 +- third_party/fwkacllib/inc/ops/ocr_ops.h | 2 +- third_party/fwkacllib/inc/ops/outfeed_ops.h | 2 +- third_party/fwkacllib/inc/ops/pad_ops.h | 2 +- third_party/fwkacllib/inc/ops/parsing_ops.h | 2 +- third_party/fwkacllib/inc/ops/quantize_ops.h | 2 +- .../fwkacllib/inc/ops/ragged_array_ops.h | 2 +- .../fwkacllib/inc/ops/ragged_conversion_ops.h | 2 +- .../fwkacllib/inc/ops/ragged_math_ops.h | 2 +- third_party/fwkacllib/inc/ops/random_ops.h | 2 +- third_party/fwkacllib/inc/ops/reduce_ops.h | 2 +- .../fwkacllib/inc/ops/resource_variable_ops.h | 2 +- third_party/fwkacllib/inc/ops/rnn.h | 2 +- third_party/fwkacllib/inc/ops/rpn_ops.h | 2 +- third_party/fwkacllib/inc/ops/save_ops.h | 2 +- third_party/fwkacllib/inc/ops/sdca_ops.h | 2 +- third_party/fwkacllib/inc/ops/selection_ops.h | 2 +- third_party/fwkacllib/inc/ops/set_ops.h | 2 +- .../fwkacllib/inc/ops/slice_write_ops.h | 2 +- third_party/fwkacllib/inc/ops/sparse_ops.h | 2 +- third_party/fwkacllib/inc/ops/spectral_ops.h | 2 +- .../fwkacllib/inc/ops/split_combination_ops.h | 2 +- third_party/fwkacllib/inc/ops/state_ops.h | 2 +- .../fwkacllib/inc/ops/stateful_random_ops.h | 2 +- .../fwkacllib/inc/ops/stateless_random_ops.h | 2 +- third_party/fwkacllib/inc/ops/string_ops.h | 2 +- third_party/fwkacllib/inc/ops/swap_co_ops.h | 2 +- .../inc/ops/target_crop_and_resize.h | 2 +- .../fwkacllib/inc/ops/transformation_ops.h | 2 +- third_party/fwkacllib/inc/ops/vector_search.h | 2 +- .../fwkacllib/inc/ops/warp_perspective_ops.h | 2 +- .../inc/register/op_kernel_registry.h | 46 - .../fwkacllib/inc/register/op_registry.h | 97 - third_party/fwkacllib/inc/runtime/base.h | 96 +- third_party/fwkacllib/inc/runtime/config.h | 26 +- third_party/fwkacllib/inc/runtime/context.h | 68 +- third_party/fwkacllib/inc/runtime/dev.h | 79 +- .../fwkacllib/inc/runtime/dvfsprofile.h | 20 +- third_party/fwkacllib/inc/runtime/event.h | 76 +- third_party/fwkacllib/inc/runtime/kernel.h | 126 +- third_party/fwkacllib/inc/runtime/mem.h | 104 +- third_party/fwkacllib/inc/runtime/rt.h | 18 +- third_party/fwkacllib/inc/runtime/rt_dfx.h | 17 +- third_party/fwkacllib/inc/runtime/rt_ffts.h | 30 +- .../fwkacllib/inc/runtime/rt_ffts_plus.h | 23 +- .../inc/runtime/rt_ffts_plus_define.h | 21 +- .../fwkacllib/inc/runtime/rt_mem_queue.h | 124 +- third_party/fwkacllib/inc/runtime/rt_model.h | 90 +- third_party/fwkacllib/inc/runtime/rt_stars.h | 29 +- .../fwkacllib/inc/runtime/rt_stars_define.h | 21 +- third_party/fwkacllib/inc/runtime/stream.h | 80 +- .../fwkacllib/inc/soft_dp/ExternalSoftDp.h | 58 - .../inc/toolchain/adx_datadump_callback.h | 18 +- .../fwkacllib/inc/toolchain/prof_acl_api.h | 100 +- .../fwkacllib/inc/toolchain/prof_callback.h | 2 +- .../inc/toolchain/tuning_tool/tune_api.h | 94 - 148 files changed, 1181 insertions(+), 9878 deletions(-) create mode 100644 inc/framework/common/file_constant_util.h delete mode 100644 third_party/fwkacllib/inc/cce/aicpu_engine.h delete mode 100644 third_party/fwkacllib/inc/cce/aicpu_engine_struct.h delete mode 100644 third_party/fwkacllib/inc/cce/blas_struct.h delete mode 100644 third_party/fwkacllib/inc/cce/cce.h delete mode 100644 third_party/fwkacllib/inc/cce/cce_def.hpp delete mode 100644 third_party/fwkacllib/inc/cce/common/attr_list.hpp delete mode 100644 third_party/fwkacllib/inc/cce/common/catch.hpp delete mode 100644 third_party/fwkacllib/inc/cce/compiler_stub.h delete mode 100644 third_party/fwkacllib/inc/cce/customize.h delete mode 100644 third_party/fwkacllib/inc/cce/dnn.h delete mode 100644 third_party/fwkacllib/inc/cce/dnn_base.h delete mode 100644 third_party/fwkacllib/inc/cce/dnn_base_def.hpp delete mode 100644 third_party/fwkacllib/inc/cce/dnn_op.h delete mode 100644 third_party/fwkacllib/inc/cce/dnn_struct.hpp delete mode 100644 third_party/fwkacllib/inc/cce/dnn_struct_base.hpp delete mode 100644 third_party/fwkacllib/inc/cce/fwk_adpt_struct.h delete mode 100644 third_party/fwkacllib/inc/cce/l2fusion_struct.hpp delete mode 100644 third_party/fwkacllib/inc/cce/optimizer/fusion_engine.h delete mode 100644 third_party/fwkacllib/inc/cce/taskdown_api.h delete mode 100644 third_party/fwkacllib/inc/cce/taskdown_common.hpp create mode 100644 third_party/fwkacllib/inc/ops/deep_md.h delete mode 100644 third_party/fwkacllib/inc/register/op_kernel_registry.h delete mode 100644 third_party/fwkacllib/inc/register/op_registry.h delete mode 100644 third_party/fwkacllib/inc/soft_dp/ExternalSoftDp.h delete mode 100644 third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h diff --git a/inc/external/acl/acl_base.h b/inc/external/acl/acl_base.h index 90da8b8f..1f81b15a 100644 --- a/inc/external/acl/acl_base.h +++ b/inc/external/acl/acl_base.h @@ -113,6 +113,7 @@ static const int ACL_ERROR_PROF_API_CONFLICT = 148047; static const int ACL_ERROR_INVALID_MAX_OPQUEUE_NUM_CONFIG = 148048; static const int ACL_ERROR_INVALID_OPP_PATH = 148049; static const int ACL_ERROR_OP_UNSUPPORTED_DYNAMIC = 148050; +static const int ACL_ERROR_RELATIVE_RESOURCE_NOT_CLEARED = 148051; static const int ACL_ERROR_BAD_ALLOC = 200000; static const int ACL_ERROR_API_NOT_SUPPORT = 200001; @@ -176,10 +177,7 @@ typedef enum { ACL_ERROR = 3, } aclLogLevel; -typedef enum { - ACL_MEMTYPE_DEVICE = 0, - ACL_MEMTYPE_HOST = 1, -} aclMemType; +typedef enum { ACL_MEMTYPE_DEVICE = 0, ACL_MEMTYPE_HOST = 1, ACL_MEMTYPE_HOST_COMPILE_INDEPENDENT = 2 } aclMemType; /** * @ingroup AscendCL @@ -601,7 +599,8 @@ ACL_FUNC_VISIBILITY aclError aclSetTensorConst(aclTensorDesc *desc, void *dataBu * @brief Set tensor memory type specified by the tensor description * * @param desc [OUT] pointer to the instance of aclTensorDesc - * @param memType [IN] ACL_MEMTYPE_DEVICE means device, ACL_MEMTYPE_HOST means host + * @param memType [IN] ACL_MEMTYPE_DEVICE means device, ACL_MEMTYPE_HOST or + * ACL_MEMTYPE_HOST_COMPILE_INDEPENDENT means host * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure diff --git a/inc/external/acl/acl_tdt_queue.h b/inc/external/acl/acl_tdt_queue.h index 95cfdb8c..01f0eebf 100644 --- a/inc/external/acl/acl_tdt_queue.h +++ b/inc/external/acl/acl_tdt_queue.h @@ -86,7 +86,7 @@ ACL_FUNC_VISIBILITY aclError acltdtDestroyQueue(uint32_t qid); * * @param qid [IN] qid * @param buf [IN] acltdtBuf - * @param timeout [IN] timeout + * @param timeout [IN] timeout, -1 means blocking * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure @@ -101,7 +101,7 @@ ACL_FUNC_VISIBILITY aclError acltdtEnqueue(uint32_t qid, acltdtBuf buf, int32_t * * @param qid [IN] qid * @param buf [OUT] pointer to the acltdtBuf - * @param timeout [IN] timeout + * @param timeout [IN] timeout, -1 means blocking * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure @@ -110,6 +110,44 @@ ACL_FUNC_VISIBILITY aclError acltdtEnqueue(uint32_t qid, acltdtBuf buf, int32_t */ ACL_FUNC_VISIBILITY aclError acltdtDequeue(uint32_t qid, acltdtBuf *buf, int32_t timeout); +/** + * @ingroup AscendCL + * @brief enqueue function + * + * @param qid [IN] qid + * @param data [IN] the pointer to data buf + * @param dataSize [IN] the size of data buf + * @param userData [IN] the pointer to user data buf + * @param userDataSize [IN] the size of user data buf + * @param timeout [IN] timeout, -1 means blocking + * @param rsv [IN] reserved param + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtDequeueData + */ +ACL_FUNC_VISIBILITY aclError acltdtEnqueueData(uint32_t qid, const void *data, size_t dataSize, const void *userData, + size_t userDataSize, int32_t timeout, uint32_t rsv); + +/** + * @ingroup AscendCL + * @brief dequeue function + * + * @param qid [IN] qid + * @param data [IN|OUT] the pointer to data buf + * @param dataSize [IN] the size of data buf + * @param retDataSize [OUT] the return size of data buf + * @param userData [IN|OUT] the pointer to user data buf + * @param userDataSize [IN] the size of user data buf + * @param timeout [IN] timeout, -1 means blocking + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see acltdtEnqueueData + */ +ACL_FUNC_VISIBILITY aclError acltdtDequeueData(uint32_t qid, void *data, size_t dataSize, size_t *retDataSize, + void *userData, size_t userDataSize, int32_t timeout); + /** * @ingroup AscendCL * @brief grant queue to other process @@ -117,7 +155,7 @@ ACL_FUNC_VISIBILITY aclError acltdtDequeue(uint32_t qid, acltdtBuf *buf, int32_t * @param qid [IN] qid * @param pid [IN] pid of dst process * @param permission [IN] permission of queue - * @param timeout [IN] timeout + * @param timeout [IN] timeout, -1 means blocking * * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure @@ -131,7 +169,7 @@ ACL_FUNC_VISIBILITY aclError acltdtGrantQueue(uint32_t qid, int32_t pid, uint32_ * @brief attach queue in current process * * @param qid [IN] qid - * @param timeout [IN] timeout + * @param timeout [IN] timeout, -1 means blocking * @param permission [OUT] permission of queue * * @retval ACL_SUCCESS The function is successfully executed. diff --git a/inc/external/acl/ops/acl_dvpp.h b/inc/external/acl/ops/acl_dvpp.h index a536a23b..b839ae48 100644 --- a/inc/external/acl/ops/acl_dvpp.h +++ b/inc/external/acl/ops/acl_dvpp.h @@ -158,9 +158,21 @@ enum acldvppJpegFormat { ACL_JPEG_CSS_UNKNOWN = 1000 }; -enum acldvppChannelDescParamType { ACL_DVPP_CSC_MATRIX_UINT32 = 0 }; - -enum aclvdecChannelDescParamType { ACL_VDEC_CSC_MATRIX_UINT32 = 0 }; +enum acldvppChannelDescParamType { ACL_DVPP_CSC_MATRIX_UINT32 = 0, ACL_DVPP_MODE_UINT32, ACL_DVPP_CHANNEL_ID_UINT64 }; + +enum aclvdecChannelDescParamType { + ACL_VDEC_CSC_MATRIX_UINT32 = 0, + ACL_VDEC_OUT_MODE_UINT32, + ACL_VDEC_THREAD_ID_UINT64, + ACL_VDEC_CALLBACK_PTR, + ACL_VDEC_CHANNEL_ID_UINT32, + ACL_VDEC_ENCODE_TYPE_UINT32, + ACL_VDEC_OUT_PIC_FORMAT_UINT32, + ACL_VDEC_OUT_PIC_WIDTH_UINT32, + ACL_VDEC_OUT_PIC_HEIGHT_UINT32, + ACL_VDEC_REF_FRAME_NUM_UINT32, + ACL_VDEC_BIT_DEPTH_UINT32 +}; // Csc Matrix can be used both for acldvppChannelDescParamType and aclvdecChannelDescParamType enum acldvppCscMatrix { diff --git a/inc/external/ge/ge_api.h b/inc/external/ge/ge_api.h index c2cbe794..1e80ac4e 100644 --- a/inc/external/ge/ge_api.h +++ b/inc/external/ge/ge_api.h @@ -57,15 +57,15 @@ class GE_FUNC_VISIBILITY Session { /// /// @ingroup client - /// @brief add a graph with a specific graphId - /// @param [in] graphId graph id + /// @brief add a graph with a specific graph id + /// @param [in] graph_id graph id /// @return Status result of function /// - Status AddGraph(uint32_t graphId, const Graph &graph); + Status AddGraph(uint32_t graph_id, const Graph &graph); /// /// @ingroup client - /// @brief add a graph with a specific graphId and graphOptions + /// @brief add a graph with a specific graph id and graphOptions /// @param [in] graphId graph id /// @param [in] graph the graph /// @param [in] options graph options @@ -106,10 +106,10 @@ class GE_FUNC_VISIBILITY Session { /// /// @ingroup ge_graph /// @brief remove a graph of the session with specific session id - /// @param [in] graphId graph id + /// @param [in] graph_d graph id /// @return Status result of function /// - Status RemoveGraph(uint32_t graphId); + Status RemoveGraph(uint32_t graph_id); /// /// @ingroup ge_graph @@ -142,7 +142,7 @@ class GE_FUNC_VISIBILITY Session { /// Status BuildGraph(uint32_t graphId, const std::vector &inputs); - Status BuildGraph(uint32_t graphId, const std::vector &inputs); /*lint !e148*/ + Status BuildGraph(uint32_t graphId, const std::vector &inputs); /*lint !e148*/ /// /// @ingroup ge_graph @@ -189,7 +189,7 @@ class GE_FUNC_VISIBILITY Session { Status RegisterCallBackFunc(const char *key, const session::pCallBackFunc &callback); - bool IsGraphNeedRebuild(uint32_t graphId); + bool IsGraphNeedRebuild(uint32_t graph_id); private: uint64_t sessionId_; diff --git a/inc/external/ge/ge_api_error_codes.h b/inc/external/ge/ge_api_error_codes.h index 2512de0a..5d2d6963 100644 --- a/inc/external/ge/ge_api_error_codes.h +++ b/inc/external/ge/ge_api_error_codes.h @@ -20,6 +20,7 @@ #include #include #include "ge_error_codes.h" +#include "graph/types.h" namespace ge { #ifdef __GNUC__ @@ -35,7 +36,7 @@ class GE_FUNC_VISIBILITY StatusFactory { return &instance; } - void RegisterErrorNo(uint32_t err, const std::string &desc) { + void RegisterErrorNo(const uint32_t err, const std::string &desc) { // Avoid repeated addition if (err_desc_.find(err) != err_desc_.end()) { return; @@ -43,19 +44,19 @@ class GE_FUNC_VISIBILITY StatusFactory { err_desc_[err] = desc; } - void RegisterErrorNo(uint32_t err, const char *desc) { + void RegisterErrorNo(const uint32_t err, const char *const desc) { if (desc == nullptr) { return; } - std::string error_desc = desc; + const std::string error_desc = desc; if (err_desc_.find(err) != err_desc_.end()) { return; } err_desc_[err] = error_desc; } - std::string GetErrDesc(uint32_t err) { - auto iter_find = err_desc_.find(err); + std::string GetErrDesc(const uint32_t err) { + const auto iter_find = err_desc_.find(err); if (iter_find == err_desc_.end()) { return ""; } @@ -72,23 +73,23 @@ class GE_FUNC_VISIBILITY StatusFactory { class GE_FUNC_VISIBILITY ErrorNoRegisterar { public: - ErrorNoRegisterar(uint32_t err, const std::string &desc) { + ErrorNoRegisterar(const uint32_t err, const std::string &desc) noexcept { StatusFactory::Instance()->RegisterErrorNo(err, desc); } - ErrorNoRegisterar(uint32_t err, const char *desc) { + ErrorNoRegisterar(const uint32_t err, const char *const desc) noexcept { StatusFactory::Instance()->RegisterErrorNo(err, desc); } ~ErrorNoRegisterar() {} }; // Code compose(4 byte), runtime: 2 bit, type: 2 bit, level: 3 bit, sysid: 8 bit, modid: 5 bit, value: 12 bit -#define GE_ERRORNO(runtime, type, level, sysid, modid, name, value, desc) \ - constexpr ge::Status name = (static_cast(0xFFU & (static_cast(runtime))) << 30) | \ - (static_cast(0xFFU & (static_cast(type))) << 28) | \ - (static_cast(0xFFU & (static_cast(level))) << 25) | \ - (static_cast(0xFFU & (static_cast(sysid))) << 17) | \ - (static_cast(0xFFU & (static_cast(modid))) << 12) | \ - (static_cast(0x0FFFU) & (static_cast(value))); \ +#define GE_ERRORNO(runtime, type, level, sysid, modid, name, value, desc) \ + constexpr ge::Status name = (static_cast(0xFFU & (static_cast(runtime))) << 30U) | \ + (static_cast(0xFFU & (static_cast(type))) << 28U) | \ + (static_cast(0xFFU & (static_cast(level))) << 25U) | \ + (static_cast(0xFFU & (static_cast(sysid))) << 17U) | \ + (static_cast(0xFFU & (static_cast(modid))) << 12U) | \ + (static_cast(0x0FFFU) & (static_cast(value))); \ const ErrorNoRegisterar g_##name##_errorno(name, desc); #define GE_ERRORNO_EXTERNAL(name, desc) const ErrorNoRegisterar g_##name##_errorno(name, desc); @@ -97,7 +98,7 @@ using Status = uint32_t; // General error code GE_ERRORNO(0, 0, 0, 0, 0, SUCCESS, 0, "success"); -GE_ERRORNO(0b11, 0b11, 0b111, 0xFF, 0b11111, FAILED, 0xFFF, "failed"); /*lint !e401*/ +GE_ERRORNO(0b11, 0b11, 0b111, 0xFFU, 0b11111, FAILED, 0xFFFU, "failed"); /*lint !e401*/ GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_PARAM_INVALID, "Parameter invalid."); GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_EXEC_NOT_INIT, "GE executor not initialized yet."); diff --git a/inc/external/ge/ge_api_types.h b/inc/external/ge/ge_api_types.h index d2d5bf5d..52881020 100644 --- a/inc/external/ge/ge_api_types.h +++ b/inc/external/ge/ge_api_types.h @@ -24,6 +24,7 @@ #include #include #include "graph/tensor.h" +#include "graph/types.h" namespace ge { // Option key: graph run mode @@ -337,6 +338,8 @@ const std::string MODIFY_MIXLIST = "ge.exec.modify_mixlist"; const std::string OP_PRECISION_MODE = "ge.exec.op_precision_mode"; +const char *const FILE_CONSTANT_PATH = "ge.exec.value_bins"; + // Graph run mode enum GraphRunMode { PREDICTION = 0, TRAIN }; @@ -353,7 +356,7 @@ struct OutputTensorInfo { std::vector dims; // shape description std::unique_ptr data; // tensor data int64_t length; // tensor length - OutputTensorInfo() : data_type(0), dims({}), data(nullptr), length(0) {} + OutputTensorInfo() : data_type(0U), dims({}), data(nullptr), length(0) {} OutputTensorInfo(OutputTensorInfo &&out) : data_type(out.data_type), dims(out.dims), data(std::move(out.data)), length(out.length) {} diff --git a/inc/external/ge/ge_error_codes.h b/inc/external/ge/ge_error_codes.h index cafc5a64..027c83ea 100644 --- a/inc/external/ge/ge_error_codes.h +++ b/inc/external/ge/ge_error_codes.h @@ -32,42 +32,43 @@ #endif #include +#include #ifdef __cplusplus extern "C" { #endif -static const uint32_t ACL_ERROR_GE_PARAM_INVALID = 145000; -static const uint32_t ACL_ERROR_GE_EXEC_NOT_INIT = 145001; -static const uint32_t ACL_ERROR_GE_EXEC_MODEL_PATH_INVALID = 145002; -static const uint32_t ACL_ERROR_GE_EXEC_MODEL_ID_INVALID = 145003; -static const uint32_t ACL_ERROR_GE_EXEC_MODEL_DATA_SIZE_INVALID = 145006; -static const uint32_t ACL_ERROR_GE_EXEC_MODEL_ADDR_INVALID = 145007; -static const uint32_t ACL_ERROR_GE_EXEC_MODEL_QUEUE_ID_INVALID = 145008; -static const uint32_t ACL_ERROR_GE_EXEC_LOAD_MODEL_REPEATED = 145009; -static const uint32_t ACL_ERROR_GE_DYNAMIC_INPUT_ADDR_INVALID = 145011; -static const uint32_t ACL_ERROR_GE_DYNAMIC_INPUT_LENGTH_INVALID = 145012; -static const uint32_t ACL_ERROR_GE_DYNAMIC_BATCH_SIZE_INVALID = 145013; -static const uint32_t ACL_ERROR_GE_AIPP_BATCH_EMPTY = 145014; -static const uint32_t ACL_ERROR_GE_AIPP_NOT_EXIST = 145015; -static const uint32_t ACL_ERROR_GE_AIPP_MODE_INVALID = 145016; -static const uint32_t ACL_ERROR_GE_OP_TASK_TYPE_INVALID = 145017; -static const uint32_t ACL_ERROR_GE_OP_KERNEL_TYPE_INVALID = 145018; -static const uint32_t ACL_ERROR_GE_PLGMGR_PATH_INVALID = 145019; -static const uint32_t ACL_ERROR_GE_FORMAT_INVALID = 145020; -static const uint32_t ACL_ERROR_GE_SHAPE_INVALID = 145021; -static const uint32_t ACL_ERROR_GE_DATATYPE_INVALID = 145022; -static const uint32_t ACL_ERROR_GE_MEMORY_ALLOCATION = 245000; -static const uint32_t ACL_ERROR_GE_MEMORY_OPERATE_FAILED = 245001; -static const uint32_t ACL_ERROR_GE_INTERNAL_ERROR = 545000; -static const uint32_t ACL_ERROR_GE_LOAD_MODEL = 545001; -static const uint32_t ACL_ERROR_GE_EXEC_LOAD_MODEL_PARTITION_FAILED = 545002; -static const uint32_t ACL_ERROR_GE_EXEC_LOAD_WEIGHT_PARTITION_FAILED = 545003; -static const uint32_t ACL_ERROR_GE_EXEC_LOAD_TASK_PARTITION_FAILED = 545004; -static const uint32_t ACL_ERROR_GE_EXEC_LOAD_KERNEL_PARTITION_FAILED = 545005; -static const uint32_t ACL_ERROR_GE_EXEC_RELEASE_MODEL_DATA = 545006; -static const uint32_t ACL_ERROR_GE_COMMAND_HANDLE = 545007; -static const uint32_t ACL_ERROR_GE_GET_TENSOR_INFO = 545008; -static const uint32_t ACL_ERROR_GE_UNLOAD_MODEL = 545009; +static const uint32_t ACL_ERROR_GE_PARAM_INVALID = 145000U; +static const uint32_t ACL_ERROR_GE_EXEC_NOT_INIT = 145001U; +static const uint32_t ACL_ERROR_GE_EXEC_MODEL_PATH_INVALID = 145002U; +static const uint32_t ACL_ERROR_GE_EXEC_MODEL_ID_INVALID = 145003U; +static const uint32_t ACL_ERROR_GE_EXEC_MODEL_DATA_SIZE_INVALID = 145006U; +static const uint32_t ACL_ERROR_GE_EXEC_MODEL_ADDR_INVALID = 145007U; +static const uint32_t ACL_ERROR_GE_EXEC_MODEL_QUEUE_ID_INVALID = 145008U; +static const uint32_t ACL_ERROR_GE_EXEC_LOAD_MODEL_REPEATED = 145009U; +static const uint32_t ACL_ERROR_GE_DYNAMIC_INPUT_ADDR_INVALID = 145011U; +static const uint32_t ACL_ERROR_GE_DYNAMIC_INPUT_LENGTH_INVALID = 145012U; +static const uint32_t ACL_ERROR_GE_DYNAMIC_BATCH_SIZE_INVALID = 145013U; +static const uint32_t ACL_ERROR_GE_AIPP_BATCH_EMPTY = 145014U; +static const uint32_t ACL_ERROR_GE_AIPP_NOT_EXIST = 145015U; +static const uint32_t ACL_ERROR_GE_AIPP_MODE_INVALID = 145016U; +static const uint32_t ACL_ERROR_GE_OP_TASK_TYPE_INVALID = 145017U; +static const uint32_t ACL_ERROR_GE_OP_KERNEL_TYPE_INVALID = 145018U; +static const uint32_t ACL_ERROR_GE_PLGMGR_PATH_INVALID = 145019U; +static const uint32_t ACL_ERROR_GE_FORMAT_INVALID = 145020U; +static const uint32_t ACL_ERROR_GE_SHAPE_INVALID = 145021U; +static const uint32_t ACL_ERROR_GE_DATATYPE_INVALID = 145022U; +static const uint32_t ACL_ERROR_GE_MEMORY_ALLOCATION = 245000U; +static const uint32_t ACL_ERROR_GE_MEMORY_OPERATE_FAILED = 245001U; +static const uint32_t ACL_ERROR_GE_INTERNAL_ERROR = 545000U; +static const uint32_t ACL_ERROR_GE_LOAD_MODEL = 545001U; +static const uint32_t ACL_ERROR_GE_EXEC_LOAD_MODEL_PARTITION_FAILED = 545002U; +static const uint32_t ACL_ERROR_GE_EXEC_LOAD_WEIGHT_PARTITION_FAILED = 545003U; +static const uint32_t ACL_ERROR_GE_EXEC_LOAD_TASK_PARTITION_FAILED = 545004U; +static const uint32_t ACL_ERROR_GE_EXEC_LOAD_KERNEL_PARTITION_FAILED = 545005U; +static const uint32_t ACL_ERROR_GE_EXEC_RELEASE_MODEL_DATA = 545006U; +static const uint32_t ACL_ERROR_GE_COMMAND_HANDLE = 545007U; +static const uint32_t ACL_ERROR_GE_GET_TENSOR_INFO = 545008U; +static const uint32_t ACL_ERROR_GE_UNLOAD_MODEL = 545009U; #ifdef __cplusplus } // namespace ge diff --git a/inc/external/ge/ge_ir_build.h b/inc/external/ge/ge_ir_build.h index cf543315..84f31145 100644 --- a/inc/external/ge/ge_ir_build.h +++ b/inc/external/ge/ge_ir_build.h @@ -36,14 +36,10 @@ #include #include "graph/graph.h" #include "graph/ge_error_codes.h" - -namespace { -const int IR_MAJOR_VERSION = 1; -const int IR_MINOR_VERSION = 0; -const int IR_PATCH_VERSION = 0; -} // namespace - namespace ge { +const int32_t IR_MAJOR_VERSION = 1; +const int32_t IR_MINOR_VERSION = 0; +const int32_t IR_PATCH_VERSION = 0; struct ModelBufferData { std::shared_ptr data = nullptr; @@ -117,7 +113,8 @@ GE_FUNC_VISIBILITY graphStatus aclgrphSaveModel(const char *output_file, const M * @retval GRAPH_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -GE_FUNC_VISIBILITY graphStatus aclgrphGetIRVersion(int *major_version, int *minor_version, int *patch_version); +GE_FUNC_VISIBILITY graphStatus aclgrphGetIRVersion(int32_t *major_version, int32_t *minor_version, + int32_t *patch_version); /** * @ingroup AscendCL diff --git a/inc/framework/common/debug/ge_log.h b/inc/framework/common/debug/ge_log.h index dbd6f875..b1bf929f 100644 --- a/inc/framework/common/debug/ge_log.h +++ b/inc/framework/common/debug/ge_log.h @@ -40,17 +40,17 @@ enum TraceStatus { TRACE_INIT = 0, TRACE_RUNNING, TRACE_WAITING, TRACE_STOP }; class GE_FUNC_VISIBILITY GeLog { public: - static uint64_t GetTid() { + static const uint64_t GetTid() { #ifdef __GNUC__ - uint64_t tid = static_cast(syscall(__NR_gettid)); + const uint64_t tid = static_cast(syscall(__NR_gettid)); #else - uint64_t tid = static_cast(GetCurrentThreadId()); + const uint64_t tid = static_cast(GetCurrentThreadId()); #endif return tid; } }; -inline bool IsLogEnable(int module_name, int log_level) { +inline bool IsLogEnable(const int32_t module_name, const int32_t log_level) { const int32_t enable = CheckLogLevel(module_name, log_level); // 1:enable, 0:disable return (enable == 1); @@ -92,10 +92,10 @@ inline bool IsLogEnable(int module_name, int log_level) { #define GELOGT(VALUE, fmt, ...) \ do { \ TraceStatus stat = VALUE; \ - const char *const TraceStatStr[] = {"INIT", "RUNNING", "WAITING", "STOP"}; \ + const char_t *const TraceStatStr[] = {"INIT", "RUNNING", "WAITING", "STOP"}; \ const int32_t idx = static_cast(stat); \ - char *k = const_cast("status"); \ - char *v = const_cast(TraceStatStr[idx]); \ + char_t *k = const_cast("status"); \ + char_t *v = const_cast(TraceStatStr[idx]); \ KeyValue kv = {k, v}; \ DlogWithKV(GE_MODULE_NAME, DLOG_TRACE, &kv, 1, "%lu %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \ } while (false) @@ -110,7 +110,7 @@ inline bool IsLogEnable(int module_name, int log_level) { // print memory when it is greater than 1KB. #define GE_PRINT_DYNAMIC_MEMORY(FUNC, PURPOSE, SIZE) \ do { \ - if ((SIZE) > 1024) { \ + if (static_cast(SIZE) > 1024UL) { \ GELOGI("MallocMemory, func=%s, size=%zu, purpose=%s", (#FUNC), static_cast(SIZE), (PURPOSE)); \ } \ } while (false) diff --git a/inc/framework/common/debug/log.h b/inc/framework/common/debug/log.h index 3b11ce57..32e915eb 100644 --- a/inc/framework/common/debug/log.h +++ b/inc/framework/common/debug/log.h @@ -26,7 +26,7 @@ #include "external/ge/ge_api_error_codes.h" #if !defined(__ANDROID__) && !defined(ANDROID) -#define DOMI_LOGE(fmt, ...) GE_LOG_ERROR(GE_MODULE_NAME, ge::FAILED, fmt, ##__VA_ARGS__) +#define DOMI_LOGE(fmt, ...) GE_LOG_ERROR(GE_MODULE_NAME, (ge::FAILED), fmt, ##__VA_ARGS__) #else #include #if defined(BUILD_VERSION_PERF) @@ -49,9 +49,9 @@ GELOGW(__VA_ARGS__); \ } -#define GE_LOGE_IF(condition, ...) \ - if ((condition)) { \ - GELOGE(ge::FAILED, __VA_ARGS__); \ +#define GE_LOGE_IF(condition, ...) \ + if ((condition)) { \ + GELOGE((ge::FAILED), __VA_ARGS__); \ } // If expr is not SUCCESS, print the log and return the same value @@ -59,7 +59,7 @@ do { \ const ge::Status _chk_status = (expr); \ if (_chk_status != ge::SUCCESS) { \ - GELOGE(ge::FAILED, __VA_ARGS__); \ + GELOGE((ge::FAILED), __VA_ARGS__); \ return _chk_status; \ } \ } while (false) @@ -69,7 +69,7 @@ do { \ const ge::Status _chk_status = (expr); \ if (_chk_status != ge::SUCCESS) { \ - GELOGE(ge::FAILED, __VA_ARGS__); \ + GELOGE((ge::FAILED), __VA_ARGS__); \ } \ } while (false) @@ -88,7 +88,7 @@ if ((expr) != ge::GRAPH_SUCCESS) { \ REPORT_CALL_ERROR("E19999", "Operator graph failed"); \ GELOGE(ge::FAILED, __VA_ARGS__); \ - return FAILED; \ + return (FAILED); \ } \ } while (false) @@ -105,8 +105,8 @@ const bool b = (expr); \ if (!b) { \ REPORT_INNER_ERROR("E19999", __VA_ARGS__); \ - GELOGE(_status, __VA_ARGS__); \ - return _status; \ + GELOGE((_status), __VA_ARGS__); \ + return (_status); \ } \ } while (false) @@ -115,7 +115,7 @@ do { \ const bool b = (expr); \ if (!b) { \ - return _status; \ + return (_status); \ } \ } while (false) @@ -196,7 +196,7 @@ REPORT_INNER_ERROR("E19999", __VA_ARGS__); \ GELOGE(ge::FAILED, __VA_ARGS__); \ exec_expr; \ - return _status; \ + return (_status); \ } \ } @@ -211,22 +211,22 @@ // -----------------runtime related macro definitions------------------------------- // If expr is not RT_ERROR_NONE, print the log -#define GE_CHK_RT(expr) \ - do { \ - const rtError_t _rt_ret = (expr); \ - if (_rt_ret != RT_ERROR_NONE) { \ - GELOGE(ge::FAILED, "Call rt api failed, ret: 0x%X", _rt_ret); \ - } \ +#define GE_CHK_RT(expr) \ + do { \ + const rtError_t _rt_ret = (expr); \ + if (_rt_ret != RT_ERROR_NONE) { \ + GELOGE(ge::RT_FAILED, "Call rt api failed, ret: 0x%X", _rt_ret); \ + } \ } while (false) // If expr is not RT_ERROR_NONE, print the log and execute the exec_expr expression -#define GE_CHK_RT_EXEC(expr, exec_expr) \ - do { \ - const rtError_t _rt_ret = (expr); \ - if (_rt_ret != RT_ERROR_NONE) { \ - GELOGE(ge::FAILED, "Call rt api failed, ret: 0x%X", _rt_ret); \ - exec_expr; \ - } \ +#define GE_CHK_RT_EXEC(expr, exec_expr) \ + do { \ + const rtError_t _rt_ret = (expr); \ + if (_rt_ret != RT_ERROR_NONE) { \ + GELOGE(ge::RT_FAILED, "Call rt api failed, ret: 0x%X", _rt_ret); \ + exec_expr; \ + } \ } while (false) // If expr is not RT_ERROR_NONE, print the log and return @@ -235,7 +235,7 @@ const rtError_t _rt_ret = (expr); \ if (_rt_ret != RT_ERROR_NONE) { \ REPORT_CALL_ERROR("E19999", "Call %s fail, ret: 0x%X", #expr, _rt_ret); \ - GELOGE(ge::FAILED, "Call rt api failed, ret: 0x%X", _rt_ret); \ + GELOGE(ge::RT_FAILED, "Call rt api failed, ret: 0x%X", _rt_ret); \ return RT_ERROR_TO_GE_STATUS(_rt_ret); \ } \ } while (false) @@ -257,26 +257,26 @@ exec_expr1; \ } -#define GE_ERRORLOG_AND_ERRORMSG(_status, errormsg) \ - { \ - GELOGE(_status, "[Check][InnerData]%s", errormsg); \ - REPORT_INNER_ERROR("E19999", "%s", errormsg); \ +#define GE_ERRORLOG_AND_ERRORMSG(_status, errormsg) \ + { \ + GELOGE((_status), "[Check][InnerData]%s", (errormsg)); \ + REPORT_INNER_ERROR("E19999", "%s", (errormsg)); \ } -#define GE_WARNINGLOG_AND_ERRORMSG(errormsg) \ - { \ - GELOGW("%s", errormsg); \ - ErrorManager::GetInstance().ATCReportErrMessage("E19021", {"reason"}, {errormsg}); \ +#define GE_WARNINGLOG_AND_ERRORMSG(errormsg) \ + { \ + GELOGW("%s", (errormsg)); \ + ErrorManager::GetInstance().ATCReportErrMessage("E19021", {"reason"}, {(errormsg)}); \ } -#define GE_CHK_LOG_AND_ERRORMSG(expr, _status, errormsg) \ - do { \ - const bool b = (expr); \ - if (!b) { \ - GELOGE(_status, "%s", errormsg); \ - ErrorManager::GetInstance().ATCReportErrMessage("E19021", {"reason"}, {errormsg}); \ - return _status; \ - } \ +#define GE_CHK_LOG_AND_ERRORMSG(expr, _status, errormsg) \ + do { \ + const bool b = (expr); \ + if (!b) { \ + GELOGE((_status), "%s", (errormsg)); \ + ErrorManager::GetInstance().ATCReportErrMessage("E19021", {"reason"}, {(errormsg)}); \ + return (_status); \ + } \ } while (false) template diff --git a/inc/framework/common/file_constant_util.h b/inc/framework/common/file_constant_util.h new file mode 100644 index 00000000..1ea81960 --- /dev/null +++ b/inc/framework/common/file_constant_util.h @@ -0,0 +1,60 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + * + * 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. + */ + +#ifndef INC_FRAMEWORK_COMMON_FILE_CONSTANT_UTIL_H +#define INC_FRAMEWORK_COMMON_FILE_CONSTANT_UTIL_H + +#include +#include +#include +#include "ge/ge_api_error_codes.h" +#include "nlohmann/json.hpp" +#include "graph/op_desc.h" +#include "graph/types.h" +#include "graph/ge_tensor.h" + +namespace ge { +extern const int64_t kBlockSize; +extern const std::string kBinFileValues; +extern const std::string kBinIdValue; +extern const std::string kBinFilePathValue; + +struct FileConstantInfo { + std::string value_bin_file_id; + std::string value_bin_file_path; +}; + +struct OptionInfo { + std::vector info; +}; + +void from_json(const nlohmann::json &j, FileConstantInfo &info); + +void from_json(const nlohmann::json &j, OptionInfo &option_info); + +Status GetFilePathFromOption(std::map &file_id_and_path_map); + +Status CopyOneWeightFromFile(const void *curr_dev_ptr, const std::string &value, const size_t file_constant_size, + size_t &left_size); + +Status GetFilePath(const OpDescPtr &op_desc, const std::map &file_id_and_path_map, + std::string &file_path); + +Status GetFileConstantElementTotalSize(const GeShape &shape, const DataType data_type, int64_t &mem_size, + const Format format = FORMAT_ND); +} // namespace ge + +#endif // INC_FRAMEWORK_COMMON_FILE_CONSTANT_UTIL_H diff --git a/inc/framework/common/fmk_error_codes.h b/inc/framework/common/fmk_error_codes.h index 139785ae..9f1719ac 100644 --- a/inc/framework/common/fmk_error_codes.h +++ b/inc/framework/common/fmk_error_codes.h @@ -42,27 +42,27 @@ #include "register/register_error_codes.h" // Each module uses the following four macros to define error codes: -#define DECLARE_ERRORNO_OMG(name, value) DECLARE_ERRORNO(SYSID_FWK, MODID_OMG, name, value) -#define DECLARE_ERRORNO_OME(name, value) DECLARE_ERRORNO(SYSID_FWK, MODID_OME, name, value) +#define DECLARE_ERRORNO_OMG(name, value) DECLARE_ERRORNO(SYSID_FWK, MODID_OMG, (name), (value)) +#define DECLARE_ERRORNO_OME(name, value) DECLARE_ERRORNO(SYSID_FWK, MODID_OME, (name), (value)) #define DECLARE_ERRORNO_CALIBRATION(name, value) DECLARE_ERRORNO(SYSID_FWK, MODID_CALIBRATION, name, value) -#define DEF_ERRORNO(name, desc) const ErrorNoRegisterar g_##name##_errorno(name, desc); +#define DEF_ERRORNO(name, desc) const ErrorNoRegisterar g_##name##_errorno((name), (desc)); // Interface for Obtaining Error Code Description #define GET_ERRORNO_STR(value) domi::StatusFactory::Instance()->GetErrDesc(value) -const int MODID_OMG = 1; // OMG module ID -const int MODID_OME = 2; // OME module ID -const int MODID_CALIBRATION = 3; // Calibration module ID - namespace domi { +constexpr int32_t MODID_OMG = 1; // OMG module ID +constexpr int32_t MODID_OME = 2; // OME module ID +constexpr int32_t MODID_CALIBRATION = 3; // Calibration module ID + class GE_FUNC_VISIBILITY StatusFactory { public: static StatusFactory *Instance(); - void RegisterErrorNo(uint32_t err, const std::string &desc); + void RegisterErrorNo(const uint32_t err, const std::string &desc); - std::string GetErrDesc(uint32_t err); + std::string GetErrDesc(const uint32_t err); protected: StatusFactory() {} diff --git a/inc/framework/common/ge_format_util.h b/inc/framework/common/ge_format_util.h index 3c621576..c6decdcc 100644 --- a/inc/framework/common/ge_format_util.h +++ b/inc/framework/common/ge_format_util.h @@ -33,7 +33,7 @@ class GE_FUNC_VISIBILITY GeFormatUtil { /// @param [out] dst_shape destination shape /// @return Status /// - static Status TransShape(const TensorDesc &src_desc, Format dst_format, std::vector &dst_shape); + static Status TransShape(const TensorDesc &src_desc, const Format dst_format, std::vector &dst_shape); }; } // namespace ge diff --git a/inc/framework/common/ge_inner_error_codes.h b/inc/framework/common/ge_inner_error_codes.h index 9e9b5d1d..529f6cb4 100644 --- a/inc/framework/common/ge_inner_error_codes.h +++ b/inc/framework/common/ge_inner_error_codes.h @@ -313,7 +313,10 @@ GE_ERRORNO_GENERATOR(GE_GENERATOR_GRAPH_MANAGER_BUILD_GRAPH_FAILED, 3, "Graph ma GE_ERRORNO_GENERATOR(GE_GENERATOR_GRAPH_MANAGER_FINALIZE_FAILED, 4, "Graph manager finalize failed."); GE_ERRORNO_GENERATOR(GE_GENERATOR_GRAPH_MANAGER_SAVE_MODEL_FAILED, 5, "Graph manager save model failed."); -#define RT_ERROR_TO_GE_STATUS(RT_ERROR) static_cast(RT_ERROR) +static inline Status TransRtErrorCode(const int32_t error_code) { + return static_cast(error_code); +} +#define RT_ERROR_TO_GE_STATUS(RT_ERROR) TransRtErrorCode(RT_ERROR) } // namespace ge #endif // INC_FRAMEWORK_COMMON_GE_INNER_ERROR_CODES_H_ diff --git a/inc/framework/common/ge_types.h b/inc/framework/common/ge_types.h index 060a7bf0..868debe7 100644 --- a/inc/framework/common/ge_types.h +++ b/inc/framework/common/ge_types.h @@ -30,7 +30,11 @@ namespace ge { enum RuntimeType { HOST = 0, DEVICE = 1 }; -enum PerfLevel { GEN_TASK_WITH_FUSION = -1, GEN_TASK_WITHOUT_L2FUSION = 3, GEN_TASK_WITHOUT_FUSION = 4 }; +enum class PerfLevel : int32_t { + GEN_TASK_WITH_FUSION = -1, + GEN_TASK_WITHOUT_L2FUSION = 3, + GEN_TASK_WITHOUT_FUSION = 4 +}; enum FrameworkType { CAFFE = 0, @@ -40,6 +44,10 @@ enum FrameworkType { ONNX, }; +enum class GraphStage : int64_t { GRAPH_STAGE_FUZZ = 0, GRAPH_STAGE_RESERVED }; + +const char *const kGraphDumpStage = "DumpStage"; + const std::map kFwkTypeToStr = { {"0", "Caffe"}, {"1", "MindSpore"}, {"3", "TensorFlow"}, {"4", "Android_NN"}, {"5", "Onnx"}}; @@ -53,17 +61,18 @@ enum OpEngineType { enum InputAippType { DATA_WITHOUT_AIPP = 0, DATA_WITH_STATIC_AIPP, DATA_WITH_DYNAMIC_AIPP, DYNAMIC_AIPP_NODE }; -const char *const GE_ENGINE_ATTR_MEM_TYPE_HBM = "HBM"; -const char *const GE_OPTION_EXEC_PLACEMENT = "ge.exec.placement"; +const char_t *const GE_ENGINE_ATTR_MEM_TYPE_HBM = "HBM"; +const char_t *const GE_OPTION_EXEC_PLACEMENT = "ge.exec.placement"; // profiling data + const std::string kTaskTypeAicore = "AI_CORE"; const std::string kTaskTypeAicpu = "AI_CPU"; const std::string kTaskTypeInvalid = "TASK_TYPE_INVALID"; const std::string kTaskTypeFftsPlus = "FFTS_PLUS"; // dynamic execute mode -const char *const kLazyRecompile = "lazy_recompile"; +const char_t *const kLazyRecompile = "lazy_recompile"; // Data cache, including data address and length struct DataBuffer { @@ -75,7 +84,7 @@ struct DataBuffer { DataBuffer(void *data_in, uint64_t data_len, bool is_support_mem_share, uint32_t placement = 0U) : data(data_in), length(data_len), isDataSupportMemShare(is_support_mem_share), placement(placement) {} - DataBuffer() : data(nullptr), length(0U), isDataSupportMemShare(false) {} + DataBuffer() : data(nullptr), length(0UL), isDataSupportMemShare(false) {} }; /// @@ -87,7 +96,7 @@ struct InputData { uint32_t timestamp; // Data creation time uint32_t timeout; // Processing timeout uint32_t model_id; // Model ID required for data processing - uint64_t request_id = 0U; // Request ID + uint64_t request_id = 0UL; // Request ID std::vector blobs; // Actual input data, currently only supports one input bool is_dynamic_batch = false; // Whether is dynamic batch size scene, default:false std::string batch_label; // Gear used for current inference in dynamic batch scene @@ -114,10 +123,10 @@ struct Command { // The definition of I/O shape description struct ShapeDescription { - int64_t num = 0; - int64_t channel = 0; - int64_t height = 0; - int64_t width = 0; + int64_t num = 0L; + int64_t channel = 0L; + int64_t height = 0L; + int64_t width = 0L; std::vector dims; std::vector> shape_ranges; }; @@ -187,14 +196,14 @@ struct AippConfigInfo { int32_t mean_chn_1; int32_t mean_chn_2; int32_t mean_chn_3; - float min_chn_0; - float min_chn_1; - float min_chn_2; - float min_chn_3; - float var_reci_chn_0; - float var_reci_chn_1; - float var_reci_chn_2; - float var_reci_chn_3; + float32_t min_chn_0; + float32_t min_chn_1; + float32_t min_chn_2; + float32_t min_chn_3; + float32_t var_reci_chn_0; + float32_t var_reci_chn_1; + float32_t var_reci_chn_2; + float32_t var_reci_chn_3; int8_t support_rotation; uint32_t related_input_rank; uint32_t max_src_image_size; diff --git a/inc/framework/common/helper/model_helper.h b/inc/framework/common/helper/model_helper.h index b3cf19a4..8da856e1 100644 --- a/inc/framework/common/helper/model_helper.h +++ b/inc/framework/common/helper/model_helper.h @@ -36,75 +36,66 @@ class GE_FUNC_VISIBILITY ModelHelper { Status SaveToOmModel(const GeModelPtr &ge_model, const SaveParam &save_param, const std::string &output_file, ge::ModelBufferData &model); Status SaveToOmRootModel(const GeRootModelPtr &ge_root_model, const SaveParam &save_param, - const std::string &output_file, ModelBufferData &model, bool is_unknown_shape); + const std::string &output_file, ModelBufferData &model, const bool is_unknown_shape); Status SaveOriginalGraphToOmModel(const ge::Graph &graph, const std::string &output_file); Status LoadModel(const ge::ModelData &model_data); Status LoadRootModel(const ge::ModelData &model_data); - Status GetModelBufferData(ge::ModelBufferData &model); - - const ModelFileHeader *GetFileHeader() const { - return file_header_; - } GeModelPtr GetGeModel(); GeRootModelPtr GetGeRootModel(); - void SetSaveMode(bool val) { + void SetSaveMode(const bool val) { is_offline_ = val; } - bool GetSaveMode(void) const { - return is_offline_; - } + bool GetModelType() const { return is_unknown_shape_model_; - }; + } - Status GetBaseNameFromFileName(const std::string &file_name, std::string &base_name); - Status GetModelNameFromMergedGraphName(const std::string &graph_name, std::string &model_name); + Status GetBaseNameFromFileName(const std::string &file_name, std::string &base_name) const; + Status GetModelNameFromMergedGraphName(const std::string &graph_name, std::string &model_name) const; private: bool is_assign_model_ = false; bool is_offline_ = true; bool is_unknown_shape_model_ = false; ModelFileHeader *file_header_ = nullptr; - // Encrypted model need delete temp model and unencrypted model need not delete model - uint8_t *model_addr_tmp_ = nullptr; - uint32_t model_len_tmp_ = 0; GeModelPtr model_; GeRootModelPtr root_model_; - ModelHelper(const ModelHelper &); - ModelHelper &operator=(const ModelHelper &); + ModelHelper(const ModelHelper &) = default; + ModelHelper &operator=(const ModelHelper &) = default; Status GenerateGeModel(OmFileLoadHelper &om_load_helper); Status GenerateGeRootModel(OmFileLoadHelper &om_load_helper); Status LoadModelData(OmFileLoadHelper &om_load_helper); - void SetModelToGeModel(GeModelPtr &ge_model, Model &model); - Status LoadModelData(OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model, size_t mode_index); + void SetModelToGeModel(GeModelPtr &ge_model, Model &model) const; + Status LoadModelData(OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model, const size_t mode_index) const; Status LoadWeights(OmFileLoadHelper &om_load_helper); - Status LoadWeights(OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model, size_t mode_index); + Status LoadWeights(OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model, const size_t mode_index) const; Status LoadTask(OmFileLoadHelper &om_load_helper); - Status LoadTask(OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model, size_t mode_index); + Status LoadTask(OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model, const size_t mode_index) const; Status LoadTBEKernelStore(OmFileLoadHelper &om_load_helper); - Status LoadTBEKernelStore(OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model, size_t mode_index); + Status LoadTBEKernelStore(OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model, const size_t mode_index) const; Status LoadCustAICPUKernelStore(OmFileLoadHelper &om_load_helper); - Status LoadCustAICPUKernelStore(OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model, size_t mode_index); - Status ReleaseLocalModelData() noexcept; - Status SaveModelPartition(std::shared_ptr &om_file_save_helper, ModelPartitionType type, - const uint8_t *data, size_t size, size_t model_index); + Status LoadCustAICPUKernelStore(OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model, + const size_t mode_index) const; + + Status SaveModelPartition(std::shared_ptr &om_file_save_helper, const ModelPartitionType type, + const uint8_t *const data, const size_t size, const size_t model_index) const; Status SaveModelDef(shared_ptr &om_file_save_helper, const GeModelPtr &ge_model, - Buffer &model_buffer, size_t model_index = 0); - Status SaveSizeToModelDef(const GeModelPtr &ge_model); + Buffer &model_buffer, const size_t model_index = 0U) const; + Status SaveSizeToModelDef(const GeModelPtr &ge_model) const; Status SaveModelWeights(shared_ptr &om_file_save_helper, const GeModelPtr &ge_model, - size_t model_index = 0); + const size_t model_index = 0U) const; Status SaveModelTbeKernel(shared_ptr &om_file_save_helper, const GeModelPtr &ge_model, - size_t model_index = 0); + const size_t model_index = 0U) const; Status SaveModelCustAICPU(shared_ptr &om_file_save_helper, const GeModelPtr &ge_model, - size_t model_index = 0); + const size_t model_index = 0U) const; Status SaveModelTaskDef(shared_ptr &om_file_save_helper, const GeModelPtr &ge_model, - Buffer &task_buffer, size_t model_index = 0); + Buffer &task_buffer, const size_t model_index = 0U) const; Status SaveModelHeader(shared_ptr &om_file_save_helper, const GeModelPtr &ge_model, - size_t model_num = 1); + const size_t model_num = 1U) const; Status SaveAllModelPartiton(shared_ptr &om_file_save_helper, const GeModelPtr &ge_model, - Buffer &model_buffer, Buffer &task_buffer, size_t model_index = 0); + Buffer &model_buffer, Buffer &task_buffer, const size_t model_index = 0U) const; }; } // namespace ge #endif // INC_FRAMEWORK_COMMON_HELPER_MODEL_HELPER_H_ diff --git a/inc/framework/common/op/attr_value_util.h b/inc/framework/common/op/attr_value_util.h index cc4e0fcf..27415df8 100644 --- a/inc/framework/common/op/attr_value_util.h +++ b/inc/framework/common/op/attr_value_util.h @@ -165,10 +165,12 @@ GE_FUNC_VISIBILITY bool GetAttrDefValue(const std::string &key, AttrDef_ListValu GE_FUNC_VISIBILITY bool GetAttrDefValue(const std::string &key, NamedAttrs *&value, AttrDefMap *attr); GE_FUNC_VISIBILITY bool GetAttrDefValue(const std::string &key, const NamedAttrs *&value, const AttrDefMap &attr); -GE_FUNC_VISIBILITY bool GetAttrDefListValue(const std::string &key, int idx, int32_t *value, const AttrDefMap &attr); -GE_FUNC_VISIBILITY bool GetAttrDefListValue(const std::string &key, int idx, uint32_t *value, const AttrDefMap &attr); -GE_FUNC_VISIBILITY bool GetAttrDefListValue(const std::string &key, int idx, float *value, const AttrDefMap &attr); -GE_FUNC_VISIBILITY bool GetAttrDefListValue(const std::string &key, int idx, double *value, const AttrDefMap &attr); +GE_FUNC_VISIBILITY bool GetAttrDefListValue(const std::string &key, int32_t idx, int32_t *value, + const AttrDefMap &attr); +GE_FUNC_VISIBILITY bool GetAttrDefListValue(const std::string &key, int32_t idx, uint32_t *value, + const AttrDefMap &attr); +GE_FUNC_VISIBILITY bool GetAttrDefListValue(const std::string &key, int32_t idx, float *value, const AttrDefMap &attr); +GE_FUNC_VISIBILITY bool GetAttrDefListValue(const std::string &key, int32_t idx, double *value, const AttrDefMap &attr); } // namespace ge #endif // INC_FRAMEWORK_COMMON_OP_ATTR_VALUE_UTIL_H_ diff --git a/inc/framework/common/op/ge_op_utils.h b/inc/framework/common/op/ge_op_utils.h index 1d12c05b..8b28258a 100644 --- a/inc/framework/common/op/ge_op_utils.h +++ b/inc/framework/common/op/ge_op_utils.h @@ -65,7 +65,7 @@ GE_FUNC_VISIBILITY extern const uint32_t FOR_LIMIT_INPUT; GE_FUNC_VISIBILITY extern const uint32_t FOR_DELTA_INPUT; GE_FUNC_VISIBILITY extern const uint32_t FOR_DATA_INPUT; -GE_FUNC_VISIBILITY extern const int NORMAL_TENSOR_SIZE; +GE_FUNC_VISIBILITY extern const int32_t NORMAL_TENSOR_SIZE; class GE_FUNC_VISIBILITY OpUtils { public: @@ -107,9 +107,10 @@ class GE_FUNC_VISIBILITY OpUtils { static Status SetOutputSliceDataByDataType(void *data, int64_t data_size, const std::vector &input_dims, const std::vector &begin, const std::vector &output_dims, ge::GeTensor *output, const std::vector &stride); - static Status SetOutputSliceData(void *data, int64_t data_size, int32_t data_type, std::vector &input_dims, - std::vector &begin, std::vector &output_dims, ge::GeTensor *output, - std::vector &stride); + static Status SetOutputSliceData(void *data, int64_t data_size, int32_t data_type, + const std::vector &input_dims, const std::vector &begin, + const std::vector &output_dims, ge::GeTensor *const output, + const std::vector &stride); /// /// @ingroup domi_omg @@ -121,7 +122,7 @@ class GE_FUNC_VISIBILITY OpUtils { /// @param [in] K value of K dimension /// @param [out] output Data pointer after conversion. The format is KCHW. /// - static void TransDataHWCK2KCHW(const void *input, int64_t H, int64_t W, int64_t C, int64_t K, void **output); + static void TransDataHWCK2KCHW(const void *input, int64_t h, int64_t w, int64_t c, int64_t k, void **output); /// /// @ingroup domi_omg /// @brief Converts the convolutional weight data from [k, c, h, w] to [h, w, c, k]. @@ -132,15 +133,16 @@ class GE_FUNC_VISIBILITY OpUtils { /// @param [in] W value of W dimension /// @param [out] output Data pointer after conversion. The format is HWCK /// - static void TransDataKCHW2HWCK(const void *input, int64_t K, int64_t C, int64_t H, int64_t W, void *output); + static void TransDataKCHW2HWCK(const void *input, int64_t k, int64_t c, int64_t h, int64_t w, void *output); static std::vector GetWeights(const ge::Node &node); static std::vector GetWeights(ge::ConstNodePtr node); static std::vector MutableWeights(const ge::Node &node); static std::vector MutableWeights(const ge::NodePtr node); static Status SetWeights(ge::Node &node, const std::vector &weights); - static Status SetWeights(ge::NodePtr node, const std::vector &weights); - static Status GetShapeDataFromConstTensor(const ConstGeTensorPtr &tensor, DataType type, std::vector &dims); + static Status SetWeights(const ge::NodePtr node, const std::vector &weights); + static Status GetShapeDataFromConstTensor(const ConstGeTensorPtr &tensor, const DataType type, + std::vector &dims); private: static uint32_t GetRealDimCnt(const GeTensorDesc &tensor_desc); diff --git a/inc/framework/common/op/op_parser_util.h b/inc/framework/common/op/op_parser_util.h index 12ce6980..6d33c508 100644 --- a/inc/framework/common/op/op_parser_util.h +++ b/inc/framework/common/op/op_parser_util.h @@ -30,7 +30,7 @@ const uint32_t NORMAL_OUTPUT_NUM = 1; const uint32_t NORMAL_WORKSPACE_NUM = 0; const int32_t NORMAL_1D_DIM_NUM = 1; const int32_t NORMAL_SCALE_DIM_NUM = 0; -const int NORMAL_TENSOR_SIZE = 4; +const int32_t NORMAL_TENSOR_SIZE = 4; const uint32_t DEFAULT_REAL_DIM_CNT = 4; // const @@ -111,8 +111,8 @@ const int32_t ROIPOOLING_DEFAULT_SAMPLING_RATIO = -1; const int32_t DETECTIONOUTPUT_INPUT_SIZE = 3; const int32_t DETECTIONOUTPUT_OUTPUT_SIZE = 2; const int32_t DETECTIONOUTPUT_WORKSPACE_NUM = 1; -const int DETECTIONOUTPUT_CLASS_NUM = 20; // Number of background categories -const int DETECTIONOUTPUT_NUM_CLASSES_DEFAULT_VALUE = 21; +const int32_t DETECTIONOUTPUT_CLASS_NUM = 20; // Number of background categories +const int32_t DETECTIONOUTPUT_NUM_CLASSES_DEFAULT_VALUE = 21; const float DETECTIONOUTPUT_NMS_THRESHOLD_DEFAULT_VALUE = 0.3; const float DETECTIONOUTPUT_CONFIDENCE_THRESHOLD_DEFAULT_VALUE = 0.8; @@ -128,8 +128,8 @@ const float PROPOSAL_SCALE_DIM_0_DEFAULT_VALUE = 8; const float PROPOSAL_SCALE_DIM_1_DEFAULT_VALUE = 16; const float PROPOSAL_SCALE_DIM_2_DEFAULT_VALUE = 32; const float PROPOSAL_MIN_SIZE_DEFAULT_VALUE = 16; -const int PROPOSAL_PRE_NMS_TOPN_DEFAULT_VALUE = 6000; -const int PROPOSAL_POST_NMS_TOPN_DEFAULT_VALUE = 304; +const int32_t PROPOSAL_PRE_NMS_TOPN_DEFAULT_VALUE = 6000; +const int32_t PROPOSAL_POST_NMS_TOPN_DEFAULT_VALUE = 304; const float PROPOSAL_NMS_THRESH_DEFAULT_VALUE = 0.7; const float PROPOSAL_FILTER_THRESH_DEFAULT_VALUE = 0; @@ -150,7 +150,7 @@ const int32_t PERMUTE_WORKSPACE_NUM = 1; const int32_t PERMUTE_ORDER_NUM = 4; // Ssd normalize -const int SSD_NORMALIZE_INPUT_SIZE = 1; +const int32_t SSD_NORMALIZE_INPUT_SIZE = 1; const float SSD_NORMALIZE_EPS_DEFAULT_VALUE = 2e-7; // SsdPriroBox @@ -163,9 +163,9 @@ const double SSD_PRIORBOX_VARIANCE_VALUE = 0.1; const double SSD_PRIORBOX_VARIANCE_SIZE_ONE = 1; const double SSD_PRIORBOX_VARIANCE_SIZE_FOUR = 4; const double SSD_PRIORBOX_ASPECT_RATIO_VALUE = 1.0; -const int SSD_PRIOR_BOX_CODETYPE_CORNER_VALUE = 1; -const int SSD_PRIOR_BOX_CODETYPE_CENTER_SIZE_VALUE = 2; -const int SSD_PRIOR_BOX_CODETYPE_CORNER_SIZE_VALUE = 3; +const int32_t SSD_PRIOR_BOX_CODETYPE_CORNER_VALUE = 1; +const int32_t SSD_PRIOR_BOX_CODETYPE_CENTER_SIZE_VALUE = 2; +const int32_t SSD_PRIOR_BOX_CODETYPE_CORNER_SIZE_VALUE = 3; // Ssd DetectionOutput const int32_t SSD_DETECTIONOUTPUT_INPUT_SIZE = 3; @@ -205,8 +205,8 @@ const int32_t CHANNEL_AXPY_INPUT_DIM_SIZE = 4; const int32_t CHANNEL_AXPY_WORKSPACE_NUM = 1; // Psroi pooling -const int PSROI_POOLING_INPUT_COUNT = 2; -const int PSROI_POOLING_WORKSPACE_NUM = 1; +const int32_t PSROI_POOLING_INPUT_COUNT = 2; +const int32_t PSROI_POOLING_WORKSPACE_NUM = 1; // MaxPoolWithArgmax const uint32_t MAX_POOL_WITH_ARGMAX_OUTPUT_NUM = 2; @@ -223,7 +223,7 @@ const int32_t ROIALIGN_DEFAULT_POOLED_W = 1; // Correlation const uint32_t CORRELATION_INPUT_NUM = 2; -const int CORRELATION_WORKSPACE_NUM = 1; +const int32_t CORRELATION_WORKSPACE_NUM = 1; // Detectionpostprocess const int32_t POSTPROCESS_INPUT_SIZE = 4; @@ -394,15 +394,15 @@ const uint32_t ATTENTION_DECODER_WORKSPACE_NUM = 1; const uint32_t ATTENTION_DECODER_INPUT_DECODER_INPUTS = 0; const uint32_t ATTENTION_DECODER_INPUT_DECODER_INITIAL_HIDDEN = 1; -const int ATTENTION_DECODER_ALGO_NORMAL = 0; -const int ATTENTION_DECODER_SYMBOLS = 10000; -const int ATTENTION_DECODER_EMBEDDING_SIZE = 128; -const int ATTENTION_DECODER_ATTENTION_NUM_HIDDEN = 256; -const int ATTENTION_DECODER_DECODER_NUM_HIDDEN = 128; -const int ATTENTION_DECODER_DECODER_NUM_LAYERS = 2; -const int ATTENTION_DECODER_RNN_UNBIDIRECTIONAL = 0; -const int ATTENTION_DECODER_SEQLEN_VALUE = 57; -const int ATTENTION_DECODER_GRU = 3; +const int32_t ATTENTION_DECODER_ALGO_NORMAL = 0; +const int32_t ATTENTION_DECODER_SYMBOLS = 10000; +const int32_t ATTENTION_DECODER_EMBEDDING_SIZE = 128; +const int32_t ATTENTION_DECODER_ATTENTION_NUM_HIDDEN = 256; +const int32_t ATTENTION_DECODER_DECODER_NUM_HIDDEN = 128; +const int32_t ATTENTION_DECODER_DECODER_NUM_LAYERS = 2; +const int32_t ATTENTION_DECODER_RNN_UNBIDIRECTIONAL = 0; +const int32_t ATTENTION_DECODER_SEQLEN_VALUE = 57; +const int32_t ATTENTION_DECODER_GRU = 3; // Logicaland const int32_t LOGICAL_AND_INPUT_NUM = 2; diff --git a/inc/framework/common/string_util.h b/inc/framework/common/string_util.h index 4d808e2e..21f09ffd 100644 --- a/inc/framework/common/string_util.h +++ b/inc/framework/common/string_util.h @@ -45,18 +45,19 @@ class GE_FUNC_VISIBILITY StringUtils { public: static std::string &Ltrim(std::string &s) { #if __cplusplus >= 201103L - (void)s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int c) { return std::isspace(c) == 0; })); + (void)s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int32_t c) { return std::isspace(c) == 0; })); #else - (void)s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); + (void)s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); #endif return s; } // lint -esym(551,*) static std::string &Rtrim(std::string &s) { /*lint !e618*/ #if __cplusplus >= 201103L - (void)s.erase(std::find_if(s.rbegin(), s.rend(), [](int c) { return std::isspace(c) == 0; }).base(), s.end()); + (void)s.erase(std::find_if(s.rbegin(), s.rend(), [](int32_t c) { return std::isspace(c) == 0; }).base(), s.end()); #else - (void)s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); + (void)s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), + s.end()); #endif return s; } diff --git a/inc/framework/common/taskdown_common.h b/inc/framework/common/taskdown_common.h index 1417677c..331bf486 100644 --- a/inc/framework/common/taskdown_common.h +++ b/inc/framework/common/taskdown_common.h @@ -21,7 +21,7 @@ namespace ge { -const int CC_FUSION_OP_MAX = 32; +const int32_t CC_FUSION_OP_MAX = 32; typedef enum tagCcStatus { CC_STATUS_SUCCESS = 0, /**< succ */ diff --git a/inc/framework/common/types.h b/inc/framework/common/types.h index 053a3423..e5681ba6 100644 --- a/inc/framework/common/types.h +++ b/inc/framework/common/types.h @@ -318,6 +318,9 @@ REGISTER_OPTYPE_DECLARE(INITDATA, "InitData"); REGISTER_OPTYPE_DECLARE(TRANSSHAPE, "TransShape") REGISTER_OPTYPE_DECLARE(REFIDENTITY, "RefIdentity"); REGISTER_OPTYPE_DECLARE(BITCAST, "Bitcast"); +REGISTER_OPTYPE_DECLARE(GATHERSHAPES, "GatherShapes"); +REGISTER_OPTYPE_DECLARE(FLATTENV2, "FlattenV2"); +REGISTER_OPTYPE_DECLARE(FILECONSTANT, "FileConstant"); // ANN dedicated operator REGISTER_OPTYPE_DECLARE(ANN_MEAN, "AnnMean"); diff --git a/inc/framework/common/util.h b/inc/framework/common/util.h index c854e016..fac7e4ca 100644 --- a/inc/framework/common/util.h +++ b/inc/framework/common/util.h @@ -235,7 +235,7 @@ using google::protobuf::Message; /// @return true success /// @return false fail /// -GE_FUNC_VISIBILITY bool ReadProtoFromArray(const void *data, int size, Message *proto); +GE_FUNC_VISIBILITY bool ReadProtoFromArray(const void *data, int32_t size, Message *proto); /// /// @ingroup domi_proto @@ -264,7 +264,7 @@ GE_FUNC_VISIBILITY extern long GetFileLength(const std::string &input_file); /// @return false fail /// @return true success /// -GE_FUNC_VISIBILITY bool ReadBytesFromBinaryFile(const char *file_name, char **buffer, int &length); +GE_FUNC_VISIBILITY bool ReadBytesFromBinaryFile(const char *const file_name, char **buffer, int32_t &length); GE_FUNC_VISIBILITY bool ReadBytesFromBinaryFile(const char *file_name, std::vector &buffer); @@ -275,7 +275,7 @@ GE_FUNC_VISIBILITY bool ReadBytesFromBinaryFile(const char *file_name, std::vect /// @return 0 success /// @return -1 fail /// -GE_FUNC_VISIBILITY extern int CreateDirectory(const std::string &directory_path); +GE_FUNC_VISIBILITY extern int32_t CreateDirectory(const std::string &directory_path); /// /// @ingroup domi_common @@ -398,10 +398,10 @@ GE_FUNC_VISIBILITY bool CheckOutputPathValid(const std::string &file_path, const /// /// @ingroup domi_common /// @brief Check whether the file path meets the whitelist verification requirements. -/// @param [in] filePath file path +/// @param [in] str file path /// @param [out] result /// -GE_FUNC_VISIBILITY bool ValidateStr(const std::string &filePath, const std::string &mode); +GE_FUNC_VISIBILITY bool ValidateStr(const std::string &str, const std::string &mode); /// /// @ingroup domi_common diff --git a/inc/framework/generator/ge_generator.h b/inc/framework/generator/ge_generator.h index b746dbac..b49fa53b 100644 --- a/inc/framework/generator/ge_generator.h +++ b/inc/framework/generator/ge_generator.h @@ -90,6 +90,10 @@ class GE_FUNC_VISIBILITY GeGenerator { Status BuildSingleOpModel(OpDescPtr &op_desc, const std::vector &inputs, const std::vector &outputs, OpEngineType engine_type, int32_t compile_flag, ModelBufferData &model_buff); + Status BuildSingleOpModel(OpDescPtr &op_desc, const std::vector &inputs, + const std::vector &outputs, OpEngineType engine_type, int32_t compile_flag, + ModelBufferData &model_buff, GraphStage graph_stage, ComputeGraphPtr &compute_graph); + /// /// @ingroup ge /// @brief: Build single Op into model buff. @@ -101,13 +105,19 @@ class GE_FUNC_VISIBILITY GeGenerator { /// @return SUCCESS or FAILED Status BuildSingleOpGraph(OpDescPtr &op_desc, const InOutTensorRef &inputs_outputs, std::string graph_name, Graph &graph, std::vector> &inputs_name_type); + Status BuildOriginalGraphInfo(OpDescPtr &op_desc, const std::vector &inputs, + const std::vector &outputs, const std::string &model_file_name, + bool is_offline, int32_t compile_flag, GraphStage graph_stage, Graph &graph, + ComputeGraphPtr &compute_graph, bool &fuzz_compile_flag, + std::vector> &inputs_name_type); private: Status GenerateModel(const Graph &graph, const std::string &file_name_prefix, const std::vector &inputs, ge::ModelBufferData &model, bool is_offline = true); Status BuildSingleOp(OpDescPtr &op_desc, const std::vector &inputs, const std::vector &outputs, const std::string &model_file_name, OpEngineType engine_type, ModelBufferData &model_buff, - bool is_offline = true, int32_t compile_flag = 0); + ComputeGraphPtr &compute_graph, bool is_offline = true, int32_t compile_flag = 0, + GraphStage graph_stage = GraphStage::GRAPH_STAGE_RESERVED); bool CheckNoAicore(const ComputeGraphPtr &graph); void RemoveConst(const std::vector &inputs, std::vector &outputs); Status CheckForSingleOp(OpDescPtr &op_desc, const std::vector &inputs, diff --git a/inc/framework/omg/parser/model_parser.h b/inc/framework/omg/parser/model_parser.h index b6ebd8a8..a0415d73 100644 --- a/inc/framework/omg/parser/model_parser.h +++ b/inc/framework/omg/parser/model_parser.h @@ -25,8 +25,6 @@ #include "graph/ge_tensor.h" #include "graph/graph.h" #include "graph/op_desc.h" -#include "graph/operator.h" -#include "graph/range_vistor.h" #include "graph/utils/attr_utils.h" #include "graph/utils/graph_utils.h" #include "graph/utils/op_desc_utils.h" @@ -54,7 +52,7 @@ class GE_FUNC_VISIBILITY ModelParser { * @return SUCCESS * @return Others failed */ - virtual Status Parse(const char *file, ge::Graph &graph) = 0; + virtual domi::Status Parse(const char *file, ge::Graph &graph) = 0; /** * @ingroup domi_omg @@ -66,7 +64,7 @@ class GE_FUNC_VISIBILITY ModelParser { * @return FAILED * @author */ - virtual Status ParseFromMemory(const char *data, uint32_t size, ge::ComputeGraphPtr &graph) = 0; + virtual domi::Status ParseFromMemory(const char *data, uint32_t size, ge::ComputeGraphPtr &graph) = 0; /** * @ingroup domi_omg @@ -78,7 +76,7 @@ class GE_FUNC_VISIBILITY ModelParser { * @return FAILED * @author */ - virtual Status ParseFromMemory(const char *data, uint32_t size, ge::Graph &graph) = 0; + virtual domi::Status ParseFromMemory(const char *data, uint32_t size, ge::Graph &graph) = 0; /** * @ingroup domi_omg @@ -88,7 +86,7 @@ class GE_FUNC_VISIBILITY ModelParser { * @return SUCCESS * @return Others failed */ - virtual Status ParseProto(const google::protobuf::Message *proto, ge::ComputeGraphPtr &graph) = 0; + virtual domi::Status ParseProto(const google::protobuf::Message *proto, ge::ComputeGraphPtr &graph) = 0; /** * @ingroup domi_omg @@ -99,8 +97,8 @@ class GE_FUNC_VISIBILITY ModelParser { * @return SUCCESS * @return Others failed */ - virtual Status ParseProtoWithSubgraph(const google::protobuf::Message *proto, GetGraphCallback callback, - ge::ComputeGraphPtr &graph) = 0; + virtual domi::Status ParseProtoWithSubgraph(const google::protobuf::Message *proto, GetGraphCallback callback, + ge::ComputeGraphPtr &graph) = 0; /** * @ingroup domi_omg * @brief Convert model files to JSON format @@ -109,7 +107,7 @@ class GE_FUNC_VISIBILITY ModelParser { * @return SUCCESS * @return Others failed */ - virtual Status ToJson(const char *model_file, const char *json_file) { + virtual domi::Status ToJson(const char *model_file, const char *json_file) { return domi::SUCCESS; } @@ -121,7 +119,7 @@ class GE_FUNC_VISIBILITY ModelParser { */ virtual ge::DataType ConvertToGeDataType(const uint32_t type) = 0; - virtual Status ParseAllGraph(const google::protobuf::Message *root_proto, ge::ComputeGraphPtr &root_graph) = 0; + virtual domi::Status ParseAllGraph(const google::protobuf::Message *root_proto, ge::ComputeGraphPtr &root_graph) = 0; /** * @ingroup domi_omg @@ -131,7 +129,7 @@ class GE_FUNC_VISIBILITY ModelParser { * @return SUCCESS * @return Others failed */ - virtual Status ParseProto(const std::string &serialized_proto, ge::ComputeGraphPtr &graph) { + virtual domi::Status ParseProto(const std::string &serialized_proto, ge::ComputeGraphPtr &graph) { return UNSUPPORTED; } @@ -144,8 +142,8 @@ class GE_FUNC_VISIBILITY ModelParser { * @return SUCCESS * @return Others failed */ - virtual Status ParseProtoWithSubgraph(const std::string &serialized_proto, GetGraphCallbackV2 callback, - ge::ComputeGraphPtr &graph) { + virtual domi::Status ParseProtoWithSubgraph(const std::string &serialized_proto, GetGraphCallbackV2 callback, + ge::ComputeGraphPtr &graph) { return UNSUPPORTED; } }; diff --git a/inc/framework/omg/parser/op_parser.h b/inc/framework/omg/parser/op_parser.h index 760b41f5..04731ff3 100644 --- a/inc/framework/omg/parser/op_parser.h +++ b/inc/framework/omg/parser/op_parser.h @@ -50,7 +50,7 @@ class GE_FUNC_VISIBILITY OpParser { * @return SUCCESS * @return FAILED */ - virtual Status ParseParams(const Message *op_src, ge::OpDescPtr &op_desc) = 0; + virtual domi::Status ParseParams(const Message *op_src, ge::OpDescPtr &op_desc) = 0; /** * @ingroup domi_omg @@ -60,7 +60,7 @@ class GE_FUNC_VISIBILITY OpParser { * @return SUCCESS * @return FAILED */ - virtual Status ParseParams(const Message *op_src, ge::Operator &op_dest) = 0; + virtual domi::Status ParseParams(const Message *op_src, ge::Operator &op_dest) = 0; /** * @ingroup domi_omg @@ -70,7 +70,7 @@ class GE_FUNC_VISIBILITY OpParser { * @return SUCCESS * @return FAILED */ - virtual Status ParseWeights(const Message *op_src, ge::NodePtr &node) = 0; + virtual domi::Status ParseWeights(const Message *op_src, ge::NodePtr &node) = 0; /** * @ingroup domi_omg @@ -80,7 +80,7 @@ class GE_FUNC_VISIBILITY OpParser { * @return SUCCESS * @return FAILED */ - virtual Status GetFormat(const Message *op_src, domi::domiTensorFormat_t &format) { + virtual domi::Status GetFormat(const Message *op_src, domi::domiTensorFormat_t &format) { (void)op_src; // Indicates that the op does not provide a value for format format = domi::DOMI_TENSOR_RESERVED; diff --git a/inc/framework/omg/parser/parser_api.h b/inc/framework/omg/parser/parser_api.h index 26c9e051..6840da2b 100644 --- a/inc/framework/omg/parser/parser_api.h +++ b/inc/framework/omg/parser/parser_api.h @@ -17,7 +17,6 @@ #ifndef INC_FRAMEWORK_OMG_PARSER_PARSER_API_H_ #define INC_FRAMEWORK_OMG_PARSER_PARSER_API_H_ -#include #include #include #include "external/ge/ge_api_error_codes.h" diff --git a/inc/framework/omg/parser/parser_factory.h b/inc/framework/omg/parser/parser_factory.h index 5b505d52..7ae286df 100644 --- a/inc/framework/omg/parser/parser_factory.h +++ b/inc/framework/omg/parser/parser_factory.h @@ -63,7 +63,7 @@ class GE_FUNC_VISIBILITY ModelParserFactory { class GE_FUNC_VISIBILITY ModelParserRegisterar { public: - ModelParserRegisterar(const domi::FrameworkType type, MODEL_PARSER_CREATOR_FUN fun) { + ModelParserRegisterar(const domi::FrameworkType type, MODEL_PARSER_CREATOR_FUN const fun) { ModelParserFactory::Instance()->RegisterCreator(type, fun); } ~ModelParserRegisterar() {} @@ -115,7 +115,7 @@ class GE_FUNC_VISIBILITY WeightsParserFactory { class GE_FUNC_VISIBILITY WeightsParserRegisterar { public: - WeightsParserRegisterar(const domi::FrameworkType type, WEIGHTS_PARSER_CREATOR_FUN fun) { + WeightsParserRegisterar(const domi::FrameworkType type, WEIGHTS_PARSER_CREATOR_FUN const fun) { WeightsParserFactory::Instance()->RegisterCreator(type, fun); } ~WeightsParserRegisterar() {} diff --git a/inc/framework/omg/parser/parser_inner_ctx.h b/inc/framework/omg/parser/parser_inner_ctx.h index fd559468..969a94f8 100644 --- a/inc/framework/omg/parser/parser_inner_ctx.h +++ b/inc/framework/omg/parser/parser_inner_ctx.h @@ -21,7 +21,6 @@ #include #include #include -#include #include #include "external/register/register_fmk_types.h" #include "external/register/register_types.h" diff --git a/inc/framework/omg/parser/weights_parser.h b/inc/framework/omg/parser/weights_parser.h index c231fd41..04f09b14 100644 --- a/inc/framework/omg/parser/weights_parser.h +++ b/inc/framework/omg/parser/weights_parser.h @@ -17,13 +17,12 @@ #ifndef INC_FRAMEWORK_OMG_PARSER_WEIGHTS_PARSER_H_ #define INC_FRAMEWORK_OMG_PARSER_WEIGHTS_PARSER_H_ +#include "external/register/register_error_codes.h" #include "graph/graph.h" #include "graph/attr_value.h" #include "graph/compute_graph.h" #include "graph/ge_tensor.h" #include "graph/op_desc.h" -#include "graph/operator.h" -#include "graph/range_vistor.h" #include "graph/utils/attr_utils.h" #include "graph/utils/op_desc_utils.h" #include "graph/utils/tensor_utils.h" diff --git a/metadef b/metadef index fe47d04d..1d99928b 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit fe47d04d75170006fc0d28538dec49a2da426ceb +Subproject commit 1d99928bfcb02e45acc7db73e3ee57304ff1131a diff --git a/third_party/fwkacllib/inc/cce/aicpu_engine.h b/third_party/fwkacllib/inc/cce/aicpu_engine.h deleted file mode 100644 index bc2e415f..00000000 --- a/third_party/fwkacllib/inc/cce/aicpu_engine.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef AICPU_ENGINE_H__ -#define AICPU_ENGINE_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - AE_STATUS_SUCCESS = 0, - AE_STATUS_BAD_PARAM = 1, - AE_STATUS_OPEN_SO_FAILED = 2, - AE_STATUS_GET_KERNEL_NAME_FAILED = 3, - AE_STATUS_INNER_ERROR = 4, - AE_STATUS_KERNEL_API_INNER_ERROR = 5, - AE_STATUS_END_OF_SEQUENCE = 6, - AE_STATUS_DUMP_FAILED = 7, - AE_STATUS_TASK_WAIT = 101, - AE_STATUS_RESERVED -} aeStatus_t; - -/** - * @ingroup aicpu engine - * @brief aeCallInterface: - * a interface to call a function in a op kernfel lib - * @param [in] addr void *, should be STR_KERNEL * format - * @return aeStatus_t - */ -aeStatus_t aeCallInterface(void *addr); - -/** - * @ingroup aicpu engine - * @brief aeBatchLoadKernelSo: - * a interface to load kernel so - * @param [in] loadSoNum load so number - * @param [in] soPaths load so paths - * @param [in] soNames load so names - * @return aeStatus_t - */ -aeStatus_t aeBatchLoadKernelSo(const uint32_t loadSoNum, const char *soPaths[], const char *soNames[]); - -#ifdef __cplusplus -} -#endif - -#endif // AICPU_ENGINE_H__ diff --git a/third_party/fwkacllib/inc/cce/aicpu_engine_struct.h b/third_party/fwkacllib/inc/cce/aicpu_engine_struct.h deleted file mode 100644 index 8c0c1847..00000000 --- a/third_party/fwkacllib/inc/cce/aicpu_engine_struct.h +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef AICPU_ENGINE_STRUCT_H__ -#define AICPU_ENGINE_STRUCT_H__ - -#include "fwk_adpt_struct.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* - The different framwork we adapted for. -*/ -typedef enum { - FMK_KERNEL_TYPE_TF = 0, - FMK_KERNEL_TYPE_CF = 10, - FMK_KERNEL_TYPE_PT = 20, - FMK_KERNEL_TYPE_RESERVED -} FwkkernelType_t; - -#pragma pack(push, 1) -typedef struct { - uint32_t fwkKernelType; // FwkkernelType_t - union { - ::aicpu::FWKAdapter::FWKOperateParam fwk_kernel; - } fwkKernelBase; -} STR_FWK_OP_KERNEL; -#pragma pack(pop) - -#pragma pack(push, 1) -struct SessionInfo { - uint64_t sessionId; - uint64_t kernelId; - bool sessFlag; -}; -#pragma pack(pop) - -#ifdef __cplusplus -} -#endif -#endif // AICPU_ENGINE_STRUCT_H__ diff --git a/third_party/fwkacllib/inc/cce/blas_struct.h b/third_party/fwkacllib/inc/cce/blas_struct.h deleted file mode 100644 index e0bcee4c..00000000 --- a/third_party/fwkacllib/inc/cce/blas_struct.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef CC_BLAS_STRUCT_API__ -#define CC_BLAS_STRUCT_API__ - -#include - -typedef enum { CCBLAS_FILL_MODE_LOWER = 0, CCBLAS_FILL_MODE_UPPER = 1 } ccblasFillMode_t; - -typedef enum { - CCBLAS_OP_N = 0, - CCBLAS_OP_T = 1, -} ccblasOperation_t; - -typedef enum { CCBLAS_DIAG_NON_UNIT = 0, CCBLAS_DIAG_UNIT = 1 } ccblasDiagType_t; - -#endif // CC_BLAS_STRUCT_API__ diff --git a/third_party/fwkacllib/inc/cce/cce.h b/third_party/fwkacllib/inc/cce/cce.h deleted file mode 100644 index 0cd9613a..00000000 --- a/third_party/fwkacllib/inc/cce/cce.h +++ /dev/null @@ -1,101 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef CCE_H__ -#define CCE_H__ - -#include -#include "cce_def.hpp" - -namespace cce { - -/** - * @ingroup cce - * @brief create cc handler - * @param [in|out] handle point of cc handler - * @return ccStatus_t - */ -ccStatus_t ccCreate(ccHandle_t *handle); - -/** - * @ingroup cce - * @brief destroy cc handler - * @param [in] *handle cc handler - * @return ccStatus_t - */ -ccStatus_t ccDestroy(ccHandle_t *handle); - -/** - * @ingroup cce - * @brief bind stream with specified cc handler - * @param [in] handle cc handler - * @param [in] streamId stream - * @return ccStatus_t - */ -ccStatus_t ccSetStream(ccHandle_t handle, rtStream_t streamId); - -/** - * @ingroup cce - * @brief get the stream from cc handler - * @param [in] handle cc handler - * @param [in|out] streamId point of stream - * @return ccStatus_t - */ -ccStatus_t ccGetStream(ccHandle_t handle, rtStream_t *streamId); - -/** - * @ingroup cce - * @brief get the stream from cc handler - * @param [in] dataTypeTransMode mode of data type transform - * @param [in] inputData input data point - * @param [in] inputDataSize input data size - * @param [in|out] outputData output data point - * @param [in] outputDataSize output data size - * @return ccStatus_t - */ -ccStatus_t ccTransDataType(ccDataTypeTransMode_t dataTypeTransMode, const void *inputData, uint32_t inputDataSize, - void *outputData, const uint32_t outputDataSize); -/** - * @ingroup cce - * @brief cce sys init func - */ -void cceSysInit(); - -/** - * @ingroup cce - * @brief cce Log Start up func - */ -void cceLogStartup(); - -/** - * @ingroup cce - * @brief cce Log Shut down func - */ -void cceLogShutdown(); - -/** - * @ingroup cce - * @brief set the profiling on or off - * @param [in] const unsigned char* target: The engine gets it from ENV. Don't need care about it. - * @param const char* job_ctx: identifies profiling job - * @param [in] uint32_t flag: value: 0, on ; 1, off. - * @return ccStatus_t value: 0, success; 1, fail. - */ -ccStatus_t CceProfilingConfig(const char *target, const char *job_ctx, uint32_t flag); - -}; // namespace cce - -#endif // CCE_H__ diff --git a/third_party/fwkacllib/inc/cce/cce_def.hpp b/third_party/fwkacllib/inc/cce/cce_def.hpp deleted file mode 100644 index 7b1a1b8a..00000000 --- a/third_party/fwkacllib/inc/cce/cce_def.hpp +++ /dev/null @@ -1,152 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef CCE_DEF_H__ -#define CCE_DEF_H__ - -#include "runtime/rt.h" - -namespace cce { - -/** - * @ingroup cce - * @brief memory configure for fusion - */ -typedef struct TagCceFusionMemCfg { - uint64_t memAddr; /**< memAddr */ - uint32_t memSize; /**< memSize */ - uint32_t addrChangeFlag; /**< op data addr change flag. value:0,valid;1,not valid */ - uint32_t poolFlag; /**< mempool flag : value:0,is valid; value: 1, not valid */ - TagCceFusionMemCfg() { - memAddr = 0; - memSize = 0; - addrChangeFlag = 0; - poolFlag = 0; - } -} CceFusionMemCfg_t; -/** - * @ingroup cce - * @brief return value - */ -typedef enum tagCcStatus { - CC_STATUS_SUCCESS = 0, /**< succ */ - CC_STATUS_NOT_INITIALIZED = 1, /**< not init */ - CC_STATUS_ALLOC_FAILED = 2, /**< alloc mem failed */ - CC_STATUS_BAD_PARAM = 3, /**< para check failed */ - CC_STATUS_INTERNAL_ERROR = 4, /**< internal error */ - CC_STATUS_KERNEL_ERROR = 5, /**< kernel error */ - CC_STATUS_RUNTIME_ERROR = 6, /**< runtime error */ - CC_STATUS_NOT_SUPPORTED = 7, /**< unsupport error */ - CC_STATUS_INVALID_VALUE = 7, /**< invalid value error for blas*/ - CC_STATUS_RESERVED /**< just for check */ -} ccStatus_t; - -/** - * @ingroup cce - * @brief original data type - */ -typedef enum tagCcDataType { - CC_DATA_FLOAT = 0, /**< float type */ - CC_DATA_HALF, /**< fp16 type */ - CC_DATA_INT8, /**< int8 type */ - CC_DATA_INT32, /**< int32 type */ - CC_DATA_UINT8, /**< uint8 type */ - CC_DATA_HALF_UINT16_PROPOSAL, /** -#include - -#define ERROR_CODE() __catch_error_code -#define ERROR_LINE_NO() __catch_error_line_no -#define ERROR_PROC() __catch_error_line_no = __LINE__; - -#define PROC \ - uint32_t __catch_error_code = 0x7FFFFFCC; \ - uint32_t __catch_error_line_no = 0xFFFFFFFF; \ - { -#define END_PROC \ - } \ - __tabErrorCode: -#define THROW(errcode) \ - { \ - __catch_error_code = (errcode); \ - ERROR_PROC(); \ - goto __tabErrorCode; \ - } -#define EXEC(func) \ - { \ - if (0 != (__catch_error_code = (func))) THROW(__catch_error_code) \ - } -#define EXEC_EX1(func, error_code) \ - { \ - if (0 != (func)) THROW(error_code) \ - } -#define EXEC_EX(func, succRet, error_code) \ - { \ - if (succRet != (__catch_error_code = (func))) THROW(error_code) \ - } -#define ASSERT_EXEC(func, succRet) \ - { \ - if (succRet != (__catch_error_code = (func))) /*GO_ASSERT_FALSE();*/ \ - THROW(__catch_error_code) \ - } \ - } -#define NEW_ERROR_EXEC(errcode, func, succRet) \ - { \ - if (succRet != (func)) { \ - THROW(errcode) \ - } \ - } -#define JUDGE(errcode, expr) \ - { \ - if (!(expr)) { \ - THROW(errcode) \ - } \ - } -#define ASSERT_JUDGE(errcode, expr) \ - { \ - if (!(expr)) { /*GO_ASSERT_FALSE();*/ \ - THROW(errcode) \ - } \ - } -#define JUDGE_FALSE(errcode, expr) \ - { \ - if (expr) { \ - THROW(errcode) \ - } \ - } -#define JUDGE_CONTINUE(expr) \ - { \ - if (expr) { \ - continue; \ - } \ - } -#define CATCH_ERROR(errcode) if (__catch_error_code == (errcode)) { // ERROR_LOG(); -#define CATCH_ALL_ERROR { -#define END_CATCH_ERROR } -#define FINAL \ - __tabFinal: -#define END_FINAL /*GO_ASSERT_FALSE()*/ ; -#define GOTO_FINAL() goto __tabFinal; -#endif // CATCH_HPP_ diff --git a/third_party/fwkacllib/inc/cce/compiler_stub.h b/third_party/fwkacllib/inc/cce/compiler_stub.h deleted file mode 100644 index 00ea467e..00000000 --- a/third_party/fwkacllib/inc/cce/compiler_stub.h +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef COMPILER_STUB_H__ -#define COMPILER_STUB_H__ - -namespace cce { - -/** - * @ingroup cce - * @brief compiler stub init func - */ -bool compilerStubInit(); - -/** - * @ingroup cce - * @brief compiler stub free func - */ -bool compilerStubFree(); - -}; // namespace cce - -#endif // COMPILER_STUB_H__ diff --git a/third_party/fwkacllib/inc/cce/customize.h b/third_party/fwkacllib/inc/cce/customize.h deleted file mode 100644 index 7dd97af1..00000000 --- a/third_party/fwkacllib/inc/cce/customize.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef CC_CUSTOMIZE_API__ -#define CC_CUSTOMIZE_API__ - -#include - -#define CC_DEVICE_DIM_MAX 8 -typedef enum tagOpTensorFormat -{ - OP_TENSOR_FORMAT_NC1HWC0 = 0, - OP_TENSOR_FORMAT_ND, - OP_TENSOR_FORMAT_RESERVED, - -} opTensorFormat_t; - - -typedef enum tagOpDataType -{ - OP_DATA_FLOAT = 0, /**< float type */ - OP_DATA_HALF, /**< fp16 type */ - OP_DATA_INT8, /**< int8 type */ - OP_DATA_INT32, /**< int32 type */ - OP_DATA_UINT8, /**< uint8 type */ - OP_DATA_HALF_UINT16_PROPOSAL, /**dimCnt, xDesc->dimCnt) - * @param [in] num the number of outputs - * @param [in] beta scaling factors - * @param [in] yDescArr descriptors of output tensors - * @param [in|out] yArr output data array in device memory - * @return ccStatus_t - */ -ccStatus_t ccSplitForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - int32_t axis, uint32_t num, const void *beta, const ccTensorDescriptor_t yDescArr[], - void *yArr[]); - -/** - * @ingroup dnn - * @brief get the output dimensions info of split - * @param [in] xDesc descriptor of input tensor - * @param [in] axis the dimension along which to split. Must be in the range [-xDesc->dimCnt, xDesc->dimCnt) - * @param [in] num the number of outputs - * @param [in] sizes Optional, used to specify the sizes of each output tensor along split dim. The tensor x would - * be split evenly along split dim if sizes is NULL - * @param [in|out] nArr point to the first element of batch sizes - * @param [in|out] cArr point to the first element of channels - * @param [in|out] hArr point to the first element of heights of feature map - * @param [in|out] wArr point to the first element of widths of feature map - * @return ccStatus_t - */ -ccStatus_t ccGetSplitForwardOutputDim(const ccTensorDescriptor_t xDesc, int32_t axis, uint32_t num, - const uint32_t sizes[], uint32_t nArr[], uint32_t cArr[], uint32_t hArr[], - uint32_t wArr[]); - -/** - * @ingroup dnn - * @brief Get split output shape(s). - * @param [in] xDesc input tensor, support ND and NC1HWC0 - * @param [in] axis split axis, negtive axis will increased by dimCnt once time. - * @param [in] num splited nums. - * @param [in] sizes splited dim size on axis. if NULL was set, The input will be divided into num equally. - * @param [output] dimCnt splited dimCnt array. One to one correspondence with the splited output. - * @param [output] dim array of splited dim array. One to one correspondence with the splited output. - * @param [in| dimlen length of dim(Pass in the length of the entire space pointed to by dim, - not just the length of the dim array, because dim is a level 2 array - dimlen = lengthof dim[][], not just lengthof dim[]) - * @return ccStatus_t - */ -ccStatus_t ccGetSplitForwardOutputDim(const ccTensorDescriptor_t xDesc, int32_t axis, uint32_t num, - const uint32_t sizes[], int32_t *dimCnt, int32_t *dim[], int32_t dimLen); - -/** - * @ingroup dnn - * @brief create weight compress info - * @param [in|out] compressInfo point to CompressInfo - * @return ccStatus_t - */ -ccStatus_t ccCreateWeightCompressInfo(ccWeightCompressInfo_t **compressInfo); - -/** - * @ingroup dnn - * @brief destory weight compress info - * @param [in] *compressInfo point to CompressInfo - * @return ccStatus_t - */ -ccStatus_t ccDestroyWeightCompressInfo(ccWeightCompressInfo_t **compressInfo); - -/** - * @ingroup dnn - * @brief create compress table - * @param [in|out] compressTab point to weight compress table - * @return ccStatus_t - */ -ccStatus_t ccCreateWeightCompressTab(ccWeightCompressTab_t **compressTab); - -/** - * @ingroup dnn - * @brief destory compress table - * @param [in] compressTab point to weight compress table - * @return ccStatus_t - */ -ccStatus_t ccDestroyWeightCompressTab(ccWeightCompressTab_t **compressTab); - -/** - * @ingroup dnn - * @brief get fc compress info - * @param [in] xDesc descriptor of input tensor - * @param [in] wDesc descriptor of weight tensor - * @param [in] biasDesc descriptor of bias tensor - * @param [in] dataTypeTransmode mode of data type transform - * @param [in] weightCompressInfo compress info, compute based on tiling method - * @param [in|out] outputSize output data size in byte - * @param [in|out] infoTabSize compress info table - * @return ccStatus_t - */ -ccStatus_t ccGetCompressedFcWeightInfo(const ccTensorDescriptor_t xDesc, const ccFilterDescriptor_t wDesc, - const ccTensorDescriptor_t biasDesc, ccDataTypeTransMode_t dataTypeTransmode, - ccWeightCompressInfo_t *weightCompressInfo, uint32_t *outputSize, - uint32_t *infoTabSize); -/** - * @ingroup dnn - * @brief compress fc - * @param [in] wDesc descriptor of weight tensor - * @param [in] w filter data in device memory - * @param [in] weightCompressInfo compress info, compute based on tiling method - * @param [in] dataTypeTransmode mode of data type transform - * @param [in|out] y output data in device memory - * @param [in] ySize transformed data size in byte - * @param [in|out] yCompressedSize compressed output data size in byte - * @param [in|out] infoTab compressed info table - * @param [in] infoTabSize compressed info table size in byte - * @return ccStatus_t - */ -ccStatus_t ccCompressWeight(const ccFilterDescriptor_t wDesc, const void *w, - const ccWeightCompressInfo_t *weightCompressInfo, ccDataTypeTransMode_t dataTypeTransmode, - ccFilterDescriptor_t yDesc, void *y, uint32_t ySize, uint32_t *yCompressedSize, - void *infoTab, uint32_t infoTabSize); - -/** - * @ingroup dnn - * @brief restore compressed fc data - * @param [in] x input data in device memory - * @param [in] xSizeInBytes input compressed weight data size in byte - * @param [in|out] y output data in device memory - * @param [in] ySizeInBytes output data size in byte - * @return ccStatus_t - */ -ccStatus_t ccRestoreCompressedWeight(const void *x, uint32_t xSizeInBytes, void *y, uint32_t ySizeInBytes, - rtMemcpyKind_t kind); - -/** - * @ingroup dnn - * @brief create quantize parameters struct - * @param [in|out] quantizeInfo descriptor of quantize parameters - * @return ccStatus_t - */ -ccStatus_t ccCreateQuantizeInfoTab(ccQuantizeDescriptor_t *quantizeInfo); - -/** - * @ingroup dnn - * @brief destroy quantize parameters struct - * @param [in] quantizeInfo descriptor of quantize parameters - * @return ccStatus_t - */ -ccStatus_t ccDestoryQuantizeInfoTab(ccQuantizeDescriptor_t *quantizeInfo); - -/** - * @ingroup dnn - * @brief set quantize parameters - * @param [in] quantizeInfo descriptor of quantize parameters - * @param [in] scaleValMode enmu type for quantize scale value type (normal or sqrt) - * @param [in] scale quantize scale value - * @param [in] offset quantize offset(when quantize algorithm is half offset or full offset,this should be - * configed) - * @param [in] offsetPad padding value for load3d (only for half offset or full offset) - * @return ccStatus_t - */ -ccStatus_t ccSetQuantizeFactors(ccQuantizeDescriptor_t quantizeInfo, ccScaleValueMode_t scaleValMode, - const uint16_t *scale, const uint16_t *offset, const uint8_t *offsetPad); - -/** - * @ingroup dnn - * @brief set Requantize parameters - * @param [in] quantizeInfo descriptor of quantize parameters - * @param [in] scaleValMode enmu type for requantize scale value type (normal or sqrt) - * @param [in] scale quantize scale value - * @param [in] offset quantize offset(when quantize algorithm is half offset or full offset,this should be - * configed) - * @param [in] offsetw offset for filter (only config for full offset quantize) - * @return ccStatus_t - */ -ccStatus_t ccSetReQuantizeFactors(ccQuantizeDescriptor_t quantizeInfo, ccScaleValueMode_t scaleValMode, - const uint16_t *scaleRq, const uint16_t *nextLayerOffset, const int32_t *offsetw); - -/** - * @ingroup dnn - * @brief set Dequantize parameters - * @param [in] quantizeInfo descriptor of quantize parameters - * @param [in] scaleValMode enmu type for dequantize scale value type (normal or sqrt) - * @param [in] scaleDq quantize scale value - * @param [in] offsetw offset for filter (only config for full offset quantize) - * @return ccStatus_t - */ -ccStatus_t ccSetDeQuantizeFactors(ccQuantizeDescriptor_t quantizeInfo, ccScaleValueMode_t scaleValMode, - const uint16_t *scaleDq, const int32_t *offsetw); - -/** - * @ingroup dnn - * @brief set convolution desciptor's quantize parameters - * @param [in] convDesc convolution descriptor - * @param [in] quantizeInfo descriptor of quantize parameters - * @return ccStatus_t - */ -ccStatus_t ccSetConvolutionQuantizeInfo(ccConvolutionDescriptor_t convDesc, const ccQuantizeDescriptor_t QuantizeInfo); - -/** - * @ingroup dnn - * @brief set convolution desciptor's all offset quantize parameters - * @param [in] convDesc convolution descriptor - * @param [in] offsetw descriptor of quantize parameters - * @param [in] scaleReq descriptor of quantize parameters - * @param [in] offset_d_next descriptor of quantize parameters - * @return ccStatus_t - */ -ccStatus_t ccSetAllOffsetQuantizeFactors(ccQuantizeDescriptor_t quantizeInfo, const uint8_t *offsetW, - const uint8_t *offsetD, const uint16_t *scaleReq, const uint16_t *offsetDNext); - -/** - * @ingroup dnn - * @brief set full connection desciptor's quantize parameters - * @param [in] fcDesc full connection descriptor - * @param [in] quantizeInfo descriptor of quantize parameters - * @return ccStatus_t - */ -ccStatus_t ccSetFullConnectionQuantizeInfo(ccFullConnectionDescriptor_t fcDesc, - const ccQuantizeDescriptor_t QuantizeInfo); - -/** - * @ingroup dnn - * @brief set pooling desciptor's quantize parameters - * @param [in] poolingDesc pooling descriptor - * @param [in] quantizeInfo descriptor of quantize parameters - * @return ccStatus_t - */ -ccStatus_t ccSetPoolingQuantizeInfo(ccPoolingDescriptor_t poolingDesc, const ccQuantizeDescriptor_t QuantizeInfo); - -/** - * @ingroup dnn - * @brief set full connection desciptor's info table - * @param [in] fcDesc full connection descriptor - * @param [in] infoTabSize table size - * @param [in] infoTab pointer to info table - * @return ccStatus_t - */ -ccStatus_t ccSetFullConnectionDescriptor(ccFullConnectionDescriptor_t fcDesc, uint32_t infoTabSize, const void *infoTab, - ccFullConnectFwdAlgo_t algo = CC_FULLCONNECT_FWD_ALGO_HALF); - -/** - * @ingroup dnn - * @brief set full connection desciptor's relu flag - * @param [in] fcDesc full connection descriptor - * @param [in] opType operation type for append at convolution operation - * @param [in] opDesc operation descritpor for the opType - * @return ccStatus_t - */ -ccStatus_t ccFullConnectionAppendOp(ccFullConnectionDescriptor_t fcDesc, tagCcOpType opType, const void *opDesc); - -/** - * @ingroup dnn - * @brief check aipp basic info - * @param [in] inputFormat format of input image - * @param [in] loadStartPosH vertical start position in source image - * @param [in] loadStartPosW horizontal start position in source image - * @param [in] srcImageSizeH vertical size of source image - * @param [in] srcImageSizeW horizontal size of source image - * @param [in] cpaddingValue C direction padding value - * @param [in] cscSwitch csc enable or not - * @param [in] rbuvSwapSwitch swap R/U and B/V position of the image - * @param [in] axSwapSwitch swap RGBA->ARGB, YUVA->AYUV - * @param [in] singleLineMode when set this bit to 1, only read 1 line. Under this case, vertical size configuration is - * not useful. - * @return ccStatus_t - */ -ccStatus_t ccCheckConvolutionAippCommInfo(ccAippInputFormat_t inputFormat, int32_t loadStartPosW, int32_t loadStartPosH, - int32_t srcImageSizeW, int32_t srcImageSizeH, float cpaddingValue, - bool cscSwitch, bool rbuvSwapSwitch, bool axSwapSwitch, bool singleLineMode); - -/** - * @ingroup dnn - * @brief check aipp dtc info - * @param [in] dtcPixelMeanChnx Mean value for YUV or RGB data channel x - * @param [in] dtcPixelMinChnx Min value for YUV or RGB data channel x - * @param [in] dtcPixelVarReciChnx Reciprocal of variance or (max-min) for YUV or RGB data channel x - * @return ccStatus_t - */ -ccStatus_t ccCheckConvolutionAippDtcInfo(int32_t dtcPixelMeanChn0, int32_t dtcPixelMeanChn1, int32_t dtcPixelMeanChn2, - float dtcPixelMinChn0, float dtcPixelMinChn1, float dtcPixelMinChn2, - float dtcPixelVarReciChn0, float dtcPixelVarReciChn1, - float dtcPixelVarReciChn2); - -/** - * @ingroup dnn - * @brief check aipp pad info - * @param [in] paddingMode padding mode - * @param [in] leftPaddingSize left hblank/padding size - * @param [in] rightPaddingSize right hblank/padding size - * @param [in] topPaddingSize top padding size - * @param [in] bottomPaddingSize bottom padding size - * @return ccStatus_t - */ -ccStatus_t ccCheckConvolutionAippPadInfo(ccAippPaddingMode_t paddingMode, int32_t leftPaddingSize, - int32_t rightPaddingSize, int32_t topPaddingSize, int32_t bottomPaddingSize); - -/** - * @ingroup dnn - * @brief check aipp csc info - * @param [in] cscMatrixRmCn 3x3 CSC matrix for YUV to RGB or RGB to YUV, element of row m and column n - * @param [in] cscOutputBiasm output Bias for RGB to YUV, element of row m - * @param [in] cscInputBiasm input Bias for YUV to RGB, element of row m - * @return ccStatus_t - */ -ccStatus_t ccCheckConvolutionAippCscInfo(int32_t cscMatrixR0C0, int32_t cscMatrixR0C1, int32_t cscMatrixR0C2, - int32_t cscMatrixR1C0, int32_t cscMatrixR1C1, int32_t cscMatrixR1C2, - int32_t cscMatrixR2C0, int32_t cscMatrixR2C1, int32_t cscMatrixR2C2, - int32_t cscOutputBias0, int32_t cscOutputBias1, int32_t cscOutputBias2, - int32_t cscInputBias0, int32_t cscInputBias1, int32_t cscInputBias2); - -/** - * @ingroup dnn - * @brief check aipp scf info - * @param [in] scfSwitch scaling enable or not - * @param [in] scfInputW input width of scaling - * @param [in] scfInputH input height of scaling - * @param [in] scfOutputW output width of scaling - * @param [in] scfOutputH output height of scaling - * @return ccStatus_t - */ -ccStatus_t ccCheckConvolutionAippScfInfo(bool scfSwitch, int32_t scfInputW, int32_t scfInputH, int32_t scfOutputW, - int32_t scfOutputH); - -/** - * @ingroup dnn - * @brief check aipp param - * @param [in] convDesc descriptor of conv operator - * @param [in] xDesc input tensor info - * @param [in] yDesc output tensor info - * @return ccStatus_t - */ -ccStatus_t ccCheckConvFwdAippParam(const ccConvolutionDescriptor_t convDesc, const ccTensorDescriptor_t xDesc, - const ccTensorDescriptor_t yDesc); - -/** - * @ingroup dnn - * @brief init aipp basic info - * @param [in|out] convDesc descriptor of conv operator - * @param [in] inputFormat format of input image - * @param [in] loadStartPosH vertical start position in source image - * @param [in] loadStartPosW horizontal start position in source image - * @param [in] srcImageSizeH vertical size of source image - * @param [in] srcImageSizeW horizontal size of source image - * @param [in] cpaddingValue C direction padding value - * @param [in] cscSwitch csc enable or not - * @param [in] rbuvSwapSwitch swap R/U and B/V position of the image - * @param [in] axSwapSwitch swap RGBA->ARGB, YUVA->AYUV - * @param [in] singleLineMode when set this bit to 1, only read 1 line. Under this case, vertical size configuration is - * not useful. - * @return ccStatus_t - */ -ccStatus_t ccSetConvolutionAippCommInfo(ccConvolutionDescriptor_t convDesc, ccAippInputFormat_t inputFormat, - int32_t loadStartPosW, int32_t loadStartPosH, int32_t srcImageSizeW, - int32_t srcImageSizeH, float cpaddingValue, bool cscSwitch, bool rbuvSwapSwitch, - bool axSwapSwitch, bool singleLineMode); -/** - * @ingroup dnn - * @brief init aipp dtc info - * @param [in|out] convDesc descriptor of conv operator - * @param [in] dtcPixelMeanChnx Mean value for YUV or RGB data channel x - * @param [in] dtcPixelMinChnx Min value for YUV or RGB data channel x - * @param [in] dtcPixelVarReciChnx Reciprocal of variance or (max-min) for YUV or RGB data channel x - * @return ccStatus_t - */ -ccStatus_t ccSetConvolutionAippDtcInfo(ccConvolutionDescriptor_t convDesc, int32_t dtcPixelMeanChn0, - int32_t dtcPixelMeanChn1, int32_t dtcPixelMeanChn2, float dtcPixelMinChn0, - float dtcPixelMinChn1, float dtcPixelMinChn2, float dtcPixelVarReciChn0, - float dtcPixelVarReciChn1, float dtcPixelVarReciChn2); -/** - * @ingroup dnn - * @brief init aipp pad info - * @param [in|out] convDesc descriptor of conv operator - * @param [in] paddingMode padding mode - * @param [in] leftPaddingSize left hblank/padding size - * @param [in] rightPaddingSize right hblank/padding size - * @param [in] topPaddingSize top padding size - * @param [in] bottomPaddingSize bottom padding size - * @return ccStatus_t - */ -ccStatus_t ccSetConvolutionAippPadInfo(ccConvolutionDescriptor_t convDesc, ccAippPaddingMode_t paddingMode, - int32_t leftPaddingSize, int32_t rightPaddingSize, int32_t topPaddingSize, - int32_t bottomPaddingSize); - -/** - * @ingroup dnn - * @brief init aipp csc info - * @param [in|out] convDesc descriptor of conv operator - * @param [in] cscMatrixRmCn 3x3 CSC matrix for YUV to RGB or RGB to YUV, element of row m and column n - * @param [in] cscOutputBiasm output Bias for RGB to YUV, element of row m - * @param [in] cscInputBiasm input Bias for YUV to RGB, element of row m - * @return ccStatus_t - */ -ccStatus_t ccSetConvolutionAippCscInfo(ccConvolutionDescriptor_t convDesc, int32_t cscMatrixR0C0, int32_t cscMatrixR0C1, - int32_t cscMatrixR0C2, int32_t cscMatrixR1C0, int32_t cscMatrixR1C1, - int32_t cscMatrixR1C2, int32_t cscMatrixR2C0, int32_t cscMatrixR2C1, - int32_t cscMatrixR2C2, int32_t cscOutputBias0, int32_t cscOutputBias1, - int32_t cscOutputBias2, int32_t cscInputBias0, int32_t cscInputBias1, - int32_t cscInputBias2); - -/** - * @ingroup dnn - * @brief init aipp scf info - * @param [in|out] convDesc descriptor of conv operator - * @param [in] scfSwitch scaling enable or not - * @param [in] scfInputW input width of scaling - * @param [in] scfInputH input height of scaling - * @param [in] scfOutputW output width of scaling - * @param [in] scfOutputH output height of scaling - * @return ccStatus_t - */ -ccStatus_t ccSetConvolutionAippScfInfo(ccConvolutionDescriptor_t convDesc, bool scfSwitch, int32_t scfInputW, - int32_t scfInputH, int32_t scfOutputW, int32_t scfOutputH); - -/** - * @ingroup dnn - * @brief set dynamic aipp parameter address and enflag info - * @param [in|out] convDesc descriptor of conv operator - * @param [in] dyncParaAddr aipp parameter address - * @param [in] dyncAippFlag flag to show whether to use dynamic aipp - * @return ccStatus_t - */ -ccStatus_t ccSetConvolutionAippDyncParaAddr(ccConvolutionDescriptor_t convDesc, const void *dyncParaAddr, - bool dyncAippFlag, bool rotationFlag = false); - -/** - * @ingroup dnn - * @brief check dynamic aipp parameter - * @param [in] dyncParaAddr aipp parameter address - * @param [in] dataLength parameter lenght - * @param [in] convolutionDimW convDimW - * @param [in] convolutionDimH convDimH - * @return ccStatus_t - */ -ccStatus_t ccCheckDynamicAippParam(const void *dynamicParamAddr, uint32_t dataLength, int64_t convolutionDimW, - int64_t convolutionDimH); - -/*** @ingroup dnn - * @brief trans mean and var - * @param [in|out] mean' = bnScale/sqrt(var) - * @param [in|out] var' = -bnScale * mean / sqrt(var) + bnBias - * @return ccStatus_t - */ - -ccStatus_t ccTransBatchnormMeanAndVar(void *mean, void *var, const ccTensorDescriptor_t bnScaleBiasMeanVarDesc, - const void *alpha, const void *beta, void *bnScale, void *bnBias, double epsilon); - -/** - * @ingroup dnn - * @brief init deconvolution adj or targetShape info. - * @param [in] convDesc conv descriptor. - * @param [in] adjH, adjust H output. - * @param [in] adjW, adjust W output. - * @param [in] targetShape, values of output shape, if this pointer was set, ignore adj. - * @return ccStatus_t - */ -ccStatus_t ccSetDeconvolutionOutShapeInfo(ccConvolutionDescriptor_t convDesc, uint32_t adjSize, const uint32_t *adj, - uint32_t targetShapeSize, const uint32_t *targetShape); - -/** - * @ingroup dnn - * @brief gather elements according to the indices. - * @param [in] alpha reserved. - * @param [in] xDesc description of the tensor from which to gather elements. - * @param [in] x data point of the tensor from which to gather elements. - * @param [in] indicesDesc description of the tensor of indices. - * @param [in] indices data point of the tensor of indices. - * @param [in] beta reserved. - * @param [in] outputDesc description of the output tensor. - * @param [output] output data point of the output tensor. - * @return ccStatus_t - */ -ccStatus_t ccGatherNdForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t indicesDesc, const void *indices, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief get output shape of gather_nd. - * @param [in] xDesc description of the tensor from which to gather elements. - * @param [in] indicesDesc description of the tensor of indices. - * @param [output] n dim-size of n-dim. - * @param [output] c dim-size of c-dim. - * @param [output] h dim-size of h-dim. - * @param [output] w dim-size of w-dim. - * @param [output] realDimCnt real dim. - * @return ccStatus_t - */ -ccStatus_t ccGetGatherNdOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t indicesDesc, int32_t *n, - int32_t *c, int32_t *h, int32_t *w, int32_t *realDimCnt); -/** - * @ingroup dnn - * @brief get output shape of realdiv. - * @param [in] xDesc description of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [output] dimCnt dim nums. - * @param [output] dim dim size. - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetGatherNdOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t indicesDesc, - int32_t *dimCnt, int32_t *dim, int32_t dimLen); -/** - * @ingroup dnn - * @brief tile tensor by multiples. - * @param [in] alpha reserved. - * @param [in] xDesc description of the tensor which to be tiled. - * @param [in] x data point of the tensor which to be tiled. - * @param [in] multiples tile coefficient of each dim. - * @param [in] beta reserved. - * @param [in] outputDesc description of the output tensor. - * @param [output] output data point of the output tensor. - * @return ccStatus_t - */ -ccStatus_t ccTileForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccIntArray_t *multiples, const void *beta, const ccTensorDescriptor_t outputDesc, - void *output); - -/** - * @ingroup dnn - * @brief get output shape of tile. - * @param [in] xDesc description of the dividend tensor. - * @param [in] multiples multiples of each dim. - * @param [in|out] dimCnt [point to the output dimCnt] - * @param [in|out] dim [arrays to save dims] - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetTileOutputDim(const ccTensorDescriptor_t xDesc, const ccIntArray_t *multiples, int32_t *dimCnt, - int32_t dim[], int32_t dimLen); - -/** - * @ingroup dnn - * @brief get output shape of tile. - * @param [in] xDesc description of the dividend tensor. - * @param [in] multiples multiples of each dim. - * @param [output] n dim-size of n-dim. - * @param [output] c dim-size of c-dim. - * @param [output] h dim-size of h-dim. - * @param [output] w dim-size of w-dim. - * @param [output] realDimCnt real dim. - * @return ccStatus_t - */ -ccStatus_t ccGetTileOutputDim(const ccTensorDescriptor_t xDesc, - // const ccIntArrayDescriptor_t multiples, - const ccIntArray_t *multiples, int32_t *n, int32_t *c, int32_t *h, int32_t *w, - int32_t *realDimCnt); -/** - * @ingroup dnn - * @brief get output shape of realdiv. - * @param [in] xDesc description of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [output] dimCnt dim nums. - * @param [output] dim dim size. - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetRealdivOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, - int32_t *dim, int32_t dimLen); - -/** - * @ingroup dnn - * @brief realdiv between two tensors. - * @param [in] alpha reserved. - * @param [in] xDesc description of the dividend tensor. - * @param [in] x data point of the dividend tensor. - * @param [in] yDesc description of the divisor tensor. - * @param [in] y data point of the divisor tensor. - * @param [in] beta reserved. - * @param [in] outputDesc description of the output tensor. - * @param [output] output data point of the output tensor. - * @return ccStatus_t - */ -ccStatus_t ccRealdivForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t yDesc, const void *y, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief get output shape of realdiv. - * @param [in] xDesc description of the dividend tensor. - * @param [in] yDesc description of the divisor tensor. - * @param [output] n dim-size of n-dim. - * @param [output] c dim-size of c-dim. - * @param [output] h dim-size of h-dim. - * @param [output] w dim-size of w-dim. - * @param [output] realDimCnt real dim. - * @return ccStatus_t - */ -ccStatus_t ccGetRealdivOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *n, - int32_t *c, int32_t *h, int32_t *w, int32_t *realDimCnt); - -/** - * @ingroup dnn - * @brief realdiv between two tensors. - * @param [in] alpha reserved. - * @param [in] xDesc description of the left operator tensor. - * @param [in] x data point of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [in] y data point of the right operator tensor. - * @param [in] beta reserved. - * @param [in] outputDesc description of the output tensor. - * @param [output] output data point of the output tensor. - * @return ccStatus_t - */ -ccStatus_t ccFloordivForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t yDesc, const void *y, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief get output shape of realdiv. - * @param [in] xDesc description of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [output] realDimCnt real dim. - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetFloordivOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, - int32_t *dim, int32_t dimLen); - -/** - * @ingroup dnn - * @brief realdiv between two tensors. - * @param [in] alpha reserved. - * @param [in] xDesc description of the left operator tensor. - * @param [in] x data point of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [in] y data point of the right operator tensor. - * @param [in] beta reserved. - * @param [in] outputDesc description of the output tensor. - * @param [output] output data point of the output tensor. - * @return ccStatus_t - */ -ccStatus_t ccGreaterForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t yDesc, const void *y, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief get output shape of realdiv. - * @param [in] xDesc description of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [output] dimCnt dim nums. - * @param [output] dim dim size. - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetGreaterOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, - int32_t *dim, int32_t dimLen); - -/** - * @ingroup dnn - * @brief realdiv between two tensors. - * @param [in] alpha reserved. - * @param [in] xDesc description of the left operator tensor. - * @param [in] x data point of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [in] y data point of the right operator tensor. - * @param [in] beta reserved. - * @param [in] outputDesc description of the output tensor. - * @param [output] output data point of the output tensor. - * @return ccStatus_t - */ -ccStatus_t ccLessForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t yDesc, const void *y, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief get output shape of realdiv. - * @param [in] xDesc description of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [output] dimCnt dim nums. - * @param [output] dim dim size. - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetLessOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, - int32_t *dim, int32_t dimLen); - -/** - * @ingroup dnn - * @brief get output shape of LogicalOr. - * @param [in] xDesc description of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [output] dimCnt dim nums. - * @param [output] dim dim size. - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetLogicalOrOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, - int32_t *dim, int32_t dimLen); - -/** - * @ingroup dnn - * @brief get output shape of LogicalXor. - * @param [in] xDesc description of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [output] dimCnt dim nums. - * @param [output] dim dim size. - * @param [in] dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetLogicalXorOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, - int32_t *dim, int32_t dimLen); - -/** - * @ingroup dnn - * @brief sqrt forward: - * data type only support bool - * data format only support ND - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccLogicalNotForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const void *beta, const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief equal between two tensors. - * @param [in] alpha reserved. - * @param [in] xDesc description of the left operator tensor. - * @param [in] x data point of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [in] y data point of the right operator tensor. - * @param [in] beta reserved. - * @param [in] outputDesc description of the output tensor. - * @param [output] output data point of the output tensor. - * @return ccStatus_t - */ - -ccStatus_t ccEqualForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t yDesc, const void *y, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief dump data during inference, only for eng ver. - * @param [in] handle cce handle - * @return ccStatus_t - */ -ccStatus_t ccDataDumpForward(ccHandle_t handle, const void *buffer, const uint64_t bufLen, const uint32_t taskIndex); - -/** - * @ingroup dnn - * @brief logicaland between two tensors. - * @param [in] alpha reserved. - * @param [in] xDesc description of the left operator tensor. - * @param [in] x data point of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [in] y data point of the right operator tensor. - * @param [in] beta reserved. - * @param [in] outputDesc description of the output tensor. - * @param [output] output data point of the output tensor. - * @return ccStatus_t - */ -ccStatus_t ccLogicalAndForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t yDesc, const void *y, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief logical or between two tensors. - * @param [in] alpha reserved. - * @param [in] xDesc description of the left operator tensor. - * @param [in] x data point of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [in] y data point of the right operator tensor. - * @param [in] beta reserved. - * @param [in] outputDesc description of the output tensor. - * @param [output] output data point of the output tensor. - * @return ccStatus_t - */ -ccStatus_t ccLogicalOrForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t yDesc, const void *y, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); -/** - * @ingroup dnn - * @brief logical Xor between two tensors(x ^ y = (x | y) & ~(x & y). - * @param [in] alpha reserved. - * @param [in] xDesc description of the left operator tensor. - * @param [in] x data point of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [in] y data point of the right operator tensor. - * @param [in] beta reserved. - * @param [in] outputDesc description of the output tensor. - * @param [output] output data point of the output tensor. - * @return ccStatus_t - */ -ccStatus_t ccLogicalXorForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t yDesc, const void *y, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief get output shape of equal. - * @param [in] xDesc description of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [output] dimCnt dim nums. - * @param [output] dim dim size. - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetEqualOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, - int32_t *dim, int32_t dimLen); -/** - * @ingroup dnn - * @brief get output shape of logicaland. - * @param [in] xDesc description of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [output] dimCnt dim nums. - * @param [output] dim dim size. - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetLogicalAndOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, - int32_t *dim, int32_t dimLen); -/** - * @ingroup dnn - * @brief realdiv between two tensors. - * @param [in] alpha reserved. - * @param [in] xDesc description of the left operator tensor. - * @param [in] x data point of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [in] y data point of the right operator tensor. - * @param [in] beta reserved. - * @param [in] outputDesc description of the output tensor. - * @param [output] output data point of the output tensor. - * @return ccStatus_t - */ -ccStatus_t ccFloormodForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t yDesc, const void *y, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief get output shape of realdiv. - * @param [in] xDesc description of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [output] dimCnt dim nums. - * @param [output] dim dim size. - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetFloormodOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, - int32_t *dim, int32_t dimLen); - -/** - * @ingroup dnn - * @brief compare between two tensors. - * @param [in] alpha reserved. - * @param [in] xDesc description of the left operator tensor. - * @param [in] x data point of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [in] y data point of the right operator tensor. - * @param [in] beta reserved. - * @param [in] outputDesc description of the output tensor. - * @param [output] output data point of the output tensor. - * @return ccStatus_t - */ -ccStatus_t ccCompareForward(ccHandle_t handle, ccCompareType_t compareType, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const ccTensorDescriptor_t yDesc, - const void *y, const void *beta, const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief get output shape of realdiv. - * @param [in] xDesc description of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [output] dimCnt dim nums. - * @param [output] dim dim size. - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetCompareOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, - int32_t *dim, int32_t dimLen); - -/** - * @ingroup dnn - * @brief create descriptor of FillParam - * @param [in|out] fillParamDesc point to descriptor of fill param - * @return ccStatus_t - */ -ccStatus_t ccCreateFillParamDescriptor(ccFillParamDescriptor_t *fillParamDesc); - -/** - * @ingroup dnn - * @brief destroy descriptor of FillParam - * @param [in] *fillParamDesc point to descriptor of fill param - * @return ccStatus_t - */ -ccStatus_t ccDestroyFillParamDescriptor(ccFillParamDescriptor_t *fillParamDesc); - -/** - * @ingroup dnn - * @brief get output shape of broadcat operations. - * @param [in] inputNum input number of the operation tensors. - * @param [in] xDesc[] description of the input operation tensors list. - * @param [output] dimCnt dim-size of output tensor. - * @param [output] dim dim of output tensor. - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetMultiNdBroadcastOpOutputDim(const int32_t inputNum, const ccTensorDescriptor_t xDesc[], int32_t *dimCnt, - int32_t *dim, int32_t dimLen); - -/** - * @ingroup dnn - * @brief get output shape of maximultitensor. - * @param [in] inputNum the num of input operator tensors. - * @param [in] xDesc[] description of the input operator tensors list. - * @param [output] dimCnt dim count of output tensor. - * @param [output] dim array of output tensor. - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetMaxMultitensorOutputDim(const int32_t inputNum, const ccTensorDescriptor_t xDesc[], int32_t *dimCnt, - int32_t *dim, int32_t dimLen); - -/** - * @ingroup dnn - * @brief get output shape of minmultitensor. - * @param [in] inputNum the num of input operator tensors. - * @param [in] xDesc[] description of the input operator tensors list. - * @param [output] dimCnt dim count of output tensor. - * @param [output] dim array of output tensor. - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetMinMultitensorOutputDim(const int32_t inputNum, const ccTensorDescriptor_t xDesc[], int32_t *dimCnt, - int32_t *dim, int32_t dimLen); - -/** - * @ingroup dnn - * @brief MaxMultitensor forward: - * data type only support float float16 and int32 - * data format only support ND - * @param [in] handle cce handle - * @param [in] inputNum input tensor number - * @param [in] alpha common scale factor - * @param [in] xDesc[] descriptor of input tensors list - * @param [in] x[] input data in device memory list - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccMaxMultitensorForward(const ccHandle_t handle, const int32_t inputNum, const void *alpha, - const ccTensorDescriptor_t xDesc[], const void *x[], const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief MinMultitensor forward: - * data type only support float float16 and int32 - * data format only support ND - * @param [in] handle cce handle - * @param [in] inputNum input tensor number - * @param [in] alpha common scale factor - * @param [in] xDesc[] descriptor of input data list - * @param [in] x[] input data in device memory list - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccMinMultitensorForward(const ccHandle_t handle, const int32_t inputNum, const void *alpha, - const ccTensorDescriptor_t xDesc[], const void *x[], const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief create descriptor of StridedSlice - * @param [in|out] stridedSliceDesc point to descriptor of StridedSlice param - * @return ccStatus_t - */ -ccStatus_t ccCreateStridedSliceDescriptor(ccStridedSliceDescriptor_t *stridedSliceDesc); - -/** - * @ingroup dnn - * @brief destroy descriptor of StridedSlice - * @param [in] *stridedSliceDesc point to descriptor of StridedSlice param - * @return ccStatus_t - */ -ccStatus_t ccDestroyStridedSliceDescriptor(ccStridedSliceDescriptor_t *stridedSliceDesc); - -/** - * @ingroup dnn - * @brief init stridedSlice descriptor_t. - * @param [out] stridedSliceDesc struct of stridedslice param - * @param [in] dimCnt dimension of the input tensor - * @param [in] begin slice begin(include) - * @param [in] end slice end index(not include) - * @param [in] strides slice stride - * @return ccStatus_t - */ -ccStatus_t ccSetStridedSliceDescriptor(ccStridedSliceDescriptor_t stridedSliceDesc, int32_t dimCnt, int32_t begin[], - int32_t end[], int32_t strides[]); - -/** - * @ingroup dnn - * @brief create descriptor of StridedSlice - * @param [in|out] stridedSliceDesc point to descriptor of StridedSlice attr - * @return ccStatus_t - */ -ccStatus_t ccCreateStridedSliceAttrsDescriptor(ccStridedSliceAttrsDescriptor_t *attrDesc); - -/** - * @ingroup dnn - * @brief destroy descriptor of StridedSlice - * @param [in] *stridedSliceDesc point to descriptor of StridedSlice attr - * @return ccStatus_t - */ -ccStatus_t ccDestroyStridedSliceAttrsDescriptor(ccStridedSliceAttrsDescriptor_t *attrDesc); - -/** - * @ingroup dnn - * @brief init stridedSlice mask attrs desescriptor. - * @param [out] attrDesc struct of stridedslice mask attrs - * @param [in] beginMask begin mask - * @param [in] endMask end mask - * @param [in] ellipsisMask ellipsis mask - * @param [in] newAxisMask new axis mask - * @param [in] shrinkAxisMask shrink axis mask - * @return ccStatus_t - */ -ccStatus_t ccSetStridedSliceAttrsDescriptor(ccStridedSliceAttrsDescriptor_t attrDesc, int32_t beginMask, - int32_t endMask, int32_t ellipsisMask, int32_t newAxisMask, - int32_t shrinkAxisMask); - -/** - * @ingroup dnn - * @brief Extracts a strided slice of a tensor. - * @param [in] xDesc descriptor of input data - * @param [in] stridedSliceDesc specifies the begin, end, strides of slice - * @param [in] attrDesc reserve for optional attributes. - * @param [out] n point to n size - * @param [out] c point to c size - * @param [out] h point to h size - * @param [out] w point to w size - * @return ccStatus_t - */ -ccStatus_t ccGetStridedSliceOutputDim(const ccTensorDescriptor_t xDesc, - const ccStridedSliceDescriptor_t stridedSliceDesc, - const ccStridedSliceAttrsDescriptor_t attrDesc, int32_t *n, int32_t *c, - int32_t *h, int32_t *w, int32_t *realDimCnt); - -/** - * @ingroup dnn - * @brief Extracts a strided slice of a tensor. - * @param [in] handle cce handle - * @param [in] stridedSliceDesc specifies the begin, end, strides of slice - * @param [in] attrDesc reserve for optional attributes. - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] beta common scale factor - * @param [in] yDesc descriptor of output data - * @param [in|out] y output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccStridedSliceForward(ccHandle_t handle, const ccStridedSliceDescriptor_t stridedSliceDesc, - const ccStridedSliceAttrsDescriptor_t attrDesc, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t yDesc, void *y); - -/** - * @ - * @brief get out put descrition of slice tensor. - * @param [in] xDesc descriptor of input data - * @param [in] begin begin position of tensor - * @param [in] size size to slice - * @param [out] n point to n size - * @param [out] c point to c size - * @param [out] h point to h size - * @param [out] w point to w size - * @param [out] realDimCnt realdim count - * @return ccStatus_t - */ -ccStatus_t ccGetSliceOutputDim(const ccTensorDescriptor_t xDesc, const ccIntArray_t *begin, const ccIntArray_t *size, - int32_t *n, int32_t *c, int32_t *h, int32_t *w, int32_t *realDimCnt); - -/** - * @ingroup dnn - * @brief slice of a tensor. - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] begin begin position of tensor - * @param [in] size size to slice - * @param [in] beta common scale factor - * @param [in] yDesc descriptor of output data - * @param [in|out] y output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccSliceForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccIntArray_t *begin, const ccIntArray_t *size, const void *beta, - const ccTensorDescriptor_t yDesc, void *y); - -/** - * @ingroup dnn - * @brief gather forward computation - * @param [in] handle cce handle - * @param [in] paramsDesc descriptor of params tensor - * @param [in] params input data in device memory - * @param [in] indicesDesc descriptor of indices tensor - * @param [in] indices indices data in device memory - * @param [in] axis descriptor of roi tensor - * @param [in] alpha reserved - * @param [in] beta reserved - * @param [in] outputDesc descriptor of output tensor - * @param [out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccGatherForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t paramsDesc, - const void *params, const ccTensorDescriptor_t indicesDesc, const void *indices, - const int32_t axis, const void *beta, ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief gather output dim computation, for NC1HWC0 - * @param [in] paramsDesc descriptor of params tensor - * @param [in] indicesDesc descriptor of indices tensor - * @param [in] axis descriptor of roi tensor - * @param [out] n dim of n - * @param [out] c dim of c - * @param [out] h dim of h - * @param [out] w dim of w - * @param [out] realDimCnt real dim count - * @return ccStatus_t - */ -ccStatus_t ccGetGatherOutputDim(const ccTensorDescriptor_t paramsDesc, const ccTensorDescriptor_t indicesDesc, - int32_t axis, int32_t *n, int32_t *c, int32_t *h, int32_t *w, int32_t *realDimCnt); - -/** - * @ingroup dnn - * @brief gather output dim computation - * @param [in] paramsDesc descriptor of params tensor - * @param [in] indicesDesc descriptor of indices tensor - * @param [in] axis descriptor of roi tensor - * @param [out] dimCnt dimcnt of output - * @param [out] dim dim of output - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetGatherOutputDim(const ccTensorDescriptor_t paramsDesc, const ccTensorDescriptor_t indicesDesc, - int32_t axis, int32_t *dimCnt, int32_t dim[], int32_t dimLen); - -/** - * @ingroup dnn - * @brief exp forward computation - * @param [in] handle cce handle - * @param [in] expDesc descriptor of expParam - * @param [in] expParam a ternary array - * @param [in] alpha reserved parameter - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] beta reserved parameter - * @param [in] yDesc descriptor of output tensor - * @param [out] y output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccExpForward(ccHandle_t handle, const ccExpDescriptor_t expDesc, const void *expParam, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t yDesc, void *y); - -/** - * @ingroup dnn - * @brief expm1 forward: - * data type only support float float16 and double - * data format only support ND - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccExpm1Forward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const void *beta, const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief log1p forward: - * data type only support float float16 and double - * data format only support ND - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccLog1pForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const void *beta, const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief init descriptor for parameter of exp function - * @param [in|out] powDesc descriptor of tensor - * @param [in] dataType data type in device - * @param [in] paramCnt number of parameters - * @return ccStatus_t - */ -ccStatus_t ccSetExpDescriptor(ccExpDescriptor_t expDesc, ccDataType_t dataType, uint32_t paramCnt); - -/** - * @ingroup dnn - * @brief exp forward computation - * @param [in] handle cce handle - * @param [in] logDesc descriptor of logParam - * @param [in] logParam a ternary array - * @param [in] alpha reserved parameter - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] beta reserved parameter - * @param [in] yDesc descriptor of output tensor - * @param [in] y output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccLogForward(ccHandle_t handle, const ccLogDescriptor_t logDesc, const void *logParam, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t yDesc, void *y); - -/** - * @ingroup dnn - * @brief init descriptor for parameter of log function - * @param [in|out] logDesc descriptor of tensor - * @param [in] dataType data type in device - * @param [in] paramCnt number of parameters - * @return ccStatus_t - */ -ccStatus_t ccSetLogDescriptor(ccLogDescriptor_t logDesc, ccDataType_t dataType, uint32_t paramCnt); - -/** - * @ingroup dnn - * @brief pow forward computation - * @param [in] handle cce handle - * @param [in] powDesc descriptor of logParam - * @param [in] powParam a ternary array - * @param [in] alpha reserved parameter - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] beta reserved parameter - * @param [in] yDesc descriptor of input tensor - * @param [in] y input data in device memory - * @param [in] zDesc descriptor of output tensor - * @param [out] z output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccPowForward(ccHandle_t handle, const ccPowDescriptor_t powDesc, const void *powParam, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const ccTensorDescriptor_t yDesc, - const void *y, const void *beta, const ccTensorDescriptor_t zDesc, void *z); - -/** - * @brief init descriptor for parameter of pow function - * @param [in|out] powDesc descriptor of tensor - * @param [in] dataType data type in device - * @param [in] paramCnt number of parameters - * @return ccStatus_t - */ -ccStatus_t ccSetPowDescriptor(ccPowDescriptor_t powDesc, ccDataType_t dataType, uint32_t paramCnt); - -/** - * @ingroup dnn - * @brief non max suppression forward. - * @param [in] handle cce handle - * @param [in] nonmaxParaDesc descriptor of para - * @param [in] nonmaxPara input para in host memory - * @param [in] maxoutputsizex input para in host memory - * @param [in] alpha common scale factor - * @param [in] boxesDesc descriptor of input data boxesDesc - * @param [in] boxes input data boxes in device memory - * @param [in] scoresDesc descriptor of input data boxesDesc - * @param [in] scores input data scores in device memory - * @param [in] workSpaceSizeInBytes workspace size - * @param [in] workSpace input workspace in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccNonMaxSuppressionForward(ccHandle_t handle, const ccNonMaxSuppressionDescriptor_t nonmaxParaDesc, - const void *nonmaxPara, const int *maxoutputsize, const void *alpha, - const ccTensorDescriptor_t boxesDesc, const void *boxes, - const ccTensorDescriptor_t scoresDesc, const void *scores, - const uint32_t workSpaceSizeInBytes, void *workSpace, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); -/** - * @brief init descriptor for parameter of NonMaxSuppression function - * @param [in|out] powDesc descriptor of tensor - * @param [in] dataType data type in device - * @param [in] paramCnt number of parameters - * @return ccStatus_t - */ -ccStatus_t ccSetNonMaxSuppressionDescriptor(ccNonMaxSuppressionDescriptor_t nonMaxSuppressionDesc, - ccDataType_t dataType, uint32_t paramCnt); - -/** - * @ingroup dnn - * @brief get the output dimension info of resizeBilinear op. - * @param [in] xDesc descriptor of input data - * @param [in] resizeBilinearDesc descriptor of resize_bilinear operator - * @param [out] dimCnt - * @param [out] dim[] dim of output - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetResizeBilinearOutputDim(const ccTensorDescriptor_t xDesc, - const ccResizeBilinearDescriptor_t resizeBilinearDesc, int32_t *dimCnt, - int32_t dim[], int32_t dimLen); - -/** - * @ingroup dnn - * @brief get the output dimension info of interp op. - * @param [in] xDesc descriptor of input data - * @param [in] resizeBilinearDesc descriptor of resize_bilinear operator - * @param [out] dimCnt - * @param [out] dim[] dim of output - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetInterpOutputDim(const ccTensorDescriptor_t xDesc, const ccResizeBilinearDescriptor_t resizeBilinearDesc, - int32_t *dimCnt, int32_t dim[], int32_t dimLen); -/** - * @ingroup dnn - * @brief resize bilinear forward for t network. - * @param [in] handle cce handle - * @param [in] resizeBilinearDesc descriptor of resize_bilinear operator - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] beta common scale factor - * @param [in] yDesc descriptor of output data - * @param [in|out] y output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccResizeBilinearForward(ccHandle_t handle, const ccResizeBilinearDescriptor_t resizeBilinearDesc, - const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief resize bilinear forward for c network. - * @param [in] handle cce handle - * @param [in] resizeBilinearDesc descriptor of resize_bilinear operator - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] beta common scale factor - * @param [in] yDesc descriptor of output data - * @param [in|out] y output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccInterpForward(ccHandle_t handle, const ccResizeBilinearDescriptor_t resizeBilinearDesc, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief create descriptor of ResizeBilinear - * @param [in|out] resizeBilinearDesc point to descriptor of resizeBilinear attr - * @return ccStatus_t - */ -ccStatus_t ccCreateResizeBilinearDescriptor(ccResizeBilinearDescriptor_t *resizeBilinearDesc); - -/** - * @ingroup dnn - * @brief destroy descriptor of Interp - * @param [in|out] resizeBilinearDesc point to descriptor of resizeBilinear attr - * @return ccStatus_t - */ -ccStatus_t ccDestroyResizeBilinearDescriptor(ccResizeBilinearDescriptor_t *resizeBilinearDesc); - -/** - * @ingroup dnn - * @brief set descriptor of resizeBilinear. - * @param [in|out] resizeBilinearDesc descriptor of resize_bilinear operator - * @param [in] resizeOutputDimMode way to decide output dimensions - * @param [in] alignCorners whether the centers of input and output are aligned - * @param [in] zoom_factor zoom factor - * @param [in] shrink_factor shrink factor - * @param [in] height height of output - * @param [in] width width of output - * @param [in] pad_begin padding at begin of input - * @param [in] pad_end padding at end of input - * @return ccStatus_t - */ -ccStatus_t ccSetResizeBilinearDescriptor(ccResizeBilinearDescriptor_t resizeBilinearDesc, - ccResizeOutputDimMode_t resizeOutputDimMode, bool alignCorners, - int32_t zoom_factor, int32_t shrink_factor, int32_t height, int32_t width, - int32_t pad_begin, int32_t pad_end); - -/** - * @ingroup dnn - * @brief fill forward computation - * @param [in] handle cce handle - * @param [in] fillParamDesc descriptor of fill parameter - * @param [in] alpha reserved - * @param [in] givenDesc descriptor of given tensor - * @param [in] givenData given data in device memory - * @param [in] workspace space for fill algorithm - * @param [in] workSpaceSizeInBytes space size in byte - * @param [in] beta reserved - * @param [in] outputDesc descriptor of output tensor - * @param [out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccFillForward(ccHandle_t handle, const ccFillParamDescriptor_t fillParamDesc, const void *alpha, - const ccTensorDescriptor_t givenDesc, const void *givenData, const void *workspace, - const uint32_t workSpaceSizeInBytes, const void *beta, const ccTensorDescriptor_t outputDesc, - void *output); - -/** - * @ingroup dnn - *[ccGetFillWorkspaceSize] - *@param fillType [fill type] - *@param givenDesc [given tensor descriptor] - *@param xDesc [input tensor descriptor] - *@param sizeInBytes [output size] - *@return ccStatus_t [status] - */ -ccStatus_t ccGetFillWorkspaceSize(const ccFillOpType_t fillType, const ccTensorDescriptor_t xDesc, - uint32_t *sizeInBytes); - -/** - *[ccCast] - *@param handle [cce handler] - *@param alpha [alpha] - *@param xDesc [tensor Description of tensor x] - *@param x [input tensor x] - *@param beta [beta - *@param yDesc [tensor Description of tensor y] - *@param y [output tensor y] - *@return ccStatus_t [status] - */ -ccStatus_t ccCast(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const void *beta, const ccTensorDescriptor_t yDesc, void *y); - -/** - * @ingroup dnn - * @brief round forward: - * data type only support float float16 and int32 - * data format only support ND - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccRoundForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const void *beta, const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief rint forward: - * data type only support float float16 - * data format only support ND - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccRintForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const void *beta, const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief sqrt forward: - * data type only support float float16 - * data format only support ND - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccSqrtForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const void *beta, const ccTensorDescriptor_t outputDesc, void *output); - -/** - *[ccCast] - *@param filterSrcInfo [cce filtersrc descriptor] - *@param filterSrc [filterSrc address] - *@param filterDstInfo [cce filterdst descriptor] - *@param filterDst [filterdst address] - *@param group [group] - *@param ySizeInBytes [fraczfilter size] - *@param outputDataType [datatype] - *@return ccStatus_t [status] - */ -ccStatus_t ccTransGroupConvFilterInt8(ccFilterDescriptor_t filterSrcInfo, const void *filterSrc, - ccFilterDescriptor_t filterDstInfo, void *filterDst, uint32_t group, - uint32_t ySizeInBytes, ccDataType_t outputDataType); - -/** - *[ccGetConcatOutputDim] - *@param xDesc[] [input tensor descriptor] - *@param axis [concat axis] - *@param inputNum [input tensor numbers] - *@param dim[] [output dim] - *@param [in| dimlen length of dim - *@return ccStatus_t [status] - */ -ccStatus_t ccGetConcatOutputDim(const ccTensorDescriptor_t xDesc[], int32_t axis, int32_t inputNum, int32_t *dimCnt, - int32_t dim[], int32_t dimLen); - -/** - * @ingroup dnn - * @brief get the output dimension info of reduce. - * @param [in] xDesc descriptor of input tensor - * @param [in] axis The dimensions to reduce - * @param [in] keepDims If true, retains reduced dimensions with length 1. - * @param [in|out] dimCnt point to the output dimCnt - * @param [in|out] dim arrays to save dims - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetReduceOutputDim(const ccTensorDescriptor_t xDesc, const ccIntArray_t *axis, bool keepDims, - int32_t *dimCnt, int32_t dim[], int32_t dimLen); - -/** - * @ingroup dnn - * @brief reduce sum forward computation - * @param [in] handle cce handle - * @param [in] axis The dimensions to reduce - * @param [in] keepDims If true, retains reduced dimensions with length 1. - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] beta bias factors - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccReduceSumForward(ccHandle_t handle, const ccIntArray_t *axis, bool keepDims, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief reduce max forward computation - * @param [in] handle cce handle - * @param [in] axis The dimensions to reduce - * @param [in] keepDims If true, retains reduced dimensions with length 1. - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] beta bias factors - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccReduceMaxForward(ccHandle_t handle, const ccIntArray_t *axis, bool keepDims, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief reduce min forward computation - * @param [in] handle cce handle - * @param [in] axis The dimensions to reduce - * @param [in] keepDims If true, retains reduced dimensions with length 1. - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] beta bias factors - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccReduceMinForward(ccHandle_t handle, const ccIntArray_t *axis, bool keepDims, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief reduce mean forward computation - * @param [in] handle cce handle - * @param [in] axis The dimensions to reduce - * @param [in] keepDims If true, retains reduced dimensions with length 1. - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] beta bias factors - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccReduceMeanForward(ccHandle_t handle, const ccIntArray_t *axis, bool keepDims, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief reduce prod forward computation - * @param [in] handle cce handle - * @param [in] axis The dimensions to reduce - * @param [in] keepDims If true, retains reduced dimensions with length 1. - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] beta bias factors - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccReduceProdForward(ccHandle_t handle, const ccIntArray_t *axis, bool keepDims, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief reduce all forward computation - * @param [in] handle cce handle - * @param [in] axis The dimensions to reduce - * @param [in] keepDims If true, retains reduced dimensions with length 1. - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] beta bias factors - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccReduceAllForward(ccHandle_t handle, const ccIntArray_t *axis, bool keepDims, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - *@brief print times stats - *@return ccStatus_t [status] - */ -ccStatus_t ccPrintTimeStat(); - -/** - * @ingroup dnn - * @brief reduce abs sum forward computation - * @param [in] handle cce handle - * @param [in] axis The dimensions to reduce - * @param [in] keepDims If true, retains reduced dimensions with length 1. - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] beta bias factors - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccReduceAbsSumForward(ccHandle_t handle, const ccIntArray_t *axis, const bool keepDims, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief reduce square sum forward computation - * @param [in] handle cce handle - * @param [in] axis The dimensions to reduce - * @param [in] keepDims If true, retains reduced dimensions with length 1. - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] beta bias factors - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccReduceSquareSumForward(ccHandle_t handle, const ccIntArray_t *axis, const bool keepDims, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief get the output dimension info of crop and resize - * @param [in] imageDesc descriptor of images - * @param [in] boxesDesc descriptor of boxes - * @param [in] boxidxDesc descriptor of boxidx - * @param [in] resizeHeight resize height - * @param [in] resizeWidth resize width - * @param [out] dimCnt dimcnt of output - * @param [out] dim dim of output - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetCropAndResizeOutputDim(const ccTensorDescriptor_t imageDesc, const ccTensorDescriptor_t boxesDesc, - const ccTensorDescriptor_t boxidxDesc, const int32_t resizeHeight, - const int32_t resizeWidth, int32_t *dimCnt, int32_t dim[], int32_t dimLen); - -/** - * @ingroup dnn - * @brief crop and resize forward. - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] imageDesc descriptor of images - * @param [in] image input data in device memory - * @param [in] boxesDesc descriptor of boxes - * @param [in] boxes input data in device memory - * @param [in] boxidxDesc descriptor of boxidx - * @param [in] boxidx input data in device memory - * @param [in] method enum of resize method - * @param [in] extrapolationValue Value used for extrapolation, when applicable - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccCropAndResizeForward(ccHandle_t handle, const ccResizeMethod_t method, const float extrapolationValue, - const void *alpha, const ccTensorDescriptor_t imageDesc, const void *image, - const ccTensorDescriptor_t boxesDesc, const void *boxes, - const ccTensorDescriptor_t boxidxDesc, const void *boxidx, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief select forward computation - * @param [in] handle cce handle - * @param [in] alpha reserved - * @param [in] condDesc descriptor of cond tensor - * @param [in] cond cond data in device memory - * @param [in] xDesc descriptor of x tensor - * @param [in] x x data in device memory - * @param [in] yDesc descriptor of y tensor - * @param [in] y y data in device memory - * @param [in] beta reserved - * @param [in] outputDesc descriptor of output tensor - * @param [out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccSelect(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t condDesc, const void *cond, - const ccTensorDescriptor_t xDesc, const void *x, const ccTensorDescriptor_t yDesc, const void *y, - const void *beta, const ccTensorDescriptor_t outDesc, void *out); - -/** - * @ingroup dnn - * @brief get the output dimension info of where - * @param [in] xDesc descriptor of input tensor - * @param [in|out] dimCnt point to the output dimCnt - * @param [in|out] dim arrays to save dims - * @return ccStatus_t - */ -ccStatus_t ccGetWhereOutputDim(const ccTensorDescriptor_t xDesc, int32_t *dimCnt, int32_t *dim, int32_t dimLen); - -/** - * @ingroup dnn - * @brief where forward computation - * @param [in] handle cce handle - * @param [in] alpha reserved - * @param [in] condDesc descriptor of cond tensor - * @param [in] cond cond data in device memory - * @param [in] xDesc descriptor of x tensor - * @param [in] x x data in device memory - * @param [in] yDesc descriptor of y tensor - * @param [out] y y data in device memory - * @return ccStatus_t - */ -ccStatus_t ccWhere(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const void *beta, const ccTensorDescriptor_t yDesc, void *y); - -/** - * @ingroup dnn - * @brief reverse forward. - * @param [in] handle cce handle - * @param [in] axis dim that need reverse - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccReverseForward(ccHandle_t handle, const ccIntArray_t *axis, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief floor forward: - * data type only support float float16 - * data format only support ND - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccFloorForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const void *beta, const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief ceil forward: - * data type only support float float16 - * data format only support ND - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccCeilForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const void *beta, const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief get the output dimension info of truncate mod - * @param [in] xDesc descriptor of input tensor - * @param [in] yDesc descriptor of input tensor - * @param [out] dimCnt [dim count of the output tensor] - * @param [out] dim[] [shape of the output tensor] - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetTruncatemodOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, - int32_t *dimCnt, int32_t dim[], int32_t dimLen); - -/** - * @ingroup dnn - * @brief truncate mod forward computation - * @param [in] handle cce handle - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] yDesc descriptor of input tensor - * @param [in] y input data in device memory - * @param [in] beta bias factors - * @param [in] outputDesc descriptor of output tensor - * @param [out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccTruncatemodForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t yDesc, const void *y, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); -/** - * @ingroup dnn - * @brief Spatial Pyramid Pooling - * @param [in] handle cce handle - * @param [in] alpha reserved - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] workspace temp workspace - * @param [in] workspaceSizeInBytes temp workspace size - * @param [in] pyramidHeight pyramid height - * @param [in] poolingMode pooling mode - * @param [in] beta reserved - * @param [in] outputDesc descriptor of output tensor - * @param [out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccSPPForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - void *workspace, const uint32_t workspaceSizeInBytes, const uint32_t pyramidHeight, - const ccPoolingMode_t poolingMode, const void *beta, const ccTensorDescriptor_t outputDesc, - void *output); -/** - * @ingroup dnn - * @brief Get Spatial Pyramid Pooling output dim - * @param [in] xDesc descriptor of input tensor - * @param [in] pyramidHeight pyramid height - * @param [in] dimLen length of dim - * @param [out] dimCnt output tensor dim cnt - * @param [out] dim output tensor dim - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetSPPOutputDim(const ccTensorDescriptor_t xDesc, const uint32_t pyramidHeight, int32_t *dimCnt, - int32_t dim[], const int32_t dimLen); -/** - * @ingroup dnn - * @brief Get Spatial Pyramid Pooling workspace size - * @param [in] xDesc descriptor of input tensor - * @param [in] pyramidHeight pyramid height - * @param [out] workspaceSizeInBytes workspace size - * @return ccStatus_t - */ -ccStatus_t ccGetSPPWorkspaceSize(const ccTensorDescriptor_t xDesc, const uint32_t pyramidHeight, - uint32_t *workspaceSizeInBytes); - -/** - * @ingroup dnn - * @brief BNLL forward computation - * @param [in] handle cce handle - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] beta bias factors - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccBNLLForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const void *beta, const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief bias forward. - * @param [in] handle cce handle - * @param [in] axis axis - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data x - * @param [in] x input data x in device memory - * @param [in] biasDesc descriptor of input data bias - * @param [in] bias input data bias in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccBiasForward(ccHandle_t handle, const int axis, const void *alpha, const ccTensorDescriptor_t xDesc, - const void *x, const ccTensorDescriptor_t biasDesc, const void *bias, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief threshold forward computation - * @param [in] handle cce handle - * @param [in] threshold threshold - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] beta bias factors - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccThresholdForward(ccHandle_t handle, const void *threshold, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief shufflechannel forward. - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] group number of groups - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -// TODO AICPU: please add shufflechannel custom params and comment -ccStatus_t ccShuffleChannelForward(ccHandle_t handle, const void *alpha, uint32_t group, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief mvn forward. - * @param [in] handle cce handle - * @param [in] acrossChannel across channel. true: across, false: not - * @param [in] normalizeVariance normalizeVariance. true: normalizeVariance, false: not - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccMVNForward(ccHandle_t handle, bool acrossChannel, bool normalizeVariance, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, void *workSpace, uint32_t workSpaceSizeInBytes, - const void *beta, const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief get the workspace size of mvn - * @param [in] xDesc descriptor of input data - * @param [in] acrossChannel across channel. true: across, false: not - * @param [in|out] sizeInBytes Workspace size need for whole computation - */ -ccStatus_t ccGetMVNWorkspaceSize(const ccTensorDescriptor_t xDesc, bool acrossChannel, uint32_t *sizeInBytes); - -/** - * @ingroup dnn - * @brief heatmap2coord forward output is hotspot value and corresponding coordinates - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] coordh calibration high - * @param [in] coordw calibration wide - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccHeatmap2coordForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - int32_t coordh, int32_t coordw, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); -/** - * @ingroup dnn - * @brief get the output dimension info of heatmap2coord - * @param [in] xDesc descriptor of input tensor - * @param [in|out] dimCnt point to the output dimCnt - * @param [in|out] dim arrays to save dims - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetHeatmap2coordOutputDim(const ccTensorDescriptor_t xDesc, int32_t *dimCnt, int32_t *dim, int32_t dimLen); - -/** - * @ingroup dnn - * @brief swish forward. - * @param [in] handle cce handle - * @param [in] scale param of swish function, y = x / (1 + sigmoid(scale * x)) - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ - -ccStatus_t ccSwishForward(ccHandle_t handle, const float scale, const void *alpha, const ccTensorDescriptor_t xDesc, - const void *x, const void *beta, const ccTensorDescriptor_t outputDesc, void *output); - -ccStatus_t ccTeForward(ccHandle_t handle, const void *stubFunc, uint32_t coreDim, const void *args, uint32_t argsSize, - const rtL2Ctrl_t *l2ctrl, int32_t inputNum, const ccTensorDescriptor_t xDesc[], const void *x[], - int32_t outputNum, const ccTensorDescriptor_t yDesc[], void *y[], bool isAiCore); - -#ifndef DAVINCI_LITE -ccStatus_t ccAiCpuCustomizeForward(ccHandle_t handle, aicpu_run_func stubFunc, opTensor_t *xOpDesc[], void *x[], - int32_t inputNum, opTensor_t *yOpDesc[], void *y[], void *op_attr_handle, - int32_t outputNum, const ccTensorDescriptor_t xDesc[], - const ccTensorDescriptor_t yDesc[], const void *op_attr_str, uint32_t op_attr_size); -#endif -/** - * @ingroup dnn - * @brief embedding lookup forward. - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data x - * @param [in] x input data x in device memory - * @param [in] idxDesc descriptor of input data idx - * @param [in] idx input data idx in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccEmbeddingLookupForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, - const void *x, const ccTensorDescriptor_t idxDesc, const void *idx, - const void *beta, const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup - * @brief embedding lookup forward. - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] inputNum inputNum - * @param [in] xDesc[] descriptor array of input data x - * @param [in] x[] input data x array in device memory - * @param [in] workSpace workSpace addr - * @param [in] workSpaceSizeInBytes workSpace size - * @param [in] idxDesc descriptor of input data idx - * @param [in] idx input data idx in device memory - * @param [in] partitionStrategy partitionStrategy - * @param [in] maxNorm addr of maxNorm - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccEmbeddingLookupForward(ccHandle_t handle, const void *alpha, const int32_t inputNum, - const ccTensorDescriptor_t xDesc[], const void *x[], void *workSpace, - const uint32_t workSpaceSizeInBytes, const ccTensorDescriptor_t idxDesc, - const void *idx, ccPartitionStrategy_t partitionStrategy, const void *maxNorm, - const void *beta, const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - *[ccGetEmbeddingLookupOutputDim] - *@param inputNum [input tensor numbers] - *@param xDesc[] [input tensor descriptor] - *@param idxDesc [idx tensor descriptor] - *@param dimCnt [output dim count] - *@param dim[] [output dim] - *@param [in| dimlen length of dim - *@return ccStatus_t [status] - */ -ccStatus_t ccGetEmbeddingLookupOutputDim(const int32_t inputNum, const ccTensorDescriptor_t xDesc[], - const ccTensorDescriptor_t idxDesc, int32_t *dimCnt, int32_t dim[], - int32_t dimLen); - -/** - * @ingroup dnn - *[ccGetEmbeddingLookupWorkspaceSize] - *@param inputNum [input tensor numbers] - *@param idxDesc [input tensor descriptor] - *@param isMaxNormExist [isMaxNormExist] - *@param sizeInBytes [output size] - *@return ccStatus_t [status] - */ -ccStatus_t ccGetEmbeddingLookupWorkspaceSize(const int32_t inputNum, const ccTensorDescriptor_t idxDesc, - const bool isMaxNormExist, uint32_t *sizeInBytes); - -/** - * @ingroup dnn - * @brief check if it is the first layer of resnet50 and semecefc - * @param [in] tensorDesc descriptor of input tensor. - * @param [in] convDesc conv descriptor. - * @param [in] filterDesc descriptor of weight tensor. - * @return ccStatus_t - */ -ccStatus_t c04DescParamCheck(const ccTensorDescriptor_t tensorDesc, const ccConvolutionDescriptor_t convDesc, - const ccFilterDescriptor_t filterDesc); - -#ifndef DAVINCI_LITE -/** - * @ingroup dnn - * @brief convolution forward computation - * @param [in] handle cce handle - * @param [in] convDesc descriptor of convolution operator - * @param [in] alpha scaling factors - * @param [in] beta scaling factors - * @param [in] xDesc x descriptor of input tensor - * @param [in] x x data in device memory - * @param [in] dyDesc descriptor of dy - * @param [in] dy dy data in device memory - * @param [in] dwDesc descriptor of dwDesc - * @param [out] dw dw data in device memory - * @param [in] algo algorithm of convolution forward - * @param [in] workSpace temp space, maybe NULL if no need temp space - * @param [in] workSpaceSizeInBytes sizeof workspace - * @return ccStatus_t - */ -ccStatus_t ccConvolutionBackwardFilter(ccHandle_t handle, const ccConvolutionDescriptor_t convDesc, void *alpha, - void *beta, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t dyDesc, const void *dy, - const ccFilterDescriptor_t dwDesc, void *dw, ccConvolutionBwdAlgo_t algo, - void *workSpace, uint32_t workSpaceSizeInBytes); -#endif - -/** - * @ingroup dnn - * @brief get the temp space size of convolution forward computation, maybe no need temp space - * @param [in] handle cce handle - * @param [in] dyDesc descriptor of input tensor dy - * @param [in] convDesc descriptor of convolution operator - * @param [in] xDesc descriptor of input tensor - * @param [in] dwDesc descriptor of filter - * @param [in] algo algorithm of convolution forward - * @param [in|out] sizeInBytes temp space size need for specified algorithm - * @return ccStatus_t - */ -ccStatus_t ccGetConvolutionBackwardFilterWorkspaceSize(ccHandle_t handle, const ccTensorDescriptor_t dyDesc, - const ccConvolutionDescriptor_t convDesc, - const ccTensorDescriptor_t xDesc, - const ccFilterDescriptor_t dwDesc, ccConvolutionBwdAlgo_t algo, - uint32_t *sizeInBytes); - -#ifndef DAVINCI_LITE -ccStatus_t ccBatchNormalizationBackward(ccHandle_t handle, ccBatchNormMode_t mode, const void *alphaDataDiff, - const void *betaDataDiff, const void *alphaParamDiff, const void *betaParamDiff, - const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t dyDesc, const void *dy, - const ccTensorDescriptor_t dxDesc, void *dx, - const ccTensorDescriptor_t bnScaleBiasDiffDesc, const void *bnScale, - void *resultBnScaleDiff, void *resultBnBiasDiff, const void *workSpace, - const uint32_t workSpaceSizeInBytes, double epsilon, const void *SaveMean, - const void *SaveInvVariance); -#endif - -ccStatus_t ccGetBatchNormalizationBackwardWorkspaceSize(ccHandle_t handle, ccBatchNormMode_t mode, - ccTensorDescriptor_t xDesc, ccTensorDescriptor_t dyDesc, - ccTensorDescriptor_t dxDesc, - ccTensorDescriptor_t bnScaleBiasDesc, uint32_t *sizeInBytes); - -#ifndef DAVINCI_LITE -ccStatus_t ccBatchNormalizationForwardTraining(ccHandle_t handle, ccBatchNormMode_t mode, const void *alpha, - const void *beta, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t yDesc, void *y, - const ccTensorDescriptor_t bnScaleBiasMeanVarDesc, const void *bnScale, - const void *bnBias, double exponentialAverageFactor, - void *resultRunningMean, void *resultRunningVariance, void *workSpace, - uint32_t workSpaceSizeInBytes, double epsilon, void *resultSaveMean, - void *resultSaveInvVariance, const bool isTraining); -#endif - -ccStatus_t ccGetBatchNormalizationForwardTrainingWorkspaceSize(ccHandle_t handle, ccBatchNormMode_t mode, - ccTensorDescriptor_t xDesc, ccTensorDescriptor_t yDesc, - const ccTensorDescriptor_t bnScaleBiasMeanVarDesc, - uint32_t *sizeInBytes); - -/** - * @ingroup dnn - * @brief generate an random normal Tensor use given on/off scale. - * @param [in] handle Stream handle. - * @param [in] alpha reserved. - * @param [in] meanDesc Mean description of one-hot position. - * @param [in] mean Data pointer of mean. - * @param [in] scaleDesc On/off scale description. - * @param [in] scale Data pointer of on/off scale. - * @param [in] seed random seed used to generate random number - * @param [in] seed2 random seed used to generate random number - * @param [in] beta reserved. - * @param [in] outputDesc Description of the generated one-hot tensor. - * @param [output] output Data pointer of output. - * @return ccStatus_t - */ -ccStatus_t ccRandomNormalForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t meanDesc, - const void *mean, const ccTensorDescriptor_t scaleDesc, const void *scale, - const int64_t seed1, const int64_t seed2, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief generate random uniform tensor. - * @param [in] handle Stream handle. - * @param [in] alpha reserved. - * @param [in] minvalDesc Mean description of one-hot position. - * @param [in] minval Data pointer of mean. - * @param [in] maxvalDesc On/off scale description. - * @param [in] maxval Data pointer of on/off scale. - * @param [in] seed random seed used to generate random number - * @param [in] seed2 random seed used to generate random number - * @param [in] beta reserved. - * @param [in] outputDesc Description of the generated one-hot tensor. - * @param [output] output Data pointer of output. - * @return ccStatus_t - */ -ccStatus_t ccRandomUniformForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t minvalDesc, - const void *minval, const ccTensorDescriptor_t maxvalDesc, const void *maxval, - const int64_t seed1, const int64_t seed2, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/**^M - * @ingroup dnn^M\r 10932 - * @brief generate BatchMatMul tensor.^M\r 10933 - * @param [in] handle Stream handle.^M\r 10934 - * @param [in] alpha reserved.^M\r 10935 - * @param [in] xDesc tensorA Desc.^M\r 10936 - * @param [in] x Data pointer of tensorA.^M\r 10937 - * @param [in] yDesc tensorB Desc.^M\r 10938 - * @param [in] y Data pointer of tensorB.^M\r 10939 - * @param [in] beta reserved.^M\r 10940 - * @param [in] adj_x tensorA transpose flag^M\r 10941 - * @param [in] adj_y tensorB transpose flag^M\r 10942 - * @param [in] outpDesc Description of the tensor output .^M\r 10943 - * @param [output] out Data pointer of output.^M\r 10944 - * @return ccStatus_t^M - */ -ccStatus_t ccBatchMatMulForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t yDesc, const void *y, const void *beta, const bool adj_x, - const bool adj_y, const ccTensorDescriptor_t outDesc, void *out); - -ccStatus_t ccGetBatchMatMulOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, bool adj_x, - bool adj_y, int32_t *dimCnt, int32_t dim[], int32_t dimLen); - -/** - * @ingroup dnn - * @brief generator conv int8 all offset factor - * @param [in] para the struct for scale and offset of input, filter and output - * @param [in|out] offsetW offset of filter - * @param [in|out] offsetPad offset of input - * @param [in|out] scaledQrq scale computing result of input , filter and output - * @param [in|out] nextoffsetq offset of output - * @return ccStatus_t - */ -ccStatus_t ccGenQuantAllOffsetFactor(const ccQuantAllOffsetPara_t *para, uint8_t &offsetW, uint8_t &offsetPad, - uint16_t &scaledQrq, uint16_t &nextoffsetq); - -/** - * @ingroup dnn - * @brief get conv int8 all offset fracZ size - * @param [in] filterDesc descriptor of filter tensor - * @param [in|out] conv int8 all offset fracZ size - * @param [in] groupNum group conv num - * @return ccStatus_t - */ -ccStatus_t ccSetGroupConvScene(const ccFilterDescriptor_t tensorDesc, ccConvolutionDescriptor_t convDesc); - -ccStatus_t ccGetInt8AllOffsetFilterFracZSizeInBytes(const ccFilterDescriptor_t filterSrcDesc, - const ccFilterDescriptor_t filterDesc, uint32_t &size, - uint32_t groupNum); - -/** - * @ingroup dnn - * @brief transform filter in conv int8 all offset scene - * @param [in] filterSrcInfo descriptor of filter tensor before fracZ transform - * @param [in] filterSrc filter addr before fracZ transform - * @param [in] filterDstInfo descriptor of filter tensor after fracZ transform - * @param [in] filterDst filter addr after fracZ transform - * @param [in] quantPara the struct for scale and offset of input, filter and output - * @param [in] ySizeInBytes filter size after fracZ transform - * @param [in|out] outputDataType output data type - * @param [in] groupNum group conv num - * @return ccStatus_t - */ -ccStatus_t ccTransFilterInt8AllOffset(ccFilterDescriptor_t filterSrcInfo, const void *filterSrc, - ccFilterDescriptor_t filterDstInfo, void *filterDst, - const ccQuantAllOffsetPara_t *quantPara, uint32_t ySizeInBytes, - ccDataType_t outputDataType, uint32_t groupNum); - -/** - * @ingroup dnn - * @brief transform bias in conv int8 all offset scene - * @param [in] filterDesc descriptor of filter tensor - * @param [in] biasDesc descriptor of bias tensor - * @param [in] quantPara the struct for scale and offset of input, filter and output - * @param [in] w filter addr - * @param [in] bias bias addr - * @return ccStatus_t - */ -ccStatus_t ccTransInt8AllOffsetBias(const ccFilterDescriptor_t filterDesc, const ccTensorDescriptor_t biasDesc, - const ccQuantAllOffsetPara_t *quantPara, const void *w, const void *bias); - -/** - * @ingroup dnn - * @get dequantize - * @param [in] handle handle id - * @param [in] alpha alpha addr - * @param [in] xDesc the input Desc descriptor - * @param [in] x x data addr - * @param [in] beta beta data addr - * @param [in] yDesc the output Desc descriptor - * @param [in] y y data addr - * @return ccStatus_t - */ -ccStatus_t ccDequantizeCoreForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, - const void *x, const void *beta, const ccTensorDescriptor_t yDesc, void *y); -/** - * @ingroup dnn - * @get quantize - * @param [in] handle handle id - * @param [in] alpha alpha addr - * @param [in] xDesc the input Desc descriptor - * @param [in] x x data addr - * @param [in] beta beta data addr - * @param [in] yDesc the output Desc descriptor - * @param [in] y y data addr - * @return ccStatus_t - */ -ccStatus_t ccQuantizeCoreForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const void *beta, const ccTensorDescriptor_t yDesc, void *y); - -#ifndef DAVINCI_LITE -ccStatus_t ccActivationBackward(ccHandle_t handle, const ccActivationDescriptor_t activationDesc, const void *alpha, - const ccTensorDescriptor_t dyDesc, const void *dy, const ccTensorDescriptor_t xDesc, - const void *x, const void *beta, const ccTensorDescriptor_t dxDesc, void *dx); -#endif - -ccStatus_t ccL2LossForward(ccHandle_t handle, const ccL2LossDescriptor_t l2lossDesc, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t yDesc, void *y); - -/** - * @ingroup dnn - * @brief get the output dimension info of top k v2 - * @param [in] xDesc descriptor of input tensor x - * @param [in] yDesc descriptor of input tensor y - * @param [in|out] dimCnt point to the output dimCnt - * @param [in|out] dim arrays to save dims - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetTopKV2OutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t kDesc, const void *k, - const int64_t axis, int32_t *dimCnt, int32_t dim[], int32_t dimLen); - -/** - * @ingroup dnn - * @brief top k v2 forward computation - * @param [in] handle cce handle - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor x - * @param [in] x input data x in device memory - * @param [in] yDesc descriptor of input tensor y - * @param [in] y input data y in device memory - * @param [in] beta bias factors - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccTopKV2Forward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t kDesc, const void *k, const void *beta, const bool sorted, - const int64_t axis, void *workSpace, const uint32_t workSpaceSizeInBytes, - const ccTensorDescriptor_t outputValuesDesc, void *outputValues, - const ccTensorDescriptor_t outputIndicesDesc, void *outputIndices); - -/** - * @ingroup dnn - * @brief get the workspace size of top k v2 - * @param [in] xDesc descriptor of input tensor x - * @param [in] yDesc descriptor of input tensor y - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] sizeInBytes point to workspace size - * @return ccStatus_t - */ -ccStatus_t ccGetTopKV2ForwardWorkspaceSize(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t kDesc, - const ccTensorDescriptor_t indiceDesc, const void *k, const int64_t axis, - uint32_t *sizeInBytes); - -/** - * @ingroup dnn - * @brief Get unsorted segment reduction output dim - * @param [in] xDesc descriptor of input tensor - * @param [in] segmentIdsDesc descriptor of input segmentIds tensor - * @param [in] segmentsNum output slice num - * @param [out] dimCnt output tensor dim cnt - * @param [out] dim output tensor dim - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetUnsortedSegmentReductionOutputDim(const ccTensorDescriptor_t xDesc, - const ccTensorDescriptor_t segmentIdsDesc, int32_t segmentsNum, - int32_t *dimCnt, int32_t dim[], int32_t dimLen); - -/** - * @ingroup dnn - * @brief reduce all forward computation - * @param [in] handle cce handle - * @param [in] segmentsNum output slice num - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] segmentIdsDesc descriptor of input segmentIds tensor - * @param [in] x input segmentIds data in device memory - * @param [in] beta bias factors - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccUnsortedSegmentSumForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, - const void *x, const ccTensorDescriptor_t segmentIdsDesc, const void *segmentIds, - const int32_t segmentsNum, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief reverse sequence forward computation - * @param [in] handle cce handle - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor x - * @param [in] x input data x in device memory - * @param [in] yDesc descriptor of input tensor y - * @param [in] y input data y in device memory - * @param [in] beta bias factors - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccReverseSequenceForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t inputDesc, - const void *input, const ccTensorDescriptor_t seqLengthsDesc, - const void *seqLengths, int64_t seqAxis, int64_t batchAxis, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief realdiv between two tensors. - * @param [in] alpha reserved. - * @param [in] xDesc description of the left operator tensor. - * @param [in] x data point of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [in] y data point of the right operator tensor. - * @param [in] beta reserved. - * @param [in] outputDesc description of the output tensor. - * @param [output] output data point of the output tensor. - * @return ccStatus_t - */ - -ccStatus_t ccEqualForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t yDesc, const void *y, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief get output shape of realdiv. - * @param [in] xDesc description of the left operator tensor. - * @param [in] yDesc description of the right operator tensor. - * @param [out] dimCnt output tensor dim cnt - * @param [out] dim output tensor dim - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetEqualOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, - int32_t *dim, int32_t dimLen); - -/** - * @ingroup dnn - * @brief invert permutation forward computation - * @param [in] handle cce handle - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] beta bias factors - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccInvertPermutationForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, - const void *x, const void *beta, const ccTensorDescriptor_t outputDesc, - void *output); - -/** - * @ingroup dnn - * @brief get the workspace size of non max suppression - * @param [in] handle descriptor of handle - * @param [in] scoresDesc descriptor of input tensor scoresDesc - * @param [in] boxesDesc descriptor of input tensor boxesDesc - * @param [in|out] sizeInBytes point to workspace size - * @return ccStatus_t - */ -ccStatus_t ccGetNonMaxSuppressionWorkspaceSize(ccHandle_t handle, const ccTensorDescriptor_t scoresDesc, - const ccTensorDescriptor_t boxesDesc, uint32_t *sizeInBytes); - -/** - * @ingroup dnn - * @brief get the output dim of non max suppression - * @param [in] scoresDesc descriptor of input tensor scoresDesc - * @param [in] maxOutPutSize the max size of output - * @param [in|out] dimCnt point to the count of dim - * @param [in|out] dim[] the array of output dim - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetNonMaxSuppressionOutputDim(const ccTensorDescriptor_t scoresDesc, const int32_t maxOutPutSize, - int32_t *dimCnt, int32_t dim[], int32_t dimLen); - -/** - * @ingroup dnn - * @brief multinomial forward. - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] numSamples number of independent samples to draw for each row slice - * @param [in] seed1 sed to create a random seed for the distribution - * @param [in] seed2 sed to create a random seed for the distribution - * @param [in] workSpace work space for inter access - * @param [in] workSpaceSizeInBytes work space size - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccMultinomialForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - int32_t numSamples, int64_t seed1, int64_t seed2, void *workSpace, - uint32_t workSpaceSizeInBytes, const void *beta, const ccTensorDescriptor_t outputDesc, - void *output); -/** - * @ingroup dnn - * @brief get output dim of generated one-hot tensor. - * @param [in] indicesDesc Indices description of one-hot position. - * @param [in] depth On/off value description. - * @param [in] axis Data pointer of on/off value. - * @param [output] dimCnt Description of the generated one-hot tensor. - * @param [output] dim Data pointer of output. - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetOneHotOutputDim(const ccTensorDescriptor_t indicesDesc, int32_t depth, int32_t axis, int32_t *dimCnt, - int32_t *dim, int32_t dimLen); - -/** - * @ingroup dnn - * @brief generate an one-hot Tensor use given on/off value. - * @param [in] handle Stream handle. - * @param [in] alpha reserved. - * @param [in] indicesDesc Indices description of one-hot position. - * @param [in] indices Data pointer of indices. - * @param [in] onDesc On value description. - * @param [in] on Data pointer of on value. - * @param [in] offDesc Off value description. - * @param [in] off Data pointer of off value. - * @param [in] depth On/off value description. - * @param [in] axis Data pointer of on/off value. - * @param [in] beta reserved. - * @param [in] outputDesc Description of the generated one-hot tensor. - * @param [output] output Data pointer of output. - * @return ccStatus_t - */ -ccStatus_t ccOneHotForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t indicesDesc, - const void *indices, const ccTensorDescriptor_t onDesc, const void *on, - const ccTensorDescriptor_t offDesc, const void *off, const int32_t depth, const int32_t axis, - const void *beta, const ccTensorDescriptor_t outputDesc, void *output); -/** - * @ingroup dnn - * @brief get the workspaceSize of multinomial - * @param [in] xDesc descriptor of input tensor - * @param [in] numSamples number sample - * @param [out] sizeInBytes wor space size of byte - * @return ccStatus_t - */ -ccStatus_t ccGetMultinomialWorkspaceSize(const ccTensorDescriptor_t xDesc, uint32_t *sizeInBytes); -/** - * @ingroup dnn - * @brief get the output dimension info of multinomial - * @param [in] xDesc descriptor of input tensor - * @param [in] numSample number of independent samples to draw for each row slice - * @param [in|out] dimCnt point to the output dimCnt - * @param [in|out] dim arrays to save dims - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetMultinomialOutputDim(const ccTensorDescriptor_t xDesc, int32_t numSample, int32_t *dimCnt, - int32_t dim[], int32_t dimLen); -/** - * @ingroup dnn - * @brief get the output dimension info of BiasAddBackward - * @param [in] dyDesc descriptor of input tensor - * @param [in] out] n outputTensor [N]CHW - * @param [in|out] c outputTensor N[C]HW - * @param [in|out] h outputTensor NC[H]W - * @param [in|out] w outputTensor NCH[W] - * @return ccStatus_t - */ -ccStatus_t ccGetBiasAddBackwardOutputDim(const ccTensorDescriptor_t dyDesc, int32_t *n, int32_t *c, int32_t *h, - int32_t *w); - -/** - * @ingroup dnn - * @brief biasadd backward. - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] dyDesc descriptor of input data - * @param [in] dy input data in device memory - * @param [in] beta common scale factor - * @param [in] dbDesc descriptor of output data - * @param [in|out] db output data in device memory - * @return ccStatus_t - */ -#ifndef DAVINCI_LITE -ccStatus_t ccBiasAddBackward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t dyDesc, const void *dy, - const void *beta, const ccTensorDescriptor_t dbDesc, void *db); - -ccStatus_t ccMaxPoolWithArgmaxForward(ccHandle_t handle, const ccPoolingDescriptor_t poolingDesc, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t yDesc, void *y, const ccTensorDescriptor_t argMaskDesc, - void *argMask); -#endif - -ccStatus_t ccCreatePoolingMaskDescriptor(ccTensorDescriptor_t *poolingMaskDesc); - -ccStatus_t ccDestroyPoolingMaskDescriptor(ccTensorDescriptor_t *poolingMaskDesc); - -ccStatus_t ccSetPoolingMaskTensorDescriptor(ccTensorDescriptor_t poolingMaskDesc, ccTensorFormat_t format, - ccDataType_t dataType, int32_t n, int32_t c, int32_t h, int32_t w, - int32_t windowH, int32_t windowW); - -ccStatus_t ccGetPoolingMaskTensorSizeInBytes(ccTensorDescriptor_t poolingMaskDesc, uint32_t *size); - -/** - * @ingroup dnn - * @brief get the mask output dimension info of maxpooling training forward - * @param [in] pooling descriptor of convolution operator - * @param [in] xDesc descriptor of input tensor - * @param [in|out] n point to batch size - * @param [in|out] c point to channels - * @param [in|out] h point to height of feature map - * @param [in|out] w point to width of feature map - * @param [in|out] windowH point to height of window - * @param [in|out] windowW point to width of windowW - * @return ccStatus_t - */ -ccStatus_t ccGetPoolingMaskDim(const ccPoolingDescriptor_t poolingDesc, const ccTensorDescriptor_t xDesc, int32_t *n, - int32_t *c, int32_t *h, int32_t *w, int32_t *windowH, int32_t *windowW); - -#ifndef DAVINCI_LITE -ccStatus_t ccSoftmaxCrossEntropyLoss(ccHandle_t handle, ccSoftmaxAlgo_t algo, ccSoftmaxMode_t mode, - ccCrossEntropyMode_t ceMode, const void *alpha, const void *scale, - const ccTensorDescriptor_t logitsDesc, const void *logits, - const ccTensorDescriptor_t labelsDesc, const void *labels, const void *labelSmooth, - const void *beta, const ccTensorDescriptor_t lossDesc, void *loss); - -ccStatus_t ccSoftmaxCrossEntropyDx(ccHandle_t handle, ccSoftmaxAlgo_t algo, ccSoftmaxMode_t mode, - ccCrossEntropyMode_t ceMode, const void *alpha, const void *scale, - const ccTensorDescriptor_t logitsDesc, const void *logits, - const ccTensorDescriptor_t labelsDesc, const void *labels, const void *labelSmooth, - const void *beta, const ccTensorDescriptor_t dxDesc, void *dx); - -ccStatus_t ccAvgPoolingBackward(ccHandle_t handle, const ccPoolingDescriptor_t poolingDesc, const void *alpha, - const ccTensorDescriptor_t dyDesc, const void *dy, const void *beta, - const ccTensorDescriptor_t dxDesc, const void *dx); - -ccStatus_t ccTrainingAssignOp(ccHandle_t handle, const ccAssignOpMode_t assignOpDesc, const void *alpha, - const void *beta, const ccTensorDescriptor_t aDesc, void *a, - const ccTensorDescriptor_t bDesc, const void *b); - -/** - * @ingroup dnn - * @brief momentum optimizer for variable update - * @param [in] handle cce handle - * @param [in] inputDesc descriptor of input tensor: gradient,accumulation,variable - * @param [in] gradient gradient input - * @param [in|out] accumulation accumulation input and updated output - * @param [in|out] variable variable input and updated output - * @param [in] algo indicate whether need FP16 output - * @param [in] momentum scaler to control accumulation - * @param [in] learningRate scaler - * @param [in] lossScaleReciprocal scaler - * @param [in] workSpace additional memory address - * @param [in] workSpaceSizeInBytes additional memory size - * @param [out] variableUpdatedFP16Desc descriptor of FP16 output tensor: variableUpdatedFP16 - * @param [out] variableUpdatedFP16 variableUpdatedFP16 - * @return ccStatus_t - */ -ccStatus_t ccApplyMomentum(ccHandle_t handle, const ccTensorDescriptor_t inputDesc, const void *gradient, - void *accumulation, void *variable, const ccMomentumAlgo_t algo, const void *momentum, - const void *learningRate, const void *lossScaleReciprocal, void *workSpace, - const uint32_t workSpaceSizeInBytes, const ccTensorDescriptor_t variableUpdatedFP16Desc, - void *variableUpdatedFP16); - -ccStatus_t ccSsdClassifyLossTrain(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t labelDesc, - const void *label, const ccTensorDescriptor_t greaterConstDesc, - const void *greaterConst, const ccTensorDescriptor_t subConstDesc, - const void *subConst, const ccTensorDescriptor_t sparseDesc, const void *sparse, - const void *beta, const ccTensorDescriptor_t castoutDesc, const void *castout, - const ccTensorDescriptor_t muloutDesc, const void *mulout); - -#endif - -/** - * @ingroup dnn - * @brief get the workspace size of applymomentum - * @param [in] inputDesc descriptor of input tensor - * @return ccStatus_t - */ -ccStatus_t ccGetApplyMomentumWorkspaceSize(const ccTensorDescriptor_t inputDesc, uint32_t *sizeInBytes); -#ifndef DAVINCI_LITE -ccStatus_t ccHwck2FracZ(ccHandle_t handle, const ccFilterDescriptor_t xDesc, const void *x, - const ccFilterDescriptor_t yDesc, void *y); - -ccStatus_t ccFracZ2Hwck(ccHandle_t handle, const ccFilterDescriptor_t xDesc, const void *x, - const ccFilterDescriptor_t yDesc, void *y); -ccStatus_t ccAddNForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const int32_t inputNum, - const void *x[], const void *beta, void *workSpace, uint32_t workSpaceSizeInBytes, - const ccTensorDescriptor_t yDesc, void *y); -#endif -ccStatus_t ccGetAddNForwardWorkspaceSize(ccHandle_t handle, const ccTensorDescriptor_t xDesc, const int32_t inputNum, - const ccTensorDescriptor_t yDesc, uint32_t *sizeInBytes); -ccStatus_t ccGetAddNForwardOutputDim(const ccTensorDescriptor_t xDesc, int32_t *dimCnt, int32_t *dim, int32_t dimLen); -ccStatus_t ccAddTrainForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t wDesc, const void *w, const void *beta, void *workSpace, - uint32_t workSpaceSizeInBytes, const ccTensorDescriptor_t yDesc, void *y); -ccStatus_t ccGetAddTrainForwardWorkspaceSize(ccHandle_t handle, const ccTensorDescriptor_t xDesc, - const ccTensorDescriptor_t wDesc, const ccTensorDescriptor_t yDesc, - uint32_t *sizeInBytes); -ccStatus_t ccGetAddTrainForwardOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t wDesc, - int32_t *dimCnt, int32_t dim[], int32_t dimLen); -ccStatus_t ccMulTrainForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t wDesc, const void *w, const void *beta, void *workSpace, - uint32_t workSpaceSizeInBytes, const ccTensorDescriptor_t yDesc, void *y); -ccStatus_t ccGetMulTrainForwardWorkspaceSize(ccHandle_t handle, const ccTensorDescriptor_t xDesc, - const ccTensorDescriptor_t wDesc, const ccTensorDescriptor_t yDesc, - uint32_t *sizeInBytes); -ccStatus_t ccGetMulTrainForwardOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t wDesc, - int32_t *dimCnt, int32_t dim[], int32_t dimLen); - -/** - * @ingroup dnn - * @brief get workspace size - * @param [in] xDesc descriptor of input tensor - * @param [in|out] sizeInBytes workspace size - * @return ccStatus_t - */ -ccStatus_t ccGetRandomShuffleWorkspaceSize(const ccTensorDescriptor_t xDesc, uint32_t *sizeInBytes); - -/** - * @ingroup dnn - * @brief random shuffle forward computation - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] workspace temporary space - * @param [in] workspaceSizeInBytes temporary space size - * @param [in] seed random seed used to generate random number - * @param [in] seed2 random seed used to generate random number - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccRandomShuffleForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - void *workspace, const uint32_t workspaceSizeInBytes, const int64_t seed1, - const int64_t seed2, const void *beta, const ccTensorDescriptor_t outputDesc, - void *output); -/** - * @ingroup dnn - * @brief sin forward: - * data type only support float float16 double - * data format only support ND - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] input input data in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccSinForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *input, - const void *beta, const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief cos forward: - * data type only support float float16 double - * data format only support ND - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] input input data in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccCosForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *input, - const void *beta, const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief tan forward: - * data type only support float float16 double - * data format only support ND - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] input input data in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccTanForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *input, - const void *beta, const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief get the output dimension info of unstack - * @param [in] xDesc descriptor of input tensor - * @param [in] axis the axis to unstack along - * @param [in|out] dimCnt point to the output dimCnt - * @param [in|out] dim arrays to save dims - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetUnstackOutputDim(const ccTensorDescriptor_t xDesc, int32_t axis, int32_t *dimCnt, int32_t dim[], - int32_t dimLen); - -/** - * @ingroup dnn - * @brief unstack forward. - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data - * @param [in] x input data in device memory - * @param [in] num the length of the dimension axis - * @param [in] axis the axis to unstack along - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ - -ccStatus_t ccUnstackForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - int32_t num, int32_t axis, const void *beta, const ccTensorDescriptor_t outputDesc, - void *output[]); - -ccStatus_t ccResizeNearestNeighborCpuForward(ccHandle_t handle, const ccResizeNearestNeighborDescriptor_t resizeDesc, - const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const void *beta, const ccTensorDescriptor_t outputDesc, void *output); -/** - * @ingroup dnn - * @brief get the output dimension info of resize nearest neighbor - * @param [in] resizeDesc descriptor of resize - * @param [in] xDesc descriptor of input tensor - * @param [in|out] dimCnt point to the output dimCnt - * @param [in|out] dim arrays to save dims - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetResizeNearestNeighborOutputDim(const ccResizeNearestNeighborDescriptor_t resizeDesc, - const ccTensorDescriptor_t xDesc, int32_t *dimCnt, int32_t dim[], - int32_t dimLen); - -/** - * @ingroup dnn - * @brief create descriptor of ResizeNearestNeighbor - * @param [in|out] resizeDesc point to descriptor of ResizeNearestNeighbor attr - * @return ccStatus_t - */ -ccStatus_t ccCreateResizeNearestNeighborDescriptor(ccResizeNearestNeighborDescriptor_t *resizeDesc); - -/** - * @ingroup dnn - * @brief destroy descriptor of ResizeNearestNeighbor - * @param [in|out] resizeDesc point to descriptor of ResizeNearestNeighbor attr - * @return ccStatus_t - */ -ccStatus_t ccDestroyResizeNearestNeighborDescriptor(ccResizeNearestNeighborDescriptor_t *resizeDesc); - -/** - * @ingroup dnn - * @brief set descriptor of ResizeNearestNeighbor. - * @param [in|out] resizeDesc descriptor of resize nearest neighbor operator - * @param [in] alignCorners whether the centers of input and output are aligned - * @param [in] height height of output - * @param [in] width width of output - * @return ccStatus_t - */ -ccStatus_t ccSetResizeNearestNeighborDescriptor(ccResizeNearestNeighborDescriptor_t resizeDesc, bool alignCorners, - int32_t height, int32_t width); - -/** - * @ingroup dnn - * [ccGetPadV2OutputDim] - * @brief get the output dimension info of pad - * @param [in] xDesc descriptor of input tensor x - * @param [in] padDesc descriptor of input paddings - * @param [in|out] dimCnt point to the output dimCnt - * @param [in|out] dim arrays to save dims - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetPadV2OutputDim(const ccTensorDescriptor_t xDesc, const ccPadV2Descriptor_t padDesc, int32_t *dimCnt, - int32_t dim[], int32_t dimLen); - -ccStatus_t ccPadV2CpuForward(ccHandle_t handle, const ccPadV2Descriptor_t padDesc, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief create descriptor of parameters for padv2 function - * @param [in] point to descriptor of parameters for padv2 function - * @return ccStatus_t - */ -ccStatus_t ccCreatePadV2Descriptor(ccPadV2Descriptor_t *padDesc); - -/** - * @ingroup dnn - * @brief destroy descriptor of parameters for padv2 function - * @param [in] point to descriptor of parameters for padv2 function - * @return ccStatus_t - */ -ccStatus_t ccDestroyPadV2Descriptor(ccPadV2Descriptor_t *padDesc); - -/** - * @brief init descriptor for parameter of padv2 function - * @param [in|out] padDesc descriptor of pad - * @param [in] padShapeCnt padshape count - * @param [in] padShapeLow padshape low - * @param [in] padShapeHigh padshape high - * @param [in] padMode pad mode - * @param [in] padValue pad value ptr - * @param [in] padValueType pad value data type - * @return ccStatus_t - */ -ccStatus_t ccSetPadV2Descriptor(ccPadV2Descriptor_t padDesc, const int32_t padShapeCnt, const int32_t padShapeLow[], - const int32_t padShapeHigh[], const ccPadMode_t padMode, const void *padValue, - const ccDataType_t padValueType); -/** - * @ingroup dnn - * @brief create descriptor of batchToSpace - * @param [in|out] batchToSpaceDesc point to descriptor of batchToSpace - * @return ccStatus_t - */ -ccStatus_t ccCreateBatchToSpaceDescriptor(ccBatchToSpaceDescriptor_t *batchToSpaceDesc); - -/** - * @ingroup dnn - * @brief set batchToSpaceDesc - * @param [in|out] batchToSpaceDesc descriptor of batchToSpace - * @param [in] blockShape blockShape of batchToSpace - * @param [in] crops crops of batchToSpace - * @param [in] blockShapeLength blockShapeLength of batchToSpace - * @return ccStatus_t - */ -ccStatus_t ccSetBatchToSpaceDescriptor(ccBatchToSpaceDescriptor_t paramsDesc, const int32_t *blockShape, - const int32_t *crops, const int32_t blockShapeLength); - -/** - * @ingroup dnn - * @brief get batchToSpaceDesc - * @param [in|out] batchToSpaceDesc descriptor of batchToSpace - * @param [in] blockShape blockShape of batchToSpace - * @param [in] crops crops of batchToSpace - * @param [in] blockShapeLength blockShapeLength of batchToSpace - * @return ccStatus_t - */ -ccStatus_t ccGetBatchToSpaceDescriptor(const ccBatchToSpaceDescriptor_t paramsDesc, int32_t *blockShape, int32_t *crops, - int32_t *blockShapeLength); - -/** - * @ingroup dnn - * @brief destroy descriptor of batchToSpace - * @param [in] *batchToSpaceDesc descriptor of batchToSpace - * @return ccStatus_t - */ -ccStatus_t ccDestroyBatchToSpaceDescriptor(ccBatchToSpaceDescriptor_t *batchToSpaceDesc); - -/** - * @ingroup dnn - * @brief get the output dimension info of batch to space - * @param [in] xDesc descriptor of input tensor - * @param [in|out] dimCnt point to the output dimCnt - * @param [in|out] dim arrays to save dims - * @param [in| dimlen length of dim - * @return ccStatus_t - */ - -ccStatus_t ccGetBatchToSpaceOutputDim(const ccTensorDescriptor_t xDesc, - const ccBatchToSpaceDescriptor_t batchToSpaceDesc, int32_t *dimCnt, int32_t dim[], - int32_t dimLen); - -/** - * @ingroup dnn - * @brief batch to space forward computation - * @param [in] handle cce handle - * @param [in] paramsDesc descriptor of input params - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] beta bias factors - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ - -ccStatus_t ccBatchToSpaceForward(ccHandle_t handle, const ccBatchToSpaceDescriptor_t paramsDesc, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief create descriptor of spaceToBatch - * @param [in|out] spaceToBatchDesc point to descriptor of spaceToBatch - * @return ccStatus_t - */ -ccStatus_t ccCreateSpaceToBatchDescriptor(ccSpaceToBatchDescriptor_t *spaceToBatchDesc); - -/** - * @ingroup dnn - * @brief set spaceToBatchDesc - * @param [in|out] spaceToBatchDesc descriptor of spaceToBatch - * @param [in] blockShape blockShape of spaceToBatch - * @param [in] paddings paddings of spaceToBatch - * @param [in] blockShapeLength blockShapeLength of spaceToBatch - * @return ccStatus_t - */ -ccStatus_t ccSetSpaceToBatchDescriptor(ccSpaceToBatchDescriptor_t paramsDesc, const int32_t *blockShape, - const int32_t *paddings, const int32_t blockShapeLength); - -/** - * @ingroup dnn - * @brief get spaceToBatchDesc - * @param [in|out] spaceToBatchDesc descriptor of spaceToBatch - * @param [in] blockShape blockShape of spaceToBatch - * @param [in] paddings paddings of spaceToBatch - * @param [in] blockShapeLength blockShapeLength of spaceToBatch - * @return ccStatus_t - */ -ccStatus_t ccGetSpaceToBatchDescriptor(const ccSpaceToBatchDescriptor_t paramsDesc, int32_t *blockShape, - int32_t *paddings, int32_t *blockShapeLength); - -/** - * @ingroup dnn - * @brief destroy descriptor of spaceToBatch - * @param [in] *spaceToBatchDesc descriptor of spaceToBatch - * @return ccStatus_t - */ -ccStatus_t ccDestroySpaceToBatchDescriptor(ccSpaceToBatchDescriptor_t *spaceToBatchDesc); - -/** - * @ingroup dnn - * @brief get the output dimension info of space to batch - * @param [in] xDesc descriptor of input tensor - * @param [in|out] dimCnt point to the output dimCnt - * @param [in|out] dim arrays to save dims - * @param [in| dimlen length of dim - * @return ccStatus_t - */ - -ccStatus_t ccGetSpaceToBatchOutputDim(const ccTensorDescriptor_t xDesc, - const ccSpaceToBatchDescriptor_t spaceToBatchDesc, int32_t *dimCnt, int32_t dim[], - int32_t dimLen); - -/** - * @ingroup dnn - * @brief space to batch forward computation - * @param [in] handle cce handle - * @param [in] paramsDesc descriptor of input params - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] beta bias factors - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ - -ccStatus_t ccSpaceToBatchForward(ccHandle_t handle, const ccSpaceToBatchDescriptor_t paramsDesc, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -ccStatus_t ccTransFilterDesc2TensorDesc(ccFilterDescriptor_t wDesc, ccTensorDescriptor_t tensorDesc); - -/* - * @brief get the output dimension info of extractImagePatches - * @param [in] xDesc descriptor of input tensor x - * @param [in] ksizes ksizes array - * @param [in] strides strides array - * @param [in] rates rates array - * @param [in] padding padding type - * @param [in|out] dimCnt point to the output dimCnt - * @param [in|out] dim arrays to save dims - * @return ccStatus_t - */ -ccStatus_t ccGetExtractImagePatchesOutputDim(const ccTensorDescriptor_t xDesc, const ccIntArray_t *ksizes, - const ccIntArray_t *strides, const ccIntArray_t *rates, - const ccExtractImagePatchesPadType_t padding, int32_t *dimCnt, - int32_t dim[], const int32_t dimLen); - -/** - * @ingroup dnn - * @brief cum forward. - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data, dimCnt:1~8 - * @param [in] x input data in device memory - * @param [in] axisDesc scale factor, dimCnt:0 - * @param [in] axis which axis to cum calc, device memory - * @param [in] beta common scale factor - * @param [in] opType calc type, eg. sum, prod.... - * @param [in] exclusive cum flag, true or false - * @param [in] reverse cum flag, true or false - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccCumForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t axisDesc, const void *axis, const void *beta, const CumOpType opType, - const bool exclusive, const bool reverse, const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @ingroup dnn - * @brief ExtractImagePatches forward. - * @param [in] handle cce handle - * @param [in] ksizes ksizes array - * @param [in] strides strides array - * @param [in] rates rates array - * @param [in] padding padding type - * @param [in] alpha common scale factor - * @param [in] xDesc descriptor of input data x - * @param [in] x input data x in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccExtractImagePatchesForward(ccHandle_t handle, const ccIntArray_t *ksizes, const ccIntArray_t *strides, - const ccIntArray_t *rates, const ccExtractImagePatchesPadType_t padding, - const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const void *beta, const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @brief get argmax output dim info - * @param [in] argDesc argmaxmin descriptor - * @param [in] xDesc descriptor of input tensor - * @param [in|out] dimCnt output dim count - * @param [in|out] dim output dim - * @param [in| dimlen length of dim - * @return ccStatus_t - */ -ccStatus_t ccGetArgMaxOutputDim(const ccArgmaxminDescriptor_t argDesc, const ccTensorDescriptor_t xDesc, - int32_t *dimCnt, int32_t dim[], int32_t dimLen); - -/** - * @ingroup dnn - * @brief argmax forward computation - * @param [in] handle cce handle - * @param [in] argDesc argmaxmin descriptor - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] workSpace workspace pointer - * @param [in] workSpaceSizeInBytes workspace size in bytes - * @param [in] beta bias factors - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccArgMaxForward(ccHandle_t handle, const ccArgmaxminDescriptor_t argDesc, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, void *workSpace, - const uint32_t workSpaceSizeInBytes, const void *beta, const ccTensorDescriptor_t outputDesc, - void *output); - -/** - * @ingroup dnn - * @brief get the output dimension info of argmaxmin - * @param [in] argDesc descriptor of tagCcArgmaxmin - * @param [in] xDesc descriptor of input tensor - * @param [in|out] sizeInBytes workspace size - * @return ccStatus_t - */ -ccStatus_t ccGetArgMaxWorkspaceSize(const ccArgmaxminDescriptor_t argDesc, const ccTensorDescriptor_t xDesc, - uint32_t *sizeInBytes); - -/** - * @ingroup dnn - * @brief create descriptor of Argmaxmin - * @param [in|out] resizeDesc point to descriptor of Argmaxmin attr - * @return ccStatus_t - */ -ccStatus_t ccCreateArgmaxminDescriptor(ccArgmaxminDescriptor_t *argDesc); - -/** - * @ingroup dnn - * @brief destroy descriptor of Interp - * @param [in|out] resizeDesc point to descriptor of Argmaxmin attr - * @return ccStatus_t - */ -ccStatus_t ccDestroyArgmaxminDescriptor(ccArgmaxminDescriptor_t *argDesc); - -/** - * @ingroup dnn - * @brief destroy descriptor of Interp - * @param [in|out] argDesc descriptor of tagCcArgmaxmin - * @param [in] axisType - * @param [in] outMaxVal whether to return the maximum value - * @param [in] topK number that returns the maximum index or maximum value - * @param [in] axis Describes which axis of the input Tensor to reduce across - * @param [in] keepDims whether to keep reduced dim - * @param [in] reduceSize the num of elements to be reduce to get topK elements, reduceSize=-1 means the total num - * of elements in axis dimension - * @param [in] reduceStride the stride for reduce operation, reduceStride=1 means the layout of target data is - * continuous - * @return ccStatus_t - */ -ccStatus_t ccSetArgmaxminDescriptor(ccArgmaxminDescriptor_t argDesc, int32_t axisType, bool outMaxVal, int64_t topK, - int64_t axis, bool keepDims, int64_t reduceSize = -1, int64_t reduceDStride = 1); - -ccStatus_t ccArgMinForward(ccHandle_t handle, const ccArgmaxminDescriptor_t argDesc, const void *alpha, - const ccTensorDescriptor_t xDesc, const void *x, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -ccStatus_t ccGetArgMinOutputDim(const ccArgmaxminDescriptor_t argDesc, const ccTensorDescriptor_t xDesc, - int32_t *dimCnt, int32_t dim[], const int32_t dimLen); -/** - * @ingroup dnn - * @brief lsh projection forward computation - * @param [in] handle cce handle - * @param [in] alpha scaling factors - * @param [in] hashDesc descriptor of input tensor hashDesc - * @param [in] hash input data hash in device memory - * @param [in] weightDesc descriptor of input tensor weightDesc - * @param [in] weight input data weight in device memory - * @param [in] inputDesc descriptor of input tensor inputDesc - * @param [in] lookup input data lookup in device memory - * @param [in] type 1:SPARSE 2.DENSE - * @param [in] beta bias factors - * @param [in] workSpace workSpace data in device memory - * @param [in] workSpaceSizeInBytes workSpace length - * @param [in] outputDesc descriptor of output tensor - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccLshProjectionForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t hashDesc, - const void *hash, const ccTensorDescriptor_t weightDesc, const void *weight, - const ccTensorDescriptor_t inputDesc, const void *input, const LSHProjectionType type, - const void *beta, void *workSpace, const uint32_t workSpaceSizeInBytes, - const ccTensorDescriptor_t outputDesc, void *output); -/** - * @ingroup dnn - * @brief get the workspace size of lsh projection - * @param [in] inputDesc descriptor of input tensor input - * @param [in] hashDataType data type of hash - * @param [in|out] sizeInBytes workspace size - * @return ccStatus_t - */ -ccStatus_t ccGetLshProjectionForwardWorkspaceSize(const ccTensorDescriptor_t inputDesc, const ccDataType_t hashDataType, - uint32_t *sizeInBytes); -/** - * @ingroup dnn - * @brief get the output dimension info of LshProjection, - * @param [in] hashDesc descriptor of hash - * @param [in] type type of mode - * @param [in|out] dimCnt point to the output dimCnt - * @param [in|out] dim arrays to save dims - * @param [in] dimLen dim length - * @return ccStatus_t - */ -ccStatus_t ccGetLshProjectionOutputDim(const ccTensorDescriptor_t hashDesc, const LSHProjectionType type, - int32_t *dimCnt, int32_t dim[], const int32_t dimLen); -/** - * @ingroup dnn - * @brief get the weight dimension info of LshProjection, - * @param [in] inputDesc descriptor of input - * @param [in|out] dimCnt point to the weight dimCnt - * @param [in|out] dim arrays to save dims - * @param [in] dimLen dim length - * @return ccStatus_t - */ -ccStatus_t ccGetLshProjectionWeightDim(const ccTensorDescriptor_t inputDesc, int32_t *dimCnt, int32_t dim[], - const int32_t dimLen); - -/** - * @ingroup dnn - * @brief init descriptor for parameter of upsample function - * @param [in] handle cce handle - * @param [in] upsamplePara input para in host memory - * @param [in] alpha common scale factor - * @param [in] bottomDesc descriptor of input data bottomDesc - * @param [in] bottom input data bottom in device memory - * @param [in] bottomMaskDesc descriptor of input data bottomMaskDesc - * @param [in] bottomMask input data bottomMask in device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor of output data - * @param [in|out] output output data in device memory - * @return ccStatus_t - */ -ccStatus_t ccUpsampleForward(ccHandle_t handle, const ccUpsampleParaDescriptor_t upsamplePara, const void *alpha, - const ccTensorDescriptor_t bottomDesc, const void *bottom, - const ccTensorDescriptor_t bottomMaskDesc, const void *bottomMask, const void *beta, - const ccTensorDescriptor_t outputDesc, void *output); - -/** - * @brief creat descriptor for parameter of usample function - * @param [in|out] upsampleDesc descriptor of upsamplepara - * @return ccStatus_t - */ -ccStatus_t ccCreateUpsampleDescriptor(ccUpsampleParaDescriptor_t *upsampleDesc); - -/** - * @brief destroy descriptor for parameter of upsample function - * @param [in|out] upsampleDesc descriptor of upsamplepara - * @return ccStatus_t - */ -ccStatus_t ccDestroyUpsampleDescriptor(ccUpsampleParaDescriptor_t *upsampleDesc); - -/** - * @brief set descriptor for parameter of upsample function - * @param [in|out] upsampleDesc descriptor of upsamplepara - * @param [in] scale the scale of height and width - * @param [in] scaleHeight the scale of height - * @param [in] scaleWidth the scale of Width - * @param [in] upsampleHeight the height of output - * @param [in] upsampleWidth the width of output - * @param [in] padOutHeight pad value height - * @param [in] padOutWidth pad value width - * @return ccStatus_t - */ -ccStatus_t ccSetUpsampleDescriptor(ccUpsampleParaDescriptor_t upsampleDesc, const int32_t scale, - const int32_t scaleHeight, const int32_t scaleWidth, const int32_t upsampleHeight, - const int32_t upsampleWidth, const bool padOutHeight, const bool padOutWidth); -/** - * @ingroup dnn - * @brief get the output dimension info of upsample - * @param [in] upsamplePara para of upsample - * @param [in] bottomDesc descriptor of input bottom tensor - * @param [in|out] dimCnt point to the output dimCnt - * @param [in|out] dim arrays to save dims - * @param [in] dimLen the len of dim array - * @return ccStatus_t - */ -ccStatus_t ccGetUpsampleOutputDim(const ccUpsampleParaDescriptor_t upsamplePara, const ccTensorDescriptor_t bottomDesc, - int32_t *dimCnt, int32_t dim[], const int32_t dimLen); - -#ifndef DAVINCI_LITE -ccStatus_t ccMatmul(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t wDesc, const void *w, const ccTensorDescriptor_t biasDesc, - const void *bias, const ccFullConnectFwdAlgo_t algo, void *workSpace, - const uint32_t workSpaceSizeInBytes, const void *beta, const ccTensorDescriptor_t yDesc, void *y, - const bool transposeA, const bool transposeB); -ccStatus_t ccGetMatmulOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t wDesc, int32_t *n, - int32_t *c, int32_t *h, int32_t *w, bool transposeA, bool transposeB); -ccStatus_t ccGetMatmulWorkspaceSize(ccHandle_t handle, const ccFullConnectFwdAlgo_t algo, - const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t wDesc, - const ccTensorDescriptor_t yDesc, uint32_t *sizeInBytes, bool transposeA, - bool transposeB); -#endif - -/** - * @ingroup dnn - * @brief gather_v2 function - * @param [in] handle cce handle - * @param [in] alpha common scale factor - * @param [in] paramsDesc descriptor - * @param [in] params device memory - * @param [in] indicesDesc descriptor - * @param [in] indices device memory - * @param [in] axisDesc descriptor - * @param [in] axis device memory - * @param [in] beta common scale factor - * @param [in] outputDesc descriptor - * @param [in|out] output device memory - * @return ccStatus_t - */ -ccStatus_t ccGatherV2(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t paramsDesc, const void *params, - const ccTensorDescriptor_t indicesDesc, const void *indices, const ccTensorDescriptor_t axisDesc, - const void *axis, const void *beta, const ccTensorDescriptor_t outputDesc, const void *output); - -/** - * @ingroup dnn - * @brief memory_clear function - * @param [in] handle cce handle - * @param [in] addrSpaceSizeInBytes addr space size - * @param [in|out] addr device memory - * @return ccStatus_t - */ -ccStatus_t ccMemoryClear(ccHandle_t handle, const uint64_t addrSpaceSizeInBytes, const void *addr); - -/** - * @ingroup dnn - * @brief check input is overflow - * @param [in] handle cce handle - * @param [in] alpha scaling factors - * @param [in] xDesc descriptor of input tensor - * @param [in] x input data in device memory - * @param [in] yDesc descriptor of output tensor - * @param [in|out] y output data in device memory - * @param [in] beta scaling factors - * @return ccStatus_t - */ -ccStatus_t ccIsFinite(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, - const ccTensorDescriptor_t yDesc, const void *y, const void *beta); -}; // namespace cce - -#endif // DNN_OP_H__ diff --git a/third_party/fwkacllib/inc/cce/dnn_struct.hpp b/third_party/fwkacllib/inc/cce/dnn_struct.hpp deleted file mode 100644 index 96566074..00000000 --- a/third_party/fwkacllib/inc/cce/dnn_struct.hpp +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef DNN_STRUCT_HPP__ -#define DNN_STRUCT_HPP__ - -#include "dnn.h" -#include "dnn_struct_base.hpp" - -#endif // DNN_STRUCT_HPP__ diff --git a/third_party/fwkacllib/inc/cce/dnn_struct_base.hpp b/third_party/fwkacllib/inc/cce/dnn_struct_base.hpp deleted file mode 100644 index dd75e9ea..00000000 --- a/third_party/fwkacllib/inc/cce/dnn_struct_base.hpp +++ /dev/null @@ -1,894 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef DNN_STRUCT_BASE_HPP__ -#define DNN_STRUCT_BASE_HPP__ - -#include "cce/cce_def.hpp" - -namespace cce { - -/** - * @ingroup dnn - * @brief max number of dimensions - */ -#define CC_DIM_MAX (8) - -/** - * @ingroup dnn - * @brief max number of dimensions when use NC1HWC0 format - */ -#define CC_REALDIM_MAX (4) - -/** - * @ingroup dnn - * @brief max input count of MscnnBoxOutput - */ -#define CC_MAX_INPUT_CNT (10) - -/** - * @ingroup dnn - * @brief image dimensions of aipp input - */ -#define CC_AIPP_IMG_DIM (2) - -/** - * @ingroup dnn - * @brief image channel number of aipp input - */ -#define CC_AIPP_IMG_CHN_NUM (4) - -/** - * @ingroup dnn - * @brief element number of aipp color space convertion matrix - */ -#define CC_AIPP_CSC_MATRIX_DIM (9) - -/** - * @ingroup dnn - * @brief element number of aipp color space convertion bias - */ -#define CC_AIPP_CSC_BIAS_DIM (3) - -/** - * @ingroup dnn - * @brief parameter number of op exp/log/pow - */ -#define PARAM_CNT_THREE (3) - -/** - * @ingroup dnn - * @brief parameter number of op nonmaxsuppression - */ -#define PARAM_CNT_TWO (2) -#define DIMCNT_NUMBER_ONE (1) -#define DIMCNT_NUMBER_TWO (2) -#define DIMCNT_NUMBER_FOUR (4) - -#define COMMON_FORMAT_NCHW_N_INDEX (0) -#define COMMON_FORMAT_NCHW_C_INDEX (1) -#define COMMON_FORMAT_NCHW_H_INDEX (2) -#define COMMON_FORMAT_NCHW_W_INDEX (3) - -/** - * @ingroup dnn - * @brief parameter number of op upsample - */ -#define UPSAMPLE_SCAL_DEFAULT_TWO (2) -#define UPSAMPLE_ILLEGAL_VALUE_1 (1) - -/** - * @ingroup dnn - * @brief struct define of StridedSlice required params. - */ - -typedef struct tagCcStridedSlice { - uint32_t dimCnt; - int32_t begin[CC_DIM_MAX]; - int32_t end[CC_DIM_MAX]; - int32_t strides[CC_DIM_MAX]; -} ccStridedSlice_t; - -/** - * @ingroup dnn - * @brief struct define of Strided_slice attrs - */ -typedef struct tagCcStridedSliceAttrs { - uint32_t beginMask; - uint32_t endMask; - uint32_t ellipsisMask; - uint32_t newAxisMask; - uint32_t shrinkAxisMask; -} ccStridedSliceAttrs_t; - -/** - * @ingroup dnn - * @brief params of batchToSpace - */ -typedef struct tagCcBatchToSpace { - int32_t blockShapeLength; - int32_t blockShape[CC_DIM_MAX]; - int32_t crops[2 * CC_DIM_MAX]; -} ccBatchToSpace_t; - -/** - * @ingroup dnn - * @brief params of spaceToBatch - */ -typedef struct tagCcSpaceToBatch { - int32_t blockShapeLength; - int32_t blockShape[CC_DIM_MAX]; - int32_t paddings[2 * CC_DIM_MAX]; -} ccSpaceToBatch_t; - -/** - * @ingroup dnn - * @brief struct define of tensor - */ -typedef struct tagCcTensor { - ccTensorFormat_t format; - ccDataType_t dataType; - int32_t dimCnt; - int32_t realDimCnt; - uint32_t dataSize; - int32_t dim[CC_DIM_MAX]; - int32_t stride[CC_DIM_MAX]; - ccVecQuantizePara_t vecQuantizePara; -} ccTensor_t; - -/** - * @ingroup dnn - * @brief struct define of filter tensor - */ -typedef struct tagCcFilter { - ccTensorFormat_t format; - ccDataType_t dataType; - int32_t dimCnt; - uint32_t dataSize; - int32_t dim[CC_DIM_MAX]; -} ccFilter_t; - -/** - * @ingroup dnn - * @brief struct define of convolution operator - */ -typedef struct tagCcConvolution { - ccConvolutionMode_t mode; - ccPaddingMode_t padMode; - int32_t dimCnt; - int32_t padding[2 * (CC_DIM_MAX - 2)]; - int32_t filterStride[CC_DIM_MAX - 2]; - int32_t dilation[CC_DIM_MAX - 2]; - int32_t group; - ccQuantizeDescriptor_t quantInfo; - ccConvolutionAipp_t aippInfo; - int32_t adj[CC_DIM_MAX - 2]; - int32_t targetShape[CC_DIM_MAX - 2]; - int32_t beforePadding[2 * (CC_DIM_MAX - 2)]; // pad before conv - uint32_t reluFlag; - int64_t concatBatchSize; -} ccConvolution_t; - -#define ccCorrelation_t ccConvolution_t -typedef struct tagCcFullConnection_t { - ccQuantizeDescriptor_t quantInfo; - uint32_t infoTabSize; - const void *infoTab; - bool reluFlag; - ccFullConnectFwdAlgo_t algo; -} ccFullConnection_t; - -typedef struct tagCcConcatFour2Five_t { - uint32_t branchNum; // how many branch for box or class - uint32_t classNum; // box branch's classNum is four, class branch's classNum is class number -} ccConcatFour2Five_t; - -typedef struct tagCcTransdata_t { - uint64_t scaleQAddr; - uint8_t scaleQValueMode; - uint64_t offsetQAddr; - uint8_t quantAlgo; - uint8_t quantize8bitFlag; -} ccTransdata_t; -/** - * @ingroup dnn - * @brief struct define of pooling operator - */ -typedef struct tagCcPooling { - ccPoolingMode_t mode; - ccPaddingMode_t padMode; - ccNanPropagation_t maxpoolingNanOpt; - int32_t dimCnt; - int32_t windowDim[CC_DIM_MAX - 2]; - int32_t padding[CC_DIM_MAX - 2]; - int32_t stride[CC_DIM_MAX - 2]; - int32_t dataMode; - int32_t ceilMode; - ccQuantizeDescriptor_t quantInfo; - ccPooingFwdAlgo_t algo; -} ccPooling_t; - -/** - * @ingroup dnn - * @brief struct define of activation operator - */ -typedef struct tagCcActivation { - ccActivationMode_t mode; - ccNanPropagation_t reluNanOpt; - double coef; /* ceiling for clipped RELU, alpha for ELU */ - ccActivationPara_u activationPara; -} ccActivation_t; - -/** - * @ingroup dnn - * @brief struct define of svdf operator - */ -typedef struct tagCcSvdf { - ccTensorFormat_t format; - ccDataType_t dataType; - uint32_t batches; - uint32_t features; - uint32_t rank; - uint32_t inputSize; - uint32_t memorySize; -} ccSvdf_t; - -/** - * @ingroup dnn - * @brief struct define of svdf operator - */ -typedef struct tagCcHashTableLookup { - ccTensorFormat_t format; - ccDataType_t lookupType; - ccDataType_t keyType; - ccDataType_t valueType; - ccDataType_t outputType; - ccDataType_t hitsType; - uint32_t lookups; - uint32_t keys; - uint32_t rows; - uint32_t features; - uint16_t valueScale; - uint16_t outputScale; - uint16_t valueOffset; - uint16_t outputOffset; -} ccHashTableLookup_t; - -/** - * @ingroup dnn - * @brief struct define of prelu operator - */ -typedef struct tagCcPRelu { - ccNanPropagation_t reluNanOpt; - int32_t slopeCount; - bool channelShared; -} ccPRelu_t; - -/** - * @ingroup dnn - * @brief struct define of crop operator - */ -typedef struct tagCcCrop { - int32_t startAxis; - int32_t offset[CC_DIM_MAX]; - int32_t offsetCnt; -} ccCrop_t; - -/** - * @ingroup dnn - * @brief struct define of SpatialTransformer operator - */ -typedef struct tagCcSpatialTransformer { - ccSamplerType_t samplerType; - ccDataType_t dataType; - int32_t dimCnt; - uint64_t dim[CC_DIM_MAX]; - uint64_t alignCorner; -} ccSpatialTransformer_t; - -/** - * @ingroup dnn - * @brief struct define of ShiftTransformer operator - */ -typedef struct tagCcShiftTransformer { - ccSamplerType_t samplerType; - double xPreDefined; - double yPreDefined; - bool xShift; - bool yShift; - int32_t gridH; - int32_t gridW; -} ccShiftTransformer_t; - -/** - * @ingroup dnn - * @brief struct define of FasterRcnnProposal operator - */ -typedef struct tagCcFasterRcnnProposal { - int32_t preNMStopK; - int32_t postNMStopK; - float nmsTresh; - float minSize; - float featStride; - float baseSize; - int32_t ratioCnt; - int32_t scaleCnt; - float *ratio; - float *scale; - int32_t imgH; - int32_t imgW; -} ccFasterRcnnProposal_t; - -/** - * @ingroup dnn - * @brief struct define of LRN operator - */ -typedef struct tagCcLRN { - ccLRNMode_t lrnMode; - int32_t lrnN; - double lrnAlpha; - double lrnBeta; - double lrnK; -} ccLRN_t; - -/** - * @ingroup dnn - * @brief struct define of instanceNorm - */ -typedef struct tagCcInstancenorm { - ccInstanceNormMode_t mode; - double epsilon; -} ccInstancenorm_t; - -/** - * @ingroup dnn - * @brief struct define of assignOp operator - */ -typedef struct tagCcAssignOp { - ccAssignOpMode_t assignOpMode; -} ccAssignOp_t; - -/** - * @ingroup dnn - * @brief struct define of arcSinCos operator - */ -typedef struct tagCcArcSinCos { - ccArcSinCosMode_t arcSinCosMode; -} ccArcSinCos_t; - -/** - * @ingroup dnn - * @brief struct define of Detectpostprocess operator - */ -typedef struct tagCcDetectpostprocess { - int32_t numClasses; - float confThreshold; - float nmsThreshold; - int32_t outTopK; - float bboxRegWeightsDx; - float bboxRegWeightsDy; - float bboxRegWeightsDw; - float bboxRegWeightsDh; -} ccDetectpostprocess_t; -/** - * @ingroup dnn - * @brief struct define of FasterRcnnDetectionOutput operator - */ -typedef struct tagCcFasterRcnnDetectionOutput { - int32_t numClasses; - float nmsThreshold; - float postConfThreshold; - int32_t imgH; - int32_t imgW; - int32_t batchSize; -} ccFasterRcnnDetectionOutput_t; - -/** - * @ingroup dnn - * @brief struct define of SsdDetectionOutput operator - */ -typedef struct tagCcSsdDetectionOutput { - int32_t numClasses; - int32_t backgroundLabelId; - double preConfThreshold; - int32_t preTopK; - double nmsThreshold; - double nmsEta; - ccBoxCodeType_t codeType; - int32_t outTopK; - bool shareLocation; - bool varianceEncodedInTarget; - uint32_t boxTypeNum; - float var[4]; - uint32_t variance_num; -} ccSsdDetectionOutput_t; - -/** - * @ingroup dnn - * @brief struct define of RefinedetDetectionOutput operator - */ -typedef struct tagCcRefinedetDetectionOutput { - int32_t numClasses; - int32_t backgroundLabelId; - double preConfThreshold; - int32_t preTopK; - double nmsThreshold; - double nmsEta; - ccBoxCodeType_t codeType; - int32_t outTopK; - bool shareLocation; - bool varianceEncodedInTarget; - uint32_t boxTypeNum; - float var[4]; - uint32_t variance_num; - double objectness_score; -} ccRefinedetDetectionOutput_t; - -/** - * @ingroup dnn - * @brief struct define of MsrGenerateRpnProposals operator - */ -typedef struct tagCcMsrGenerateRpnProposals { - int32_t preNmsTopK; - int32_t postNmsTopK; - float nmsThreshold; - float rpnMiniSize; - int32_t imgH; - int32_t imgW; - uint32_t boxTypeNum; - float scoreThreshold; -} ccMsrGenerateRpnProposals_t; - -/** - * @ingroup dnn - * @brief struct define of RetinaPostprocessor operator - */ -typedef struct tagCcRetinaPostprocessor { - int32_t numClasses; - int32_t maxDetections; - float nmsThreshold; - float scoreThreshold; - int32_t imgH; - int32_t imgW; - uint32_t boxTypeNum; - float mean[4]; - int32_t meanNum; - float std[4]; - int32_t stdNum; - int32_t outputNum; - bool ocrFlag; -} ccRetinaPostprocessor_t; - -/** - * @ingroup dnn - * @brief struct define of GenerateSsdAnchors operator - */ -typedef struct tagCcGenerateSsdAnchors { - int32_t featureMapShapeList[20]; - uint32_t featureMapShapeListSize; - int32_t boxSpecsNum[10]; - uint32_t boxSpecsNumSize; - float scales[10]; - uint32_t scalesNum; - float aspectRatios[10]; - uint32_t aspectRatiosNum; - int32_t baseAnchorSize[2]; - uint32_t baseAnchorSizeNum; - int32_t anchorStride[2]; - uint32_t anchorStrideNum; - int32_t anchorOffset[2]; - uint32_t anchorOffsetNum; - bool reduceBoxesInLowestLayer; - float minScale; - float maxScale; - int32_t imgH; - int32_t imgW; -} ccGenerateSsdAnchors_t; - -/** - * @ingroup dnn - * @brief struct define of MscnnBoxOutput operator - */ -typedef struct tagCcMscnnBoxOutput { - double fgThreshold; - double nmsThreshold; - ccNmsType_t nmsType; - int32_t fieldH[CC_MAX_INPUT_CNT]; - int32_t fieldW[CC_MAX_INPUT_CNT]; - int32_t downsampleRate[CC_MAX_INPUT_CNT]; - int32_t defaultBoxCnt; - double fieldWhr; - double fieldXyr; - int32_t maxNmsNum; - int32_t maxPostNmsNum; - double minSize; -} ccMscnnBoxOutput_t; - -/** - * @ingroup dnn - * @brief struct define of NMS operator - */ -typedef struct tagCcNms { - int32_t numClasses; - int32_t backgroundLabelId; - double preConfThreshold; - int32_t preTopK; - double nmsThreshold; - double nmsEta; - int32_t postTopK; - int32_t outTopK; - double postConfThreshold; - bool shareLocation; -} ccNms_t; - -/** - * @ingroup dnn - * @brief struct define of NMS/MultiClassNMS operator - */ -typedef struct tagCcMultiClassNms { - uint64_t numClasses; - float objThreshold; - float nmsThreshold; - float clsThreshold; - bool normal; - uint64_t coorType; -} ccCcMultiClassNms_t; - -/** - * @ingroup dnn - * @brief struct define of YoloDetectionOutput operator - */ -typedef struct tagCcYoloDetectionOutput { - ccYoloVersion_t yoloVersion; - uint32_t netH; - uint32_t netW; - uint32_t postTopK; - uint32_t classes; - float nmsThreshold; - float iouThreDecay; - float coorScaleFactor; - bool relative; - float objThreshold; - float clsThreshold; - uint32_t biasNum; - float *bias; -} ccYoloDetectionOutput_t; - -/** - * @ingroup dnn - * @brief struct define of GetRegionBox operator - */ -#ifndef CC_MAX_YOLO_BIAS_NUM -#define CC_MAX_YOLO_BIAS_NUM (16) -#endif - -typedef struct tagCcGetRegionBox { - uint32_t biasNum; - uint32_t H; - uint32_t W; - float bias[CC_MAX_YOLO_BIAS_NUM]; -} ccGetRegionBox_t; - -/** - * @ingroup dnn - * @brief struct define of CorrectBoxes operator - */ -typedef struct tagCorrectBoxes { - uint32_t netW; - uint32_t netH; - bool relative; -} ccCorrectBoxes_t; - -/** - * @ingroup dnn - * @brief struct define of ClsProb operator - */ -typedef struct tagClsProb { - float objThreshold; -} ccClsProb_t; - -/** - * @ingroup dnn - * @brief struct define of SsdPriorBox operator - */ -typedef struct tagCcSsdPriorBox { - ccBoxCodeType_t codeType; - double *minSize; - int32_t minSizeNum; - double *maxSize; - int32_t maxSizeNum; - double *aspectRatio; - int32_t aspectRatioNum; - double *variance; - int32_t varianceNum; - int32_t imgH; - int32_t imgW; - double stepH; - double stepW; - double offset; - bool flip; - bool clip; -} ccSsdPriorBox_t; - -/** - * @ingroup dnn - * @brief struct define of Yolo2Region operator - */ -typedef struct tagCcYolo2Region { - ccSoftmaxTree_t softmaxTree; - bool softmax; - bool background; - bool treeSoftmax; -} ccYolo2Region_t; - -/** - * @ingroup dnn - * @brief struct define of YoloRegion operator - */ -typedef struct tagCcYoloRegion { - ccSoftmaxTree_t softmaxTree; - bool softmax; - bool background; - bool treeSoftmax; - int32_t classes; - int32_t coords; - int32_t boxes; - ccYoloVersion_t yoloV; -} ccYoloRegion_t; - -/** - * @ingroup dnn - * @brief struct define of power operator - */ -typedef struct tagCcPower { - float scale; - float shift; - float power; -} ccPower_t; - -/** - * @ingroup dnn - * @brief struct define of exp operator - */ -typedef struct tagCcExp { - ccDataType_t dataType; - uint32_t paramCnt; -} ccExp_t; - -/** - * @ingroup dnn - * @brief struct define of exp operator - */ -typedef struct tagCcLog { - ccDataType_t dataType; - uint32_t paramCnt; -} ccLog_t; - -/** - * @ingroup dnn - * @brief struct define of pow operator - */ -typedef struct tagCcPow { - ccDataType_t dataType; - uint32_t paramCnt; -} ccPow_t; - -/** - * @ingroup dnn - * @brief struct define of padv2 operator - */ -typedef struct tagCcPadV2 { - ccPadMode_t padMode; - void *padValue; - ccDataType_t padValueType; - int32_t padDimCnt; - int32_t padShapeLow[CC_DIM_MAX]; - int32_t padShapeHigh[CC_DIM_MAX]; -} ccPadV2_t; - -/** - * @ingroup dnn - * @brief struct define of psROIPooling operator - */ -typedef struct tagCcPsRoiPooling { - ccPoolingMode_t poolingMode; - int32_t pooledH; - int32_t pooledW; - float spatialScale; - float padRatio; - int32_t groupSize; - int32_t outputDim; -} ccPsRoiPooling_t; - -/** - * @ingroup dnn - * @brief struct define of RoIAlign operator - */ -typedef struct tagCcRoiAlign { - int32_t pooledH; - int32_t pooledW; - float spatialScale; - int32_t samplingRatio; -} ccRoiAlign_t; - -/** - * @ingroup dnn - * @brief struct define of RoiInterpPooling operator - */ -typedef struct tagCcRoiInterpPooling { - int32_t pooledH; - int32_t pooledW; - int32_t poolKernelH; - int32_t poolKernelW; - int32_t pooledTailH; - int32_t pooledTailW; - float spatialScaleH; - float spatialScaleW; -} ccRoiInterpPooling_t; - -/** - * @ingroup dnn - * @brief struct define of DetectionFull3DOutput operator - */ -typedef struct tagCcDetectionFull3DOutput { - int32_t imageWidth; - int32_t imageHeight; - int32_t numAngleBins; - float trcMarginRatioX; - float trcMarginRatioY; - int32_t pitchRangeD; - int32_t pitchPresetD; - float mountHeight; - int32_t visiblenessBins; - float meanVisibleness; - bool discreteVisibleness; -} ccDetectionFull3DOutput_t; - -/** - * @ingroup dnn - * @brief struct define of MsrFastRcnnPredictions operator - */ -typedef struct tagMsrFastRcnnPredictions { - int32_t numClasses; // num of classes - float scoreThreshold; // the threshold of the score - double nmsThreshold; // the threshold of nms - int32_t postTopK; - int32_t outTopK; - int32_t imgH; // the height of image - int32_t imgW; // the width of image -} ccMsrFastRcnnPredictions_t; - -typedef struct tagCcResizeBilinear { - ccResizeOutputDimMode_t resizeOutputDimMode; - bool alignCorners; - int32_t zoom_factor; - int32_t shrink_factor; - int32_t height; - int32_t width; - int32_t pad_begin; - int32_t pad_end; -} ccResizeBilinear_t; - -typedef struct tagCcResizeNearestNeighbor { - bool alignCorners; - int32_t height; - int32_t width; -} ccResizeNearestNeighbor_t; - -typedef struct tagCcEltwise { - ccQuantize_t *quantInfo; - bool reluFlag; -} ccEltwise_t; - -typedef struct tagCcBatchNorm { - bool reluFlag; -} ccBatchNorm_t; - -typedef struct tagCcPad { - ccPadMode_t padMode; - float padValue; - int32_t htoppad; // padLow[0] - int32_t hbottompad; // padHigh[0] - int32_t wleftpad; // padLow[1] - int32_t wrightpad; // padHigh[1] -} ccPad_t; - -typedef struct tagCcSubCondition { - uint32_t BaseCondValue[4]; - ccCMPType_t condType[4]; - ccResultType_t resultType; -} ccSubCondition; - -typedef struct tagCcShapeClassifyCond { - uint32_t subConditionNum; - ccResultType_t resultType; - uint32_t true_value; - ccSubCondition subCond[2]; -} ccShapeClassifyCond; - -#ifndef CC_SHAPE_CLASSIFY_CONDITION_NUM -#define CC_SHAPE_CLASSIFY_CONDITION_NUM (8) -#endif - -typedef struct tagCcShapeClassify { - uint32_t shapeClassifyConditionNum; - uint32_t defaultValue; - ccShapeClassifyCond shapeClassifyCond[CC_SHAPE_CLASSIFY_CONDITION_NUM]; -} ccShapeClassify_t; - -/** - * @ingroup dnn - * @bref struct define of square operator - */ -typedef struct tagCcSquare { - ccSquareMode_t mode; -} ccSquare_t; - -/* - * @ingroup dnn - * @brief operation of segment reduction - */ -typedef enum { - CC_SEGMENT_REDUCTION_OP_SUM = 0, /**< sum */ - CC_SEGMENT_REDUCTION_OP_INVALID -} ccSegmentReductionOpType_t; - -typedef struct tagCcFillParam { - // The filler type. - ccFillOpType_t fillType; - ccDataType_t valueDatatype; - const void *value; // the value in constant fill - const void *min; // the min value in uniform fill - const void *max; // the max value in uniform fill - const void *mean; // the mean value in Gaussian fill - const void *std; // the std value in Gaussian fill - // the seed used to generate data in Gaussian and uniform fill - int64_t seed1; - int64_t seed2; -} ccFillParam_t; - -typedef struct tagNonMaxSuppression { - ccDataType_t dataType; - uint32_t paraCount; -} ccNonMaxSuppression_t; - -typedef struct tagCcArgmaxmin { - int32_t axisType; - bool outMaxVal; - int64_t topK; - int64_t reduceSize; - int64_t reduceStride; - int64_t axis; - bool keepDims; -} ccArgmaxmin_t; - -typedef struct tagUpsamplePara { - int32_t scale; - int32_t scaleHeight; - int32_t scaleWidth; - int32_t upsampleHeight; - int32_t upsampleWidth; - bool padOutHeight; - bool padOutWidth; -} ccUpsamplePara_t; - -typedef struct tagCcConcatFive2Four_t { - ccTransForLossMode_t mode; - uint32_t classNum; -} ccConcatFive2Four_t; - -}; // namespace cce -#endif // DNN_STRUCT_BASE_HPP__ diff --git a/third_party/fwkacllib/inc/cce/fwk_adpt_struct.h b/third_party/fwkacllib/inc/cce/fwk_adpt_struct.h deleted file mode 100644 index 5733d68f..00000000 --- a/third_party/fwkacllib/inc/cce/fwk_adpt_struct.h +++ /dev/null @@ -1,155 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef FWK_ADPT_STRUCT_H__ -#define FWK_ADPT_STRUCT_H__ - -#include - -namespace aicpu { -namespace FWKAdapter { - -// API RETURN CODE -enum FWKAdptAPIRetCode { - FWK_ADPT_SUCCESS = 0, // success - FWK_ADPT_NOT_INIT = 1, // not init - FWK_ADPT_ALLOC_FAILED = 2, // allocate memory failed - FWK_ADPT_PARAM_INVALID = 3, // invalid input param - FWK_ADPT_PARAM_PARSE_FAILED = 4, // parase input param failed - FWK_ADPT_NATIVE_ERROR = 5, // error code - FWK_ADPT_NOT_SUPPORT_OPTYPE = 6, // unsupport operate type - FWK_ADPT_INTERNAL_ERROR = 7, // adpter internal error - FWK_ADPT_NOT_SUPPORT_DATATYPE = 8, // unsupport input/output data type - FWK_ADPT_KERNEL_ALREADY_RUNING = 9, // kernel already runing, not support parallel run - FWK_ADPT_SESSION_NOT_EXIST = 10, // session id not exist - FWK_ADPT_SESSION_ALREADY_EXIST = 11, // session id alread exist for create session - FWK_ADPT_NATIVE_END_OF_SEQUENCE = 12, // end of sequence - FWK_ADPT_EXTEND_TYPE_NOT_EXIST = 13, // extend info type not exist - FWK_ADPT_UNKNOWN_ERROR = 99 // unknown error code -}; - -// FWKAdapter operate type -// Notice: add new operate type need check with OMM, and make sure append to the end line. -enum FWKOperateType { - FWK_ADPT_SESSION_CREATE = 0, - FWK_ADPT_KERNEL_RUN, - FWK_ADPT_KERNEL_DESTROY, - FWK_ADPT_SESSION_DESTROY, - FWK_ADPT_SINGLE_OP_RUN, - FWK_ADPT_KERNEL_RUN_NO_SESS, -}; - -// Extend Info type for task -enum FWKTaskExtInfoType { - FWK_ADPT_EXT_SHAPE_TYPE = 0, - FWK_ADPT_EXT_INPUT_SHAPE, - FWK_ADPT_EXT_OUTPUT_SHAPE, - FWK_ADPT_EXT_UPDATE_ADDR, - FWK_ADPT_EXT_OP_NAME, - FWK_ADPT_EXT_SESSION_INFO, - FWK_ADPT_EXT_BITMAP, - FWK_ADPT_EXT_TOPIC_TYPE, - FWK_ADPT_EXT_ASYNCWAIT, - FWK_ADPT_EXT_INVALID -}; - -enum FWKExtTopicType { - FWK_ADPT_TOPIC_DEVICE_ONLY = 0, - FWK_ADPT_TOPIC_DEVICE_FIRST, - FWK_ADPT_TOPIC_HOST_ONLY, - FWK_ADPT_TOPIC_HOST_FIRST, - FWK_ADPT_TOPIC_INVALID -}; - -enum FWKExtUpdateAddrType { - FWK_ADPT_UPDATE_NULL = 0, - FWK_ADPT_UPDATE_INPUT, - FWK_ADPT_UPDATE_OUTPUT, - FWK_ADPT_UPDATE_INPUT_OUTPUT -}; - -enum FWKExtWaitType { - FWK_ADPT_WAIT_TYPE_NULL = 0, - FWK_ADPT_WAIT_TYPE_EVENT, - FWK_ADPT_WAIT_TYPE_INVALID -}; - -#pragma pack(push, 1) -// API Parameter Structure -struct StrFWKKernel { - FWKOperateType opType; - uint64_t sessionID; // unique - - uint64_t stepIDAddr; // step id addr - uint64_t kernelID; // run kernel id, unique in session - uint64_t nodeDefLen; // nodeDef protobuf len - uint64_t nodeDefBuf; // NodeDef protobuf offset addr, need convert to void* - uint64_t funDefLibLen; // FunctionDefLibrary protobuf len - uint64_t funDefLibBuf; // FunctionDefLibrary protobuf addr which use in NodeDef, need convert to void* - - uint64_t inputOutputLen; // InputOutput shap protobuf len - uint64_t inputOutputBuf; // InputOutput shap protobuf addr, need convert to void* - uint64_t workspaceBaseAddr; // Workspace base addr, need convert to void* - uint64_t inputOutputAddr; // InputOutput addr, need convert to void* - - uint64_t extInfoLen; // extend info total length - uint64_t extInfoAddr; // extend info addr, ExtInfo structure -}; -#pragma pack(pop) - -typedef StrFWKKernel FWKOperateParam; - -// Extent info ShapeAndType -const uint32_t kMaxShapeDims = 8; -#pragma pack(push, 1) -struct ShapeAndType { - int32_t type; - int64_t dims[kMaxShapeDims]; -}; -#pragma pack(pop) - -// Extend info structure for extInfoAddr -const uint32_t kExtInfoHeadSize = 8; - -#pragma pack(push, 1) -struct ExtInfo { - int32_t infoType; // extend type - uint32_t infoLen; // length for infoMsg - char infoMsg[0]; // extend value -}; -#pragma pack(pop) - -#pragma pack(push, 1) -struct ResultSummary { - uint64_t shape_data_ptr; // shape data addr, need convert to void* - uint64_t shape_data_size; // num of dims - uint64_t raw_data_ptr; // raw data addr, need convert to void* - uint64_t raw_data_size; // size of raw data -}; -#pragma pack(pop) - -#pragma pack(push, 1) -struct AsyncWait { - uint8_t waitType; // wait type, FWK_ADPT_WAIT_TYPE_EVENT: event wait - uint32_t waitId; // wait id, GE refresh - uint32_t timeOut; // reserved - uint64_t reserved; -}; -#pragma pack(pop) -} // end namespace FWKAdapter -} // namespace aicpu - -#endif // FWK_ADPT_STRUCT_H__ diff --git a/third_party/fwkacllib/inc/cce/l2fusion_struct.hpp b/third_party/fwkacllib/inc/cce/l2fusion_struct.hpp deleted file mode 100644 index fa5a95c9..00000000 --- a/third_party/fwkacllib/inc/cce/l2fusion_struct.hpp +++ /dev/null @@ -1,56 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef L2FUSION_STRUCT_HPP_ -#define L2FUSION_STRUCT_HPP_ - -#include -#include -#include "runtime/kernel.h" - -#define L2_DYNAMIC_SPLIT_NUM - -using namespace std; - -namespace fusion { - -typedef struct tagL2Data { - uint32_t l2Index; - uint64_t l2Addr; - uint64_t l2PageNum; -} L2Data_t; - -typedef std::map L2DataMap_t; // the key is ddr addr -typedef std::pair L2DataPair_t; // the key is ddr addr - -typedef struct TagTaskL2Info { - string nodeName; - rtL2Ctrl_t l2ctrl; - - L2DataMap_t input; - L2DataMap_t output; - uint32_t isUsed; -} TaskL2Info_t; - -typedef std::map TaskL2InfoMap_t; // the key is nodeId -typedef std::pair TaskL2InfoPair_t; // the key is nodeId - -typedef std::map TaskL2InfoFEMap_t; // the key is nodeName -typedef std::pair TaskL2InfoFEPair_t; // the key is nodeName - -} // namespace fusion - -#endif // L2FUSION_STRUCT_HPP_ diff --git a/third_party/fwkacllib/inc/cce/optimizer/fusion_engine.h b/third_party/fwkacllib/inc/cce/optimizer/fusion_engine.h deleted file mode 100644 index 299998e3..00000000 --- a/third_party/fwkacllib/inc/cce/optimizer/fusion_engine.h +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef FUSION_ENGINE_HPP_ -#define FUSION_ENGINE_HPP_ - -#include "cce/cce.h" -#include "graph/compute_graph.h" -#include "proto/task.pb.h" - -#include -#include - -using namespace domi; -using namespace std; - -namespace fusion { -enum { - FUSION_STATUS_SUCCESS = 0, - FUSION_STATUS_FAIL = 1, -}; - -typedef struct { - uint64_t weightSize; - uint64_t memorySize; - uint8_t *dataMemBase; - uint8_t *weightMemBase; - uint32_t l2Enable; // 1 //1 - enable l2 buffer allocation, 0 - disable l2 buffer allocation - uint32_t fusionEnable; // 1 // 1 - enable buffer fusion, 0 - disable buffer fusion -} ModelRes; - -static const std::string SCOPE_ID_ATTR = "fusion_scope"; -static const std::string L2FUSION_DYNAMIC_CONVERGE_OP = "l2fusion_dynamic_converge_op"; -static const std::string L2FUSION_DYNAMIC_SPLIT_NUM = "l2fusion_dynamic_split_num"; -static const std::string FUSION_VIRTUAL_OP = "fusion_virtual_op"; -static const std::string FUSION_MULTI_BATCH_STRIDE = "fusion_multi_bathc_stride"; - -#define TVM_TYPE 1 - -typedef std::map> kScopeNodeMap_t; -typedef std::pair> kScopeNodePair_t; - -uint32_t BufferFusion(ge::ComputeGraphPtr origGraph, ge::ComputeGraphPtr fusionGraph, bool enable_l2dynamic = true); -uint32_t BufferFusionTrain(ge::ComputeGraphPtr origGraph, ge::ComputeGraphPtr fusionGraph); -uint32_t GraphFusion(ge::ComputeGraphPtr origGraph, ge::ComputeGraphPtr fusionGraph); -uint32_t FusionTaskBuild(cce::ccHandle_t ccHandle, ge::ComputeGraphPtr fusionGraph, ge::Buffer &buffer, - ModelRes &modelRes, std::vector &task_def_list_); -void FusionTaskBuildComplete(std::vector cchandleList); -uint32_t GraphFusionTrain(ge::ComputeGraphPtr origGraph, ge::ComputeGraphPtr fusionGraph); -} // namespace fusion - -#endif // FUSION_ENGINE_HPP_ diff --git a/third_party/fwkacllib/inc/cce/taskdown_api.h b/third_party/fwkacllib/inc/cce/taskdown_api.h deleted file mode 100644 index 2323aaa7..00000000 --- a/third_party/fwkacllib/inc/cce/taskdown_api.h +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef TASKDOWN_API_H_ -#define TASKDOWN_API_H_ - -#include -#include -#include "cce/cce.h" -#include "l2fusion_struct.hpp" -#include "taskdown_common.hpp" - -namespace cce { - -#define CC_FUSION_OP_MAX 32 - -typedef struct tagOpAddrsInfo { - void *addrPos; - uintptr_t addrData; -} ccOpAddrsInfo; - -#ifdef __cplusplus -extern "C" { -#endif - -ccStatus_t ccUpdateKernelArgs(ccOpContext &opContext, uint64_t dataBaseAddr, uint64_t weightBaseAddr, - uint64_t variableBaseAddr, void *argsAddr, uint64_t argsSize, void *l2ctrlAddr); - -#ifdef __cplusplus -} -#endif - -ccStatus_t ccGetKernelArgsAddrs(ccOpContext &opContext, void *argsAddr, uint64_t argsSize, void *l2ctrlAddr, - std::vector &opAddrsInfo); - -ccStatus_t ccSetKernelArgs(std::vector &dateInfo); - -ccStatus_t ccGetKernelTypeByOpId(uint32_t opId, ccKernelType &kernelType); - -} // namespace cce -#endif // TASKDOWN_API_H_ diff --git a/third_party/fwkacllib/inc/cce/taskdown_common.hpp b/third_party/fwkacllib/inc/cce/taskdown_common.hpp deleted file mode 100644 index 7954162e..00000000 --- a/third_party/fwkacllib/inc/cce/taskdown_common.hpp +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef TASKDOWN_COMMON_H_ -#define TASKDOWN_COMMON_H_ - -#include -#include "cce/cce_def.hpp" -#include "common/attr_list.hpp" -#include "l2fusion_struct.hpp" - -namespace cce { - -#define CC_FUSION_OP_MAX 32 - -typedef enum tagccKernelType { - CCE_AI_CORE = 0, /* cce aicore */ - CCE_AI_CPU = 1, /* cce aicpu */ - TE = 2, /* te operator*/ - CUSTOMIZED = 3, /* customized operator */ - TE_AI_CORE = 4, /* te aicore operator*/ - TE_AI_CPU = 5, /* te aicpu operator */ - AI_CPU = 6, /* aicpu */ - CUST_AI_CPU = 7, /* custom aicpu*/ - HOST_CPU = 8, /* host cpu */ - INVALID = 10000 /* unknown kernel type */ -} ccKernelType; - -typedef struct tagOpContext { - ccKernelType kernelType; - uint32_t opId; - uint32_t kernelFuncId; - uint32_t opIndex; - uint32_t opCount; - uint32_t opIndex2[CC_FUSION_OP_MAX]; - bool isFlowtable; - uint16_t *argsOffset; - uint32_t argsCount; - uint64_t genDataBaseAddr; - uint64_t genDataBaseSize; - uint64_t genWeightBaseAddr; - uint64_t genWeightBaseSize; - uint64_t genVariableBaseAddr; - uint64_t genVariableBaseSize; - uint64_t l2ctrlSize; -} ccOpContext; - -typedef struct tagOpReadCount { - bool isEnable; - std::map tensorRc; -} ccOpReadCount; - -typedef enum tagTaskDownKernelIdMode { - CC_TASKDOWN_RESERVED = 0, - CC_TASKDOWN_ROIPOOLING, - CC_TASKDOWN_ROIPOOLING_PERF, - CC_TASKDOWN_ROIALIGN, - CC_TASKDOWN_ROIALIGN_PERF, - CC_TASKDOWN_FC, - CC_TASKDOWN_FC_COMPRESS, - CC_TASKDOWN_SOFTMAX_LOWEST, - CC_TASKDOWN_ROIALIGN_FP16, - CC_TASKDOWN_RESIZE_NEAREST_NEIGHBOR, - CC_TASKDOWN_RESIZE_NEAREST_NEIGHBOR_COMMON, -} ccTaskDownKernelIdMode_t; - -ccStatus_t GetStream(ccHandle_t handle, rtStream_t *streamId); - -ccStatus_t ccClearOpMap(ccHandle_t handle); - -ccStatus_t ccSetKernelOpMap(ccHandle_t handle); - -ccStatus_t ccSetKernelContext(ccHandle_t handle, uint32_t opId, AttrList &attrList, bool isFlowtable, - ccKernelType kernelType, void *pgraph); - -ccStatus_t ccGetKernelContext(rtStream_t streamId, ccOpContext &opContext); - -ccStatus_t ccGetKernelTypeByOpId(uint32_t opId, ccKernelType &kernelType); - -ccStatus_t ccSetStreamL2Map(ccHandle_t handle, fusion::TaskL2InfoMap_t &l2AllocRes); - -ccStatus_t ccGetStreamL2Map(rtStream_t streamId, uint32_t opIndex, fusion::TaskL2Info_t *&l2Data); - -ccStatus_t ccSetOpIndex(ccHandle_t handle, uint32_t opIndex); - -ccStatus_t ccGetOpIndex(ccHandle_t handle, uint32_t &opIndex); - -ccStatus_t ccGetOpIndexByStream(rtStream_t streamId, uint32_t &opIndex); - -ccStatus_t ccClearStreamL2Map(ccHandle_t handle); - -ccStatus_t ccGetKernelReadCount(rtStream_t streamId, ccOpReadCount &rc); - -} // namespace cce -#endif // TASKDOWN_COMMON_H_ diff --git a/third_party/fwkacllib/inc/ops/aipp.h b/third_party/fwkacllib/inc/ops/aipp.h index 6db4d783..86805f72 100644 --- a/third_party/fwkacllib/inc/ops/aipp.h +++ b/third_party/fwkacllib/inc/ops/aipp.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/all_ops.h b/third_party/fwkacllib/inc/ops/all_ops.h index b67ead37..6c4d615d 100644 --- a/third_party/fwkacllib/inc/ops/all_ops.h +++ b/third_party/fwkacllib/inc/ops/all_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -78,4 +78,5 @@ #include "condtake_ops.h" #include "warp_perspective_ops.h" #include "vector_search.h" +#include "deep_md.h" #endif // OPS_BUILT_IN_OP_PROTO_INC_ALL_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/array_ops.h b/third_party/fwkacllib/inc/ops/array_ops.h index c02537cd..d56ac5bb 100644 --- a/third_party/fwkacllib/inc/ops/array_ops.h +++ b/third_party/fwkacllib/inc/ops/array_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -1014,6 +1014,25 @@ REG_OP(Shape) .ATTR(dtype, Int, DT_INT32) .OP_END_FACTORY_REG(Shape) +/** +*@brief Gather selected dims of input which returns the shape of tensor shape after gathershapes.\n + +*@par Inputs: +*x: A list of input tensors. It's a dynamic input. \n + +*@par Attributes: +*axes: Select some dims of input. \n + +*@par Outputs: +*shape: The shape of tensor shape after gathershapes. \n +*/ +REG_OP(GatherShapes) + .DYNAMIC_INPUT(x, TensorType::ALL()) + .OUTPUT(shape, TensorType({DT_INT32, DT_INT64})) + .REQUIRED_ATTR(axes, ListListInt) + .ATTR(dtype, Int, DT_INT32) + .OP_END_FACTORY_REG(GatherShapes) + /** *@brief Returns shape of tensors. \n diff --git a/third_party/fwkacllib/inc/ops/audio_ops.h b/third_party/fwkacllib/inc/ops/audio_ops.h index d9883253..f05135d1 100644 --- a/third_party/fwkacllib/inc/ops/audio_ops.h +++ b/third_party/fwkacllib/inc/ops/audio_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h b/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h index 9583eff9..d0800a08 100644 --- a/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h +++ b/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/batch_ops.h b/third_party/fwkacllib/inc/ops/batch_ops.h index 4b78951d..ca4fe1db 100644 --- a/third_party/fwkacllib/inc/ops/batch_ops.h +++ b/third_party/fwkacllib/inc/ops/batch_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/bitwise_ops.h b/third_party/fwkacllib/inc/ops/bitwise_ops.h index d032476d..dac78118 100644 --- a/third_party/fwkacllib/inc/ops/bitwise_ops.h +++ b/third_party/fwkacllib/inc/ops/bitwise_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/boosted_trees_ops.h b/third_party/fwkacllib/inc/ops/boosted_trees_ops.h index 550e8b7d..08e54824 100644 --- a/third_party/fwkacllib/inc/ops/boosted_trees_ops.h +++ b/third_party/fwkacllib/inc/ops/boosted_trees_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h b/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h index e20607bf..890c52ae 100644 --- a/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h +++ b/third_party/fwkacllib/inc/ops/candidate_sampling_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/case_condition_ops.h b/third_party/fwkacllib/inc/ops/case_condition_ops.h index 85064845..85dba609 100644 --- a/third_party/fwkacllib/inc/ops/case_condition_ops.h +++ b/third_party/fwkacllib/inc/ops/case_condition_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/cluster.h b/third_party/fwkacllib/inc/ops/cluster.h index f3242a13..19b4ea05 100644 --- a/third_party/fwkacllib/inc/ops/cluster.h +++ b/third_party/fwkacllib/inc/ops/cluster.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2021 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. diff --git a/third_party/fwkacllib/inc/ops/condtake_ops.h b/third_party/fwkacllib/inc/ops/condtake_ops.h index 5e91eb07..029cffbf 100644 --- a/third_party/fwkacllib/inc/ops/condtake_ops.h +++ b/third_party/fwkacllib/inc/ops/condtake_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/control_flow_ops.h b/third_party/fwkacllib/inc/ops/control_flow_ops.h index 53a213f7..cd993599 100644 --- a/third_party/fwkacllib/inc/ops/control_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/control_flow_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h b/third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h index 79a64c2c..f52c90b0 100644 --- a/third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h +++ b/third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/correlation.h b/third_party/fwkacllib/inc/ops/correlation.h index c7262cbb..caebba50 100644 --- a/third_party/fwkacllib/inc/ops/correlation.h +++ b/third_party/fwkacllib/inc/ops/correlation.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/third_party/fwkacllib/inc/ops/ctc_ops.h b/third_party/fwkacllib/inc/ops/ctc_ops.h index 7729432e..6e908091 100644 --- a/third_party/fwkacllib/inc/ops/ctc_ops.h +++ b/third_party/fwkacllib/inc/ops/ctc_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/data_flow_ops.h b/third_party/fwkacllib/inc/ops/data_flow_ops.h index 492a58ae..3034730d 100644 --- a/third_party/fwkacllib/inc/ops/data_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/data_flow_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -2415,6 +2415,23 @@ REG_OP(AdpGetNext) .ATTR(output_shapes, ListListInt, {{}, {}}) .ATTR(queue_name, String, "") .OP_END_FACTORY_REG(AdpGetNext) -} // namespace ge +/** +*@brief GetNextV2 +*@par Outputs: +*y: the data in iterator, all types are available +*@par Attributes: +*output_types: types of all outputs +*output_shapes: shapes of all outputs +*queue_name: cdqm queue name +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(GetNextV2) + .DYNAMIC_OUTPUT(y, TensorType::ALL()) + .ATTR(output_types, ListType, {}) + .ATTR(output_shapes, ListListInt, {{}, {}}) + .ATTR(channel_name, String, "") + .OP_END_FACTORY_REG(GetNextV2) +} // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_DATA_FLOW_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/deep_md.h b/third_party/fwkacllib/inc/ops/deep_md.h new file mode 100644 index 00000000..fadfe128 --- /dev/null +++ b/third_party/fwkacllib/inc/ops/deep_md.h @@ -0,0 +1,59 @@ +/** + * Copyright 2021 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. + */ + +/*! + * \file deep_md.h + * \brief + */ +#ifndef OPS_BUILT_IN_OP_PROTO_INC_DEEP_MD_H_ +#define OPS_BUILT_IN_OP_PROTO_INC_DEEP_MD_H_ + +#include "graph/operator_reg.h" + +namespace ge { +/** +* @brief Calculate ProdForceSeA. \n +* +* @par Inputs: +* Five inputs, including: +* @li net_deriv: A Tensor. Must be one of the following types: float16, float32, float64. +* @li in_deriv: A Tensor. Must be one of the following types: float16, float32, float64. +* @li nlist: A Tensor. dtype is int32. +* @li natoms: A Tensor. dtype is int32. \n +* +* @par Outputs: +* atom_force: A Tensor. Must be one of the following types: float16, float32, float64. \n +* +* @par Attributes: +* Two attributes, including: +* @li n_a_sel: A Scalar. +* @li n_r_sel: A Scalar. \n +* +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(ProdForceSeA) + .INPUT(net_deriv, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(in_deriv, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(nlist, TensorType({DT_INT32})) + .INPUT(natoms, TensorType({DT_INT32})) + .OUTPUT(atom_force, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .REQUIRED_ATTR(n_a_sel, Int) + .REQUIRED_ATTR(n_r_sel, Int) + .OP_END_FACTORY_REG(ProdForceSeA) +} // namespace ge + +#endif // OPS_BUILT_IN_OP_PROTO_INC_DEEP_MD_H_ diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index 4cb3d961..be201579 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/third_party/fwkacllib/inc/ops/functional_ops.h b/third_party/fwkacllib/inc/ops/functional_ops.h index e1fbe6b3..7cfe39c4 100644 --- a/third_party/fwkacllib/inc/ops/functional_ops.h +++ b/third_party/fwkacllib/inc/ops/functional_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/get_data_ops.h b/third_party/fwkacllib/inc/ops/get_data_ops.h index 33dc4f14..e5518ef8 100644 --- a/third_party/fwkacllib/inc/ops/get_data_ops.h +++ b/third_party/fwkacllib/inc/ops/get_data_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/hcom_ops.h b/third_party/fwkacllib/inc/ops/hcom_ops.h index 6db276a9..497f6a68 100644 --- a/third_party/fwkacllib/inc/ops/hcom_ops.h +++ b/third_party/fwkacllib/inc/ops/hcom_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/third_party/fwkacllib/inc/ops/hvd_ops.h b/third_party/fwkacllib/inc/ops/hvd_ops.h index a49ec5ed..00299ef7 100644 --- a/third_party/fwkacllib/inc/ops/hvd_ops.h +++ b/third_party/fwkacllib/inc/ops/hvd_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/third_party/fwkacllib/inc/ops/image_ops.h b/third_party/fwkacllib/inc/ops/image_ops.h index e771d67c..dc3a96b6 100644 --- a/third_party/fwkacllib/inc/ops/image_ops.h +++ b/third_party/fwkacllib/inc/ops/image_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -585,6 +585,40 @@ REG_OP(ResizeNearestNeighborV2GradD) *@li original_image: A Tensor. 4-D shape. Must set the format, supported format list ["NCHW, NHWC"] channels], The image tensor that was resized . \n +*@par Attributes: +*@li align_corners: An optional bool. Defaults to False. If true, the centers of +the 4 corner pixels of the input and grad tensors are aligned. Defaults to +false . +*@li half_pixel_centers: indicates if the offset coordinates are normalized. Defaults +to false . \n + +*@par Outputs: +*y: A Tensor. Has the same type as original_image . \n + +*@attention Constraints: +*Input grads must be a 4-D tensor . \n + +*@par Third-party framework compatibility +*Compatible with tensorflow ResizeBilinearV2Grad operator. +*/ + +REG_OP(ResizeBilinearV2Grad) + .INPUT(grads, TensorType({DT_FLOAT})) + .INPUT(original_image, TensorType::FloatingDataType()) + .OUTPUT(y, TensorType({DT_FLOAT})) + .ATTR(align_corners, Bool, false) + .ATTR(half_pixel_centers, Bool, false) + .OP_END_FACTORY_REG(ResizeBilinearV2Grad) + +/** +*@brief Computes the gradient of bilinear interpolation . \n + +*@par Inputs: +*Input grads must be a 4-D tensor. Inputs include: +*@li grads: A Tensor of type float32. Must set the format, supported format list ["NCHW, NHWC"] +*@li original_image: A Tensor. 4-D shape. Must set the format, supported format list ["NCHW, NHWC"] +channels], The image tensor that was resized . \n + *@par Attributes: *@li size: An optional listint. Defaults to {}. *@par Attributes: @@ -607,10 +641,10 @@ to false . \n *Input grads must be a 4-D tensor . \n *@par Third-party framework compatibility -*Compatible with tensorflow ResizeBilinearV2Grad operator. +*Compatible with mindspore ResizeBilinearV2Grad operator. */ -REG_OP(ResizeBilinearV2Grad) +REG_OP(SyncResizeBilinearV2Grad) .INPUT(grads, TensorType({DT_FLOAT})) .INPUT(original_image, TensorType::FloatingDataType()) .OUTPUT(y, TensorType({DT_FLOAT})) @@ -620,7 +654,7 @@ REG_OP(ResizeBilinearV2Grad) .ATTR(dst_start_w, Int, 0) .ATTR(align_corners, Bool, false) .ATTR(half_pixel_centers, Bool, false) - .OP_END_FACTORY_REG(ResizeBilinearV2Grad) + .OP_END_FACTORY_REG(SyncResizeBilinearV2Grad) /** *@brief Resize images to size using bilinear interpolation . \n @@ -636,10 +670,6 @@ size for the images . \n output tensors are aligned, preserving the values at the corner pixels. Defaults to false . * @li half_pixel_centers: An optional bool. Defaults to False . \n -*@li ori_image_size: An optional listint. Defaults to {}. -*@li split_size: An optional listint. Defaults to {}. -*@li src_start_w: An optional int. Defaults to 0. -*@li dst_start_w: An optional int. Defaults to 0. *@par Outputs: *y: 4-D with shape [batch, new_height, new_width, channels] . \n @@ -655,13 +685,49 @@ REG_OP(ResizeBilinearV2) DT_INT32, DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) .INPUT(size, TensorType({DT_INT32})) .OUTPUT(y, TensorType({DT_FLOAT})) + .ATTR(align_corners, Bool, false) + .ATTR(half_pixel_centers, Bool, false) + .OP_END_FACTORY_REG(ResizeBilinearV2) + +/** +*@brief Resize images to size using bilinear interpolation . \n + +*@par Inputs: +*Input images must be a 4-D tensor. Inputs include: +*@li x: 4-D tensor. Must set the format, supported format list ["NCHW, NHWC"] +*@li size: A 1-D int32 Tensor of 2 elements: new_height, new_width. The new +size for the images . \n + +*@par Attributes: +* @li align_corners: If true, the centers of the 4 corner pixels of the input and +output tensors are aligned, preserving the values at the corner pixels. +Defaults to false . +* @li half_pixel_centers: An optional bool. Defaults to False . \n +*@li ori_image_size: An optional listint. Defaults to {}. +*@li split_size: An optional listint. Defaults to {}. +*@li src_start_w: An optional int. Defaults to 0. +*@li dst_start_w: An optional int. Defaults to 0. +*@par Outputs: +*y: 4-D with shape [batch, new_height, new_width, channels] . \n + +*@attention Constraints: +*Input images can be of different types but output images are always float . \n + +*@par Third-party framework compatibility +*Compatible with mindspore ResizeBilinearV2 operator. +*/ + +REG_OP(SyncResizeBilinearV2) + .INPUT(x, TensorType({DT_FLOAT})) + .INPUT(size, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT})) .ATTR(ori_image_size, ListInt, {}) .ATTR(split_size, ListInt, {}) .ATTR(src_start_w, Int, 0) .ATTR(dst_start_w, Int, 0) .ATTR(align_corners, Bool, false) .ATTR(half_pixel_centers, Bool, false) - .OP_END_FACTORY_REG(ResizeBilinearV2) + .OP_END_FACTORY_REG(SyncResizeBilinearV2) /** *@brief Converts one or more images from RGB to HSV . \n diff --git a/third_party/fwkacllib/inc/ops/index_to_addr_ops.h b/third_party/fwkacllib/inc/ops/index_to_addr_ops.h index c6bbaaa8..3af17a45 100644 --- a/third_party/fwkacllib/inc/ops/index_to_addr_ops.h +++ b/third_party/fwkacllib/inc/ops/index_to_addr_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/internal_ops.h b/third_party/fwkacllib/inc/ops/internal_ops.h index 9dde14a5..bcc3f1c3 100644 --- a/third_party/fwkacllib/inc/ops/internal_ops.h +++ b/third_party/fwkacllib/inc/ops/internal_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/linalg_ops.h b/third_party/fwkacllib/inc/ops/linalg_ops.h index 0f362d31..5e31bebd 100644 --- a/third_party/fwkacllib/inc/ops/linalg_ops.h +++ b/third_party/fwkacllib/inc/ops/linalg_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/list_ops.h b/third_party/fwkacllib/inc/ops/list_ops.h index 53024878..0aa94e73 100644 --- a/third_party/fwkacllib/inc/ops/list_ops.h +++ b/third_party/fwkacllib/inc/ops/list_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/logging_ops.h b/third_party/fwkacllib/inc/ops/logging_ops.h index a20370fd..dd565657 100644 --- a/third_party/fwkacllib/inc/ops/logging_ops.h +++ b/third_party/fwkacllib/inc/ops/logging_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/lookup_ops.h b/third_party/fwkacllib/inc/ops/lookup_ops.h index 3fdc01fe..b1fc254f 100644 --- a/third_party/fwkacllib/inc/ops/lookup_ops.h +++ b/third_party/fwkacllib/inc/ops/lookup_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/math_ops.h b/third_party/fwkacllib/inc/ops/math_ops.h index 48867203..d3e8c0bf 100644 --- a/third_party/fwkacllib/inc/ops/math_ops.h +++ b/third_party/fwkacllib/inc/ops/math_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -691,7 +691,7 @@ REG_OP(Conj) REG_OP(NLLLoss) .INPUT(x, TensorType({DT_FLOAT})) .INPUT(target, TensorType({DT_INT32})) - .INPUT(weight, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(weight, TensorType({DT_FLOAT})) .OUTPUT(y, TensorType({DT_FLOAT})) .OUTPUT(total_weight, TensorType({DT_FLOAT})) .ATTR(reduction, String, "mean") diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index 289a33a6..0d9a8424 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h index ccafa01f..398c6568 100644 --- a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -113,7 +113,8 @@ if input "x" is with format NC1HWC0. Specifies the mean of "x". Must be 5D if input "x" is with format NC1HWC0. Specifies the variance of "x". *@li reserve_space_1: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D if input "x" is with format NC1HWC0. Specifies the mean of "x" for gradient computation. Pass "None" to skip this output. -*@li reserve_space_2: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. \n +*@li reserve_space_2: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. +*@li reserve_space_3: An optional Tensor of type float32. For compatibility with tensorflow, only has one useless emement. \n *@attention Constraints: *@li If the operation is used for inference and outputs "reserve_space_1" and "reserve_space_2" are available, @@ -135,6 +136,7 @@ REG_OP(BatchNorm) .OUTPUT(batch_variance, TensorType({DT_FLOAT})) .OUTPUT(reserve_space_1, TensorType({DT_FLOAT})) .OUTPUT(reserve_space_2, TensorType({DT_FLOAT})) + .OUTPUT(reserve_space_3, TensorType({DT_FLOAT})) .ATTR(epsilon, Float, 0.0001) .ATTR(data_format, String, "NHWC") .ATTR(is_training, Bool, true) @@ -309,7 +311,8 @@ REG_OP(BatchNormExt2) *@li x: A 4D or 5D Tensor of type float16 or float32, with format NHWC, NCHW, or NC1HWC0. *@li scale: A 4D or 5D Tensor of type float32, with format NHWC, NCHW, or NC1HWC0. *@li reserve_space_1: A 4D or 5D Tensor of type float32, with format NHWC, NCHW, or NC1HWC0. It is an output of BatchNorm. -*@li reserve_space_2: A 4D or 5D Tensor of type float32, with format NHWC, NCHW, or NC1HWC0. It is an output of BatchNorm . \n +*@li reserve_space_2: A 4D or 5D Tensor of type float32, with format NHWC, NCHW, or NC1HWC0. It is an output of BatchNorm . +*@li reserve_space_3: A 1D optional Tensor of type float32. It is an output of BatchNorm . \n *@par Attributes: *@li epsilon: An optional float32. Defaults to "0.0001". A small float number added to the variance of "x". @@ -336,6 +339,7 @@ REG_OP(BatchNormGrad) .INPUT(scale, TensorType({DT_FLOAT})) .INPUT(reserve_space_1, TensorType({DT_FLOAT})) .INPUT(reserve_space_2, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(reserve_space_3, TensorType({DT_FLOAT})) .OUTPUT(x_backprop, TensorType({DT_FLOAT16,DT_FLOAT})) .OUTPUT(scale_backprop, TensorType({DT_FLOAT})) .OUTPUT(offset_backprop, TensorType({DT_FLOAT})) diff --git a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h index 025f669c..6f58f028 100644 --- a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -314,9 +314,9 @@ REG_OP(DepthwiseConv2DBackpropInputD) REG_OP(DepthwiseConv2D) .INPUT(x, TensorType({DT_FLOAT16, DT_INT8, DT_INT4})) .INPUT(filter, TensorType({DT_FLOAT16, DT_INT8, DT_INT4})) - .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT16, DT_INT32})) + .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT16, DT_INT32, DT_FLOAT})) .OPTIONAL_INPUT(offset_w, TensorType({DT_FLOAT16, DT_INT8, DT_INT4})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_INT32, DT_FLOAT})) .REQUIRED_ATTR(strides, ListInt) .ATTR(dilations, ListInt, {1, 1, 1, 1}) .REQUIRED_ATTR(pads, ListInt) diff --git a/third_party/fwkacllib/inc/ops/nn_detect_ops.h b/third_party/fwkacllib/inc/ops/nn_detect_ops.h index e960234e..108a20a7 100644 --- a/third_party/fwkacllib/inc/ops/nn_detect_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_detect_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. @@ -1667,6 +1667,8 @@ REG_OP(DecodeBboxV2) * @li y1: A Tensor. Must have the same type as x. * @li y2: A Tensor. Indices of y1 in x. Dtype must be int32. * +*@attention Constraints: +* The operator depends on the unstable sorting algorithm. */ REG_OP(Sort) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT16, DT_INT8, @@ -2058,6 +2060,33 @@ REG_OP(GIoUGrad) .ATTR(is_cross, Bool, true) .ATTR(mode, String, "iou") .OP_END_FACTORY_REG(GIoUGrad) + +/** +*@brief RotatedOverlaps . \n + +*@par Inputs: +*@li boxes : data of grad increment, a 3D Tensor of type float32 with +* shape (B, 5, N). "N" indicates the number of boxes, and the value +* "5" refers to [x1, y1, x2, y2, theta] or [x, y, w, h, theta]. +*@li query_boxes: Bounding boxes, a 3D Tensor of type float32 with +* shape (B, 5, K). "K" indicates the number of boxes, and the value +* "5" refers to [x1, y1, x2, y2, theta] or [x, y, w, h, theta]. + +*@par Attributes: +* trans: An optional attr, true for 'xyxyt', false for 'xywht'. + +*@par Outputs: +* overlaps: A 3D Tensor of type float16 or float32 with shape [B, N, K]. + +*@attention Constraints: +* In each batch, the invalid box cannot appear before the valid box. +*/ +REG_OP(RotatedOverlaps) + .INPUT(boxes, TensorType({DT_FLOAT})) + .INPUT(query_boxes, TensorType({DT_FLOAT})) + .OUTPUT(overlaps, TensorType({DT_FLOAT})) + .ATTR(trans, Bool, false) + .OP_END_FACTORY_REG(RotatedOverlaps) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_DETECT_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index d66c8948..9ce7abfd 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/nn_ops.h b/third_party/fwkacllib/inc/ops/nn_ops.h index a08b610b..5b1a4dd0 100644 --- a/third_party/fwkacllib/inc/ops/nn_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h index 978c480c..ee599a76 100644 --- a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/nn_training_ops.h b/third_party/fwkacllib/inc/ops/nn_training_ops.h index 39234057..bc75cfb7 100644 --- a/third_party/fwkacllib/inc/ops/nn_training_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_training_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/third_party/fwkacllib/inc/ops/no_op.h b/third_party/fwkacllib/inc/ops/no_op.h index 7834591c..b27b1fa0 100644 --- a/third_party/fwkacllib/inc/ops/no_op.h +++ b/third_party/fwkacllib/inc/ops/no_op.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h index a4f2fe80..d5960395 100644 --- a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h +++ b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. @@ -1127,6 +1127,34 @@ REG_OP(Shrink) .ATTR(lambd, Float, 0.5) .ATTR(bias, Float, 0.0) .OP_END_FACTORY_REG(Shrink) + +/** +* @brief Thresholds each element of the input Tensor: y = (x > threshold) ? x : value \n + +* @par Inputs: +* Three inputs, including: +* @li x: A Tensor. +* Must be one of the following types on Ascend310: float16, int8, int32, uint8. +* Must be one of the following types on Ascend710 or Ascend910: float16, float32, int8, int32, uint8. \n +* @li threshold: A Tensor which should have the shape (1,), the value to threshold at. +* Must be one of the following types on Ascend310: float16, int8, int32, uint8. +* Must be one of the following types on Ascend710 or Ascend910: float16, float32, int8, int32, uint8. \n +* @li value: A Tensor which should have the shape (1,), the value to replace with. default value is 0. +* Must be one of the following types on Ascend310: float16, int8, int32, uint8. +* Must be one of the following types on Ascend710 or Ascend910: float16, float32, int8, int32, uint8. \n + +* @par Outputs: +* y: A Tensor which has the same shape and type as the input x. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Threshold. +*/ +REG_OP(ThresholdV2) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT32, DT_INT8, DT_INT32, DT_UINT8})) + .INPUT(threshold, TensorType({DT_FLOAT16, DT_FLOAT32, DT_INT8, DT_INT32, DT_UINT8})) + .OPTIONAL_INPUT(value, TensorType({DT_FLOAT16, DT_FLOAT32, DT_INT8, DT_INT32, DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT32, DT_INT8, DT_INT32, DT_UINT8})) + .OP_END_FACTORY_REG(ThresholdV2) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NONLINEAR_FUC_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h b/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h index 8d7ef9f9..f36d2935 100644 --- a/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h +++ b/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/ocr_ops.h b/third_party/fwkacllib/inc/ops/ocr_ops.h index baab5af2..a5755659 100644 --- a/third_party/fwkacllib/inc/ops/ocr_ops.h +++ b/third_party/fwkacllib/inc/ops/ocr_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/outfeed_ops.h b/third_party/fwkacllib/inc/ops/outfeed_ops.h index e0b783bc..53b9d701 100644 --- a/third_party/fwkacllib/inc/ops/outfeed_ops.h +++ b/third_party/fwkacllib/inc/ops/outfeed_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/pad_ops.h b/third_party/fwkacllib/inc/ops/pad_ops.h index a9a3b0f0..6d4bcd5e 100644 --- a/third_party/fwkacllib/inc/ops/pad_ops.h +++ b/third_party/fwkacllib/inc/ops/pad_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/third_party/fwkacllib/inc/ops/parsing_ops.h b/third_party/fwkacllib/inc/ops/parsing_ops.h index 03024f96..e578997c 100644 --- a/third_party/fwkacllib/inc/ops/parsing_ops.h +++ b/third_party/fwkacllib/inc/ops/parsing_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/quantize_ops.h b/third_party/fwkacllib/inc/ops/quantize_ops.h index e4b1075b..fd855734 100644 --- a/third_party/fwkacllib/inc/ops/quantize_ops.h +++ b/third_party/fwkacllib/inc/ops/quantize_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/ragged_array_ops.h b/third_party/fwkacllib/inc/ops/ragged_array_ops.h index 9d116760..5af2dd74 100644 --- a/third_party/fwkacllib/inc/ops/ragged_array_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_array_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h b/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h index 2e253ed4..ceaa64e4 100644 --- a/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_conversion_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/ragged_math_ops.h b/third_party/fwkacllib/inc/ops/ragged_math_ops.h index b2caa0be..4376437f 100644 --- a/third_party/fwkacllib/inc/ops/ragged_math_ops.h +++ b/third_party/fwkacllib/inc/ops/ragged_math_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/random_ops.h b/third_party/fwkacllib/inc/ops/random_ops.h index 28fbb7f2..ad7f9003 100644 --- a/third_party/fwkacllib/inc/ops/random_ops.h +++ b/third_party/fwkacllib/inc/ops/random_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/reduce_ops.h b/third_party/fwkacllib/inc/ops/reduce_ops.h index 4e4c74af..fa572b66 100644 --- a/third_party/fwkacllib/inc/ops/reduce_ops.h +++ b/third_party/fwkacllib/inc/ops/reduce_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2020 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. diff --git a/third_party/fwkacllib/inc/ops/resource_variable_ops.h b/third_party/fwkacllib/inc/ops/resource_variable_ops.h index a5d7f9c3..156f2f34 100644 --- a/third_party/fwkacllib/inc/ops/resource_variable_ops.h +++ b/third_party/fwkacllib/inc/ops/resource_variable_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/rnn.h b/third_party/fwkacllib/inc/ops/rnn.h index 691f1e9f..b374fa5c 100644 --- a/third_party/fwkacllib/inc/ops/rnn.h +++ b/third_party/fwkacllib/inc/ops/rnn.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/rpn_ops.h b/third_party/fwkacllib/inc/ops/rpn_ops.h index 90707602..850b3e5a 100644 --- a/third_party/fwkacllib/inc/ops/rpn_ops.h +++ b/third_party/fwkacllib/inc/ops/rpn_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/save_ops.h b/third_party/fwkacllib/inc/ops/save_ops.h index 0ce473b7..5ce6c2e0 100644 --- a/third_party/fwkacllib/inc/ops/save_ops.h +++ b/third_party/fwkacllib/inc/ops/save_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/sdca_ops.h b/third_party/fwkacllib/inc/ops/sdca_ops.h index e8f3e6b6..601b360b 100644 --- a/third_party/fwkacllib/inc/ops/sdca_ops.h +++ b/third_party/fwkacllib/inc/ops/sdca_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/selection_ops.h b/third_party/fwkacllib/inc/ops/selection_ops.h index 8812a14f..b09d08b0 100644 --- a/third_party/fwkacllib/inc/ops/selection_ops.h +++ b/third_party/fwkacllib/inc/ops/selection_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/set_ops.h b/third_party/fwkacllib/inc/ops/set_ops.h index 1d02fa15..04e04f1b 100644 --- a/third_party/fwkacllib/inc/ops/set_ops.h +++ b/third_party/fwkacllib/inc/ops/set_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/slice_write_ops.h b/third_party/fwkacllib/inc/ops/slice_write_ops.h index 994f197c..0c161b2d 100644 --- a/third_party/fwkacllib/inc/ops/slice_write_ops.h +++ b/third_party/fwkacllib/inc/ops/slice_write_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/sparse_ops.h b/third_party/fwkacllib/inc/ops/sparse_ops.h index d9fb4d0a..8eb7b521 100644 --- a/third_party/fwkacllib/inc/ops/sparse_ops.h +++ b/third_party/fwkacllib/inc/ops/sparse_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/spectral_ops.h b/third_party/fwkacllib/inc/ops/spectral_ops.h index d17cbfdd..ab9e1dec 100644 --- a/third_party/fwkacllib/inc/ops/spectral_ops.h +++ b/third_party/fwkacllib/inc/ops/spectral_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/split_combination_ops.h b/third_party/fwkacllib/inc/ops/split_combination_ops.h index cba8e648..08726080 100644 --- a/third_party/fwkacllib/inc/ops/split_combination_ops.h +++ b/third_party/fwkacllib/inc/ops/split_combination_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/state_ops.h b/third_party/fwkacllib/inc/ops/state_ops.h index 49029317..d1ec00b5 100644 --- a/third_party/fwkacllib/inc/ops/state_ops.h +++ b/third_party/fwkacllib/inc/ops/state_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/stateful_random_ops.h b/third_party/fwkacllib/inc/ops/stateful_random_ops.h index a3d18922..f4eb763c 100644 --- a/third_party/fwkacllib/inc/ops/stateful_random_ops.h +++ b/third_party/fwkacllib/inc/ops/stateful_random_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/stateless_random_ops.h b/third_party/fwkacllib/inc/ops/stateless_random_ops.h index dad3c379..ff9daaa3 100644 --- a/third_party/fwkacllib/inc/ops/stateless_random_ops.h +++ b/third_party/fwkacllib/inc/ops/stateless_random_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/string_ops.h b/third_party/fwkacllib/inc/ops/string_ops.h index a2699315..a78d63a1 100644 --- a/third_party/fwkacllib/inc/ops/string_ops.h +++ b/third_party/fwkacllib/inc/ops/string_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/swap_co_ops.h b/third_party/fwkacllib/inc/ops/swap_co_ops.h index a1bf4f8b..6e8eaac3 100644 --- a/third_party/fwkacllib/inc/ops/swap_co_ops.h +++ b/third_party/fwkacllib/inc/ops/swap_co_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/target_crop_and_resize.h b/third_party/fwkacllib/inc/ops/target_crop_and_resize.h index 9c61f2c9..9bef1d7b 100644 --- a/third_party/fwkacllib/inc/ops/target_crop_and_resize.h +++ b/third_party/fwkacllib/inc/ops/target_crop_and_resize.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/transformation_ops.h b/third_party/fwkacllib/inc/ops/transformation_ops.h index 775dd4a9..2bbab7a2 100644 --- a/third_party/fwkacllib/inc/ops/transformation_ops.h +++ b/third_party/fwkacllib/inc/ops/transformation_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/ops/vector_search.h b/third_party/fwkacllib/inc/ops/vector_search.h index 8f2201af..1e8c574b 100644 --- a/third_party/fwkacllib/inc/ops/vector_search.h +++ b/third_party/fwkacllib/inc/ops/vector_search.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2021 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. diff --git a/third_party/fwkacllib/inc/ops/warp_perspective_ops.h b/third_party/fwkacllib/inc/ops/warp_perspective_ops.h index e19cbd7c..8ef69d8b 100644 --- a/third_party/fwkacllib/inc/ops/warp_perspective_ops.h +++ b/third_party/fwkacllib/inc/ops/warp_perspective_ops.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019 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. diff --git a/third_party/fwkacllib/inc/register/op_kernel_registry.h b/third_party/fwkacllib/inc/register/op_kernel_registry.h deleted file mode 100644 index 35fcc857..00000000 --- a/third_party/fwkacllib/inc/register/op_kernel_registry.h +++ /dev/null @@ -1,46 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef INC_REGISTER_OP_KERNEL_REGISTRY_H_ -#define INC_REGISTER_OP_KERNEL_REGISTRY_H_ -#include -#include -#include "register/register_types.h" -#include "register.h" - -namespace ge { -class FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY OpKernelRegistry { - public: - using CreateFn = HostCpuOp* (*)(); - ~OpKernelRegistry(); - - static OpKernelRegistry& GetInstance(); - - bool IsRegistered(const std::string &op_type); - - void RegisterHostCpuOp(const std::string &op_type, CreateFn create_fn); - - std::unique_ptr CreateHostCpuOp(const std::string &op_type); - - private: - OpKernelRegistry(); - class OpKernelRegistryImpl; - /*lint -e148*/ - std::unique_ptr impl_; -}; -} // namespace ge - -#endif // INC_REGISTER_OP_KERNEL_REGISTRY_H_ diff --git a/third_party/fwkacllib/inc/register/op_registry.h b/third_party/fwkacllib/inc/register/op_registry.h deleted file mode 100644 index f7e37390..00000000 --- a/third_party/fwkacllib/inc/register/op_registry.h +++ /dev/null @@ -1,97 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef INC_REGISTER_OP_REGISTRY_H_ -#define INC_REGISTER_OP_REGISTRY_H_ - -#include -#include -#include -#include -#include -#include - -#include "register/register.h" - -namespace domi { -enum RemoveInputType { - OMG_MOVE_TYPE_DTYPE = 0, - OMG_MOVE_TYPE_VALUE, - OMG_MOVE_TYPE_SHAPE, - OMG_MOVE_TYPE_FORMAT, - OMG_MOVE_TYPE_AXIS, - OMG_MOVE_TYPE_SCALAR_VALUE, - OMG_REMOVE_TYPE_WITH_COND = 1000, - OMG_REMOVE_INPUT_WITH_ORIGINAL_TYPE, - OMG_INPUT_REORDER, -}; - -struct RemoveInputConfigure { - int inputIdx = INT_MAX; - std::string attrName; - RemoveInputType moveType; - bool attrValue = false; - std::string originalType; - std::vector input_order; -}; - -class FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY OpRegistry { - public: - static OpRegistry *Instance(); - - std::vector registrationDatas; - - bool Register(const OpRegistrationData ®_data); - - domi::ImplyType GetImplyType(const std::string &op_type); - - void GetOpTypeByImplyType(std::vector &vec_op_type, const domi::ImplyType &imply_type); - - domi::ParseParamFunc GetParseParamFunc(const std::string &op_type, const std::string &ori_type); - - domi::ParseParamByOpFunc GetParseParamByOperatorFunc(const std::string &ori_type); - - domi::FusionParseParamFunc GetFusionParseParamFunc(const std::string &op_type, const std::string &ori_type); - - domi::FusionParseParamByOpFunc GetFusionParseParamByOpFunc(const std::string &op_type, - const std::string &ori_type); - - domi::ParseSubgraphFunc GetParseSubgraphPostFunc(const std::string &op_type); - - Status GetParseSubgraphPostFunc(const std::string &op_type, domi::ParseSubgraphFuncV2 &parse_subgraph_func); - - domi::ImplyType GetImplyTypeByOriOpType(const std::string &ori_optype); - - const std::vector &GetRemoveInputConfigure(const std::string &ori_optype) const; - - bool GetOmTypeByOriOpType(const std::string &ori_optype, std::string &om_type); - - ParseOpToGraphFunc GetParseOpToGraphFunc(const std::string &op_type, const std::string &ori_type); - - private: - std::unordered_map op_run_mode_map_; - std::unordered_map op_parse_params_fn_map_; - std::unordered_map parse_params_by_op_func_map_; - std::unordered_map fusion_op_parse_params_fn_map_; - std::unordered_map fusion_parse_params_by_op_fn_map_; - std::unordered_map op_types_to_parse_subgraph_post_func_; - std::unordered_map> remove_input_configure_map_; - std::map origin_type_to_om_type_; - std::unordered_map parse_op_to_graph_fn_map_; - std::unordered_map op_types_to_parse_subgraph_post_func_v2_; -}; -} // namespace domi -#endif // INC_REGISTER_OP_REGISTRY_H_ diff --git a/third_party/fwkacllib/inc/runtime/base.h b/third_party/fwkacllib/inc/runtime/base.h index 39301554..aa98ed9a 100644 --- a/third_party/fwkacllib/inc/runtime/base.h +++ b/third_party/fwkacllib/inc/runtime/base.h @@ -1,17 +1,7 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. + * Description: base.h + * Create: 2020-01-01 */ #ifndef CCE_RUNTIME_BASE_H @@ -95,7 +85,7 @@ typedef enum tagRtSwitchDataType { typedef enum tagRtStreamFlagType { RT_HEAD_STREAM = 0, // first stream - RT_INVALID_FLAG = 0xFFFFFFFF, + RT_INVALID_FLAG = 0x7FFFFFFF, } rtStreamFlagType_t; typedef enum tagRtLimitType { @@ -196,13 +186,13 @@ RTS_API rtError_t rtProfilerConfig(uint16_t profConfig); * @ingroup profiling_base * @brief ts send keypoint profiler log. */ -RTS_API rtError_t rtProfilerTrace(uint64_t id, bool notify, uint32_t flags, rtStream_t stream); +RTS_API rtError_t rtProfilerTrace(uint64_t id, bool notify, uint32_t flags, rtStream_t stm); /** * @ingroup profiling_base * @brief ts send keypoint profiler log. */ -RTS_API rtError_t rtProfilerTraceEx(uint64_t id, uint64_t modelId, uint16_t tagId, rtStream_t stream); +RTS_API rtError_t rtProfilerTraceEx(uint64_t id, uint64_t modelId, uint16_t tagId, rtStream_t stm); /** * @ingroup profiling_base @@ -306,134 +296,134 @@ typedef void *rtNotify_t; /** * @ingroup dvrt_base * @brief create label instance - * @param [out] label created label + * @param [out] lbl created label * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtLabelCreate(rtLabel_t *label); +RTS_API rtError_t rtLabelCreate(rtLabel_t *lbl); /** * @ingroup dvrt_base * @brief create label instance - * @param [out] label created label - * @param [in] model label set model + * @param [out] lbl created label + * @param [in] mdl label set model * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtLabelCreateV2(rtLabel_t *label, rtModel_t model); +RTS_API rtError_t rtLabelCreateV2(rtLabel_t *lbl, rtModel_t mdl); /** * @ingroup dvrt_base * @brief set label and stream instance - * @param [in] label set label - * @param [in] stream set stream + * @param [in] lbl set label + * @param [in] stm set stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtLabelSet(rtLabel_t label, rtStream_t stream); +RTS_API rtError_t rtLabelSet(rtLabel_t lbl, rtStream_t stm); /** * @ingroup dvrt_base * @brief destroy label instance - * @param [in] label label to destroy + * @param [in] lbl label to destroy * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtLabelDestroy(rtLabel_t label); +RTS_API rtError_t rtLabelDestroy(rtLabel_t lbl); /** * @ingroup dvrt_base * @brief label switch instance * @param [in] ptr address to get value compared * @param [in] condition - * @param [in] value to compare + * @param [in] val to compare * @param [in] true_label goto label - * @param [in] stream to submit label_switch task + * @param [in] stm to submit label_switch task * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtLabelSwitch(void *ptr, rtCondition_t condition, uint32_t value, rtLabel_t trueLabel, - rtStream_t stream); +RTS_API rtError_t rtLabelSwitch(void *ptr, rtCondition_t condition, uint32_t val, rtLabel_t trueLabel, + rtStream_t stm); /** * @ingroup dvrt_base * @brief goto label instance - * @param [in] label goto label - * @param [in] stream to submit label_goto task + * @param [in] lbl goto label + * @param [in] stm to submit label_goto task * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtLabelGoto(rtLabel_t label, rtStream_t stream); +RTS_API rtError_t rtLabelGoto(rtLabel_t lbl, rtStream_t stm); /** * @ingroup dvrt_base * @brief name label instance - * @param [in] label instance + * @param [in] lbl instance * @param [in] name label name * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtNameLabel(rtLabel_t label, const char_t *name); +RTS_API rtError_t rtNameLabel(rtLabel_t lbl, const char_t *name); /** * @ingroup dvrt_base * @brief label switch by index * @param [in] ptr index value ptr - * @param [in] max index max value + * @param [in] maxValue index max value * @param [in] labelInfoPtr label content info ptr - * @param [in] stream set stream + * @param [in] stm set stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtLabelSwitchByIndex(void *ptr, uint32_t max, void *labelInfoPtr, rtStream_t stream); +RTS_API rtError_t rtLabelSwitchByIndex(void *ptr, uint32_t maxValue, void *labelInfoPtr, rtStream_t stm); /** * @ingroup dvrt_base * @brief stream goto label - * @param [in] label goto label - * @param [in] stream stream to submit label_goto task + * @param [in] lbl goto label + * @param [in] stm stream to submit label_goto task * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtLabelGotoEx(rtLabel_t label, rtStream_t stream); +RTS_API rtError_t rtLabelGotoEx(rtLabel_t lbl, rtStream_t stm); /** * @ingroup dvrt_base * @brief labels to dev info - * @param [in] label model label list + * @param [in] lbl model label list * @param [in] labelNumber label number * @param [in] dst device ptr * @param [in] dstMax dst size * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtLabelListCpy(rtLabel_t *label, uint32_t labelNumber, void *dst, uint32_t dstMax); +RTS_API rtError_t rtLabelListCpy(rtLabel_t *lbl, uint32_t labelNumber, void *dst, uint32_t dstMax); /** * @ingroup dvrt_base * @brief labels to dev info - * @param [out] label created label handle - * @param [in] stream label bind stream + * @param [out] lbl created label handle + * @param [in] stm label bind stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtLabelCreateEx(rtLabel_t *label, rtStream_t stream); +RTS_API rtError_t rtLabelCreateEx(rtLabel_t *lbl, rtStream_t stm); /** * @ingroup dvrt_base * @brief labels to dev info - * @param [out] label created label handle - * @param [in] model label bind model - * @param [in] stream label bind stream + * @param [out] lbl created label handle + * @param [in] mdl label bind model + * @param [in] stm label bind stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtLabelCreateExV2(rtLabel_t *label, rtModel_t model, rtStream_t stream); +RTS_API rtError_t rtLabelCreateExV2(rtLabel_t *lbl, rtModel_t mdl, rtStream_t stm); /** * @ingroup dvrt_base * @brief get current thread last stream id and task id - * @param [out] stream id and task id + * @param [out] stm id and task id * @param [in] null * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for input null ptr @@ -443,4 +433,4 @@ RTS_API rtError_t rtGetTaskIdAndStreamID(uint32_t *taskId, uint32_t *streamId); } #endif -#endif // CCE_RUNTIME_BASE_H \ No newline at end of file +#endif // CCE_RUNTIME_BASE_H diff --git a/third_party/fwkacllib/inc/runtime/config.h b/third_party/fwkacllib/inc/runtime/config.h index f9e6a49e..c83c1521 100644 --- a/third_party/fwkacllib/inc/runtime/config.h +++ b/third_party/fwkacllib/inc/runtime/config.h @@ -1,17 +1,7 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. + * Description: config.h + * Create: 2020-01-01 */ #ifndef CCE_RUNTIME_CONFIG_H @@ -193,10 +183,10 @@ RTS_API rtError_t rtGetMemoryConfig(rtMemoryConfig_t *memoryConfig); /** * @ingroup * @brief get l2 buffer Info,virtual baseaddr,Size - * @param [in] stream + * @param [in] stm * @return RT_ERROR_NONE for ok, errno for failed */ -RTS_API rtError_t rtMemGetL2Info(rtStream_t stream, void **ptr, uint32_t *size); +RTS_API rtError_t rtMemGetL2Info(rtStream_t stm, void **ptr, uint32_t *size); /** * @ingroup @@ -215,11 +205,11 @@ RTS_API rtError_t rtGetRuntimeVersion(uint32_t *runtimeVersion); * @param [in] deviceId * @param [in] moduleType * @param [in] featureType - * @param [out] value + * @param [out] val * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtGetDeviceCapability(int32_t deviceId, int32_t moduleType, int32_t featureType, int32_t *value); +RTS_API rtError_t rtGetDeviceCapability(int32_t deviceId, int32_t moduleType, int32_t featureType, int32_t *val); /** * @ingroup diff --git a/third_party/fwkacllib/inc/runtime/context.h b/third_party/fwkacllib/inc/runtime/context.h index bc8dda52..e920a939 100644 --- a/third_party/fwkacllib/inc/runtime/context.h +++ b/third_party/fwkacllib/inc/runtime/context.h @@ -1,17 +1,7 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. + * Description: context.h + * Create: 2020-01-01 */ #ifndef CCE_RUNTIME_CONTEXT_H @@ -53,57 +43,57 @@ typedef struct tagRtGroupInfo { /** * @ingroup rt_context * @brief create context and associates it with the calling thread - * @param [out] ctx created context + * @param [out] createCtx created context * @param [in] flags context creation flag. set to 0. - * @param [in] device device to create context on + * @param [in] devId device to create context on * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtCtxCreate(rtContext_t *ctx, uint32_t flags, int32_t device); +RTS_API rtError_t rtCtxCreate(rtContext_t *createCtx, uint32_t flags, int32_t devId); /** * @ingroup rt_context * @brief create context and associates it with the calling thread - * @param [out] ctx created context + * @param [out] createCtx created context * @param [in] flags context creation flag. set to 0. - * @param [in] device device to create context on + * @param [in] devId device to create context on * @param [in] deviceMode the device mode * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtCtxCreateV2(rtContext_t *ctx, uint32_t flags, int32_t device, rtDeviceMode deviceMode); +RTS_API rtError_t rtCtxCreateV2(rtContext_t *createCtx, uint32_t flags, int32_t devId, rtDeviceMode deviceMode); /** * @ingroup rt_context * @brief create context and associates it with the calling thread - * @param [out] ctx created context + * @param [out] createCtx created context * @param [in] flags context creation flag. set to 0. - * @param [in] device device to create context on + * @param [in] devId device to create context on * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtCtxCreateEx(rtContext_t *ctx, uint32_t flags, int32_t device); +RTS_API rtError_t rtCtxCreateEx(rtContext_t *createCtx, uint32_t flags, int32_t devId); /** * @ingroup rt_context * @brief destroy context instance - * @param [in] ctx context to destroy + * @param [in] destroyCtx context to destroy * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtCtxDestroy(rtContext_t ctx); +RTS_API rtError_t rtCtxDestroy(rtContext_t destroyCtx); /** * @ingroup rt_context * @brief destroy context instance - * @param [in] ctx context to destroy + * @param [in] destroyCtx context to destroy * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtCtxDestroyEx(rtContext_t ctx); +RTS_API rtError_t rtCtxDestroyEx(rtContext_t destroyCtx); /** * @ingroup rt_context * @brief binds context to the calling CPU thread. - * @param [in] ctx context to bind. if NULL, unbind current context. + * @param [in] currentCtx context to bind. if NULL, unbind current context. * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtCtxSetCurrent(rtContext_t ctx); +RTS_API rtError_t rtCtxSetCurrent(rtContext_t currentCtx); /** * @ingroup rt_context @@ -115,26 +105,26 @@ RTS_API rtError_t rtCtxSynchronize(void); /** * @ingroup rt_context * @brief returns the context bound to the calling CPU thread. - * @param [out] ctx returned context + * @param [out] currentCtx returned context * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtCtxGetCurrent(rtContext_t *ctx); +RTS_API rtError_t rtCtxGetCurrent(rtContext_t *currentCtx); /** * @ingroup rt_context * @brief returns the primary context of device. - * @param [out] ctx returned context + * @param [out] primaryCtx returned context * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtGetPriCtxByDeviceId(int32_t device, rtContext_t *ctx); +RTS_API rtError_t rtGetPriCtxByDeviceId(int32_t devId, rtContext_t *primaryCtx); /** * @ingroup rt_context * @brief returns the device ID for the current context - * @param [out] device returned device id + * @param [out] devId returned device id * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtCtxGetDevice(int32_t *device); +RTS_API rtError_t rtCtxGetDevice(int32_t *devId); /** * @ingroup @@ -158,19 +148,19 @@ RTS_API rtError_t rtGetGroupInfo(int32_t groupId, rtGroupInfo_t *groupInfo, uint * @param [in] groupid count * @return RT_ERROR_NONE for ok, errno for failed */ -RTS_API rtError_t rtGetGroupCount(uint32_t *count); +RTS_API rtError_t rtGetGroupCount(uint32_t *cnt); /** * @ingroup rt_context * @brief set context INF mode - * @param [in] mode + * @param [in] infMode * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtSetCtxINFMode(bool mode); +RTS_API rtError_t rtSetCtxINFMode(bool infMode); #if defined(__cplusplus) } #endif -#endif // CCE_RUNTIME_CONTEXT_H \ No newline at end of file +#endif // CCE_RUNTIME_CONTEXT_H diff --git a/third_party/fwkacllib/inc/runtime/dev.h b/third_party/fwkacllib/inc/runtime/dev.h index 75d01f36..e5b741c7 100644 --- a/third_party/fwkacllib/inc/runtime/dev.h +++ b/third_party/fwkacllib/inc/runtime/dev.h @@ -1,17 +1,7 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. + * Description: dev.h + * Create: 2020-01-01 */ #ifndef CCE_RUNTIME_DEVICE_H @@ -146,30 +136,30 @@ RTS_API rtError_t rtGetDeviceIDs(uint32_t *devices, uint32_t len); INFO_TYPE_IP, INFO_TYPE_ENDIAN, } DEV_INFO_TYPE; - * @param [out] value the device info + * @param [out] val the device info * @return RT_ERROR_NONE for ok * @return RT_ERROR_DRV_ERR for error */ -RTS_API rtError_t rtGetDeviceInfo(uint32_t deviceId, int32_t moduleType, int32_t infoType, int64_t *value); +RTS_API rtError_t rtGetDeviceInfo(uint32_t deviceId, int32_t moduleType, int32_t infoType, int64_t *val); /** * @ingroup dvrt_dev * @brief set target device for current thread - * @param [int] device the device id + * @param [int] devId the device id * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtSetDevice(int32_t device); +RTS_API rtError_t rtSetDevice(int32_t devId); /** * @ingroup dvrt_dev * @brief set target device for current thread - * @param [int] device the device id + * @param [int] devId the device id * @param [int] deviceMode the device mode * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtSetDeviceV2(int32_t device, rtDeviceMode deviceMode); +RTS_API rtError_t rtSetDeviceV2(int32_t devId, rtDeviceMode deviceMode); /** * @ingroup dvrt_dev @@ -201,11 +191,11 @@ RTS_API rtError_t rtGetDie(int32_t *die); /** * @ingroup dvrt_dev * @brief set target device for current thread - * @param [int] device the device id + * @param [int] devId the device id * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtSetDeviceEx(int32_t device); +RTS_API rtError_t rtSetDeviceEx(int32_t devId); /** * @ingroup dvrt_dev @@ -250,13 +240,13 @@ RTS_API rtError_t rtDisableP2P(uint32_t devIdDes, uint32_t phyIdSrc); /** * @ingroup dvrt_dev * @brief get cability of P2P omemry copy betwen device and peeredevic. - * @param [in] device the logical device id + * @param [in] devId the logical device id * @param [in] peerDevice the physical device id * @param [outv] *canAccessPeer 1:enable 0:disable * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtDeviceCanAccessPeer(int32_t *canAccessPeer, uint32_t device, uint32_t peerDevice); +RTS_API rtError_t rtDeviceCanAccessPeer(int32_t *canAccessPeer, uint32_t devId, uint32_t peerDevice); /** * @ingroup dvrt_dev @@ -280,11 +270,11 @@ RTS_API rtError_t rtDeviceGetBareTgid(uint32_t *pid); /** * @ingroup dvrt_dev * @brief get target device of current thread - * @param [in|out] device the device id + * @param [in|out] devId the device id * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtGetDevice(int32_t *device); +RTS_API rtError_t rtGetDevice(int32_t *devId); /** * @ingroup dvrt_dev @@ -292,7 +282,7 @@ RTS_API rtError_t rtGetDevice(int32_t *device); * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtDeviceReset(int32_t device); +RTS_API rtError_t rtDeviceReset(int32_t devId); /** * @ingroup dvrt_dev @@ -300,19 +290,19 @@ RTS_API rtError_t rtDeviceReset(int32_t device); * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtDeviceResetEx(int32_t device); +RTS_API rtError_t rtDeviceResetEx(int32_t devId); /** * @ingroup dvrt_dev * @brief get total device infomation. - * @param [in] device the device id + * @param [in] devId the device id * @param [in] type limit type RT_LIMIT_TYPE_LOW_POWER_TIMEOUT=0 - * @param [in] value limit value + * @param [in] val limit value * @param [out] info the device info * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtDeviceSetLimit(int32_t device, rtLimitType_t type, uint32_t value); +RTS_API rtError_t rtDeviceSetLimit(int32_t devId, rtLimitType_t type, uint32_t val); /** * @ingroup dvrt_dev @@ -332,15 +322,6 @@ RTS_API rtError_t rtDeviceSynchronize(void); */ RTS_API rtError_t rtDeviceGetStreamPriorityRange(int32_t *leastPriority, int32_t *greatestPriority); -/** - * @ingroup dvrt_dev - * @brief Set exception handling callback function - * @param [in] callback rtExceptiontype - * @return RT_ERROR_NONE for ok - * @return RT_ERROR_INVALID_VALUE for error input - */ -RTS_API rtError_t rtSetExceptCallback(rtErrorCallback callback); - /** * @ingroup dvrt_dev * @brief Setting Scheduling Type of Graph @@ -373,14 +354,14 @@ RTS_API rtError_t rtGetAicpuDeploy(rtAicpuDeployType_t *deployType); * @brief set chipType * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtSetSocVersion(const char_t *version); +RTS_API rtError_t rtSetSocVersion(const char_t *ver); /** * @ingroup dvrt_dev * @brief get chipType * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtGetSocVersion(char_t *version, const uint32_t maxLen); +RTS_API rtError_t rtGetSocVersion(char_t *ver, const uint32_t maxLen); /** * @ingroup dvrt_dev @@ -388,10 +369,10 @@ RTS_API rtError_t rtGetSocVersion(char_t *version, const uint32_t maxLen); * @param [in] devId the logical device id * @param [in] otherDevId the other logical device id * @param [in] infoType info type - * @param [in|out] value pair info + * @param [in|out] val pair info * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtGetPairDevicesInfo(uint32_t devId, uint32_t otherDevId, int32_t infoType, int64_t *value); +RTS_API rtError_t rtGetPairDevicesInfo(uint32_t devId, uint32_t otherDevId, int32_t infoType, int64_t *val); /** * @ingroup dvrt_dev @@ -406,19 +387,19 @@ RTS_API rtError_t rtGetPairDevicesInfo(uint32_t devId, uint32_t otherDevId, int3 MEMCPY_INFO_SUPPORT_ZEROCOPY = 0, MEMCPY_INFO _RSV, } rtMemcpyInfo_t; - * @param [out] value the capability info RT_CAPABILITY_SUPPORT or RT_CAPABILITY_NOT_SUPPORT + * @param [out] val the capability info RT_CAPABILITY_SUPPORT or RT_CAPABILITY_NOT_SUPPORT * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtGetRtCapability(rtFeatureType_t featureType, int32_t featureInfo, int64_t *value); +RTS_API rtError_t rtGetRtCapability(rtFeatureType_t featureType, int32_t featureInfo, int64_t *val); /** * @ingroup dvrt_dev * @brief set target device for current thread - * @param [int] device the device id + * @param [int] devId the device id * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtSetDeviceWithoutTsd(int32_t device); +RTS_API rtError_t rtSetDeviceWithoutTsd(int32_t devId); /** * @ingroup dvrt_dev @@ -426,7 +407,7 @@ RTS_API rtError_t rtSetDeviceWithoutTsd(int32_t device); * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtDeviceResetWithoutTsd(int32_t device); +RTS_API rtError_t rtDeviceResetWithoutTsd(int32_t devId); /** * @ingroup dvrt_dev diff --git a/third_party/fwkacllib/inc/runtime/dvfsprofile.h b/third_party/fwkacllib/inc/runtime/dvfsprofile.h index c610bbb6..7cb8c8a6 100644 --- a/third_party/fwkacllib/inc/runtime/dvfsprofile.h +++ b/third_party/fwkacllib/inc/runtime/dvfsprofile.h @@ -1,17 +1,7 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. + * Description: dvfsprofile.h + * Create: 2020-01-01 */ #ifndef CCE_RUNTIME_DVFSPROFILE_H @@ -60,4 +50,4 @@ RTS_API rtError_t rtGetDvfsProfile(DvfsProfileMode *pmode); } #endif -#endif // CCE_RUNTIME_DVFSPROFILE_H \ No newline at end of file +#endif // CCE_RUNTIME_DVFSPROFILE_H diff --git a/third_party/fwkacllib/inc/runtime/event.h b/third_party/fwkacllib/inc/runtime/event.h index f6141d42..024ff3e3 100644 --- a/third_party/fwkacllib/inc/runtime/event.h +++ b/third_party/fwkacllib/inc/runtime/event.h @@ -1,17 +1,7 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. + * Description: event.h + * Create: 2020-01-01 */ #ifndef CCE_RUNTIME_EVENT_H @@ -48,7 +38,7 @@ typedef enum rtEventWaitStatus { * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtEventCreate(rtEvent_t *event); +RTS_API rtError_t rtEventCreate(rtEvent_t *evt); /** * @ingroup dvrt_event @@ -57,103 +47,103 @@ RTS_API rtError_t rtEventCreate(rtEvent_t *event); * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtEventCreateWithFlag(rtEvent_t *event, uint32_t flag); +RTS_API rtError_t rtEventCreateWithFlag(rtEvent_t *evt, uint32_t flag); /** * @ingroup dvrt_event * @brief destroy event instance - * @param [in] event event to destroy + * @param [in] evt event to destroy * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtEventDestroy(rtEvent_t event); +RTS_API rtError_t rtEventDestroy(rtEvent_t evt); /** * @ingroup dvrt_event * @brief get event id - * @param [in] event_ event to be get + * @param [in] evt event to be get * @param [in|out] event_id event_id id * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtGetEventID(rtEvent_t event, uint32_t *eventId); +RTS_API rtError_t rtGetEventID(rtEvent_t evt, uint32_t *evtId); /** * @ingroup dvrt_event * @brief event record * @param [int] event event to record - * @param [int] stream stream handle + * @param [int] stm stream handle * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtEventRecord(rtEvent_t event, rtStream_t stream); +RTS_API rtError_t rtEventRecord(rtEvent_t evt, rtStream_t stm); /** * @ingroup dvrt_event * @brief event reset * @param [int] event event to reset - * @param [int] stream stream handle + * @param [int] stm stream handle * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtEventReset(rtEvent_t event, rtStream_t stream); +RTS_API rtError_t rtEventReset(rtEvent_t evt, rtStream_t stm); /** * @ingroup dvrt_event * @brief wait event to be complete - * @param [in] event event to wait + * @param [in] evt event to wait * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtEventSynchronize(rtEvent_t event); +RTS_API rtError_t rtEventSynchronize(rtEvent_t evt); /** * @ingroup dvrt_event * @brief Queries an event's status - * @param [in] event event to query + * @param [in] evt event to query * @return RT_ERROR_NONE for complete * @return RT_ERROR_EVENT_NOT_COMPLETE for not complete */ -RTS_API rtError_t rtEventQuery(rtEvent_t event); +RTS_API rtError_t rtEventQuery(rtEvent_t evt); /** * @ingroup dvrt_event * @brief Queries an event's wait status - * @param [in] event event to query + * @param [in] evt event to query * @param [in out] EVENT_WAIT_STATUS status * @return EVENT_STATUS_COMPLETE for complete * @return EVENT_STATUS_NOT_READY for not complete */ -RTS_API rtError_t rtEventQueryWaitStatus(rtEvent_t event, rtEventWaitStatus_t *status); +RTS_API rtError_t rtEventQueryWaitStatus(rtEvent_t evt, rtEventWaitStatus_t *status); /** * @ingroup dvrt_event * @brief computes the elapsed time between events. - * @param [in] time time between start and end in ms - * @param [in] start starting event - * @param [in] end ending event + * @param [in] timeInterval time between start and end in ms + * @param [in] startEvent starting event + * @param [in] endEvent ending event * @return RT_ERROR_NONE for ok, errno for failed */ -RTS_API rtError_t rtEventElapsedTime(float32_t *time, rtEvent_t start, rtEvent_t end); +RTS_API rtError_t rtEventElapsedTime(float32_t *timeInterval, rtEvent_t startEvent, rtEvent_t endEvent); /** * @ingroup dvrt_event * @brief get the elapsed time from a event after event recorded. - * @param [in] time time in ms - * @param [in] event event handle + * @param [in] timeStamp time in ms + * @param [in] evt event handle * @return RT_ERROR_NONE for ok, errno for failed */ -RTS_API rtError_t rtEventGetTimeStamp(uint64_t *time, rtEvent_t event); +RTS_API rtError_t rtEventGetTimeStamp(uint64_t *timeStamp, rtEvent_t evt); /** * @ingroup dvrt_event * @brief name an event - * @param [in] event event to be named + * @param [in] evt event to be named * @param [in] name identification name * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input of event, name * @return RT_ERROR_DRV_ERR for driver error */ -RTS_API rtError_t rtNameEvent(rtEvent_t event, const char_t *name); +RTS_API rtError_t rtNameEvent(rtEvent_t evt, const char_t *name); /** * @ingroup dvrt_event @@ -184,7 +174,7 @@ RTS_API rtError_t rtNotifyDestroy(rtNotify_t notify); * @return RT_ERROR_INVALID_VALUE for error input * @return RT_ERROR_STREAM_CONTEXT for stream is not in current ctx */ -RTS_API rtError_t rtNotifyRecord(rtNotify_t notify, rtStream_t stream); +RTS_API rtError_t rtNotifyRecord(rtNotify_t notify, rtStream_t stm); /** * @ingroup dvrt_event @@ -195,19 +185,19 @@ RTS_API rtError_t rtNotifyRecord(rtNotify_t notify, rtStream_t stream); * @return RT_ERROR_INVALID_VALUE for error input * @return RT_ERROR_STREAM_CONTEXT for stream is not in current ctx */ -RTS_API rtError_t rtNotifyWait(rtNotify_t notify, rtStream_t stream); +RTS_API rtError_t rtNotifyWait(rtNotify_t notify, rtStream_t stm); /** * @ingroup dvrt_event * @brief Wait for a notify with time out * @param [in] notify notify to be wait - * @param [in] stream input stream + * @param [in] stm input stream * @param [in] timeOut input timeOut * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input * @return RT_ERROR_STREAM_CONTEXT for stream is not in current ctx */ -RTS_API rtError_t rtNotifyWaitWithTimeOut(rtNotify_t notify, rtStream_t stream, uint32_t timeOut); +RTS_API rtError_t rtNotifyWaitWithTimeOut(rtNotify_t notify, rtStream_t stm, uint32_t timeOut); /** * @ingroup dvrt_event diff --git a/third_party/fwkacllib/inc/runtime/kernel.h b/third_party/fwkacllib/inc/runtime/kernel.h index 2bd7f284..08860ccd 100644 --- a/third_party/fwkacllib/inc/runtime/kernel.h +++ b/third_party/fwkacllib/inc/runtime/kernel.h @@ -1,17 +1,7 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. + * Description: kernel.h + * Create: 2020-01-01 */ #ifndef CCE_RUNTIME_KERNEL_H @@ -154,7 +144,7 @@ typedef enum tagRtDumpKind { * @ingroup rt_kernel * @brief report callback */ -typedef rtError_t (*rtKernelReportCallback)(rtStream_t stream, rtKernelInfo_t kernelInfo); +typedef rtError_t (*rtKernelReportCallback)(rtStream_t stm, rtKernelInfo_t kernelInfo); /** * @ingroup rt_kernel @@ -237,49 +227,49 @@ typedef void (*rtCallback_t)(void *fnData); * @ingroup rt_kernel * @brief register device binary * @param [in] bin device binary description - * @param [out] handle device binary handle + * @param [out] hdl device binary handle * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtDevBinaryRegister(const rtDevBinary_t *bin, void **handle); +RTS_API rtError_t rtDevBinaryRegister(const rtDevBinary_t *bin, void **hdl); /** * @ingroup rt_kernel * @brief register device binary with all kernel * @param [in] bin device binary description - * @param [out] handle device binary handle + * @param [out] hdl device binary handle * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtRegisterAllKernel(const rtDevBinary_t *bin, void **handle); +RTS_API rtError_t rtRegisterAllKernel(const rtDevBinary_t *bin, void **hdl); /** * @ingroup rt_kernel * @brief register fast memeory device binary - * @param [in] handle device binary handle + * @param [in] hdl device binary handle * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtBinaryRegisterToFastMemory(void *handle); +RTS_API rtError_t rtBinaryRegisterToFastMemory(void *hdl); /** * @ingroup rt_kernel * @brief unregister device binary - * @param [in] handle device binary handle + * @param [in] hdl device binary handle * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtDevBinaryUnRegister(void *handle); +RTS_API rtError_t rtDevBinaryUnRegister(void *hdl); /** * @ingroup rt_kernel * @brief register device binary metadata - * @param [in] handle device binary description + * @param [in] hdl device binary description * @param [in] metadata device binary metadata * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtMetadataRegister(void *handle, const char_t *metadata); +RTS_API rtError_t rtMetadataRegister(void *hdl, const char_t *metadata); /** * @ingroup rt_kernel @@ -343,7 +333,7 @@ RTS_API rtError_t rtQueryFunctionRegistered(const char_t *stubName); * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtKernelConfigDump(uint32_t kind, uint32_t dumpSizePerBlock, uint32_t blockDim, void **dumpBaseAddr, - rtStream_t stream); + rtStream_t stm); /** * @ingroup rt_kernel @@ -353,28 +343,28 @@ RTS_API rtError_t rtKernelConfigDump(uint32_t kind, uint32_t dumpSizePerBlock, u * @param [in] args argments address for kernel function * @param [in] argsSize argements size * @param [in] smDesc shared memory description - * @param [in] stream associated stream + * @param [in] stm associated stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtKernelLaunch(const void *stubFunc, uint32_t blockDim, void *args, uint32_t argsSize, - rtSmDesc_t *smDesc, rtStream_t stream); + rtSmDesc_t *smDesc, rtStream_t stm); /** * @ingroup rt_kernel * @brief launch kernel with handle to device - * @param [in] handle program + * @param [in] hdl program * @param [in] devFunc device function description. * @param [in] blockDim block dimentions * @param [in] args argments address for kernel function * @param [in] argsSize argements size * @param [in] smDesc shared memory description - * @param [in] stream associated stream + * @param [in] stm associated stream * @param [in] kernelInfo kernel info * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtKernelLaunchWithHandle(void *handle, const void *devFunc, uint32_t blockDim, +RTS_API rtError_t rtKernelLaunchWithHandle(void *hdl, const void *devFunc, uint32_t blockDim, void *args, uint32_t argsSize, rtSmDesc_t *smDesc, rtStream_t stream_, const void *kernelInfo); @@ -386,13 +376,13 @@ RTS_API rtError_t rtKernelLaunchWithHandle(void *handle, const void *devFunc, ui * @param [in] args argments address for kernel function * @param [in] argsSize argements size * @param [in] smDesc shared memory description - * @param [in] stream associated stream + * @param [in] stm associated stream * @param [in] flag dump flag * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtKernelLaunchWithFlag(const void *stubFunc, uint32_t blockDim, void *args, uint32_t argsSize, - rtSmDesc_t *smDesc, rtStream_t stream, uint32_t flags); + rtSmDesc_t *smDesc, rtStream_t stm, uint32_t flags); /** * @ingroup rt_kernel(abandoned) @@ -400,11 +390,11 @@ RTS_API rtError_t rtKernelLaunchWithFlag(const void *stubFunc, uint32_t blockDim * @param [in] args argments address for kernel function * @param [in] argsSize argements size * @param [in] flags launch flags - * @param [in] stream associated stream + * @param [in] stm associated stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtKernelLaunchEx(void *args, uint32_t argsSize, uint32_t flags, rtStream_t stream); +RTS_API rtError_t rtKernelLaunchEx(void *args, uint32_t argsSize, uint32_t flags, rtStream_t stm); /** * @ingroup rt_kernel(in use) @@ -413,7 +403,7 @@ RTS_API rtError_t rtKernelLaunchEx(void *args, uint32_t argsSize, uint32_t flags * @param [in] args argments address for kernel function * @param [in] argsSize argements size * @param [in] flags launch flags - * @param [in] stream associated stream + * @param [in] stm associated stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ @@ -429,12 +419,12 @@ RTS_API rtError_t rtKernelLaunchFwk(const char_t *opName, void *args, uint32_t a * @param [in] args argments address for kernel function * @param [in] argsSize argments size * @param [in] smDesc shared memory description - * @param [in] stream associated stream + * @param [in] stm associated stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtCpuKernelLaunch(const void *soName, const void *kernelName, uint32_t blockDim, const void *args, - uint32_t argsSize, rtSmDesc_t *smDesc, rtStream_t stream); + uint32_t argsSize, rtSmDesc_t *smDesc, rtStream_t stm); /** * @ingroup rt_kernel(in use) @@ -444,12 +434,12 @@ RTS_API rtError_t rtCpuKernelLaunch(const void *soName, const void *kernelName, * @param [in] args argments address for kernel function * @param [in] argsSize argments size * @param [in] smDesc shared memory description - * @param [in] stream associated stream + * @param [in] stm associated stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtAicpuKernelLaunch(const rtKernelLaunchNames_t *launchNames, - uint32_t blockDim, const void *args, uint32_t argsSize, rtSmDesc_t *smDesc, rtStream_t stream); + uint32_t blockDim, const void *args, uint32_t argsSize, rtSmDesc_t *smDesc, rtStream_t stm); /** * @ingroup rt_kernel(abandoned) @@ -460,13 +450,13 @@ RTS_API rtError_t rtAicpuKernelLaunch(const rtKernelLaunchNames_t *launchNames, * @param [in] args argments address for kernel function * @param [in] argsSize argments size * @param [in] smDesc shared memory description - * @param [in] stream associated stream + * @param [in] stm associated stream * @param [in] flag dump flag or others function flag * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtCpuKernelLaunchWithFlag(const void *soName, const void *kernelName, uint32_t blockDim, - const void *args, uint32_t argsSize, rtSmDesc_t *smDesc, rtStream_t stream, + const void *args, uint32_t argsSize, rtSmDesc_t *smDesc, rtStream_t stm, uint32_t flags); /** @@ -477,25 +467,25 @@ RTS_API rtError_t rtCpuKernelLaunchWithFlag(const void *soName, const void *kern * @param [in] args argments address for kernel function * @param [in] argsSize argments size * @param [in] smDesc shared memory description - * @param [in] stream associated stream + * @param [in] stm associated stream * @param [in] flag dump flag or others function flag * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtAicpuKernelLaunchWithFlag(const rtKernelLaunchNames_t *launchNames, uint32_t blockDim, - const void *args, uint32_t argsSize, rtSmDesc_t *smDesc, rtStream_t stream, uint32_t flags); + const void *args, uint32_t argsSize, rtSmDesc_t *smDesc, rtStream_t stm, uint32_t flags); /** * @ingroup rt_kernel * @brief L1 fusion dump addr transfered to device - * @param [in] model handle info + * @param [in] mdl handle info * @param [in] addr ddr address of L1 Fusion Dump * @param [in] dumpSize memory size * @param [in] flag memory flag * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtDumpAddrSet(rtModel_t model, void *addr, uint32_t dumpSize, uint32_t flag); +RTS_API rtError_t rtDumpAddrSet(rtModel_t mdl, void *addr, uint32_t dumpSize, uint32_t flag); /** * @ingroup rt_kernel @@ -514,14 +504,14 @@ RTS_API rtError_t rtDatadumpInfoLoad(const void *dumpInfo, uint32_t length); * @brief configure call argment for next rtLaunch in current thread * @param [in] numBlocks block dimentions * @param [in] smDesc shared memory description - * @param [in] stream associated stream + * @param [in] stm associated stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ #ifdef __cplusplus -RTS_API rtError_t rtConfigureCall(uint32_t numBlocks, rtSmDesc_t *smDesc = nullptr, rtStream_t stream = nullptr); +RTS_API rtError_t rtConfigureCall(uint32_t numBlocks, rtSmDesc_t *smDesc = nullptr, rtStream_t stm = nullptr); #else -RTS_API rtError_t rtConfigureCall(uint32_t numBlocks, rtSmDesc_t *smDesc, rtStream_t stream); +RTS_API rtError_t rtConfigureCall(uint32_t numBlocks, rtSmDesc_t *smDesc, rtStream_t stm); #endif #endif // __CLANG_CCE_RUNTIME_H__ @@ -563,20 +553,20 @@ RTS_API rtError_t rtKernelConfigTransArg(const void *ptr, uint64_t size, uint32_ /** * @ingroup rt_kernel * @brief start fusion kernels. - * @param [in] stream stream for fusion kernels + * @param [in] stm stream for fusion kernels * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtKernelFusionStart(rtStream_t stream); +RTS_API rtError_t rtKernelFusionStart(rtStream_t stm); /** * @ingroup rt_kernel * @brief end fusion kernels. - * @param [in] stream stream for fusion kernels + * @param [in] stm stream for fusion kernels * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtKernelFusionEnd(rtStream_t stream); +RTS_API rtError_t rtKernelFusionEnd(rtStream_t stm); /** * @ingroup rt_kernel @@ -591,22 +581,22 @@ RTS_API rtError_t rtSetKernelReportCallback(rtKernelReportCallback callBack); * @ingroup rt_kernel * @brief subscribe stream callback report. * @param [in] threadId thread id for stream - * @param [in] stream stream for subscribe + * @param [in] stm stream for subscribe * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtSubscribeReport(uint64_t threadId, rtStream_t stream); +RTS_API rtError_t rtSubscribeReport(uint64_t threadId, rtStream_t stm); /** * @ingroup rt_kernel * @brief add callback launch task in stream. * @param [in] callBackFunc app callback function * @param [in] fnData user data - * @param [in] stream subscribed stream + * @param [in] stm subscribed stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtCallbackLaunch(rtCallback_t callBackFunc, void *fnData, rtStream_t stream, bool isBlock); +RTS_API rtError_t rtCallbackLaunch(rtCallback_t callBackFunc, void *fnData, rtStream_t stm, bool isBlock); /** * @ingroup rt_kernel @@ -621,11 +611,11 @@ RTS_API rtError_t rtProcessReport(int32_t timeout); * @ingroup rt_kernel * @brief unsubscribe callback report. * @param [in] threadId thread id for stream - * @param [in] stream stream for subscribe + * @param [in] stm stream for subscribe * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtUnSubscribeReport(uint64_t threadId, rtStream_t stream); +RTS_API rtError_t rtUnSubscribeReport(uint64_t threadId, rtStream_t stm); /** * @ingroup profiling_base @@ -633,7 +623,7 @@ RTS_API rtError_t rtUnSubscribeReport(uint64_t threadId, rtStream_t stream); * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtStartOnlineProf(rtStream_t stream, uint32_t sampleNum); +RTS_API rtError_t rtStartOnlineProf(rtStream_t stm, uint32_t sampleNum); /** * @ingroup profiling_base @@ -641,7 +631,7 @@ RTS_API rtError_t rtStartOnlineProf(rtStream_t stream, uint32_t sampleNum); * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtStopOnlineProf(rtStream_t stream); +RTS_API rtError_t rtStopOnlineProf(rtStream_t stm); /** * @ingroup profiling_base @@ -649,7 +639,7 @@ RTS_API rtError_t rtStopOnlineProf(rtStream_t stream); * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtGetOnlineProfData(rtStream_t stream, rtProfDataInfo_t *pProfData, uint32_t profDataNum); +RTS_API rtError_t rtGetOnlineProfData(rtStream_t stm, rtProfDataInfo_t *pProfData, uint32_t profDataNum); /** * @ingroup profiling_base @@ -674,28 +664,28 @@ RTS_API rtError_t rtStopMDCProfiler(void *addr); * @param [in] blockDim block dimentions * @param [in] argsInfo argments info address for kernel function * @param [in] smDesc shared memory description - * @param [in] stream associated stream + * @param [in] stm associated stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtKernelLaunchWithTiling(const void *stubFunc, uint32_t blockDim, - rtArgsWithTiling_t *argsInfo, rtSmDesc_t *smDesc, rtStream_t stream); + rtArgsWithTiling_t *argsInfo, rtSmDesc_t *smDesc, rtStream_t stm); /** * @ingroup rt_kernel * @brief launch kernel with handle and tiling data to device - * @param [in] handle program + * @param [in] hdl program * @param [in] devFunc device function description. * @param [in] blockDim block dimentions * @param [in] argsInfo argments info address for kernel function * @param [in] smDesc shared memory description - * @param [in] stream associated stream + * @param [in] stm associated stream * @param [in] kernelInfo kernel info * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtKernelLaunchWithHandleAndTiling(void *handle, const void *devFunc, uint32_t blockDim, - rtArgsWithTiling_t *argsInfo, rtSmDesc_t *smDesc, rtStream_t stream, const void* kernelInfo); +RTS_API rtError_t rtKernelLaunchWithHandleAndTiling(void *hdl, const void *devFunc, uint32_t blockDim, + rtArgsWithTiling_t *argsInfo, rtSmDesc_t *smDesc, rtStream_t stm, const void* kernelInfo); #if defined(__cplusplus) } diff --git a/third_party/fwkacllib/inc/runtime/mem.h b/third_party/fwkacllib/inc/runtime/mem.h index d095ef0c..c086da10 100644 --- a/third_party/fwkacllib/inc/runtime/mem.h +++ b/third_party/fwkacllib/inc/runtime/mem.h @@ -1,17 +1,7 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. + * Description: mem.h + * Create: 2020-01-01 */ #ifndef CCE_RUNTIME_MEM_H @@ -59,12 +49,13 @@ extern "C" { * @brief memory Policy */ #define RT_MEMORY_POLICY_NONE (0x0U) // Malloc mem prior huge page, then default page -#define RT_MEMORY_POLICY_HUGE_PAGE_FIRST (0x1U << 10U) // Malloc mem prior huge page, then default page -#define RT_MEMORY_POLICY_HUGE_PAGE_ONLY (0x1U << 11U) // Malloc mem only use huge page -#define RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY (0x1U << 12U) // Malloc mem only use default page -#define RT_MEMORY_POLICY_HUGE_PAGE_FIRST_P2P (0x1U << 13U) // Malloc mem prior huge page, then default page, for p2p -#define RT_MEMORY_POLICY_HUGE_PAGE_ONLY_P2P (0x1U << 14U) // Malloc mem only use huge page, use for p2p -#define RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY_P2P (0x1U << 15U) // Malloc mem only use default page, use for p2p +#define RT_MEMORY_POLICY_HUGE_PAGE_FIRST (0x400U) // Malloc mem prior huge page, then default page, 0x1U << 10U +#define RT_MEMORY_POLICY_HUGE_PAGE_ONLY (0x800U) // Malloc mem only use huge page, 0x1U << 11U +#define RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY (0x1000U) // Malloc mem only use default page, 0x1U << 12U +// Malloc mem prior huge page, then default page, for p2p, 0x1U << 13U +#define RT_MEMORY_POLICY_HUGE_PAGE_FIRST_P2P (0x2000U) +#define RT_MEMORY_POLICY_HUGE_PAGE_ONLY_P2P (0x4000U) // Malloc mem only use huge page, use for p2p, 0x1U << 14U +#define RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY_P2P (0x8000U) // Malloc mem only use default page, use for p2p, 0x1U << 15U #define MEM_ALLOC_TYPE_BIT (0x3FFU) // mem type bit in <0, 9> @@ -130,8 +121,8 @@ typedef enum tagRtDataType { RT_DATA_TYPE_BFP16 = 6, // bfp16 RT_DATA_TYPE_BFP32 = 7, // bfp32 RT_DATA_TYPE_UINT8 = 8, // uint8 - RT_DATA_TYPE_UINT16= 9, // uint16 - RT_DATA_TYPE_UINT32= 10,// uint32 + RT_DATA_TYPE_UINT16 = 9, // uint16 + RT_DATA_TYPE_UINT32 = 10, // uint32 RT_DATA_TYPE_END = 11, } rtDataType_t; @@ -188,19 +179,19 @@ typedef struct tagRtPointerAttributes { } rtPointerAttributes_t; -typedef struct rtMallocHostSharedMemoryIn { +typedef struct { const char_t *name; const uint64_t size; uint32_t flag; } rtMallocHostSharedMemoryIn; -typedef struct rtMallocHostSharedMemoryOut { +typedef struct { int32_t fd; void *ptr; void *devPtr; } rtMallocHostSharedMemoryOut; -typedef struct rtFreeHostSharedMemoryIn { +typedef struct { const char_t *name; const uint64_t size; int32_t fd; @@ -309,17 +300,6 @@ RTS_API rtError_t rtMemAllocManaged(void **ptr, uint64_t size, uint32_t flag); */ RTS_API rtError_t rtMemFreeManaged(void *ptr); -/** - * @ingroup dvrt_mem - * @brief Specifies how memory is use - * @param [in] devPtr memory pointer - * @param [in] size memory size - * @param [in] advise reserved, set to 1 - * @return RT_ERROR_NONE for ok - * @return others for error - */ -RTS_API rtError_t rtMemAdvise(void *devPtr, uint64_t size, uint32_t advise); - /** * @ingroup dvrt_mem * @brief alloc cached device memory @@ -354,12 +334,12 @@ RTS_API rtError_t rtInvalidCache(void *base, size_t len); * @param [in] dst destination address pointer * @param [in] Max length of destination address memory * @param [in] src source address pointer - * @param [in] count the number of byte to copy + * @param [in] cnt the number of byte to copy * @param [in] kind memcpy type * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtMemcpy(void *dst, uint64_t destMax, const void *src, uint64_t count, rtMemcpyKind_t kind); +RTS_API rtError_t rtMemcpy(void *dst, uint64_t destMax, const void *src, uint64_t cnt, rtMemcpyKind_t kind); /** * @ingroup dvrt_mem @@ -367,14 +347,14 @@ RTS_API rtError_t rtMemcpy(void *dst, uint64_t destMax, const void *src, uint64_ * @param [in] dst destination address pointer * @param [in] Max length of destination address memory * @param [in] src source address pointer - * @param [in] count the number of byte to copy + * @param [in] cnt the number of byte to copy * @param [in] kind memcpy type - * @param [in] stream asynchronized task stream + * @param [in] stm asynchronized task stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtMemcpyAsync(void *dst, uint64_t destMax, const void *src, uint64_t count, rtMemcpyKind_t kind, - rtStream_t stream); +RTS_API rtError_t rtMemcpyAsync(void *dst, uint64_t destMax, const void *src, uint64_t cnt, rtMemcpyKind_t kind, + rtStream_t stm); /** * @ingroup dvrt_mem @@ -382,15 +362,15 @@ RTS_API rtError_t rtMemcpyAsync(void *dst, uint64_t destMax, const void *src, ui * @param [in] dst destination address pointer * @param [in] Max length of destination address memory * @param [in] src source address pointer - * @param [in] count the number of byte to copy + * @param [in] cnt the number of byte to copy * @param [in] kind memcpy type * @param [in] type data type - * @param [in] stream asynchronized task stream + * @param [in] stm asynchronized task stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtReduceAsync(void *dst, uint64_t destMax, const void *src, uint64_t count, rtRecudeKind_t kind, - rtDataType_t type, rtStream_t stream); +RTS_API rtError_t rtReduceAsync(void *dst, uint64_t destMax, const void *src, uint64_t cnt, rtRecudeKind_t kind, + rtDataType_t type, rtStream_t stm); /** * @ingroup dvrt_mem @@ -418,12 +398,12 @@ RTS_API rtError_t rtMemcpy2d(void *dst, uint64_t dstPitch, const void *src, uint * @param [in] width width of matrix transfer * @param [in] height height of matrix transfer * @param [in] kind memcpy type - * @param [in] stream asynchronized task stream + * @param [in] stm asynchronized task stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtMemcpy2dAsync(void *dst, uint64_t dstPitch, const void *src, uint64_t srcPitch, uint64_t width, - uint64_t height, rtMemcpyKind_t kind, rtStream_t stream); + uint64_t height, rtMemcpyKind_t kind, rtStream_t stm); /** * @ingroup dvrt_mem @@ -449,25 +429,25 @@ RTS_API rtError_t rtSetAiCoreMemorySizes(rtAiCoreMemorySize_t *aiCoreMemorySize) * @brief set memory with uint32_t value * @param [in] devPtr * @param [in] Max length of destination address memory - * @param [in] value - * @param [in] count byte num + * @param [in] val + * @param [in] cnt byte num * @return RT_ERROR_NONE for ok, errno for failed * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtMemset(void *devPtr, uint64_t destMax, uint32_t value, uint64_t count); +RTS_API rtError_t rtMemset(void *devPtr, uint64_t destMax, uint32_t val, uint64_t cnt); /** * @ingroup dvrt_mem * @brief set memory with uint32_t value async * @param [in] devPtr * @param [in] Max length of destination address memory - * @param [in] value - * @param [in] count byte num - * @param [in] stream + * @param [in] val + * @param [in] cnt byte num + * @param [in] stm * @return RT_ERROR_NONE for ok, errno for failed * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtMemsetAsync(void *ptr, uint64_t destMax, uint32_t value, uint64_t count, rtStream_t stream); +RTS_API rtError_t rtMemsetAsync(void *ptr, uint64_t destMax, uint32_t val, uint64_t cnt, rtStream_t stm); /** * @ingroup dvrt_mem @@ -494,11 +474,11 @@ RTS_API rtError_t rtMemGetInfoEx(rtMemInfoType_t memInfoType, size_t *freeSize, * @brief set memory with uint32_t value * @param [in] devPtr * @param [in] len - * @param [in] device + * @param [in] devId * @return RT_ERROR_NONE for ok, errno for failed * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtMemPrefetchToDevice(void *devPtr, uint64_t len, int32_t device); +RTS_API rtError_t rtMemPrefetchToDevice(void *devPtr, uint64_t len, int32_t devId); /** * @ingroup dvrt_mem @@ -557,14 +537,14 @@ RTS_API rtError_t rtIpcCloseMemory(const void *ptr); /** * @ingroup dvrt_mem * @brief HCCL Async memory cpy - * @param [in] index sq index + * @param [in] sqIndex sq index * @param [in] wqeIndex moudle index - * @param [in] stream asynchronized task stream + * @param [in] stm asynchronized task stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input * @return RT_ERROR_DRV_ERR for driver error */ -RTS_API rtError_t rtRDMASend(uint32_t index, uint32_t wqeIndex, rtStream_t stream); +RTS_API rtError_t rtRDMASend(uint32_t sqIndex, uint32_t wqeIndex, rtStream_t stm); /** * @ingroup dvrt_mem @@ -583,12 +563,12 @@ RTS_API rtError_t rtSetIpcMemPid(const char_t *name, int32_t pid[], int32_t num) * @brief HCCL Async memory cpy * @param [in] dbindex single device 0 * @param [in] dbinfo doorbell info - * @param [in] stream asynchronized task stream + * @param [in] stm asynchronized task stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input * @return RT_ERROR_DRV_ERR for driver error */ -RTS_API rtError_t rtRDMADBSend(uint32_t dbIndex, uint64_t dbInfo, rtStream_t stream); +RTS_API rtError_t rtRDMADBSend(uint32_t dbIndex, uint64_t dbInfo, rtStream_t stm); #if defined(__cplusplus) } diff --git a/third_party/fwkacllib/inc/runtime/rt.h b/third_party/fwkacllib/inc/runtime/rt.h index 8c3e339f..10b763b2 100644 --- a/third_party/fwkacllib/inc/runtime/rt.h +++ b/third_party/fwkacllib/inc/runtime/rt.h @@ -1,17 +1,7 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. + * Description: rt.h + * Create: 2020-01-01 */ #ifndef CCE_RUNTIME_RT_H diff --git a/third_party/fwkacllib/inc/runtime/rt_dfx.h b/third_party/fwkacllib/inc/runtime/rt_dfx.h index 7e0bc280..f96c0859 100644 --- a/third_party/fwkacllib/inc/runtime/rt_dfx.h +++ b/third_party/fwkacllib/inc/runtime/rt_dfx.h @@ -1,17 +1,6 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + * Description: dfx interface */ #ifndef CCE_RUNTIME_RT_DFX_H diff --git a/third_party/fwkacllib/inc/runtime/rt_ffts.h b/third_party/fwkacllib/inc/runtime/rt_ffts.h index ded78d25..5c0ab971 100644 --- a/third_party/fwkacllib/inc/runtime/rt_ffts.h +++ b/third_party/fwkacllib/inc/runtime/rt_ffts.h @@ -1,17 +1,6 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2021. All rights reserved. + * Description: ffts interface */ #ifndef CCE_RUNTIME_RT_FFTS_H @@ -91,8 +80,11 @@ typedef struct tagAutoThreadPrefetch { typedef struct tagAutoThreadAicAivInfo { uint64_t taskParamAddr; // device mem uint16_t taskParamOffset; - // when satMode=1 and FP16 computation with none INF inputs overflows/underflows, results will be +/-INF of FP16 - // when satMode=0 and FP16 computation with none INF inputs overflows/underflows, results will be saturated to +/-MAX of FP16 + /* + * when satMode=1 and FP16 computation with none INF inputs overflows/underflows, results will be +/-INF of FP16 + * when satMode=0 and FP16 computation with none INF inputs overflows/underflows, results will be saturated to + * +/-MAX of FP16 + */ uint8_t satMode; uint8_t scheduleMode; // 0:normal mode, 1:batch mode, 2:sync mode 3:reserved uint8_t iCachePrefetchCnt; // units is 2K @@ -187,12 +179,12 @@ typedef struct tagFftsTaskInfo { rtTicketCache_t ticketCache[RT_FFTS_MAX_TICKET_CACHE_NUM]; } rtFftsTaskInfo_t; -RTS_API rtError_t rtFftsTaskLaunch(rtFftsTaskInfo_t *fftsTaskInfo, rtStream_t stream); +RTS_API rtError_t rtFftsTaskLaunch(rtFftsTaskInfo_t *fftsTaskInfo, rtStream_t stm); RTS_API rtError_t rtGetC2cCtrlAddr(uint64_t *addr, uint32_t *len); -RTS_API rtError_t rtFftsTaskLaunchWithFlag(rtFftsTaskInfo_t *fftsTaskInfo, rtStream_t stream, uint32_t flag); +RTS_API rtError_t rtFftsTaskLaunchWithFlag(rtFftsTaskInfo_t *fftsTaskInfo, rtStream_t stm, uint32_t flag); #if defined(__cplusplus) } #endif -#endif // CCE_RUNTIME_RT_FFTS_H \ No newline at end of file +#endif // CCE_RUNTIME_RT_FFTS_H diff --git a/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h b/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h index 53f3e60a..18b25d36 100644 --- a/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h +++ b/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h @@ -1,17 +1,6 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + * Description: ffts plus interface */ #ifndef CCE_RUNTIME_RT_FFTS_PLUS_H @@ -36,11 +25,11 @@ typedef struct tagFftsPlusTaskInfo { #pragma pack(pop) -RTS_API rtError_t rtGetAddrAndPrefCntWithHandle(void *handle, const void *devFunc, void **addr, uint32_t *prefetchCnt); +RTS_API rtError_t rtGetAddrAndPrefCntWithHandle(void *hdl, const void *devFunc, void **addr, uint32_t *prefetchCnt); -RTS_API rtError_t rtFftsPlusTaskLaunch(rtFftsPlusTaskInfo_t *fftsPlusTaskInfo, rtStream_t stream); +RTS_API rtError_t rtFftsPlusTaskLaunch(rtFftsPlusTaskInfo_t *fftsPlusTaskInfo, rtStream_t stm); -RTS_API rtError_t rtFftsPlusTaskLaunchWithFlag(rtFftsPlusTaskInfo_t *fftsPlusTaskInfo, rtStream_t stream, +RTS_API rtError_t rtFftsPlusTaskLaunchWithFlag(rtFftsPlusTaskInfo_t *fftsPlusTaskInfo, rtStream_t stm, uint32_t flag); #if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) diff --git a/third_party/fwkacllib/inc/runtime/rt_ffts_plus_define.h b/third_party/fwkacllib/inc/runtime/rt_ffts_plus_define.h index 8956e009..b1a6232a 100644 --- a/third_party/fwkacllib/inc/runtime/rt_ffts_plus_define.h +++ b/third_party/fwkacllib/inc/runtime/rt_ffts_plus_define.h @@ -1,17 +1,6 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + * Description: the definition of ffts plus */ #ifndef CCE_RUNTIME_RT_FFTS_PLUS_DEFINE_H @@ -370,8 +359,8 @@ typedef struct tagFftsPlusWriteValueCtx { // 80-83 uint32_t writeAddressBaseL; // 84-87 - uint32_t writeAddressBaseH: 17; - uint32_t res10: 15; + uint32_t writeAddressBaseH : 17; + uint32_t res10 : 15; // 88-91 uint32_t writeAddressOffset; // 92-95 diff --git a/third_party/fwkacllib/inc/runtime/rt_mem_queue.h b/third_party/fwkacllib/inc/runtime/rt_mem_queue.h index c6f56064..49a272f0 100644 --- a/third_party/fwkacllib/inc/runtime/rt_mem_queue.h +++ b/third_party/fwkacllib/inc/runtime/rt_mem_queue.h @@ -187,107 +187,107 @@ typedef enum rtGroupType { /** * @ingroup rt_mem_queue * @brief init queue schedule - * @param [in] device the logical device id + * @param [in] devId the logical device id * @param [in] grpName the name of group, can be nullptr * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMemQueueInitQS(int32_t device, const char* grpName); +RTS_API rtError_t rtMemQueueInitQS(int32_t devId, const char_t *grpName); /** * @ingroup rt_mem_queue * @brief create mbuf queue - * @param [in] device the logical device id - * @param [in] rtMemQueueAttr attribute of queue + * @param [in] devId the logical device id + * @param [in] queAttr attribute of queue * @param [out] qid queue id * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMemQueueCreate(int32_t device, const rtMemQueueAttr_t *queueAttr, uint32_t *qid); +RTS_API rtError_t rtMemQueueCreate(int32_t devId, const rtMemQueueAttr_t *queAttr, uint32_t *qid); /** * @ingroup rt_mem_queue * @brief destroy mbuf queue - * @param [in] device the logical device id + * @param [in] devId the logical device id * @param [in] qid queue id * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMemQueueDestroy(int32_t device, uint32_t qid); +RTS_API rtError_t rtMemQueueDestroy(int32_t devId, uint32_t qid); /** * @ingroup rt_mem_queue * @brief destroy mbuf queue init - * @param [in] device the logical device id + * @param [in] devId the logical device id * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMemQueueInit(int32_t device); +RTS_API rtError_t rtMemQueueInit(int32_t devId); /** * @ingroup rt_mem_queue * @brief enqueu mbuf - * @param [in] device the logical device id + * @param [in] devId the logical device id * @param [in] qid queue id * @param [in] mbuf enqueue mbuf * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMemQueueEnQueue(int32_t device, uint32_t qid, void *mbuf); +RTS_API rtError_t rtMemQueueEnQueue(int32_t devId, uint32_t qid, void *mbuf); /** * @ingroup rt_mem_queue * @brief enqueu mbuf - * @param [in] device the logical device id + * @param [in] devId the logical device id * @param [in] qid queue id * @param [out] mbuf dequeue mbuf * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMemQueueDeQueue(int32_t device, uint32_t qid, void **mbuf); +RTS_API rtError_t rtMemQueueDeQueue(int32_t devId, uint32_t qid, void **mbuf); /** * @ingroup rt_mem_queue * @brief enqueu peek - * @param [in] device the logical device id + * @param [in] devId the logical device id * @param [in] qid queue id * @param [out] bufLen length of mbuf in queue * @param [in] timeout peek timeout (ms), -1: wait all the time until peeking success * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMemQueuePeek(int32_t device, uint32_t qid, size_t *bufLen, int32_t timeout); +RTS_API rtError_t rtMemQueuePeek(int32_t devId, uint32_t qid, size_t *bufLen, int32_t timeout); /** * @ingroup rt_mem_queue * @brief enqueu buff - * @param [in] device the logical device id + * @param [in] devId the logical device id * @param [in] qid queue id * @param [in] inBuf enqueue buff * @param [in] timeout enqueue timeout (ms), -1: wait all the time until enqueue success * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMemQueueEnQueueBuff(int32_t device, uint32_t qid, rtMemQueueBuff_t *inBuf, int32_t timeout); +RTS_API rtError_t rtMemQueueEnQueueBuff(int32_t devId, uint32_t qid, rtMemQueueBuff_t *inBuf, int32_t timeout); /** * @ingroup rt_mem_queue * @brief enqueu buff - * @param [in] device the logical device id + * @param [in] devId the logical device id * @param [in] qid queue id * @param [out] outBuf dequeue buff * @param [in] timeout dequeue timeout (ms), -1: wait all the time until dequeue success * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMemQueueDeQueueBuff(int32_t device, uint32_t qid, rtMemQueueBuff_t *outBuf, int32_t timeout); +RTS_API rtError_t rtMemQueueDeQueueBuff(int32_t devId, uint32_t qid, rtMemQueueBuff_t *outBuf, int32_t timeout); /** * @ingroup rt_mem_queue * @brief query current queue info - * @param [in] device the logical device id + * @param [in] devId the logical device id * @param [in] qid queue id - * @param [out] queueInfo current queue info + * @param [out] queInfo current queue info * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMemQueueQueryInfo(int32_t device, uint32_t qid, rtMemQueueInfo_t *queueInfo); +RTS_API rtError_t rtMemQueueQueryInfo(int32_t devId, uint32_t qid, rtMemQueueInfo_t *queInfo); /** * @ingroup rt_mem_queue * @brief query queue status -* @param [in] device: the logical device id +* @param [in] devId: the logical device id * @param [in] cmd: query cmd * @param [in] inBuff: input buff * @param [in] inLen: the length of input @@ -295,39 +295,39 @@ RTS_API rtError_t rtMemQueueQueryInfo(int32_t device, uint32_t qid, rtMemQueueIn * @param [in|out] outLen: the length of output * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMemQueueQuery(int32_t device, rtMemQueueQueryCmd_t cmd, const void *inBuff, uint32_t inLen, +RTS_API rtError_t rtMemQueueQuery(int32_t devId, rtMemQueueQueryCmd_t cmd, const void *inBuff, uint32_t inLen, void *outBuff, uint32_t *outLen); /** * @ingroup rt_mem_queue * @brief grant queue -* @param [in] device: logic devid +* @param [in] devId: logic devid * @param [in] qid: queue id * @param [in] pid: pid * @param [in] attr: queue share attr * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMemQueueGrant(int32_t device, uint32_t qid, int32_t pid, rtMemQueueShareAttr_t *attr); +RTS_API rtError_t rtMemQueueGrant(int32_t devId, uint32_t qid, int32_t pid, rtMemQueueShareAttr_t *attr); /** * @ingroup rt_mem_queue * @brief attach queue -* @param [in] device: logic devid +* @param [in] devId: logic devid * @param [in] qid: queue id * @param [in] timeOut: timeOut * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMemQueueAttach(int32_t device, uint32_t qid, int32_t timeOut); +RTS_API rtError_t rtMemQueueAttach(int32_t devId, uint32_t qid, int32_t timeOut); /** * @ingroup rt_mem_queue * @brief Commit the event to a specific process -* @param [in] device: logic devid -* @param [in] event: event summary info +* @param [in] devId: logic devid +* @param [in] evt: event summary info * @param [out] ack: event reply info * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtEschedSubmitEventSync(int32_t device, rtEschedEventSummary_t *event, +RTS_API rtError_t rtEschedSubmitEventSync(int32_t devId, rtEschedEventSummary_t *evt, rtEschedEventReply_t *ack); /** @@ -411,8 +411,11 @@ typedef struct { int32_t pid; } rtMemGrpQueryByProc_t; // cmd: GRP_QUERY_GROUPS_OF_PROCESS -typedef union { - rtMemGrpQueryByProc_t grpQueryByProc; // cmd: GRP_QUERY_GROUPS_OF_PROCESS +typedef struct { + int32_t cmd; + union { + rtMemGrpQueryByProc_t grpQueryByProc; // cmd: GRP_QUERY_GROUPS_OF_PROCESS + }; } rtMemGrpQueryInput_t; #define RT_MEM_GRP_NAME_LEN 32 // it must be same as driver define BUFF_GRP_NAME_LEN @@ -460,116 +463,115 @@ RTS_API rtError_t rtMemGrpAttach(const char_t *name, int32_t timeout); /** * @ingroup rt_mem_queue * @brief buff group query -* @param [in] cmd, cmd type * @param [in] input, query input * @param [in|out] output, query output * @return 0 for success, others for fail */ -RTS_API rtError_t rtMemGrpQuery(int32_t cmd, const rtMemGrpQueryInput_t *input, rtMemGrpQueryOutput_t *output); +RTS_API rtError_t rtMemGrpQuery(const rtMemGrpQueryInput_t *input, rtMemGrpQueryOutput_t *output); /** * @ingroup rt_mem_queue * @brief buff group query -* @param [in] device, cdevice id +* @param [in] devId, cdevice id * @param [in] name, group name * @param [out] qid, queue id * @return 0 for success, others for fail */ -RTS_API rtError_t rtMemQueueGetQidByName(int32_t device, const char *name, uint32_t *qId); +RTS_API rtError_t rtMemQueueGetQidByName(int32_t devId, const char_t *name, uint32_t *qId); /** * @ingroup rt_mem_queue * @brief esched attach device -* @param [in] device, device id +* @param [in] devId, device id * @return 0 for success, others for fail */ -RTS_API rtError_t rtEschedAttachDevice(int32_t device); +RTS_API rtError_t rtEschedAttachDevice(int32_t devId); /** * @ingroup rt_mem_queue * @brief esched dettach device -* @param [in] device, device id +* @param [in] devId, device id * @return 0 for success, others for fail */ -RTS_API rtError_t rtEschedDettachDevice(int32_t device); +RTS_API rtError_t rtEschedDettachDevice(int32_t devId); /** * @ingroup rt_mem_queue * @brief esched wait event -* @param [in] device, device id +* @param [in] devId, device id * @param [in] grpId, group id * @param [in] threadId, thread id * @param [in] timeout -* @param [in] event +* @param [in] evt * @return 0 for success, others for fail */ -RTS_API rtError_t rtEschedWaitEvent(int32_t device, uint32_t grpId, uint32_t threadId, - int timeout, rtEschedEventSummary_t *event); +RTS_API rtError_t rtEschedWaitEvent(int32_t devId, uint32_t grpId, uint32_t threadId, + int32_t timeout, rtEschedEventSummary_t *evt); /** * @ingroup rt_mem_queue * @brief esched create group -* @param [in] device, device id +* @param [in] devId, device id * @param [in] grpId, group id * @param [in] type, group type * @return 0 for success, others for fail */ -RTS_API rtError_t rtEschedCreateGrp(int32_t device, uint32_t grpId, rtGroupType_t type); +RTS_API rtError_t rtEschedCreateGrp(int32_t devId, uint32_t grpId, rtGroupType_t type); /** * @ingroup rt_mem_queue * @brief esched submit event -* @param [in] device, device id -* @param [in] event +* @param [in] devId, device id +* @param [in] evt * @return 0 for success, others for fail */ -RTS_API rtError_t rtEschedSubmitEvent(int32_t device, rtEschedEventSummary_t *event); +RTS_API rtError_t rtEschedSubmitEvent(int32_t devId, rtEschedEventSummary_t *evt); /** * @ingroup rt_mem_queue * @brief esched submit event -* @param [in] device, device id +* @param [in] devId, device id * @param [in] grpId, group id * @param [in] threadId, thread id * @param [in] eventBitmap * @return 0 for success, others for fail */ -RTS_API rtError_t rtEschedSubscribeEvent(int32_t device, uint32_t grpId, uint32_t threadId, uint64_t eventBitmap); +RTS_API rtError_t rtEschedSubscribeEvent(int32_t devId, uint32_t grpId, uint32_t threadId, uint64_t eventBitmap); /** * @ingroup rtEschedAckEvent * @brief esched ack event -* @param [in] device, device id -* @param [in] eventId, event type -* @param [in] subeventId, sub event type +* @param [in] devId, device id +* @param [in] evtId, event type +* @param [in] subEvtId, sub event type * @param [in] msg, message info * @param [in] len, message length * @return 0 for success, others for fail */ -RTS_API rtError_t rtEschedAckEvent(int32_t device, rtEventIdType_t eventId, - uint32_t subeventId, char *msg, uint32_t len); +RTS_API rtError_t rtEschedAckEvent(int32_t devId, rtEventIdType_t evtId, + uint32_t subEvtId, char_t *msg, uint32_t len); /** * @ingroup rtQueueSubF2NFEvent * @brief full to not full event -* @param [in] device, device id +* @param [in] devId, device id * @param [in] qid, queue id * @param [in] groupId, group id * @return 0 for success, others for fail */ -RTS_API rtError_t rtQueueSubF2NFEvent(int32_t device, uint32_t qId, uint32_t groupId); +RTS_API rtError_t rtQueueSubF2NFEvent(int32_t devId, uint32_t qId, uint32_t groupId); /** * @ingroup rtQueueSubscribe * @brief queue subscribe -* @param [in] device, device id +* @param [in] devId, device id * @param [in] qid, queue id * @param [in] groupId, group id * @param [in] type * @return 0 for success, others for fail */ -RTS_API rtError_t rtQueueSubscribe(int32_t device, uint32_t qId, uint32_t groupId, int type); +RTS_API rtError_t rtQueueSubscribe(int32_t devId, uint32_t qId, uint32_t groupId, int32_t type); #if defined(__cplusplus) } diff --git a/third_party/fwkacllib/inc/runtime/rt_model.h b/third_party/fwkacllib/inc/runtime/rt_model.h index 9486639d..2807a705 100644 --- a/third_party/fwkacllib/inc/runtime/rt_model.h +++ b/third_party/fwkacllib/inc/runtime/rt_model.h @@ -1,17 +1,7 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. + * Description: rt_model.h + * Create: 2020-01-01 */ #ifndef CCE_RUNTIME_RT_MODEL_H @@ -320,7 +310,7 @@ typedef struct tagLabelDevInfo_t { }u; }rtLabelDevInfo; -typedef rtError_t (*rtTaskGenCallback)(rtModel_t model, rtTaskInfo_t *taskInfo); +typedef rtError_t (*rtTaskGenCallback)(rtModel_t mdl, rtTaskInfo_t *taskInfo); /** * @ingroup rt_model @@ -334,165 +324,165 @@ RTS_API rtError_t rtSetTaskGenCallback(rtTaskGenCallback callback); /** * @ingroup rt_model * @brief create model instance - * @param [out] model created model + * @param [out] mdl created model * @param [in] flag reserved * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtModelCreate(rtModel_t *model, uint32_t flag); +RTS_API rtError_t rtModelCreate(rtModel_t *mdl, uint32_t flag); /** * @ingroup rt_model * @brief destroy model instance - * @param [in] model model to destroy + * @param [in] mdl model to destroy * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtModelDestroy(rtModel_t model); +RTS_API rtError_t rtModelDestroy(rtModel_t mdl); /** * @ingroup rt_model * @brief bind model and stream instance - * @param [in] model binded model - * @param [in] stream binded stream + * @param [in] mdl binded model + * @param [in] stm binded stream * @param [in] flag reserved * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtModelBindStream(rtModel_t model, rtStream_t stream, uint32_t flag); +RTS_API rtError_t rtModelBindStream(rtModel_t mdl, rtStream_t stm, uint32_t flag); /** * @ingroup rt_model * @brief unbind model and stream instance - * @param [in] model unbinded model - * @param [in] stream unbinded stream + * @param [in] mdl unbinded model + * @param [in] stm unbinded stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtModelUnbindStream(rtModel_t model, rtStream_t stream); +RTS_API rtError_t rtModelUnbindStream(rtModel_t mdl, rtStream_t stm); /** * @ingroup rt_model * @brief tell runtime Model has been Loaded - * @param [in] model model to execute + * @param [in] mdl model to execute * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtModelLoadComplete(rtModel_t model); +RTS_API rtError_t rtModelLoadComplete(rtModel_t mdl); /** * @ingroup rt_model * @brief execute model instance - * @param [in] model model to execute + * @param [in] mdl model to execute * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtModelExecute(rtModel_t model, rtStream_t stream, uint32_t flag); +RTS_API rtError_t rtModelExecute(rtModel_t mdl, rtStream_t stm, uint32_t flag); /** * @ingroup rt_model * @brief get model the last persist task id - * @param [in] model model to execute + * @param [in] mdl model to execute * @param [out] taskId last task id of the model * @param [out] streamId last steam id of the model * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtModelGetTaskId(rtModel_t model, uint32_t *taskId, uint32_t *streamId); +RTS_API rtError_t rtModelGetTaskId(rtModel_t mdl, uint32_t *taskId, uint32_t *streamId); /** * @ingroup rt_model * @brief add a end graph task to stream - * @param [in] model model to execute + * @param [in] mdl model to execute * @param [in] end graph stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtEndGraph(rtModel_t model, rtStream_t stream); +RTS_API rtError_t rtEndGraph(rtModel_t mdl, rtStream_t stm); /** * @ingroup rt_model * @brief add a end graph task with flag to stream - * @param [in] model model to execute + * @param [in] mdl model to execute * @param [in] end graph stream * @param [in] flags AICPU datadump * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtEndGraphEx(rtModel_t model, rtStream_t stream, uint32_t flags); +RTS_API rtError_t rtEndGraphEx(rtModel_t mdl, rtStream_t stm, uint32_t flags); /** * @ingroup rt_model * @brief add a end graph task to stream - * @param [in] model model to execute + * @param [in] mdl model to execute * @param [in] flags EXECUTOR_TS | EXECUTOR_AICPU * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtModelExecutorSet(rtModel_t model, uint8_t flags); +RTS_API rtError_t rtModelExecutorSet(rtModel_t mdl, uint8_t flags); /** * @ingroup rt_model * @brief abort model - * @param [in] model model to abort + * @param [in] mdl model to abort * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtModelAbort(rtModel_t model); +RTS_API rtError_t rtModelAbort(rtModel_t mdl); /** * @ingroup rt_model * @brief end graph task to model default stream - * @param [in] model model to execute + * @param [in] mdl model to execute * @param [in] end graph stream * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtModelExit(rtModel_t model, rtStream_t stream); +RTS_API rtError_t rtModelExit(rtModel_t mdl, rtStream_t stm); /** * @ingroup rt_model * @brief bind queue - * @param [in] model model to bind + * @param [in] mdl model to bind * @param [in] queueId queueId to bind * @param [in] flag * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtModelBindQueue(rtModel_t model, uint32_t queueId, rtModelQueueFlag_t flag); +RTS_API rtError_t rtModelBindQueue(rtModel_t mdl, uint32_t queueId, rtModelQueueFlag_t flag); /** * @ingroup rt_model * @brief get model id - * @param [in] model + * @param [in] mdl * @param [out] modelId model id * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtModelGetId(rtModel_t model, uint32_t *modelId); +RTS_API rtError_t rtModelGetId(rtModel_t mdl, uint32_t *modelId); /* * @ingroup rt_model * @brief enable debug for dump overflow exception * @param [in] addr: ddr address of kernel exception dumpped - * @param [in] model: model handle + * @param [in] mdl: model handle * @param [in] flag: debug flag * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtDebugRegister(rtModel_t model, uint32_t flag, const void *addr, +RTS_API rtError_t rtDebugRegister(rtModel_t mdl, uint32_t flag, const void *addr, uint32_t *streamId, uint32_t *taskId); /* * @ingroup rt_model * @brief disable debug for dump overflow exception - * @param [in] model: model handle + * @param [in] mdl: model handle * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtDebugUnRegister(rtModel_t model); +RTS_API rtError_t rtDebugUnRegister(rtModel_t mdl); #if defined(__cplusplus) } #endif -#endif // CCE_RUNTIME_RT_MODEL_H \ No newline at end of file +#endif // CCE_RUNTIME_RT_MODEL_H diff --git a/third_party/fwkacllib/inc/runtime/rt_stars.h b/third_party/fwkacllib/inc/runtime/rt_stars.h index 857006b5..a9c91897 100644 --- a/third_party/fwkacllib/inc/runtime/rt_stars.h +++ b/third_party/fwkacllib/inc/runtime/rt_stars.h @@ -1,17 +1,6 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + * Description: the definition of stars */ #ifndef CCE_RUNTIME_RT_STARS_H @@ -29,10 +18,10 @@ extern "C" { * used for send star sqe directly. * @param [in] taskSqe stars task sqe * @param [in] sqeLen stars task sqe length - * @param [in] stream associated stream + * @param [in] stm associated stream * @return RT_ERROR_NONE for ok, others failed */ -RTS_API rtError_t rtStarsTaskLaunch(const void *taskSqe, uint32_t sqeLen, rtStream_t stream); +RTS_API rtError_t rtStarsTaskLaunch(const void *taskSqe, uint32_t sqeLen, rtStream_t stm); /** @@ -71,11 +60,11 @@ RTS_API rtError_t rtCdqAllocBatch(const char_t *queName, int32_t timeout, uint32 * @param [in] cdqeIndex cdqe index * @param [in] data cdqe infomation * @param [in] dataSize data size - * @param [in] stream launch task on the stream + * @param [in] stm launch task on the stream * @return RT_ERROR_NONE for ok, others failed */ RTS_API rtError_t rtCdqEnQueue(const char_t *queName, uint32_t cdqeIndex, void *data, uint32_t dataSize, - rtStream_t stream); + rtStream_t stm); /** * @ingroup rt_stars @@ -85,11 +74,11 @@ RTS_API rtError_t rtCdqEnQueue(const char_t *queName, uint32_t cdqeIndex, void * * @param [in] cdqeIndex cdqe index * @param [in] data cdqe infomation * @param [in] dataSize data size - * @param [in] stream launch task on the stream + * @param [in] stm launch task on the stream * @return RT_ERROR_NONE for ok, others failed */ RTS_API rtError_t rtCdqEnQueuePtrMode(const char_t *queName, uint32_t cdqeIndex, const void *ptrAddr, - rtStream_t stream); + rtStream_t stm); #if defined(__cplusplus) diff --git a/third_party/fwkacllib/inc/runtime/rt_stars_define.h b/third_party/fwkacllib/inc/runtime/rt_stars_define.h index 861af80b..260809af 100644 --- a/third_party/fwkacllib/inc/runtime/rt_stars_define.h +++ b/third_party/fwkacllib/inc/runtime/rt_stars_define.h @@ -1,17 +1,6 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + * Description: the definition of stars */ #ifndef CCE_RUNTIME_RT_STARS_DEFINE_H @@ -83,9 +72,9 @@ typedef struct tagFftsPlusSqe { uint16_t aicPrefetchUpper : 5; uint16_t reserved12 : 3; uint16_t aivPrefetchLower : 5; - uint16_t Reserved13 : 3; + uint16_t reserved13 : 3; uint16_t aivPrefetchUpper : 5; - uint16_t Reserved14 : 3; + uint16_t reserved14 : 3; // 40-47 bytes uint32_t contextAddressBaseL; uint32_t contextAddressBaseH : 17; diff --git a/third_party/fwkacllib/inc/runtime/stream.h b/third_party/fwkacllib/inc/runtime/stream.h index a7ca9ebb..026b0155 100644 --- a/third_party/fwkacllib/inc/runtime/stream.h +++ b/third_party/fwkacllib/inc/runtime/stream.h @@ -1,17 +1,7 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. + * Description: stream.h + * Create: 2020-01-01 */ #ifndef CCE_RUNTIME_STREAM_H @@ -53,70 +43,70 @@ extern "C" { /** * @ingroup dvrt_stream * @brief create stream instance - * @param [in|out] stream created stream + * @param [in|out] stm created stream * @param [in] priority stream priority * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtStreamCreate(rtStream_t *stream, int32_t priority); +RTS_API rtError_t rtStreamCreate(rtStream_t *stm, int32_t priority); /** * @ingroup dvrt_stream * @brief create stream instance - * @param [in|out] stream created stream + * @param [in|out] stm created stream * @param [in] priority stream priority * @param [in] flags stream op flags * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtStreamCreateWithFlags(rtStream_t *stream, int32_t priority, uint32_t flags); +RTS_API rtError_t rtStreamCreateWithFlags(rtStream_t *stm, int32_t priority, uint32_t flags); /** * @ingroup dvrt_stream * @brief destroy stream instance. - * @param [in] stream the stream to destroy + * @param [in] stm the stream to destroy * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtStreamDestroy(rtStream_t stream); +RTS_API rtError_t rtStreamDestroy(rtStream_t stm); /** * @ingroup dvrt_stream * @brief wait an recorded event for stream - * @param [in] stream the wait stream + * @param [in] stm the wait stream * @param [in] event the event to wait * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtStreamWaitEvent(rtStream_t stream, rtEvent_t event); +RTS_API rtError_t rtStreamWaitEvent(rtStream_t stm, rtEvent_t evt); /** * @ingroup dvrt_stream * @brief wait stream to be complete - * @param [in] stream stream to wait + * @param [in] stm stream to wait * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtStreamSynchronize(rtStream_t stream); +RTS_API rtError_t rtStreamSynchronize(rtStream_t stm); /** * @ingroup dvrt_stream * @brief queries an asynchronous stream for completion status - * @param [in] stream stream to query + * @param [in] stm stream to query * @return RT_ERROR_NONE for complete * @return RT_ERROR_STREAM_NOT_COMPLETE for not complete */ -RTS_API rtError_t rtStreamQuery(rtStream_t stream); +RTS_API rtError_t rtStreamQuery(rtStream_t stm); /** * @ingroup dvrt_stream * @brief get stream id from a stream handle - * @param [in] stream stream hadle + * @param [in] stm stream hadle * @param [in] streamId stream id * @return RT_ERROR_NONE for complete * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtGetStreamId(rtStream_t stream, int32_t *streamId); +RTS_API rtError_t rtGetStreamId(rtStream_t stm, int32_t *streamId); /** * @ingroup dvrt_stream @@ -132,26 +122,26 @@ RTS_API rtError_t rtGetMaxStreamAndTask(uint32_t streamType, uint32_t *maxStrCou /** * @ingroup dvrt_stream * @brief Name a stream - * @param [in] stream stream to be named + * @param [in] stm stream to be named * @param [in] name identification name * @return RT_ERROR_NONE for complete * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtNameStream(rtStream_t stream, const char_t *name); +RTS_API rtError_t rtNameStream(rtStream_t stm, const char_t *name); /** * @ingroup dvrt_stream * @brief switch to the corresponding stream according to the contents of the ptr * @param [in] ptr Determine the address where the value of the true and false branches is located * @param [in] condition switch condition - * @param [in] value switch value + * @param [in] val switch value * @param [in] trueStream Stream that needs to be activated when the value is non-zero - * @param [in] stream input stream to init task + * @param [in] stm input stream to init task * @return RT_ERROR_NONE for complete * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtStreamSwitch(void *ptr, rtCondition_t condition, int64_t value, rtStream_t trueStream, - rtStream_t stream); +RTS_API rtError_t rtStreamSwitch(void *ptr, rtCondition_t condition, int64_t val, rtStream_t trueStream, + rtStream_t stm); /** * @brief execute extensible stream switch task @@ -159,22 +149,22 @@ RTS_API rtError_t rtStreamSwitch(void *ptr, rtCondition_t condition, int64_t val * @param [in] condition judge condition * @param [in] value_ptr pointer of target value * @param [in] true_stream stream to be activated when value is not zero - * @param [in] stream stream id + * @param [in] stm stream id * @param [in] dataType data type of target value * @return RT_ERROR_NONE for complete */ RTS_API rtError_t rtStreamSwitchEx(void *ptr, rtCondition_t condition, void *valuePtr, rtStream_t trueStream, - rtStream_t stream, rtSwitchDataType_t dataType); + rtStream_t stm, rtSwitchDataType_t dataType); /** * @ingroup dvrt_stream * @brief Active a stream * @param [in] activeStream stream to be activated - * @param [in] stream input stream to init task + * @param [in] stm input stream to init task * @return RT_ERROR_NONE for complete * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtStreamActive(rtStream_t activeStream, rtStream_t stream); +RTS_API rtError_t rtStreamActive(rtStream_t activeStream, rtStream_t stm); /** * @brief execute extensible stream case switch task @@ -183,36 +173,36 @@ RTS_API rtError_t rtStreamActive(rtStream_t activeStream, rtStream_t stream); * @param [in] valuePtr pointer of target value, length = size * elementSize * @param [in] trueStreamPtr streams to be activated * @param [in] elementSize size of to be activated true streams - * @param [in] stream input stream to init task + * @param [in] stm input stream to init task * @param [in] dataType data type of target value * @return RT_ERROR_NONE for complete */ RTS_API rtError_t rtStreamSwitchN(void *ptr, uint32_t size, void *valuePtr, rtStream_t *trueStreamPtr, - uint32_t elementSize, rtStream_t stream, rtSwitchDataType_t dataType); + uint32_t elementSize, rtStream_t stm, rtSwitchDataType_t dataType); /* * @ingroup dvrt_stream * @brief enable debug for dump overflow exception with stream * @param [in] addr: ddr address of kernel exception dumpped - * @param [in] stream: stream handle + * @param [in] stm: stream handle * @param [in] flag: debug flag * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtDebugRegisterForStream(rtStream_t stream, uint32_t flag, const void *addr, +RTS_API rtError_t rtDebugRegisterForStream(rtStream_t stm, uint32_t flag, const void *addr, uint32_t *streamId, uint32_t *taskId); /* * @ingroup rt_model * @brief disable debug for dump overflow exception with stream - * @param [in] stream: stream handle + * @param [in] stm: stream handle * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtDebugUnRegisterForStream(rtStream_t stream); +RTS_API rtError_t rtDebugUnRegisterForStream(rtStream_t stm); #if defined(__cplusplus) } #endif -#endif // CCE_RUNTIME_STREAM_H \ No newline at end of file +#endif // CCE_RUNTIME_STREAM_H diff --git a/third_party/fwkacllib/inc/soft_dp/ExternalSoftDp.h b/third_party/fwkacllib/inc/soft_dp/ExternalSoftDp.h deleted file mode 100644 index 975043b3..00000000 --- a/third_party/fwkacllib/inc/soft_dp/ExternalSoftDp.h +++ /dev/null @@ -1,58 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef EXTERNALSOFTDP_H -#define EXTERNALSOFTDP_H - -#include - -extern "C" { -struct SoftDpProcsessInfo { - uint8_t* inputBuffer; - uint32_t inputBufferSize; - - uint8_t* outputBuffer; - uint32_t outputBufferSize; - - uint32_t outputWidth; - uint32_t outputHeight; - - uint32_t reserved; -}; - -struct DpCropInfo { - uint32_t left; - uint32_t right; - uint32_t up; - uint32_t down; -}; - -/* - * @brief decode and resize interface - * @param [in] SoftDpProcsessInfo& softDpProcsessInfo : soft dp struct - * @return success: return 0, fail: return error number - */ -uint32_t DecodeAndResizeJpeg(SoftDpProcsessInfo& softDpProcsessInfo); - -/* - * @brief decode crop and resize interface - * @param [in] SoftDpProcsessInfo& softDpProcsessInfo : soft dp struct - * @param [in] const DpCropInfo& cropInfo: crop struct - * @return success: return 0, fail: return error number - */ -uint32_t DecodeAndCropAndResizeJpeg(SoftDpProcsessInfo& softDpProcsessInfo, const DpCropInfo& cropInfo); -} -#endif // EXTERNALSOFTDP_H \ No newline at end of file diff --git a/third_party/fwkacllib/inc/toolchain/adx_datadump_callback.h b/third_party/fwkacllib/inc/toolchain/adx_datadump_callback.h index e2391f72..ca428e6a 100644 --- a/third_party/fwkacllib/inc/toolchain/adx_datadump_callback.h +++ b/third_party/fwkacllib/inc/toolchain/adx_datadump_callback.h @@ -18,15 +18,15 @@ #define ADX_DATADUMP_CALLBACK_H #include namespace Adx { - const uint32_t MAX_FILE_PATH_LENGTH = 4096; - struct DumpChunk { - char fileName[MAX_FILE_PATH_LENGTH]; - uint32_t bufLen; - uint32_t isLastChunk; - int64_t offset; - int32_t flag; - uint8_t dataBuf[0]; - }; +const uint32_t MAX_FILE_PATH_LENGTH = 4096; +struct DumpChunk { + char fileName[MAX_FILE_PATH_LENGTH]; // file name, absolute path + uint32_t bufLen; // dataBuf length + uint32_t isLastChunk; // is last chunk. 0: not 1: yes + int64_t offset; // Offset in file. -1: append write + int32_t flag; // flag + uint8_t dataBuf[0]; // data buffer +}; int AdxRegDumpProcessCallBack(int (* const messageCallback) (const Adx::DumpChunk *, int)); void AdxUnRegDumpProcessCallBack(); diff --git a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h index 80f4baab..8ecd5f14 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h +++ b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h @@ -18,62 +18,62 @@ #define MSPROFILER_API_PROF_ACL_API_H_ // DataTypeConfig -#define PROF_ACL_API 0x00000001 -#define PROF_TASK_TIME 0x00000002 -#define PROF_AICORE_METRICS 0x00000004 -#define PROF_AICPU_TRACE 0x00000008 -#define PROF_L2CACHE 0x00000010 -#define PROF_HCCL_TRACE 0x00000020 -#define PROF_TRAINING_TRACE 0x00000040 +#define PROF_ACL_API 0x00000001ULL +#define PROF_TASK_TIME 0x00000002ULL +#define PROF_AICORE_METRICS 0x00000004ULL +#define PROF_AICPU_TRACE 0x00000008ULL +#define PROF_L2CACHE 0x00000010ULL +#define PROF_HCCL_TRACE 0x00000020ULL +#define PROF_TRAINING_TRACE 0x00000040ULL // system profilinig switch -#define PROF_CPU 0x00010000 -#define PROF_HARDWARE_MEMORY 0x00020000 -#define PROF_IO 0x00040000 -#define PROF_INTER_CONNECTION 0x00080000 -#define PROF_DVPP 0x00100000 -#define PROF_SYS_AICORE_SAMPLE 0x00200000 -#define PROF_AIVECTORCORE_SAMPLE 0x00400000 - -#define PROF_MODEL_EXECUTE 0x0000001000000 -#define PROF_RUNTIME_API 0x0000002000000 -#define PROF_RUNTIME_TRACE 0x0000004000000 -#define PROF_SCHEDULE_TIMELINE 0x0000008000000 -#define PROF_SCHEDULE_TRACE 0x0000010000000 -#define PROF_AIVECTORCORE_METRICS 0x0000020000000 -#define PROF_SUBTASK_TIME 0x0000040000000 - -#define PROF_TASK_TRACE 0x0000005000062 - -#define PROF_MODEL_LOAD 0x8000000000000000 +#define PROF_CPU 0x00010000ULL +#define PROF_HARDWARE_MEMORY 0x00020000ULL +#define PROF_IO 0x00040000ULL +#define PROF_INTER_CONNECTION 0x00080000ULL +#define PROF_DVPP 0x00100000ULL +#define PROF_SYS_AICORE_SAMPLE 0x00200000ULL +#define PROF_AIVECTORCORE_SAMPLE 0x00400000ULL + +#define PROF_MODEL_EXECUTE 0x0000001000000ULL +#define PROF_RUNTIME_API 0x0000002000000ULL +#define PROF_RUNTIME_TRACE 0x0000004000000ULL +#define PROF_SCHEDULE_TIMELINE 0x0000008000000ULL +#define PROF_SCHEDULE_TRACE 0x0000010000000ULL +#define PROF_AIVECTORCORE_METRICS 0x0000020000000ULL +#define PROF_SUBTASK_TIME 0x0000040000000ULL + +#define PROF_TASK_TRACE 0x0000005000062ULL + +#define PROF_MODEL_LOAD 0x8000000000000000ULL // DataTypeConfig MASK -#define PROF_ACL_API_MASK 0x00000001 -#define PROF_TASK_TIME_MASK 0x00000002 -#define PROF_AICORE_METRICS_MASK 0x00000004 -#define PROF_AICPU_TRACE_MASK 0x00000008 -#define PROF_L2CACHE_MASK 0x00000010 -#define PROF_HCCL_TRACE_MASK 0x00000020 -#define PROF_TRAINING_TRACE_MASK 0x00000040 +#define PROF_ACL_API_MASK 0x00000001ULL +#define PROF_TASK_TIME_MASK 0x00000002ULL +#define PROF_AICORE_METRICS_MASK 0x00000004ULL +#define PROF_AICPU_TRACE_MASK 0x00000008ULL +#define PROF_L2CACHE_MASK 0x00000010ULL +#define PROF_HCCL_TRACE_MASK 0x00000020ULL +#define PROF_TRAINING_TRACE_MASK 0x00000040ULL // system profilinig mask -#define PROF_CPU_MASK 0x00010000 -#define PROF_HARDWARE_MEMORY_MASK 0x00020000 -#define PROF_IO_MASK 0x00040000 -#define PROF_INTER_CONNECTION_MASK 0x00080000 -#define PROF_DVPP_MASK 0x00100000 -#define PROF_SYS_AICORE_SAMPLE_MASK 0x00200000 -#define PROF_AIVECTORCORE_SAMPLE_MASK 0x00400000 - -#define PROF_MODEL_EXECUTE_MASK 0x0000001000000 -#define PROF_RUNTIME_API_MASK 0x0000002000000 -#define PROF_RUNTIME_TRACE_MASK 0x0000004000000 -#define PROF_SCHEDULE_TIMELINE_MASK 0x0000008000000 -#define PROF_SCHEDULE_TRACE_MASK 0x0000010000000 -#define PROF_AIVECTORCORE_METRICS_MASK 0x0000020000000 -#define PROF_SUBTASK_TIME_MASK 0x0000040000000 - -#define PROF_MODEL_LOAD_MASK 0x8000000000000000 +#define PROF_CPU_MASK 0x00010000ULL +#define PROF_HARDWARE_MEMORY_MASK 0x00020000ULL +#define PROF_IO_MASK 0x00040000ULL +#define PROF_INTER_CONNECTION_MASK 0x00080000ULL +#define PROF_DVPP_MASK 0x00100000ULL +#define PROF_SYS_AICORE_SAMPLE_MASK 0x00200000ULL +#define PROF_AIVECTORCORE_SAMPLE_MASK 0x00400000ULL + +#define PROF_MODEL_EXECUTE_MASK 0x0000001000000ULL +#define PROF_RUNTIME_API_MASK 0x0000002000000ULL +#define PROF_RUNTIME_TRACE_MASK 0x0000004000000ULL +#define PROF_SCHEDULE_TIMELINE_MASK 0x0000008000000ULL +#define PROF_SCHEDULE_TRACE_MASK 0x0000010000000ULL +#define PROF_AIVECTORCORE_METRICS_MASK 0x0000020000000ULL +#define PROF_SUBTASK_TIME_MASK 0x0000040000000ULL + +#define PROF_MODEL_LOAD_MASK 0x8000000000000000ULL #if (defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)) #define MSVP_PROF_API __declspec(dllexport) diff --git a/third_party/fwkacllib/inc/toolchain/prof_callback.h b/third_party/fwkacllib/inc/toolchain/prof_callback.h index cb531417..5f5a151b 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_callback.h +++ b/third_party/fwkacllib/inc/toolchain/prof_callback.h @@ -43,7 +43,7 @@ enum MsprofErrorCode { MSPROF_ERROR, }; -#define MSPROF_ENGINE_MAX_TAG_LEN (31) +#define MSPROF_ENGINE_MAX_TAG_LEN (63) /** * @name ReporterData diff --git a/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h b/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h deleted file mode 100644 index 4ba835b6..00000000 --- a/third_party/fwkacllib/inc/toolchain/tuning_tool/tune_api.h +++ /dev/null @@ -1,94 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -/** @defgroup aoe aoe调优接口 */ -#ifndef TUNE_API_H -#define TUNE_API_H -#include -#include -#include "ge/ge_api.h" -#include "aoe_types.h" - -/** - * @ingroup aoe - * @par 描述: 命令行调优 - * - * @attention 无 - * @param option [IN] 调优参数 - * @param msg [OUT] 调优异常下返回信息 - * @retval #AOE_SUCCESS 执行成功 - * @retval #AOE_FAILURE 执行失败 - * @par 依赖: - * @li tune_api.cpp:该接口所属的开发包。 - * @li tune_api.h:该接口声明所在的头文件。 - * @see 无 - * @since - */ -AoeStatus AoeOfflineTuning(const std::map &option, std::string &msg); - -/** - * @ingroup aoe - * @par 描述: 调优初始化 - * - * @attention 无 - * @param session [IN] ge连接会话 - * @param option [IN] 参数集. 包含调优参数及ge参数 - * @retval #AOE_SUCCESS 执行成功 - * @retval #AOE_FAILURE 执行失败 - * @par 依赖: - * @li tune_api.cpp:该接口所属的开发包。 - * @li tune_api.h:该接口声明所在的头文件。 - * @see 无 - * @since - */ -extern "C" AoeStatus AoeOnlineInitialize(ge::Session *session, const std::map &option); - -/** - * @ingroup aoe - * @par 描述: 调优去初始化 - * - * @attention 无 - * @param 无 - * @retval #AOE_SUCCESS 执行成功 - * @retval #AOE_FAILURE 执行失败 - * @par 依赖: - * @li tune_api.cpp:该接口所属的开发包。 - * @li tune_api.h:该接口声明所在的头文件。 - * @see 无 - * @since - */ -extern "C" AoeStatus AoeOnlineFinalize(); - -/** - * @ingroup aoe - * @par 描述: 调优处理 - * - * @attention 无 - * @param tuningGraph [IN] 调优图 - * @param dependGraph [IN] 调优依赖图 - * @param session [IN] ge连接会话 - * @param option [IN] 参数集. 包含调优参数及ge参数 - * @retval #AOE_SUCCESS 执行成功 - * @retval #AOE_FAILURE 执行失败 - * @par 依赖: - * @li tune_api.cpp:该接口所属的开发包。 - * @li tune_api.h:该接口声明所在的头文件。 - * @see 无 - * @since - */ -extern "C" AoeStatus AoeOnlineTuning(ge::Graph &tuningGraph, std::vector &dependGraph, - ge::Session *session, const std::map &option); -#endif From f85064db077260757db51d71cc96d2e65baa8ac3 Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Thu, 2 Dec 2021 21:00:03 +0800 Subject: [PATCH 46/59] add cce back --- third_party/fwkacllib/inc/cce/aicpu_engine.h | 63 + .../fwkacllib/inc/cce/aicpu_engine_struct.h | 56 + third_party/fwkacllib/inc/cce/blas_struct.h | 31 + third_party/fwkacllib/inc/cce/cce.h | 101 + third_party/fwkacllib/inc/cce/cce_def.hpp | 152 + .../fwkacllib/inc/cce/common/attr_list.hpp | 82 + .../fwkacllib/inc/cce/common/catch.hpp | 95 + third_party/fwkacllib/inc/cce/compiler_stub.h | 36 + third_party/fwkacllib/inc/cce/customize.h | 60 + third_party/fwkacllib/inc/cce/dnn.h | 23 + third_party/fwkacllib/inc/cce/dnn_base.h | 676 +++ .../fwkacllib/inc/cce/dnn_base_def.hpp | 994 ++++ third_party/fwkacllib/inc/cce/dnn_op.h | 4838 +++++++++++++++++ third_party/fwkacllib/inc/cce/dnn_struct.hpp | 23 + .../fwkacllib/inc/cce/dnn_struct_base.hpp | 894 +++ .../fwkacllib/inc/cce/fwk_adpt_struct.h | 155 + .../fwkacllib/inc/cce/l2fusion_struct.hpp | 56 + .../inc/cce/optimizer/fusion_engine.h | 65 + third_party/fwkacllib/inc/cce/taskdown_api.h | 54 + .../fwkacllib/inc/cce/taskdown_common.hpp | 108 + 20 files changed, 8562 insertions(+) create mode 100644 third_party/fwkacllib/inc/cce/aicpu_engine.h create mode 100644 third_party/fwkacllib/inc/cce/aicpu_engine_struct.h create mode 100644 third_party/fwkacllib/inc/cce/blas_struct.h create mode 100644 third_party/fwkacllib/inc/cce/cce.h create mode 100644 third_party/fwkacllib/inc/cce/cce_def.hpp create mode 100644 third_party/fwkacllib/inc/cce/common/attr_list.hpp create mode 100644 third_party/fwkacllib/inc/cce/common/catch.hpp create mode 100644 third_party/fwkacllib/inc/cce/compiler_stub.h create mode 100644 third_party/fwkacllib/inc/cce/customize.h create mode 100644 third_party/fwkacllib/inc/cce/dnn.h create mode 100644 third_party/fwkacllib/inc/cce/dnn_base.h create mode 100644 third_party/fwkacllib/inc/cce/dnn_base_def.hpp create mode 100644 third_party/fwkacllib/inc/cce/dnn_op.h create mode 100644 third_party/fwkacllib/inc/cce/dnn_struct.hpp create mode 100644 third_party/fwkacllib/inc/cce/dnn_struct_base.hpp create mode 100644 third_party/fwkacllib/inc/cce/fwk_adpt_struct.h create mode 100644 third_party/fwkacllib/inc/cce/l2fusion_struct.hpp create mode 100644 third_party/fwkacllib/inc/cce/optimizer/fusion_engine.h create mode 100644 third_party/fwkacllib/inc/cce/taskdown_api.h create mode 100644 third_party/fwkacllib/inc/cce/taskdown_common.hpp diff --git a/third_party/fwkacllib/inc/cce/aicpu_engine.h b/third_party/fwkacllib/inc/cce/aicpu_engine.h new file mode 100644 index 00000000..bc2e415f --- /dev/null +++ b/third_party/fwkacllib/inc/cce/aicpu_engine.h @@ -0,0 +1,63 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef AICPU_ENGINE_H__ +#define AICPU_ENGINE_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + AE_STATUS_SUCCESS = 0, + AE_STATUS_BAD_PARAM = 1, + AE_STATUS_OPEN_SO_FAILED = 2, + AE_STATUS_GET_KERNEL_NAME_FAILED = 3, + AE_STATUS_INNER_ERROR = 4, + AE_STATUS_KERNEL_API_INNER_ERROR = 5, + AE_STATUS_END_OF_SEQUENCE = 6, + AE_STATUS_DUMP_FAILED = 7, + AE_STATUS_TASK_WAIT = 101, + AE_STATUS_RESERVED +} aeStatus_t; + +/** + * @ingroup aicpu engine + * @brief aeCallInterface: + * a interface to call a function in a op kernfel lib + * @param [in] addr void *, should be STR_KERNEL * format + * @return aeStatus_t + */ +aeStatus_t aeCallInterface(void *addr); + +/** + * @ingroup aicpu engine + * @brief aeBatchLoadKernelSo: + * a interface to load kernel so + * @param [in] loadSoNum load so number + * @param [in] soPaths load so paths + * @param [in] soNames load so names + * @return aeStatus_t + */ +aeStatus_t aeBatchLoadKernelSo(const uint32_t loadSoNum, const char *soPaths[], const char *soNames[]); + +#ifdef __cplusplus +} +#endif + +#endif // AICPU_ENGINE_H__ diff --git a/third_party/fwkacllib/inc/cce/aicpu_engine_struct.h b/third_party/fwkacllib/inc/cce/aicpu_engine_struct.h new file mode 100644 index 00000000..8c0c1847 --- /dev/null +++ b/third_party/fwkacllib/inc/cce/aicpu_engine_struct.h @@ -0,0 +1,56 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef AICPU_ENGINE_STRUCT_H__ +#define AICPU_ENGINE_STRUCT_H__ + +#include "fwk_adpt_struct.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* + The different framwork we adapted for. +*/ +typedef enum { + FMK_KERNEL_TYPE_TF = 0, + FMK_KERNEL_TYPE_CF = 10, + FMK_KERNEL_TYPE_PT = 20, + FMK_KERNEL_TYPE_RESERVED +} FwkkernelType_t; + +#pragma pack(push, 1) +typedef struct { + uint32_t fwkKernelType; // FwkkernelType_t + union { + ::aicpu::FWKAdapter::FWKOperateParam fwk_kernel; + } fwkKernelBase; +} STR_FWK_OP_KERNEL; +#pragma pack(pop) + +#pragma pack(push, 1) +struct SessionInfo { + uint64_t sessionId; + uint64_t kernelId; + bool sessFlag; +}; +#pragma pack(pop) + +#ifdef __cplusplus +} +#endif +#endif // AICPU_ENGINE_STRUCT_H__ diff --git a/third_party/fwkacllib/inc/cce/blas_struct.h b/third_party/fwkacllib/inc/cce/blas_struct.h new file mode 100644 index 00000000..e0bcee4c --- /dev/null +++ b/third_party/fwkacllib/inc/cce/blas_struct.h @@ -0,0 +1,31 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef CC_BLAS_STRUCT_API__ +#define CC_BLAS_STRUCT_API__ + +#include + +typedef enum { CCBLAS_FILL_MODE_LOWER = 0, CCBLAS_FILL_MODE_UPPER = 1 } ccblasFillMode_t; + +typedef enum { + CCBLAS_OP_N = 0, + CCBLAS_OP_T = 1, +} ccblasOperation_t; + +typedef enum { CCBLAS_DIAG_NON_UNIT = 0, CCBLAS_DIAG_UNIT = 1 } ccblasDiagType_t; + +#endif // CC_BLAS_STRUCT_API__ diff --git a/third_party/fwkacllib/inc/cce/cce.h b/third_party/fwkacllib/inc/cce/cce.h new file mode 100644 index 00000000..0cd9613a --- /dev/null +++ b/third_party/fwkacllib/inc/cce/cce.h @@ -0,0 +1,101 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef CCE_H__ +#define CCE_H__ + +#include +#include "cce_def.hpp" + +namespace cce { + +/** + * @ingroup cce + * @brief create cc handler + * @param [in|out] handle point of cc handler + * @return ccStatus_t + */ +ccStatus_t ccCreate(ccHandle_t *handle); + +/** + * @ingroup cce + * @brief destroy cc handler + * @param [in] *handle cc handler + * @return ccStatus_t + */ +ccStatus_t ccDestroy(ccHandle_t *handle); + +/** + * @ingroup cce + * @brief bind stream with specified cc handler + * @param [in] handle cc handler + * @param [in] streamId stream + * @return ccStatus_t + */ +ccStatus_t ccSetStream(ccHandle_t handle, rtStream_t streamId); + +/** + * @ingroup cce + * @brief get the stream from cc handler + * @param [in] handle cc handler + * @param [in|out] streamId point of stream + * @return ccStatus_t + */ +ccStatus_t ccGetStream(ccHandle_t handle, rtStream_t *streamId); + +/** + * @ingroup cce + * @brief get the stream from cc handler + * @param [in] dataTypeTransMode mode of data type transform + * @param [in] inputData input data point + * @param [in] inputDataSize input data size + * @param [in|out] outputData output data point + * @param [in] outputDataSize output data size + * @return ccStatus_t + */ +ccStatus_t ccTransDataType(ccDataTypeTransMode_t dataTypeTransMode, const void *inputData, uint32_t inputDataSize, + void *outputData, const uint32_t outputDataSize); +/** + * @ingroup cce + * @brief cce sys init func + */ +void cceSysInit(); + +/** + * @ingroup cce + * @brief cce Log Start up func + */ +void cceLogStartup(); + +/** + * @ingroup cce + * @brief cce Log Shut down func + */ +void cceLogShutdown(); + +/** + * @ingroup cce + * @brief set the profiling on or off + * @param [in] const unsigned char* target: The engine gets it from ENV. Don't need care about it. + * @param const char* job_ctx: identifies profiling job + * @param [in] uint32_t flag: value: 0, on ; 1, off. + * @return ccStatus_t value: 0, success; 1, fail. + */ +ccStatus_t CceProfilingConfig(const char *target, const char *job_ctx, uint32_t flag); + +}; // namespace cce + +#endif // CCE_H__ diff --git a/third_party/fwkacllib/inc/cce/cce_def.hpp b/third_party/fwkacllib/inc/cce/cce_def.hpp new file mode 100644 index 00000000..7b1a1b8a --- /dev/null +++ b/third_party/fwkacllib/inc/cce/cce_def.hpp @@ -0,0 +1,152 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef CCE_DEF_H__ +#define CCE_DEF_H__ + +#include "runtime/rt.h" + +namespace cce { + +/** + * @ingroup cce + * @brief memory configure for fusion + */ +typedef struct TagCceFusionMemCfg { + uint64_t memAddr; /**< memAddr */ + uint32_t memSize; /**< memSize */ + uint32_t addrChangeFlag; /**< op data addr change flag. value:0,valid;1,not valid */ + uint32_t poolFlag; /**< mempool flag : value:0,is valid; value: 1, not valid */ + TagCceFusionMemCfg() { + memAddr = 0; + memSize = 0; + addrChangeFlag = 0; + poolFlag = 0; + } +} CceFusionMemCfg_t; +/** + * @ingroup cce + * @brief return value + */ +typedef enum tagCcStatus { + CC_STATUS_SUCCESS = 0, /**< succ */ + CC_STATUS_NOT_INITIALIZED = 1, /**< not init */ + CC_STATUS_ALLOC_FAILED = 2, /**< alloc mem failed */ + CC_STATUS_BAD_PARAM = 3, /**< para check failed */ + CC_STATUS_INTERNAL_ERROR = 4, /**< internal error */ + CC_STATUS_KERNEL_ERROR = 5, /**< kernel error */ + CC_STATUS_RUNTIME_ERROR = 6, /**< runtime error */ + CC_STATUS_NOT_SUPPORTED = 7, /**< unsupport error */ + CC_STATUS_INVALID_VALUE = 7, /**< invalid value error for blas*/ + CC_STATUS_RESERVED /**< just for check */ +} ccStatus_t; + +/** + * @ingroup cce + * @brief original data type + */ +typedef enum tagCcDataType { + CC_DATA_FLOAT = 0, /**< float type */ + CC_DATA_HALF, /**< fp16 type */ + CC_DATA_INT8, /**< int8 type */ + CC_DATA_INT32, /**< int32 type */ + CC_DATA_UINT8, /**< uint8 type */ + CC_DATA_HALF_UINT16_PROPOSAL, /** +#include + +#define ERROR_CODE() __catch_error_code +#define ERROR_LINE_NO() __catch_error_line_no +#define ERROR_PROC() __catch_error_line_no = __LINE__; + +#define PROC \ + uint32_t __catch_error_code = 0x7FFFFFCC; \ + uint32_t __catch_error_line_no = 0xFFFFFFFF; \ + { +#define END_PROC \ + } \ + __tabErrorCode: +#define THROW(errcode) \ + { \ + __catch_error_code = (errcode); \ + ERROR_PROC(); \ + goto __tabErrorCode; \ + } +#define EXEC(func) \ + { \ + if (0 != (__catch_error_code = (func))) THROW(__catch_error_code) \ + } +#define EXEC_EX1(func, error_code) \ + { \ + if (0 != (func)) THROW(error_code) \ + } +#define EXEC_EX(func, succRet, error_code) \ + { \ + if (succRet != (__catch_error_code = (func))) THROW(error_code) \ + } +#define ASSERT_EXEC(func, succRet) \ + { \ + if (succRet != (__catch_error_code = (func))) /*GO_ASSERT_FALSE();*/ \ + THROW(__catch_error_code) \ + } \ + } +#define NEW_ERROR_EXEC(errcode, func, succRet) \ + { \ + if (succRet != (func)) { \ + THROW(errcode) \ + } \ + } +#define JUDGE(errcode, expr) \ + { \ + if (!(expr)) { \ + THROW(errcode) \ + } \ + } +#define ASSERT_JUDGE(errcode, expr) \ + { \ + if (!(expr)) { /*GO_ASSERT_FALSE();*/ \ + THROW(errcode) \ + } \ + } +#define JUDGE_FALSE(errcode, expr) \ + { \ + if (expr) { \ + THROW(errcode) \ + } \ + } +#define JUDGE_CONTINUE(expr) \ + { \ + if (expr) { \ + continue; \ + } \ + } +#define CATCH_ERROR(errcode) if (__catch_error_code == (errcode)) { // ERROR_LOG(); +#define CATCH_ALL_ERROR { +#define END_CATCH_ERROR } +#define FINAL \ + __tabFinal: +#define END_FINAL /*GO_ASSERT_FALSE()*/ ; +#define GOTO_FINAL() goto __tabFinal; +#endif // CATCH_HPP_ diff --git a/third_party/fwkacllib/inc/cce/compiler_stub.h b/third_party/fwkacllib/inc/cce/compiler_stub.h new file mode 100644 index 00000000..00ea467e --- /dev/null +++ b/third_party/fwkacllib/inc/cce/compiler_stub.h @@ -0,0 +1,36 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef COMPILER_STUB_H__ +#define COMPILER_STUB_H__ + +namespace cce { + +/** + * @ingroup cce + * @brief compiler stub init func + */ +bool compilerStubInit(); + +/** + * @ingroup cce + * @brief compiler stub free func + */ +bool compilerStubFree(); + +}; // namespace cce + +#endif // COMPILER_STUB_H__ diff --git a/third_party/fwkacllib/inc/cce/customize.h b/third_party/fwkacllib/inc/cce/customize.h new file mode 100644 index 00000000..7dd97af1 --- /dev/null +++ b/third_party/fwkacllib/inc/cce/customize.h @@ -0,0 +1,60 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef CC_CUSTOMIZE_API__ +#define CC_CUSTOMIZE_API__ + +#include + +#define CC_DEVICE_DIM_MAX 8 +typedef enum tagOpTensorFormat +{ + OP_TENSOR_FORMAT_NC1HWC0 = 0, + OP_TENSOR_FORMAT_ND, + OP_TENSOR_FORMAT_RESERVED, + +} opTensorFormat_t; + + +typedef enum tagOpDataType +{ + OP_DATA_FLOAT = 0, /**< float type */ + OP_DATA_HALF, /**< fp16 type */ + OP_DATA_INT8, /**< int8 type */ + OP_DATA_INT32, /**< int32 type */ + OP_DATA_UINT8, /**< uint8 type */ + OP_DATA_HALF_UINT16_PROPOSAL, /**dimCnt, xDesc->dimCnt) + * @param [in] num the number of outputs + * @param [in] beta scaling factors + * @param [in] yDescArr descriptors of output tensors + * @param [in|out] yArr output data array in device memory + * @return ccStatus_t + */ +ccStatus_t ccSplitForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + int32_t axis, uint32_t num, const void *beta, const ccTensorDescriptor_t yDescArr[], + void *yArr[]); + +/** + * @ingroup dnn + * @brief get the output dimensions info of split + * @param [in] xDesc descriptor of input tensor + * @param [in] axis the dimension along which to split. Must be in the range [-xDesc->dimCnt, xDesc->dimCnt) + * @param [in] num the number of outputs + * @param [in] sizes Optional, used to specify the sizes of each output tensor along split dim. The tensor x would + * be split evenly along split dim if sizes is NULL + * @param [in|out] nArr point to the first element of batch sizes + * @param [in|out] cArr point to the first element of channels + * @param [in|out] hArr point to the first element of heights of feature map + * @param [in|out] wArr point to the first element of widths of feature map + * @return ccStatus_t + */ +ccStatus_t ccGetSplitForwardOutputDim(const ccTensorDescriptor_t xDesc, int32_t axis, uint32_t num, + const uint32_t sizes[], uint32_t nArr[], uint32_t cArr[], uint32_t hArr[], + uint32_t wArr[]); + +/** + * @ingroup dnn + * @brief Get split output shape(s). + * @param [in] xDesc input tensor, support ND and NC1HWC0 + * @param [in] axis split axis, negtive axis will increased by dimCnt once time. + * @param [in] num splited nums. + * @param [in] sizes splited dim size on axis. if NULL was set, The input will be divided into num equally. + * @param [output] dimCnt splited dimCnt array. One to one correspondence with the splited output. + * @param [output] dim array of splited dim array. One to one correspondence with the splited output. + * @param [in| dimlen length of dim(Pass in the length of the entire space pointed to by dim, + not just the length of the dim array, because dim is a level 2 array + dimlen = lengthof dim[][], not just lengthof dim[]) + * @return ccStatus_t + */ +ccStatus_t ccGetSplitForwardOutputDim(const ccTensorDescriptor_t xDesc, int32_t axis, uint32_t num, + const uint32_t sizes[], int32_t *dimCnt, int32_t *dim[], int32_t dimLen); + +/** + * @ingroup dnn + * @brief create weight compress info + * @param [in|out] compressInfo point to CompressInfo + * @return ccStatus_t + */ +ccStatus_t ccCreateWeightCompressInfo(ccWeightCompressInfo_t **compressInfo); + +/** + * @ingroup dnn + * @brief destory weight compress info + * @param [in] *compressInfo point to CompressInfo + * @return ccStatus_t + */ +ccStatus_t ccDestroyWeightCompressInfo(ccWeightCompressInfo_t **compressInfo); + +/** + * @ingroup dnn + * @brief create compress table + * @param [in|out] compressTab point to weight compress table + * @return ccStatus_t + */ +ccStatus_t ccCreateWeightCompressTab(ccWeightCompressTab_t **compressTab); + +/** + * @ingroup dnn + * @brief destory compress table + * @param [in] compressTab point to weight compress table + * @return ccStatus_t + */ +ccStatus_t ccDestroyWeightCompressTab(ccWeightCompressTab_t **compressTab); + +/** + * @ingroup dnn + * @brief get fc compress info + * @param [in] xDesc descriptor of input tensor + * @param [in] wDesc descriptor of weight tensor + * @param [in] biasDesc descriptor of bias tensor + * @param [in] dataTypeTransmode mode of data type transform + * @param [in] weightCompressInfo compress info, compute based on tiling method + * @param [in|out] outputSize output data size in byte + * @param [in|out] infoTabSize compress info table + * @return ccStatus_t + */ +ccStatus_t ccGetCompressedFcWeightInfo(const ccTensorDescriptor_t xDesc, const ccFilterDescriptor_t wDesc, + const ccTensorDescriptor_t biasDesc, ccDataTypeTransMode_t dataTypeTransmode, + ccWeightCompressInfo_t *weightCompressInfo, uint32_t *outputSize, + uint32_t *infoTabSize); +/** + * @ingroup dnn + * @brief compress fc + * @param [in] wDesc descriptor of weight tensor + * @param [in] w filter data in device memory + * @param [in] weightCompressInfo compress info, compute based on tiling method + * @param [in] dataTypeTransmode mode of data type transform + * @param [in|out] y output data in device memory + * @param [in] ySize transformed data size in byte + * @param [in|out] yCompressedSize compressed output data size in byte + * @param [in|out] infoTab compressed info table + * @param [in] infoTabSize compressed info table size in byte + * @return ccStatus_t + */ +ccStatus_t ccCompressWeight(const ccFilterDescriptor_t wDesc, const void *w, + const ccWeightCompressInfo_t *weightCompressInfo, ccDataTypeTransMode_t dataTypeTransmode, + ccFilterDescriptor_t yDesc, void *y, uint32_t ySize, uint32_t *yCompressedSize, + void *infoTab, uint32_t infoTabSize); + +/** + * @ingroup dnn + * @brief restore compressed fc data + * @param [in] x input data in device memory + * @param [in] xSizeInBytes input compressed weight data size in byte + * @param [in|out] y output data in device memory + * @param [in] ySizeInBytes output data size in byte + * @return ccStatus_t + */ +ccStatus_t ccRestoreCompressedWeight(const void *x, uint32_t xSizeInBytes, void *y, uint32_t ySizeInBytes, + rtMemcpyKind_t kind); + +/** + * @ingroup dnn + * @brief create quantize parameters struct + * @param [in|out] quantizeInfo descriptor of quantize parameters + * @return ccStatus_t + */ +ccStatus_t ccCreateQuantizeInfoTab(ccQuantizeDescriptor_t *quantizeInfo); + +/** + * @ingroup dnn + * @brief destroy quantize parameters struct + * @param [in] quantizeInfo descriptor of quantize parameters + * @return ccStatus_t + */ +ccStatus_t ccDestoryQuantizeInfoTab(ccQuantizeDescriptor_t *quantizeInfo); + +/** + * @ingroup dnn + * @brief set quantize parameters + * @param [in] quantizeInfo descriptor of quantize parameters + * @param [in] scaleValMode enmu type for quantize scale value type (normal or sqrt) + * @param [in] scale quantize scale value + * @param [in] offset quantize offset(when quantize algorithm is half offset or full offset,this should be + * configed) + * @param [in] offsetPad padding value for load3d (only for half offset or full offset) + * @return ccStatus_t + */ +ccStatus_t ccSetQuantizeFactors(ccQuantizeDescriptor_t quantizeInfo, ccScaleValueMode_t scaleValMode, + const uint16_t *scale, const uint16_t *offset, const uint8_t *offsetPad); + +/** + * @ingroup dnn + * @brief set Requantize parameters + * @param [in] quantizeInfo descriptor of quantize parameters + * @param [in] scaleValMode enmu type for requantize scale value type (normal or sqrt) + * @param [in] scale quantize scale value + * @param [in] offset quantize offset(when quantize algorithm is half offset or full offset,this should be + * configed) + * @param [in] offsetw offset for filter (only config for full offset quantize) + * @return ccStatus_t + */ +ccStatus_t ccSetReQuantizeFactors(ccQuantizeDescriptor_t quantizeInfo, ccScaleValueMode_t scaleValMode, + const uint16_t *scaleRq, const uint16_t *nextLayerOffset, const int32_t *offsetw); + +/** + * @ingroup dnn + * @brief set Dequantize parameters + * @param [in] quantizeInfo descriptor of quantize parameters + * @param [in] scaleValMode enmu type for dequantize scale value type (normal or sqrt) + * @param [in] scaleDq quantize scale value + * @param [in] offsetw offset for filter (only config for full offset quantize) + * @return ccStatus_t + */ +ccStatus_t ccSetDeQuantizeFactors(ccQuantizeDescriptor_t quantizeInfo, ccScaleValueMode_t scaleValMode, + const uint16_t *scaleDq, const int32_t *offsetw); + +/** + * @ingroup dnn + * @brief set convolution desciptor's quantize parameters + * @param [in] convDesc convolution descriptor + * @param [in] quantizeInfo descriptor of quantize parameters + * @return ccStatus_t + */ +ccStatus_t ccSetConvolutionQuantizeInfo(ccConvolutionDescriptor_t convDesc, const ccQuantizeDescriptor_t QuantizeInfo); + +/** + * @ingroup dnn + * @brief set convolution desciptor's all offset quantize parameters + * @param [in] convDesc convolution descriptor + * @param [in] offsetw descriptor of quantize parameters + * @param [in] scaleReq descriptor of quantize parameters + * @param [in] offset_d_next descriptor of quantize parameters + * @return ccStatus_t + */ +ccStatus_t ccSetAllOffsetQuantizeFactors(ccQuantizeDescriptor_t quantizeInfo, const uint8_t *offsetW, + const uint8_t *offsetD, const uint16_t *scaleReq, const uint16_t *offsetDNext); + +/** + * @ingroup dnn + * @brief set full connection desciptor's quantize parameters + * @param [in] fcDesc full connection descriptor + * @param [in] quantizeInfo descriptor of quantize parameters + * @return ccStatus_t + */ +ccStatus_t ccSetFullConnectionQuantizeInfo(ccFullConnectionDescriptor_t fcDesc, + const ccQuantizeDescriptor_t QuantizeInfo); + +/** + * @ingroup dnn + * @brief set pooling desciptor's quantize parameters + * @param [in] poolingDesc pooling descriptor + * @param [in] quantizeInfo descriptor of quantize parameters + * @return ccStatus_t + */ +ccStatus_t ccSetPoolingQuantizeInfo(ccPoolingDescriptor_t poolingDesc, const ccQuantizeDescriptor_t QuantizeInfo); + +/** + * @ingroup dnn + * @brief set full connection desciptor's info table + * @param [in] fcDesc full connection descriptor + * @param [in] infoTabSize table size + * @param [in] infoTab pointer to info table + * @return ccStatus_t + */ +ccStatus_t ccSetFullConnectionDescriptor(ccFullConnectionDescriptor_t fcDesc, uint32_t infoTabSize, const void *infoTab, + ccFullConnectFwdAlgo_t algo = CC_FULLCONNECT_FWD_ALGO_HALF); + +/** + * @ingroup dnn + * @brief set full connection desciptor's relu flag + * @param [in] fcDesc full connection descriptor + * @param [in] opType operation type for append at convolution operation + * @param [in] opDesc operation descritpor for the opType + * @return ccStatus_t + */ +ccStatus_t ccFullConnectionAppendOp(ccFullConnectionDescriptor_t fcDesc, tagCcOpType opType, const void *opDesc); + +/** + * @ingroup dnn + * @brief check aipp basic info + * @param [in] inputFormat format of input image + * @param [in] loadStartPosH vertical start position in source image + * @param [in] loadStartPosW horizontal start position in source image + * @param [in] srcImageSizeH vertical size of source image + * @param [in] srcImageSizeW horizontal size of source image + * @param [in] cpaddingValue C direction padding value + * @param [in] cscSwitch csc enable or not + * @param [in] rbuvSwapSwitch swap R/U and B/V position of the image + * @param [in] axSwapSwitch swap RGBA->ARGB, YUVA->AYUV + * @param [in] singleLineMode when set this bit to 1, only read 1 line. Under this case, vertical size configuration is + * not useful. + * @return ccStatus_t + */ +ccStatus_t ccCheckConvolutionAippCommInfo(ccAippInputFormat_t inputFormat, int32_t loadStartPosW, int32_t loadStartPosH, + int32_t srcImageSizeW, int32_t srcImageSizeH, float cpaddingValue, + bool cscSwitch, bool rbuvSwapSwitch, bool axSwapSwitch, bool singleLineMode); + +/** + * @ingroup dnn + * @brief check aipp dtc info + * @param [in] dtcPixelMeanChnx Mean value for YUV or RGB data channel x + * @param [in] dtcPixelMinChnx Min value for YUV or RGB data channel x + * @param [in] dtcPixelVarReciChnx Reciprocal of variance or (max-min) for YUV or RGB data channel x + * @return ccStatus_t + */ +ccStatus_t ccCheckConvolutionAippDtcInfo(int32_t dtcPixelMeanChn0, int32_t dtcPixelMeanChn1, int32_t dtcPixelMeanChn2, + float dtcPixelMinChn0, float dtcPixelMinChn1, float dtcPixelMinChn2, + float dtcPixelVarReciChn0, float dtcPixelVarReciChn1, + float dtcPixelVarReciChn2); + +/** + * @ingroup dnn + * @brief check aipp pad info + * @param [in] paddingMode padding mode + * @param [in] leftPaddingSize left hblank/padding size + * @param [in] rightPaddingSize right hblank/padding size + * @param [in] topPaddingSize top padding size + * @param [in] bottomPaddingSize bottom padding size + * @return ccStatus_t + */ +ccStatus_t ccCheckConvolutionAippPadInfo(ccAippPaddingMode_t paddingMode, int32_t leftPaddingSize, + int32_t rightPaddingSize, int32_t topPaddingSize, int32_t bottomPaddingSize); + +/** + * @ingroup dnn + * @brief check aipp csc info + * @param [in] cscMatrixRmCn 3x3 CSC matrix for YUV to RGB or RGB to YUV, element of row m and column n + * @param [in] cscOutputBiasm output Bias for RGB to YUV, element of row m + * @param [in] cscInputBiasm input Bias for YUV to RGB, element of row m + * @return ccStatus_t + */ +ccStatus_t ccCheckConvolutionAippCscInfo(int32_t cscMatrixR0C0, int32_t cscMatrixR0C1, int32_t cscMatrixR0C2, + int32_t cscMatrixR1C0, int32_t cscMatrixR1C1, int32_t cscMatrixR1C2, + int32_t cscMatrixR2C0, int32_t cscMatrixR2C1, int32_t cscMatrixR2C2, + int32_t cscOutputBias0, int32_t cscOutputBias1, int32_t cscOutputBias2, + int32_t cscInputBias0, int32_t cscInputBias1, int32_t cscInputBias2); + +/** + * @ingroup dnn + * @brief check aipp scf info + * @param [in] scfSwitch scaling enable or not + * @param [in] scfInputW input width of scaling + * @param [in] scfInputH input height of scaling + * @param [in] scfOutputW output width of scaling + * @param [in] scfOutputH output height of scaling + * @return ccStatus_t + */ +ccStatus_t ccCheckConvolutionAippScfInfo(bool scfSwitch, int32_t scfInputW, int32_t scfInputH, int32_t scfOutputW, + int32_t scfOutputH); + +/** + * @ingroup dnn + * @brief check aipp param + * @param [in] convDesc descriptor of conv operator + * @param [in] xDesc input tensor info + * @param [in] yDesc output tensor info + * @return ccStatus_t + */ +ccStatus_t ccCheckConvFwdAippParam(const ccConvolutionDescriptor_t convDesc, const ccTensorDescriptor_t xDesc, + const ccTensorDescriptor_t yDesc); + +/** + * @ingroup dnn + * @brief init aipp basic info + * @param [in|out] convDesc descriptor of conv operator + * @param [in] inputFormat format of input image + * @param [in] loadStartPosH vertical start position in source image + * @param [in] loadStartPosW horizontal start position in source image + * @param [in] srcImageSizeH vertical size of source image + * @param [in] srcImageSizeW horizontal size of source image + * @param [in] cpaddingValue C direction padding value + * @param [in] cscSwitch csc enable or not + * @param [in] rbuvSwapSwitch swap R/U and B/V position of the image + * @param [in] axSwapSwitch swap RGBA->ARGB, YUVA->AYUV + * @param [in] singleLineMode when set this bit to 1, only read 1 line. Under this case, vertical size configuration is + * not useful. + * @return ccStatus_t + */ +ccStatus_t ccSetConvolutionAippCommInfo(ccConvolutionDescriptor_t convDesc, ccAippInputFormat_t inputFormat, + int32_t loadStartPosW, int32_t loadStartPosH, int32_t srcImageSizeW, + int32_t srcImageSizeH, float cpaddingValue, bool cscSwitch, bool rbuvSwapSwitch, + bool axSwapSwitch, bool singleLineMode); +/** + * @ingroup dnn + * @brief init aipp dtc info + * @param [in|out] convDesc descriptor of conv operator + * @param [in] dtcPixelMeanChnx Mean value for YUV or RGB data channel x + * @param [in] dtcPixelMinChnx Min value for YUV or RGB data channel x + * @param [in] dtcPixelVarReciChnx Reciprocal of variance or (max-min) for YUV or RGB data channel x + * @return ccStatus_t + */ +ccStatus_t ccSetConvolutionAippDtcInfo(ccConvolutionDescriptor_t convDesc, int32_t dtcPixelMeanChn0, + int32_t dtcPixelMeanChn1, int32_t dtcPixelMeanChn2, float dtcPixelMinChn0, + float dtcPixelMinChn1, float dtcPixelMinChn2, float dtcPixelVarReciChn0, + float dtcPixelVarReciChn1, float dtcPixelVarReciChn2); +/** + * @ingroup dnn + * @brief init aipp pad info + * @param [in|out] convDesc descriptor of conv operator + * @param [in] paddingMode padding mode + * @param [in] leftPaddingSize left hblank/padding size + * @param [in] rightPaddingSize right hblank/padding size + * @param [in] topPaddingSize top padding size + * @param [in] bottomPaddingSize bottom padding size + * @return ccStatus_t + */ +ccStatus_t ccSetConvolutionAippPadInfo(ccConvolutionDescriptor_t convDesc, ccAippPaddingMode_t paddingMode, + int32_t leftPaddingSize, int32_t rightPaddingSize, int32_t topPaddingSize, + int32_t bottomPaddingSize); + +/** + * @ingroup dnn + * @brief init aipp csc info + * @param [in|out] convDesc descriptor of conv operator + * @param [in] cscMatrixRmCn 3x3 CSC matrix for YUV to RGB or RGB to YUV, element of row m and column n + * @param [in] cscOutputBiasm output Bias for RGB to YUV, element of row m + * @param [in] cscInputBiasm input Bias for YUV to RGB, element of row m + * @return ccStatus_t + */ +ccStatus_t ccSetConvolutionAippCscInfo(ccConvolutionDescriptor_t convDesc, int32_t cscMatrixR0C0, int32_t cscMatrixR0C1, + int32_t cscMatrixR0C2, int32_t cscMatrixR1C0, int32_t cscMatrixR1C1, + int32_t cscMatrixR1C2, int32_t cscMatrixR2C0, int32_t cscMatrixR2C1, + int32_t cscMatrixR2C2, int32_t cscOutputBias0, int32_t cscOutputBias1, + int32_t cscOutputBias2, int32_t cscInputBias0, int32_t cscInputBias1, + int32_t cscInputBias2); + +/** + * @ingroup dnn + * @brief init aipp scf info + * @param [in|out] convDesc descriptor of conv operator + * @param [in] scfSwitch scaling enable or not + * @param [in] scfInputW input width of scaling + * @param [in] scfInputH input height of scaling + * @param [in] scfOutputW output width of scaling + * @param [in] scfOutputH output height of scaling + * @return ccStatus_t + */ +ccStatus_t ccSetConvolutionAippScfInfo(ccConvolutionDescriptor_t convDesc, bool scfSwitch, int32_t scfInputW, + int32_t scfInputH, int32_t scfOutputW, int32_t scfOutputH); + +/** + * @ingroup dnn + * @brief set dynamic aipp parameter address and enflag info + * @param [in|out] convDesc descriptor of conv operator + * @param [in] dyncParaAddr aipp parameter address + * @param [in] dyncAippFlag flag to show whether to use dynamic aipp + * @return ccStatus_t + */ +ccStatus_t ccSetConvolutionAippDyncParaAddr(ccConvolutionDescriptor_t convDesc, const void *dyncParaAddr, + bool dyncAippFlag, bool rotationFlag = false); + +/** + * @ingroup dnn + * @brief check dynamic aipp parameter + * @param [in] dyncParaAddr aipp parameter address + * @param [in] dataLength parameter lenght + * @param [in] convolutionDimW convDimW + * @param [in] convolutionDimH convDimH + * @return ccStatus_t + */ +ccStatus_t ccCheckDynamicAippParam(const void *dynamicParamAddr, uint32_t dataLength, int64_t convolutionDimW, + int64_t convolutionDimH); + +/*** @ingroup dnn + * @brief trans mean and var + * @param [in|out] mean' = bnScale/sqrt(var) + * @param [in|out] var' = -bnScale * mean / sqrt(var) + bnBias + * @return ccStatus_t + */ + +ccStatus_t ccTransBatchnormMeanAndVar(void *mean, void *var, const ccTensorDescriptor_t bnScaleBiasMeanVarDesc, + const void *alpha, const void *beta, void *bnScale, void *bnBias, double epsilon); + +/** + * @ingroup dnn + * @brief init deconvolution adj or targetShape info. + * @param [in] convDesc conv descriptor. + * @param [in] adjH, adjust H output. + * @param [in] adjW, adjust W output. + * @param [in] targetShape, values of output shape, if this pointer was set, ignore adj. + * @return ccStatus_t + */ +ccStatus_t ccSetDeconvolutionOutShapeInfo(ccConvolutionDescriptor_t convDesc, uint32_t adjSize, const uint32_t *adj, + uint32_t targetShapeSize, const uint32_t *targetShape); + +/** + * @ingroup dnn + * @brief gather elements according to the indices. + * @param [in] alpha reserved. + * @param [in] xDesc description of the tensor from which to gather elements. + * @param [in] x data point of the tensor from which to gather elements. + * @param [in] indicesDesc description of the tensor of indices. + * @param [in] indices data point of the tensor of indices. + * @param [in] beta reserved. + * @param [in] outputDesc description of the output tensor. + * @param [output] output data point of the output tensor. + * @return ccStatus_t + */ +ccStatus_t ccGatherNdForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t indicesDesc, const void *indices, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief get output shape of gather_nd. + * @param [in] xDesc description of the tensor from which to gather elements. + * @param [in] indicesDesc description of the tensor of indices. + * @param [output] n dim-size of n-dim. + * @param [output] c dim-size of c-dim. + * @param [output] h dim-size of h-dim. + * @param [output] w dim-size of w-dim. + * @param [output] realDimCnt real dim. + * @return ccStatus_t + */ +ccStatus_t ccGetGatherNdOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t indicesDesc, int32_t *n, + int32_t *c, int32_t *h, int32_t *w, int32_t *realDimCnt); +/** + * @ingroup dnn + * @brief get output shape of realdiv. + * @param [in] xDesc description of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [output] dimCnt dim nums. + * @param [output] dim dim size. + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetGatherNdOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t indicesDesc, + int32_t *dimCnt, int32_t *dim, int32_t dimLen); +/** + * @ingroup dnn + * @brief tile tensor by multiples. + * @param [in] alpha reserved. + * @param [in] xDesc description of the tensor which to be tiled. + * @param [in] x data point of the tensor which to be tiled. + * @param [in] multiples tile coefficient of each dim. + * @param [in] beta reserved. + * @param [in] outputDesc description of the output tensor. + * @param [output] output data point of the output tensor. + * @return ccStatus_t + */ +ccStatus_t ccTileForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccIntArray_t *multiples, const void *beta, const ccTensorDescriptor_t outputDesc, + void *output); + +/** + * @ingroup dnn + * @brief get output shape of tile. + * @param [in] xDesc description of the dividend tensor. + * @param [in] multiples multiples of each dim. + * @param [in|out] dimCnt [point to the output dimCnt] + * @param [in|out] dim [arrays to save dims] + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetTileOutputDim(const ccTensorDescriptor_t xDesc, const ccIntArray_t *multiples, int32_t *dimCnt, + int32_t dim[], int32_t dimLen); + +/** + * @ingroup dnn + * @brief get output shape of tile. + * @param [in] xDesc description of the dividend tensor. + * @param [in] multiples multiples of each dim. + * @param [output] n dim-size of n-dim. + * @param [output] c dim-size of c-dim. + * @param [output] h dim-size of h-dim. + * @param [output] w dim-size of w-dim. + * @param [output] realDimCnt real dim. + * @return ccStatus_t + */ +ccStatus_t ccGetTileOutputDim(const ccTensorDescriptor_t xDesc, + // const ccIntArrayDescriptor_t multiples, + const ccIntArray_t *multiples, int32_t *n, int32_t *c, int32_t *h, int32_t *w, + int32_t *realDimCnt); +/** + * @ingroup dnn + * @brief get output shape of realdiv. + * @param [in] xDesc description of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [output] dimCnt dim nums. + * @param [output] dim dim size. + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetRealdivOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, + int32_t *dim, int32_t dimLen); + +/** + * @ingroup dnn + * @brief realdiv between two tensors. + * @param [in] alpha reserved. + * @param [in] xDesc description of the dividend tensor. + * @param [in] x data point of the dividend tensor. + * @param [in] yDesc description of the divisor tensor. + * @param [in] y data point of the divisor tensor. + * @param [in] beta reserved. + * @param [in] outputDesc description of the output tensor. + * @param [output] output data point of the output tensor. + * @return ccStatus_t + */ +ccStatus_t ccRealdivForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t yDesc, const void *y, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief get output shape of realdiv. + * @param [in] xDesc description of the dividend tensor. + * @param [in] yDesc description of the divisor tensor. + * @param [output] n dim-size of n-dim. + * @param [output] c dim-size of c-dim. + * @param [output] h dim-size of h-dim. + * @param [output] w dim-size of w-dim. + * @param [output] realDimCnt real dim. + * @return ccStatus_t + */ +ccStatus_t ccGetRealdivOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *n, + int32_t *c, int32_t *h, int32_t *w, int32_t *realDimCnt); + +/** + * @ingroup dnn + * @brief realdiv between two tensors. + * @param [in] alpha reserved. + * @param [in] xDesc description of the left operator tensor. + * @param [in] x data point of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [in] y data point of the right operator tensor. + * @param [in] beta reserved. + * @param [in] outputDesc description of the output tensor. + * @param [output] output data point of the output tensor. + * @return ccStatus_t + */ +ccStatus_t ccFloordivForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t yDesc, const void *y, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief get output shape of realdiv. + * @param [in] xDesc description of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [output] realDimCnt real dim. + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetFloordivOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, + int32_t *dim, int32_t dimLen); + +/** + * @ingroup dnn + * @brief realdiv between two tensors. + * @param [in] alpha reserved. + * @param [in] xDesc description of the left operator tensor. + * @param [in] x data point of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [in] y data point of the right operator tensor. + * @param [in] beta reserved. + * @param [in] outputDesc description of the output tensor. + * @param [output] output data point of the output tensor. + * @return ccStatus_t + */ +ccStatus_t ccGreaterForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t yDesc, const void *y, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief get output shape of realdiv. + * @param [in] xDesc description of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [output] dimCnt dim nums. + * @param [output] dim dim size. + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetGreaterOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, + int32_t *dim, int32_t dimLen); + +/** + * @ingroup dnn + * @brief realdiv between two tensors. + * @param [in] alpha reserved. + * @param [in] xDesc description of the left operator tensor. + * @param [in] x data point of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [in] y data point of the right operator tensor. + * @param [in] beta reserved. + * @param [in] outputDesc description of the output tensor. + * @param [output] output data point of the output tensor. + * @return ccStatus_t + */ +ccStatus_t ccLessForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t yDesc, const void *y, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief get output shape of realdiv. + * @param [in] xDesc description of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [output] dimCnt dim nums. + * @param [output] dim dim size. + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetLessOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, + int32_t *dim, int32_t dimLen); + +/** + * @ingroup dnn + * @brief get output shape of LogicalOr. + * @param [in] xDesc description of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [output] dimCnt dim nums. + * @param [output] dim dim size. + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetLogicalOrOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, + int32_t *dim, int32_t dimLen); + +/** + * @ingroup dnn + * @brief get output shape of LogicalXor. + * @param [in] xDesc description of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [output] dimCnt dim nums. + * @param [output] dim dim size. + * @param [in] dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetLogicalXorOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, + int32_t *dim, int32_t dimLen); + +/** + * @ingroup dnn + * @brief sqrt forward: + * data type only support bool + * data format only support ND + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccLogicalNotForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const void *beta, const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief equal between two tensors. + * @param [in] alpha reserved. + * @param [in] xDesc description of the left operator tensor. + * @param [in] x data point of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [in] y data point of the right operator tensor. + * @param [in] beta reserved. + * @param [in] outputDesc description of the output tensor. + * @param [output] output data point of the output tensor. + * @return ccStatus_t + */ + +ccStatus_t ccEqualForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t yDesc, const void *y, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief dump data during inference, only for eng ver. + * @param [in] handle cce handle + * @return ccStatus_t + */ +ccStatus_t ccDataDumpForward(ccHandle_t handle, const void *buffer, const uint64_t bufLen, const uint32_t taskIndex); + +/** + * @ingroup dnn + * @brief logicaland between two tensors. + * @param [in] alpha reserved. + * @param [in] xDesc description of the left operator tensor. + * @param [in] x data point of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [in] y data point of the right operator tensor. + * @param [in] beta reserved. + * @param [in] outputDesc description of the output tensor. + * @param [output] output data point of the output tensor. + * @return ccStatus_t + */ +ccStatus_t ccLogicalAndForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t yDesc, const void *y, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief logical or between two tensors. + * @param [in] alpha reserved. + * @param [in] xDesc description of the left operator tensor. + * @param [in] x data point of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [in] y data point of the right operator tensor. + * @param [in] beta reserved. + * @param [in] outputDesc description of the output tensor. + * @param [output] output data point of the output tensor. + * @return ccStatus_t + */ +ccStatus_t ccLogicalOrForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t yDesc, const void *y, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); +/** + * @ingroup dnn + * @brief logical Xor between two tensors(x ^ y = (x | y) & ~(x & y). + * @param [in] alpha reserved. + * @param [in] xDesc description of the left operator tensor. + * @param [in] x data point of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [in] y data point of the right operator tensor. + * @param [in] beta reserved. + * @param [in] outputDesc description of the output tensor. + * @param [output] output data point of the output tensor. + * @return ccStatus_t + */ +ccStatus_t ccLogicalXorForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t yDesc, const void *y, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief get output shape of equal. + * @param [in] xDesc description of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [output] dimCnt dim nums. + * @param [output] dim dim size. + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetEqualOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, + int32_t *dim, int32_t dimLen); +/** + * @ingroup dnn + * @brief get output shape of logicaland. + * @param [in] xDesc description of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [output] dimCnt dim nums. + * @param [output] dim dim size. + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetLogicalAndOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, + int32_t *dim, int32_t dimLen); +/** + * @ingroup dnn + * @brief realdiv between two tensors. + * @param [in] alpha reserved. + * @param [in] xDesc description of the left operator tensor. + * @param [in] x data point of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [in] y data point of the right operator tensor. + * @param [in] beta reserved. + * @param [in] outputDesc description of the output tensor. + * @param [output] output data point of the output tensor. + * @return ccStatus_t + */ +ccStatus_t ccFloormodForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t yDesc, const void *y, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief get output shape of realdiv. + * @param [in] xDesc description of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [output] dimCnt dim nums. + * @param [output] dim dim size. + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetFloormodOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, + int32_t *dim, int32_t dimLen); + +/** + * @ingroup dnn + * @brief compare between two tensors. + * @param [in] alpha reserved. + * @param [in] xDesc description of the left operator tensor. + * @param [in] x data point of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [in] y data point of the right operator tensor. + * @param [in] beta reserved. + * @param [in] outputDesc description of the output tensor. + * @param [output] output data point of the output tensor. + * @return ccStatus_t + */ +ccStatus_t ccCompareForward(ccHandle_t handle, ccCompareType_t compareType, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const ccTensorDescriptor_t yDesc, + const void *y, const void *beta, const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief get output shape of realdiv. + * @param [in] xDesc description of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [output] dimCnt dim nums. + * @param [output] dim dim size. + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetCompareOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, + int32_t *dim, int32_t dimLen); + +/** + * @ingroup dnn + * @brief create descriptor of FillParam + * @param [in|out] fillParamDesc point to descriptor of fill param + * @return ccStatus_t + */ +ccStatus_t ccCreateFillParamDescriptor(ccFillParamDescriptor_t *fillParamDesc); + +/** + * @ingroup dnn + * @brief destroy descriptor of FillParam + * @param [in] *fillParamDesc point to descriptor of fill param + * @return ccStatus_t + */ +ccStatus_t ccDestroyFillParamDescriptor(ccFillParamDescriptor_t *fillParamDesc); + +/** + * @ingroup dnn + * @brief get output shape of broadcat operations. + * @param [in] inputNum input number of the operation tensors. + * @param [in] xDesc[] description of the input operation tensors list. + * @param [output] dimCnt dim-size of output tensor. + * @param [output] dim dim of output tensor. + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetMultiNdBroadcastOpOutputDim(const int32_t inputNum, const ccTensorDescriptor_t xDesc[], int32_t *dimCnt, + int32_t *dim, int32_t dimLen); + +/** + * @ingroup dnn + * @brief get output shape of maximultitensor. + * @param [in] inputNum the num of input operator tensors. + * @param [in] xDesc[] description of the input operator tensors list. + * @param [output] dimCnt dim count of output tensor. + * @param [output] dim array of output tensor. + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetMaxMultitensorOutputDim(const int32_t inputNum, const ccTensorDescriptor_t xDesc[], int32_t *dimCnt, + int32_t *dim, int32_t dimLen); + +/** + * @ingroup dnn + * @brief get output shape of minmultitensor. + * @param [in] inputNum the num of input operator tensors. + * @param [in] xDesc[] description of the input operator tensors list. + * @param [output] dimCnt dim count of output tensor. + * @param [output] dim array of output tensor. + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetMinMultitensorOutputDim(const int32_t inputNum, const ccTensorDescriptor_t xDesc[], int32_t *dimCnt, + int32_t *dim, int32_t dimLen); + +/** + * @ingroup dnn + * @brief MaxMultitensor forward: + * data type only support float float16 and int32 + * data format only support ND + * @param [in] handle cce handle + * @param [in] inputNum input tensor number + * @param [in] alpha common scale factor + * @param [in] xDesc[] descriptor of input tensors list + * @param [in] x[] input data in device memory list + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccMaxMultitensorForward(const ccHandle_t handle, const int32_t inputNum, const void *alpha, + const ccTensorDescriptor_t xDesc[], const void *x[], const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief MinMultitensor forward: + * data type only support float float16 and int32 + * data format only support ND + * @param [in] handle cce handle + * @param [in] inputNum input tensor number + * @param [in] alpha common scale factor + * @param [in] xDesc[] descriptor of input data list + * @param [in] x[] input data in device memory list + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccMinMultitensorForward(const ccHandle_t handle, const int32_t inputNum, const void *alpha, + const ccTensorDescriptor_t xDesc[], const void *x[], const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief create descriptor of StridedSlice + * @param [in|out] stridedSliceDesc point to descriptor of StridedSlice param + * @return ccStatus_t + */ +ccStatus_t ccCreateStridedSliceDescriptor(ccStridedSliceDescriptor_t *stridedSliceDesc); + +/** + * @ingroup dnn + * @brief destroy descriptor of StridedSlice + * @param [in] *stridedSliceDesc point to descriptor of StridedSlice param + * @return ccStatus_t + */ +ccStatus_t ccDestroyStridedSliceDescriptor(ccStridedSliceDescriptor_t *stridedSliceDesc); + +/** + * @ingroup dnn + * @brief init stridedSlice descriptor_t. + * @param [out] stridedSliceDesc struct of stridedslice param + * @param [in] dimCnt dimension of the input tensor + * @param [in] begin slice begin(include) + * @param [in] end slice end index(not include) + * @param [in] strides slice stride + * @return ccStatus_t + */ +ccStatus_t ccSetStridedSliceDescriptor(ccStridedSliceDescriptor_t stridedSliceDesc, int32_t dimCnt, int32_t begin[], + int32_t end[], int32_t strides[]); + +/** + * @ingroup dnn + * @brief create descriptor of StridedSlice + * @param [in|out] stridedSliceDesc point to descriptor of StridedSlice attr + * @return ccStatus_t + */ +ccStatus_t ccCreateStridedSliceAttrsDescriptor(ccStridedSliceAttrsDescriptor_t *attrDesc); + +/** + * @ingroup dnn + * @brief destroy descriptor of StridedSlice + * @param [in] *stridedSliceDesc point to descriptor of StridedSlice attr + * @return ccStatus_t + */ +ccStatus_t ccDestroyStridedSliceAttrsDescriptor(ccStridedSliceAttrsDescriptor_t *attrDesc); + +/** + * @ingroup dnn + * @brief init stridedSlice mask attrs desescriptor. + * @param [out] attrDesc struct of stridedslice mask attrs + * @param [in] beginMask begin mask + * @param [in] endMask end mask + * @param [in] ellipsisMask ellipsis mask + * @param [in] newAxisMask new axis mask + * @param [in] shrinkAxisMask shrink axis mask + * @return ccStatus_t + */ +ccStatus_t ccSetStridedSliceAttrsDescriptor(ccStridedSliceAttrsDescriptor_t attrDesc, int32_t beginMask, + int32_t endMask, int32_t ellipsisMask, int32_t newAxisMask, + int32_t shrinkAxisMask); + +/** + * @ingroup dnn + * @brief Extracts a strided slice of a tensor. + * @param [in] xDesc descriptor of input data + * @param [in] stridedSliceDesc specifies the begin, end, strides of slice + * @param [in] attrDesc reserve for optional attributes. + * @param [out] n point to n size + * @param [out] c point to c size + * @param [out] h point to h size + * @param [out] w point to w size + * @return ccStatus_t + */ +ccStatus_t ccGetStridedSliceOutputDim(const ccTensorDescriptor_t xDesc, + const ccStridedSliceDescriptor_t stridedSliceDesc, + const ccStridedSliceAttrsDescriptor_t attrDesc, int32_t *n, int32_t *c, + int32_t *h, int32_t *w, int32_t *realDimCnt); + +/** + * @ingroup dnn + * @brief Extracts a strided slice of a tensor. + * @param [in] handle cce handle + * @param [in] stridedSliceDesc specifies the begin, end, strides of slice + * @param [in] attrDesc reserve for optional attributes. + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] beta common scale factor + * @param [in] yDesc descriptor of output data + * @param [in|out] y output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccStridedSliceForward(ccHandle_t handle, const ccStridedSliceDescriptor_t stridedSliceDesc, + const ccStridedSliceAttrsDescriptor_t attrDesc, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t yDesc, void *y); + +/** + * @ + * @brief get out put descrition of slice tensor. + * @param [in] xDesc descriptor of input data + * @param [in] begin begin position of tensor + * @param [in] size size to slice + * @param [out] n point to n size + * @param [out] c point to c size + * @param [out] h point to h size + * @param [out] w point to w size + * @param [out] realDimCnt realdim count + * @return ccStatus_t + */ +ccStatus_t ccGetSliceOutputDim(const ccTensorDescriptor_t xDesc, const ccIntArray_t *begin, const ccIntArray_t *size, + int32_t *n, int32_t *c, int32_t *h, int32_t *w, int32_t *realDimCnt); + +/** + * @ingroup dnn + * @brief slice of a tensor. + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] begin begin position of tensor + * @param [in] size size to slice + * @param [in] beta common scale factor + * @param [in] yDesc descriptor of output data + * @param [in|out] y output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccSliceForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccIntArray_t *begin, const ccIntArray_t *size, const void *beta, + const ccTensorDescriptor_t yDesc, void *y); + +/** + * @ingroup dnn + * @brief gather forward computation + * @param [in] handle cce handle + * @param [in] paramsDesc descriptor of params tensor + * @param [in] params input data in device memory + * @param [in] indicesDesc descriptor of indices tensor + * @param [in] indices indices data in device memory + * @param [in] axis descriptor of roi tensor + * @param [in] alpha reserved + * @param [in] beta reserved + * @param [in] outputDesc descriptor of output tensor + * @param [out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccGatherForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t paramsDesc, + const void *params, const ccTensorDescriptor_t indicesDesc, const void *indices, + const int32_t axis, const void *beta, ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief gather output dim computation, for NC1HWC0 + * @param [in] paramsDesc descriptor of params tensor + * @param [in] indicesDesc descriptor of indices tensor + * @param [in] axis descriptor of roi tensor + * @param [out] n dim of n + * @param [out] c dim of c + * @param [out] h dim of h + * @param [out] w dim of w + * @param [out] realDimCnt real dim count + * @return ccStatus_t + */ +ccStatus_t ccGetGatherOutputDim(const ccTensorDescriptor_t paramsDesc, const ccTensorDescriptor_t indicesDesc, + int32_t axis, int32_t *n, int32_t *c, int32_t *h, int32_t *w, int32_t *realDimCnt); + +/** + * @ingroup dnn + * @brief gather output dim computation + * @param [in] paramsDesc descriptor of params tensor + * @param [in] indicesDesc descriptor of indices tensor + * @param [in] axis descriptor of roi tensor + * @param [out] dimCnt dimcnt of output + * @param [out] dim dim of output + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetGatherOutputDim(const ccTensorDescriptor_t paramsDesc, const ccTensorDescriptor_t indicesDesc, + int32_t axis, int32_t *dimCnt, int32_t dim[], int32_t dimLen); + +/** + * @ingroup dnn + * @brief exp forward computation + * @param [in] handle cce handle + * @param [in] expDesc descriptor of expParam + * @param [in] expParam a ternary array + * @param [in] alpha reserved parameter + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] beta reserved parameter + * @param [in] yDesc descriptor of output tensor + * @param [out] y output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccExpForward(ccHandle_t handle, const ccExpDescriptor_t expDesc, const void *expParam, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t yDesc, void *y); + +/** + * @ingroup dnn + * @brief expm1 forward: + * data type only support float float16 and double + * data format only support ND + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccExpm1Forward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const void *beta, const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief log1p forward: + * data type only support float float16 and double + * data format only support ND + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccLog1pForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const void *beta, const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief init descriptor for parameter of exp function + * @param [in|out] powDesc descriptor of tensor + * @param [in] dataType data type in device + * @param [in] paramCnt number of parameters + * @return ccStatus_t + */ +ccStatus_t ccSetExpDescriptor(ccExpDescriptor_t expDesc, ccDataType_t dataType, uint32_t paramCnt); + +/** + * @ingroup dnn + * @brief exp forward computation + * @param [in] handle cce handle + * @param [in] logDesc descriptor of logParam + * @param [in] logParam a ternary array + * @param [in] alpha reserved parameter + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] beta reserved parameter + * @param [in] yDesc descriptor of output tensor + * @param [in] y output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccLogForward(ccHandle_t handle, const ccLogDescriptor_t logDesc, const void *logParam, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t yDesc, void *y); + +/** + * @ingroup dnn + * @brief init descriptor for parameter of log function + * @param [in|out] logDesc descriptor of tensor + * @param [in] dataType data type in device + * @param [in] paramCnt number of parameters + * @return ccStatus_t + */ +ccStatus_t ccSetLogDescriptor(ccLogDescriptor_t logDesc, ccDataType_t dataType, uint32_t paramCnt); + +/** + * @ingroup dnn + * @brief pow forward computation + * @param [in] handle cce handle + * @param [in] powDesc descriptor of logParam + * @param [in] powParam a ternary array + * @param [in] alpha reserved parameter + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] beta reserved parameter + * @param [in] yDesc descriptor of input tensor + * @param [in] y input data in device memory + * @param [in] zDesc descriptor of output tensor + * @param [out] z output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccPowForward(ccHandle_t handle, const ccPowDescriptor_t powDesc, const void *powParam, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const ccTensorDescriptor_t yDesc, + const void *y, const void *beta, const ccTensorDescriptor_t zDesc, void *z); + +/** + * @brief init descriptor for parameter of pow function + * @param [in|out] powDesc descriptor of tensor + * @param [in] dataType data type in device + * @param [in] paramCnt number of parameters + * @return ccStatus_t + */ +ccStatus_t ccSetPowDescriptor(ccPowDescriptor_t powDesc, ccDataType_t dataType, uint32_t paramCnt); + +/** + * @ingroup dnn + * @brief non max suppression forward. + * @param [in] handle cce handle + * @param [in] nonmaxParaDesc descriptor of para + * @param [in] nonmaxPara input para in host memory + * @param [in] maxoutputsizex input para in host memory + * @param [in] alpha common scale factor + * @param [in] boxesDesc descriptor of input data boxesDesc + * @param [in] boxes input data boxes in device memory + * @param [in] scoresDesc descriptor of input data boxesDesc + * @param [in] scores input data scores in device memory + * @param [in] workSpaceSizeInBytes workspace size + * @param [in] workSpace input workspace in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccNonMaxSuppressionForward(ccHandle_t handle, const ccNonMaxSuppressionDescriptor_t nonmaxParaDesc, + const void *nonmaxPara, const int *maxoutputsize, const void *alpha, + const ccTensorDescriptor_t boxesDesc, const void *boxes, + const ccTensorDescriptor_t scoresDesc, const void *scores, + const uint32_t workSpaceSizeInBytes, void *workSpace, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); +/** + * @brief init descriptor for parameter of NonMaxSuppression function + * @param [in|out] powDesc descriptor of tensor + * @param [in] dataType data type in device + * @param [in] paramCnt number of parameters + * @return ccStatus_t + */ +ccStatus_t ccSetNonMaxSuppressionDescriptor(ccNonMaxSuppressionDescriptor_t nonMaxSuppressionDesc, + ccDataType_t dataType, uint32_t paramCnt); + +/** + * @ingroup dnn + * @brief get the output dimension info of resizeBilinear op. + * @param [in] xDesc descriptor of input data + * @param [in] resizeBilinearDesc descriptor of resize_bilinear operator + * @param [out] dimCnt + * @param [out] dim[] dim of output + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetResizeBilinearOutputDim(const ccTensorDescriptor_t xDesc, + const ccResizeBilinearDescriptor_t resizeBilinearDesc, int32_t *dimCnt, + int32_t dim[], int32_t dimLen); + +/** + * @ingroup dnn + * @brief get the output dimension info of interp op. + * @param [in] xDesc descriptor of input data + * @param [in] resizeBilinearDesc descriptor of resize_bilinear operator + * @param [out] dimCnt + * @param [out] dim[] dim of output + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetInterpOutputDim(const ccTensorDescriptor_t xDesc, const ccResizeBilinearDescriptor_t resizeBilinearDesc, + int32_t *dimCnt, int32_t dim[], int32_t dimLen); +/** + * @ingroup dnn + * @brief resize bilinear forward for t network. + * @param [in] handle cce handle + * @param [in] resizeBilinearDesc descriptor of resize_bilinear operator + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] beta common scale factor + * @param [in] yDesc descriptor of output data + * @param [in|out] y output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccResizeBilinearForward(ccHandle_t handle, const ccResizeBilinearDescriptor_t resizeBilinearDesc, + const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief resize bilinear forward for c network. + * @param [in] handle cce handle + * @param [in] resizeBilinearDesc descriptor of resize_bilinear operator + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] beta common scale factor + * @param [in] yDesc descriptor of output data + * @param [in|out] y output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccInterpForward(ccHandle_t handle, const ccResizeBilinearDescriptor_t resizeBilinearDesc, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief create descriptor of ResizeBilinear + * @param [in|out] resizeBilinearDesc point to descriptor of resizeBilinear attr + * @return ccStatus_t + */ +ccStatus_t ccCreateResizeBilinearDescriptor(ccResizeBilinearDescriptor_t *resizeBilinearDesc); + +/** + * @ingroup dnn + * @brief destroy descriptor of Interp + * @param [in|out] resizeBilinearDesc point to descriptor of resizeBilinear attr + * @return ccStatus_t + */ +ccStatus_t ccDestroyResizeBilinearDescriptor(ccResizeBilinearDescriptor_t *resizeBilinearDesc); + +/** + * @ingroup dnn + * @brief set descriptor of resizeBilinear. + * @param [in|out] resizeBilinearDesc descriptor of resize_bilinear operator + * @param [in] resizeOutputDimMode way to decide output dimensions + * @param [in] alignCorners whether the centers of input and output are aligned + * @param [in] zoom_factor zoom factor + * @param [in] shrink_factor shrink factor + * @param [in] height height of output + * @param [in] width width of output + * @param [in] pad_begin padding at begin of input + * @param [in] pad_end padding at end of input + * @return ccStatus_t + */ +ccStatus_t ccSetResizeBilinearDescriptor(ccResizeBilinearDescriptor_t resizeBilinearDesc, + ccResizeOutputDimMode_t resizeOutputDimMode, bool alignCorners, + int32_t zoom_factor, int32_t shrink_factor, int32_t height, int32_t width, + int32_t pad_begin, int32_t pad_end); + +/** + * @ingroup dnn + * @brief fill forward computation + * @param [in] handle cce handle + * @param [in] fillParamDesc descriptor of fill parameter + * @param [in] alpha reserved + * @param [in] givenDesc descriptor of given tensor + * @param [in] givenData given data in device memory + * @param [in] workspace space for fill algorithm + * @param [in] workSpaceSizeInBytes space size in byte + * @param [in] beta reserved + * @param [in] outputDesc descriptor of output tensor + * @param [out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccFillForward(ccHandle_t handle, const ccFillParamDescriptor_t fillParamDesc, const void *alpha, + const ccTensorDescriptor_t givenDesc, const void *givenData, const void *workspace, + const uint32_t workSpaceSizeInBytes, const void *beta, const ccTensorDescriptor_t outputDesc, + void *output); + +/** + * @ingroup dnn + *[ccGetFillWorkspaceSize] + *@param fillType [fill type] + *@param givenDesc [given tensor descriptor] + *@param xDesc [input tensor descriptor] + *@param sizeInBytes [output size] + *@return ccStatus_t [status] + */ +ccStatus_t ccGetFillWorkspaceSize(const ccFillOpType_t fillType, const ccTensorDescriptor_t xDesc, + uint32_t *sizeInBytes); + +/** + *[ccCast] + *@param handle [cce handler] + *@param alpha [alpha] + *@param xDesc [tensor Description of tensor x] + *@param x [input tensor x] + *@param beta [beta + *@param yDesc [tensor Description of tensor y] + *@param y [output tensor y] + *@return ccStatus_t [status] + */ +ccStatus_t ccCast(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const void *beta, const ccTensorDescriptor_t yDesc, void *y); + +/** + * @ingroup dnn + * @brief round forward: + * data type only support float float16 and int32 + * data format only support ND + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccRoundForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const void *beta, const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief rint forward: + * data type only support float float16 + * data format only support ND + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccRintForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const void *beta, const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief sqrt forward: + * data type only support float float16 + * data format only support ND + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccSqrtForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const void *beta, const ccTensorDescriptor_t outputDesc, void *output); + +/** + *[ccCast] + *@param filterSrcInfo [cce filtersrc descriptor] + *@param filterSrc [filterSrc address] + *@param filterDstInfo [cce filterdst descriptor] + *@param filterDst [filterdst address] + *@param group [group] + *@param ySizeInBytes [fraczfilter size] + *@param outputDataType [datatype] + *@return ccStatus_t [status] + */ +ccStatus_t ccTransGroupConvFilterInt8(ccFilterDescriptor_t filterSrcInfo, const void *filterSrc, + ccFilterDescriptor_t filterDstInfo, void *filterDst, uint32_t group, + uint32_t ySizeInBytes, ccDataType_t outputDataType); + +/** + *[ccGetConcatOutputDim] + *@param xDesc[] [input tensor descriptor] + *@param axis [concat axis] + *@param inputNum [input tensor numbers] + *@param dim[] [output dim] + *@param [in| dimlen length of dim + *@return ccStatus_t [status] + */ +ccStatus_t ccGetConcatOutputDim(const ccTensorDescriptor_t xDesc[], int32_t axis, int32_t inputNum, int32_t *dimCnt, + int32_t dim[], int32_t dimLen); + +/** + * @ingroup dnn + * @brief get the output dimension info of reduce. + * @param [in] xDesc descriptor of input tensor + * @param [in] axis The dimensions to reduce + * @param [in] keepDims If true, retains reduced dimensions with length 1. + * @param [in|out] dimCnt point to the output dimCnt + * @param [in|out] dim arrays to save dims + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetReduceOutputDim(const ccTensorDescriptor_t xDesc, const ccIntArray_t *axis, bool keepDims, + int32_t *dimCnt, int32_t dim[], int32_t dimLen); + +/** + * @ingroup dnn + * @brief reduce sum forward computation + * @param [in] handle cce handle + * @param [in] axis The dimensions to reduce + * @param [in] keepDims If true, retains reduced dimensions with length 1. + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] beta bias factors + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccReduceSumForward(ccHandle_t handle, const ccIntArray_t *axis, bool keepDims, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief reduce max forward computation + * @param [in] handle cce handle + * @param [in] axis The dimensions to reduce + * @param [in] keepDims If true, retains reduced dimensions with length 1. + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] beta bias factors + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccReduceMaxForward(ccHandle_t handle, const ccIntArray_t *axis, bool keepDims, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief reduce min forward computation + * @param [in] handle cce handle + * @param [in] axis The dimensions to reduce + * @param [in] keepDims If true, retains reduced dimensions with length 1. + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] beta bias factors + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccReduceMinForward(ccHandle_t handle, const ccIntArray_t *axis, bool keepDims, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief reduce mean forward computation + * @param [in] handle cce handle + * @param [in] axis The dimensions to reduce + * @param [in] keepDims If true, retains reduced dimensions with length 1. + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] beta bias factors + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccReduceMeanForward(ccHandle_t handle, const ccIntArray_t *axis, bool keepDims, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief reduce prod forward computation + * @param [in] handle cce handle + * @param [in] axis The dimensions to reduce + * @param [in] keepDims If true, retains reduced dimensions with length 1. + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] beta bias factors + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccReduceProdForward(ccHandle_t handle, const ccIntArray_t *axis, bool keepDims, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief reduce all forward computation + * @param [in] handle cce handle + * @param [in] axis The dimensions to reduce + * @param [in] keepDims If true, retains reduced dimensions with length 1. + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] beta bias factors + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccReduceAllForward(ccHandle_t handle, const ccIntArray_t *axis, bool keepDims, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + *@brief print times stats + *@return ccStatus_t [status] + */ +ccStatus_t ccPrintTimeStat(); + +/** + * @ingroup dnn + * @brief reduce abs sum forward computation + * @param [in] handle cce handle + * @param [in] axis The dimensions to reduce + * @param [in] keepDims If true, retains reduced dimensions with length 1. + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] beta bias factors + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccReduceAbsSumForward(ccHandle_t handle, const ccIntArray_t *axis, const bool keepDims, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief reduce square sum forward computation + * @param [in] handle cce handle + * @param [in] axis The dimensions to reduce + * @param [in] keepDims If true, retains reduced dimensions with length 1. + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] beta bias factors + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccReduceSquareSumForward(ccHandle_t handle, const ccIntArray_t *axis, const bool keepDims, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief get the output dimension info of crop and resize + * @param [in] imageDesc descriptor of images + * @param [in] boxesDesc descriptor of boxes + * @param [in] boxidxDesc descriptor of boxidx + * @param [in] resizeHeight resize height + * @param [in] resizeWidth resize width + * @param [out] dimCnt dimcnt of output + * @param [out] dim dim of output + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetCropAndResizeOutputDim(const ccTensorDescriptor_t imageDesc, const ccTensorDescriptor_t boxesDesc, + const ccTensorDescriptor_t boxidxDesc, const int32_t resizeHeight, + const int32_t resizeWidth, int32_t *dimCnt, int32_t dim[], int32_t dimLen); + +/** + * @ingroup dnn + * @brief crop and resize forward. + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] imageDesc descriptor of images + * @param [in] image input data in device memory + * @param [in] boxesDesc descriptor of boxes + * @param [in] boxes input data in device memory + * @param [in] boxidxDesc descriptor of boxidx + * @param [in] boxidx input data in device memory + * @param [in] method enum of resize method + * @param [in] extrapolationValue Value used for extrapolation, when applicable + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccCropAndResizeForward(ccHandle_t handle, const ccResizeMethod_t method, const float extrapolationValue, + const void *alpha, const ccTensorDescriptor_t imageDesc, const void *image, + const ccTensorDescriptor_t boxesDesc, const void *boxes, + const ccTensorDescriptor_t boxidxDesc, const void *boxidx, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief select forward computation + * @param [in] handle cce handle + * @param [in] alpha reserved + * @param [in] condDesc descriptor of cond tensor + * @param [in] cond cond data in device memory + * @param [in] xDesc descriptor of x tensor + * @param [in] x x data in device memory + * @param [in] yDesc descriptor of y tensor + * @param [in] y y data in device memory + * @param [in] beta reserved + * @param [in] outputDesc descriptor of output tensor + * @param [out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccSelect(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t condDesc, const void *cond, + const ccTensorDescriptor_t xDesc, const void *x, const ccTensorDescriptor_t yDesc, const void *y, + const void *beta, const ccTensorDescriptor_t outDesc, void *out); + +/** + * @ingroup dnn + * @brief get the output dimension info of where + * @param [in] xDesc descriptor of input tensor + * @param [in|out] dimCnt point to the output dimCnt + * @param [in|out] dim arrays to save dims + * @return ccStatus_t + */ +ccStatus_t ccGetWhereOutputDim(const ccTensorDescriptor_t xDesc, int32_t *dimCnt, int32_t *dim, int32_t dimLen); + +/** + * @ingroup dnn + * @brief where forward computation + * @param [in] handle cce handle + * @param [in] alpha reserved + * @param [in] condDesc descriptor of cond tensor + * @param [in] cond cond data in device memory + * @param [in] xDesc descriptor of x tensor + * @param [in] x x data in device memory + * @param [in] yDesc descriptor of y tensor + * @param [out] y y data in device memory + * @return ccStatus_t + */ +ccStatus_t ccWhere(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const void *beta, const ccTensorDescriptor_t yDesc, void *y); + +/** + * @ingroup dnn + * @brief reverse forward. + * @param [in] handle cce handle + * @param [in] axis dim that need reverse + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccReverseForward(ccHandle_t handle, const ccIntArray_t *axis, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief floor forward: + * data type only support float float16 + * data format only support ND + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccFloorForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const void *beta, const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief ceil forward: + * data type only support float float16 + * data format only support ND + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccCeilForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const void *beta, const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief get the output dimension info of truncate mod + * @param [in] xDesc descriptor of input tensor + * @param [in] yDesc descriptor of input tensor + * @param [out] dimCnt [dim count of the output tensor] + * @param [out] dim[] [shape of the output tensor] + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetTruncatemodOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, + int32_t *dimCnt, int32_t dim[], int32_t dimLen); + +/** + * @ingroup dnn + * @brief truncate mod forward computation + * @param [in] handle cce handle + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] yDesc descriptor of input tensor + * @param [in] y input data in device memory + * @param [in] beta bias factors + * @param [in] outputDesc descriptor of output tensor + * @param [out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccTruncatemodForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t yDesc, const void *y, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); +/** + * @ingroup dnn + * @brief Spatial Pyramid Pooling + * @param [in] handle cce handle + * @param [in] alpha reserved + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] workspace temp workspace + * @param [in] workspaceSizeInBytes temp workspace size + * @param [in] pyramidHeight pyramid height + * @param [in] poolingMode pooling mode + * @param [in] beta reserved + * @param [in] outputDesc descriptor of output tensor + * @param [out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccSPPForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + void *workspace, const uint32_t workspaceSizeInBytes, const uint32_t pyramidHeight, + const ccPoolingMode_t poolingMode, const void *beta, const ccTensorDescriptor_t outputDesc, + void *output); +/** + * @ingroup dnn + * @brief Get Spatial Pyramid Pooling output dim + * @param [in] xDesc descriptor of input tensor + * @param [in] pyramidHeight pyramid height + * @param [in] dimLen length of dim + * @param [out] dimCnt output tensor dim cnt + * @param [out] dim output tensor dim + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetSPPOutputDim(const ccTensorDescriptor_t xDesc, const uint32_t pyramidHeight, int32_t *dimCnt, + int32_t dim[], const int32_t dimLen); +/** + * @ingroup dnn + * @brief Get Spatial Pyramid Pooling workspace size + * @param [in] xDesc descriptor of input tensor + * @param [in] pyramidHeight pyramid height + * @param [out] workspaceSizeInBytes workspace size + * @return ccStatus_t + */ +ccStatus_t ccGetSPPWorkspaceSize(const ccTensorDescriptor_t xDesc, const uint32_t pyramidHeight, + uint32_t *workspaceSizeInBytes); + +/** + * @ingroup dnn + * @brief BNLL forward computation + * @param [in] handle cce handle + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] beta bias factors + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccBNLLForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const void *beta, const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief bias forward. + * @param [in] handle cce handle + * @param [in] axis axis + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data x + * @param [in] x input data x in device memory + * @param [in] biasDesc descriptor of input data bias + * @param [in] bias input data bias in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccBiasForward(ccHandle_t handle, const int axis, const void *alpha, const ccTensorDescriptor_t xDesc, + const void *x, const ccTensorDescriptor_t biasDesc, const void *bias, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief threshold forward computation + * @param [in] handle cce handle + * @param [in] threshold threshold + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] beta bias factors + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccThresholdForward(ccHandle_t handle, const void *threshold, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief shufflechannel forward. + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] group number of groups + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +// TODO AICPU: please add shufflechannel custom params and comment +ccStatus_t ccShuffleChannelForward(ccHandle_t handle, const void *alpha, uint32_t group, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief mvn forward. + * @param [in] handle cce handle + * @param [in] acrossChannel across channel. true: across, false: not + * @param [in] normalizeVariance normalizeVariance. true: normalizeVariance, false: not + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccMVNForward(ccHandle_t handle, bool acrossChannel, bool normalizeVariance, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, void *workSpace, uint32_t workSpaceSizeInBytes, + const void *beta, const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief get the workspace size of mvn + * @param [in] xDesc descriptor of input data + * @param [in] acrossChannel across channel. true: across, false: not + * @param [in|out] sizeInBytes Workspace size need for whole computation + */ +ccStatus_t ccGetMVNWorkspaceSize(const ccTensorDescriptor_t xDesc, bool acrossChannel, uint32_t *sizeInBytes); + +/** + * @ingroup dnn + * @brief heatmap2coord forward output is hotspot value and corresponding coordinates + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] coordh calibration high + * @param [in] coordw calibration wide + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccHeatmap2coordForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + int32_t coordh, int32_t coordw, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); +/** + * @ingroup dnn + * @brief get the output dimension info of heatmap2coord + * @param [in] xDesc descriptor of input tensor + * @param [in|out] dimCnt point to the output dimCnt + * @param [in|out] dim arrays to save dims + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetHeatmap2coordOutputDim(const ccTensorDescriptor_t xDesc, int32_t *dimCnt, int32_t *dim, int32_t dimLen); + +/** + * @ingroup dnn + * @brief swish forward. + * @param [in] handle cce handle + * @param [in] scale param of swish function, y = x / (1 + sigmoid(scale * x)) + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ + +ccStatus_t ccSwishForward(ccHandle_t handle, const float scale, const void *alpha, const ccTensorDescriptor_t xDesc, + const void *x, const void *beta, const ccTensorDescriptor_t outputDesc, void *output); + +ccStatus_t ccTeForward(ccHandle_t handle, const void *stubFunc, uint32_t coreDim, const void *args, uint32_t argsSize, + const rtL2Ctrl_t *l2ctrl, int32_t inputNum, const ccTensorDescriptor_t xDesc[], const void *x[], + int32_t outputNum, const ccTensorDescriptor_t yDesc[], void *y[], bool isAiCore); + +#ifndef DAVINCI_LITE +ccStatus_t ccAiCpuCustomizeForward(ccHandle_t handle, aicpu_run_func stubFunc, opTensor_t *xOpDesc[], void *x[], + int32_t inputNum, opTensor_t *yOpDesc[], void *y[], void *op_attr_handle, + int32_t outputNum, const ccTensorDescriptor_t xDesc[], + const ccTensorDescriptor_t yDesc[], const void *op_attr_str, uint32_t op_attr_size); +#endif +/** + * @ingroup dnn + * @brief embedding lookup forward. + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data x + * @param [in] x input data x in device memory + * @param [in] idxDesc descriptor of input data idx + * @param [in] idx input data idx in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccEmbeddingLookupForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, + const void *x, const ccTensorDescriptor_t idxDesc, const void *idx, + const void *beta, const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup + * @brief embedding lookup forward. + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] inputNum inputNum + * @param [in] xDesc[] descriptor array of input data x + * @param [in] x[] input data x array in device memory + * @param [in] workSpace workSpace addr + * @param [in] workSpaceSizeInBytes workSpace size + * @param [in] idxDesc descriptor of input data idx + * @param [in] idx input data idx in device memory + * @param [in] partitionStrategy partitionStrategy + * @param [in] maxNorm addr of maxNorm + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccEmbeddingLookupForward(ccHandle_t handle, const void *alpha, const int32_t inputNum, + const ccTensorDescriptor_t xDesc[], const void *x[], void *workSpace, + const uint32_t workSpaceSizeInBytes, const ccTensorDescriptor_t idxDesc, + const void *idx, ccPartitionStrategy_t partitionStrategy, const void *maxNorm, + const void *beta, const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + *[ccGetEmbeddingLookupOutputDim] + *@param inputNum [input tensor numbers] + *@param xDesc[] [input tensor descriptor] + *@param idxDesc [idx tensor descriptor] + *@param dimCnt [output dim count] + *@param dim[] [output dim] + *@param [in| dimlen length of dim + *@return ccStatus_t [status] + */ +ccStatus_t ccGetEmbeddingLookupOutputDim(const int32_t inputNum, const ccTensorDescriptor_t xDesc[], + const ccTensorDescriptor_t idxDesc, int32_t *dimCnt, int32_t dim[], + int32_t dimLen); + +/** + * @ingroup dnn + *[ccGetEmbeddingLookupWorkspaceSize] + *@param inputNum [input tensor numbers] + *@param idxDesc [input tensor descriptor] + *@param isMaxNormExist [isMaxNormExist] + *@param sizeInBytes [output size] + *@return ccStatus_t [status] + */ +ccStatus_t ccGetEmbeddingLookupWorkspaceSize(const int32_t inputNum, const ccTensorDescriptor_t idxDesc, + const bool isMaxNormExist, uint32_t *sizeInBytes); + +/** + * @ingroup dnn + * @brief check if it is the first layer of resnet50 and semecefc + * @param [in] tensorDesc descriptor of input tensor. + * @param [in] convDesc conv descriptor. + * @param [in] filterDesc descriptor of weight tensor. + * @return ccStatus_t + */ +ccStatus_t c04DescParamCheck(const ccTensorDescriptor_t tensorDesc, const ccConvolutionDescriptor_t convDesc, + const ccFilterDescriptor_t filterDesc); + +#ifndef DAVINCI_LITE +/** + * @ingroup dnn + * @brief convolution forward computation + * @param [in] handle cce handle + * @param [in] convDesc descriptor of convolution operator + * @param [in] alpha scaling factors + * @param [in] beta scaling factors + * @param [in] xDesc x descriptor of input tensor + * @param [in] x x data in device memory + * @param [in] dyDesc descriptor of dy + * @param [in] dy dy data in device memory + * @param [in] dwDesc descriptor of dwDesc + * @param [out] dw dw data in device memory + * @param [in] algo algorithm of convolution forward + * @param [in] workSpace temp space, maybe NULL if no need temp space + * @param [in] workSpaceSizeInBytes sizeof workspace + * @return ccStatus_t + */ +ccStatus_t ccConvolutionBackwardFilter(ccHandle_t handle, const ccConvolutionDescriptor_t convDesc, void *alpha, + void *beta, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t dyDesc, const void *dy, + const ccFilterDescriptor_t dwDesc, void *dw, ccConvolutionBwdAlgo_t algo, + void *workSpace, uint32_t workSpaceSizeInBytes); +#endif + +/** + * @ingroup dnn + * @brief get the temp space size of convolution forward computation, maybe no need temp space + * @param [in] handle cce handle + * @param [in] dyDesc descriptor of input tensor dy + * @param [in] convDesc descriptor of convolution operator + * @param [in] xDesc descriptor of input tensor + * @param [in] dwDesc descriptor of filter + * @param [in] algo algorithm of convolution forward + * @param [in|out] sizeInBytes temp space size need for specified algorithm + * @return ccStatus_t + */ +ccStatus_t ccGetConvolutionBackwardFilterWorkspaceSize(ccHandle_t handle, const ccTensorDescriptor_t dyDesc, + const ccConvolutionDescriptor_t convDesc, + const ccTensorDescriptor_t xDesc, + const ccFilterDescriptor_t dwDesc, ccConvolutionBwdAlgo_t algo, + uint32_t *sizeInBytes); + +#ifndef DAVINCI_LITE +ccStatus_t ccBatchNormalizationBackward(ccHandle_t handle, ccBatchNormMode_t mode, const void *alphaDataDiff, + const void *betaDataDiff, const void *alphaParamDiff, const void *betaParamDiff, + const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t dyDesc, const void *dy, + const ccTensorDescriptor_t dxDesc, void *dx, + const ccTensorDescriptor_t bnScaleBiasDiffDesc, const void *bnScale, + void *resultBnScaleDiff, void *resultBnBiasDiff, const void *workSpace, + const uint32_t workSpaceSizeInBytes, double epsilon, const void *SaveMean, + const void *SaveInvVariance); +#endif + +ccStatus_t ccGetBatchNormalizationBackwardWorkspaceSize(ccHandle_t handle, ccBatchNormMode_t mode, + ccTensorDescriptor_t xDesc, ccTensorDescriptor_t dyDesc, + ccTensorDescriptor_t dxDesc, + ccTensorDescriptor_t bnScaleBiasDesc, uint32_t *sizeInBytes); + +#ifndef DAVINCI_LITE +ccStatus_t ccBatchNormalizationForwardTraining(ccHandle_t handle, ccBatchNormMode_t mode, const void *alpha, + const void *beta, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t yDesc, void *y, + const ccTensorDescriptor_t bnScaleBiasMeanVarDesc, const void *bnScale, + const void *bnBias, double exponentialAverageFactor, + void *resultRunningMean, void *resultRunningVariance, void *workSpace, + uint32_t workSpaceSizeInBytes, double epsilon, void *resultSaveMean, + void *resultSaveInvVariance, const bool isTraining); +#endif + +ccStatus_t ccGetBatchNormalizationForwardTrainingWorkspaceSize(ccHandle_t handle, ccBatchNormMode_t mode, + ccTensorDescriptor_t xDesc, ccTensorDescriptor_t yDesc, + const ccTensorDescriptor_t bnScaleBiasMeanVarDesc, + uint32_t *sizeInBytes); + +/** + * @ingroup dnn + * @brief generate an random normal Tensor use given on/off scale. + * @param [in] handle Stream handle. + * @param [in] alpha reserved. + * @param [in] meanDesc Mean description of one-hot position. + * @param [in] mean Data pointer of mean. + * @param [in] scaleDesc On/off scale description. + * @param [in] scale Data pointer of on/off scale. + * @param [in] seed random seed used to generate random number + * @param [in] seed2 random seed used to generate random number + * @param [in] beta reserved. + * @param [in] outputDesc Description of the generated one-hot tensor. + * @param [output] output Data pointer of output. + * @return ccStatus_t + */ +ccStatus_t ccRandomNormalForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t meanDesc, + const void *mean, const ccTensorDescriptor_t scaleDesc, const void *scale, + const int64_t seed1, const int64_t seed2, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief generate random uniform tensor. + * @param [in] handle Stream handle. + * @param [in] alpha reserved. + * @param [in] minvalDesc Mean description of one-hot position. + * @param [in] minval Data pointer of mean. + * @param [in] maxvalDesc On/off scale description. + * @param [in] maxval Data pointer of on/off scale. + * @param [in] seed random seed used to generate random number + * @param [in] seed2 random seed used to generate random number + * @param [in] beta reserved. + * @param [in] outputDesc Description of the generated one-hot tensor. + * @param [output] output Data pointer of output. + * @return ccStatus_t + */ +ccStatus_t ccRandomUniformForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t minvalDesc, + const void *minval, const ccTensorDescriptor_t maxvalDesc, const void *maxval, + const int64_t seed1, const int64_t seed2, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/**^M + * @ingroup dnn^M\r 10932 + * @brief generate BatchMatMul tensor.^M\r 10933 + * @param [in] handle Stream handle.^M\r 10934 + * @param [in] alpha reserved.^M\r 10935 + * @param [in] xDesc tensorA Desc.^M\r 10936 + * @param [in] x Data pointer of tensorA.^M\r 10937 + * @param [in] yDesc tensorB Desc.^M\r 10938 + * @param [in] y Data pointer of tensorB.^M\r 10939 + * @param [in] beta reserved.^M\r 10940 + * @param [in] adj_x tensorA transpose flag^M\r 10941 + * @param [in] adj_y tensorB transpose flag^M\r 10942 + * @param [in] outpDesc Description of the tensor output .^M\r 10943 + * @param [output] out Data pointer of output.^M\r 10944 + * @return ccStatus_t^M + */ +ccStatus_t ccBatchMatMulForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t yDesc, const void *y, const void *beta, const bool adj_x, + const bool adj_y, const ccTensorDescriptor_t outDesc, void *out); + +ccStatus_t ccGetBatchMatMulOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, bool adj_x, + bool adj_y, int32_t *dimCnt, int32_t dim[], int32_t dimLen); + +/** + * @ingroup dnn + * @brief generator conv int8 all offset factor + * @param [in] para the struct for scale and offset of input, filter and output + * @param [in|out] offsetW offset of filter + * @param [in|out] offsetPad offset of input + * @param [in|out] scaledQrq scale computing result of input , filter and output + * @param [in|out] nextoffsetq offset of output + * @return ccStatus_t + */ +ccStatus_t ccGenQuantAllOffsetFactor(const ccQuantAllOffsetPara_t *para, uint8_t &offsetW, uint8_t &offsetPad, + uint16_t &scaledQrq, uint16_t &nextoffsetq); + +/** + * @ingroup dnn + * @brief get conv int8 all offset fracZ size + * @param [in] filterDesc descriptor of filter tensor + * @param [in|out] conv int8 all offset fracZ size + * @param [in] groupNum group conv num + * @return ccStatus_t + */ +ccStatus_t ccSetGroupConvScene(const ccFilterDescriptor_t tensorDesc, ccConvolutionDescriptor_t convDesc); + +ccStatus_t ccGetInt8AllOffsetFilterFracZSizeInBytes(const ccFilterDescriptor_t filterSrcDesc, + const ccFilterDescriptor_t filterDesc, uint32_t &size, + uint32_t groupNum); + +/** + * @ingroup dnn + * @brief transform filter in conv int8 all offset scene + * @param [in] filterSrcInfo descriptor of filter tensor before fracZ transform + * @param [in] filterSrc filter addr before fracZ transform + * @param [in] filterDstInfo descriptor of filter tensor after fracZ transform + * @param [in] filterDst filter addr after fracZ transform + * @param [in] quantPara the struct for scale and offset of input, filter and output + * @param [in] ySizeInBytes filter size after fracZ transform + * @param [in|out] outputDataType output data type + * @param [in] groupNum group conv num + * @return ccStatus_t + */ +ccStatus_t ccTransFilterInt8AllOffset(ccFilterDescriptor_t filterSrcInfo, const void *filterSrc, + ccFilterDescriptor_t filterDstInfo, void *filterDst, + const ccQuantAllOffsetPara_t *quantPara, uint32_t ySizeInBytes, + ccDataType_t outputDataType, uint32_t groupNum); + +/** + * @ingroup dnn + * @brief transform bias in conv int8 all offset scene + * @param [in] filterDesc descriptor of filter tensor + * @param [in] biasDesc descriptor of bias tensor + * @param [in] quantPara the struct for scale and offset of input, filter and output + * @param [in] w filter addr + * @param [in] bias bias addr + * @return ccStatus_t + */ +ccStatus_t ccTransInt8AllOffsetBias(const ccFilterDescriptor_t filterDesc, const ccTensorDescriptor_t biasDesc, + const ccQuantAllOffsetPara_t *quantPara, const void *w, const void *bias); + +/** + * @ingroup dnn + * @get dequantize + * @param [in] handle handle id + * @param [in] alpha alpha addr + * @param [in] xDesc the input Desc descriptor + * @param [in] x x data addr + * @param [in] beta beta data addr + * @param [in] yDesc the output Desc descriptor + * @param [in] y y data addr + * @return ccStatus_t + */ +ccStatus_t ccDequantizeCoreForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, + const void *x, const void *beta, const ccTensorDescriptor_t yDesc, void *y); +/** + * @ingroup dnn + * @get quantize + * @param [in] handle handle id + * @param [in] alpha alpha addr + * @param [in] xDesc the input Desc descriptor + * @param [in] x x data addr + * @param [in] beta beta data addr + * @param [in] yDesc the output Desc descriptor + * @param [in] y y data addr + * @return ccStatus_t + */ +ccStatus_t ccQuantizeCoreForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const void *beta, const ccTensorDescriptor_t yDesc, void *y); + +#ifndef DAVINCI_LITE +ccStatus_t ccActivationBackward(ccHandle_t handle, const ccActivationDescriptor_t activationDesc, const void *alpha, + const ccTensorDescriptor_t dyDesc, const void *dy, const ccTensorDescriptor_t xDesc, + const void *x, const void *beta, const ccTensorDescriptor_t dxDesc, void *dx); +#endif + +ccStatus_t ccL2LossForward(ccHandle_t handle, const ccL2LossDescriptor_t l2lossDesc, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t yDesc, void *y); + +/** + * @ingroup dnn + * @brief get the output dimension info of top k v2 + * @param [in] xDesc descriptor of input tensor x + * @param [in] yDesc descriptor of input tensor y + * @param [in|out] dimCnt point to the output dimCnt + * @param [in|out] dim arrays to save dims + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetTopKV2OutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t kDesc, const void *k, + const int64_t axis, int32_t *dimCnt, int32_t dim[], int32_t dimLen); + +/** + * @ingroup dnn + * @brief top k v2 forward computation + * @param [in] handle cce handle + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor x + * @param [in] x input data x in device memory + * @param [in] yDesc descriptor of input tensor y + * @param [in] y input data y in device memory + * @param [in] beta bias factors + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccTopKV2Forward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t kDesc, const void *k, const void *beta, const bool sorted, + const int64_t axis, void *workSpace, const uint32_t workSpaceSizeInBytes, + const ccTensorDescriptor_t outputValuesDesc, void *outputValues, + const ccTensorDescriptor_t outputIndicesDesc, void *outputIndices); + +/** + * @ingroup dnn + * @brief get the workspace size of top k v2 + * @param [in] xDesc descriptor of input tensor x + * @param [in] yDesc descriptor of input tensor y + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] sizeInBytes point to workspace size + * @return ccStatus_t + */ +ccStatus_t ccGetTopKV2ForwardWorkspaceSize(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t kDesc, + const ccTensorDescriptor_t indiceDesc, const void *k, const int64_t axis, + uint32_t *sizeInBytes); + +/** + * @ingroup dnn + * @brief Get unsorted segment reduction output dim + * @param [in] xDesc descriptor of input tensor + * @param [in] segmentIdsDesc descriptor of input segmentIds tensor + * @param [in] segmentsNum output slice num + * @param [out] dimCnt output tensor dim cnt + * @param [out] dim output tensor dim + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetUnsortedSegmentReductionOutputDim(const ccTensorDescriptor_t xDesc, + const ccTensorDescriptor_t segmentIdsDesc, int32_t segmentsNum, + int32_t *dimCnt, int32_t dim[], int32_t dimLen); + +/** + * @ingroup dnn + * @brief reduce all forward computation + * @param [in] handle cce handle + * @param [in] segmentsNum output slice num + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] segmentIdsDesc descriptor of input segmentIds tensor + * @param [in] x input segmentIds data in device memory + * @param [in] beta bias factors + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccUnsortedSegmentSumForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, + const void *x, const ccTensorDescriptor_t segmentIdsDesc, const void *segmentIds, + const int32_t segmentsNum, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief reverse sequence forward computation + * @param [in] handle cce handle + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor x + * @param [in] x input data x in device memory + * @param [in] yDesc descriptor of input tensor y + * @param [in] y input data y in device memory + * @param [in] beta bias factors + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccReverseSequenceForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t inputDesc, + const void *input, const ccTensorDescriptor_t seqLengthsDesc, + const void *seqLengths, int64_t seqAxis, int64_t batchAxis, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief realdiv between two tensors. + * @param [in] alpha reserved. + * @param [in] xDesc description of the left operator tensor. + * @param [in] x data point of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [in] y data point of the right operator tensor. + * @param [in] beta reserved. + * @param [in] outputDesc description of the output tensor. + * @param [output] output data point of the output tensor. + * @return ccStatus_t + */ + +ccStatus_t ccEqualForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t yDesc, const void *y, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief get output shape of realdiv. + * @param [in] xDesc description of the left operator tensor. + * @param [in] yDesc description of the right operator tensor. + * @param [out] dimCnt output tensor dim cnt + * @param [out] dim output tensor dim + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetEqualOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t yDesc, int32_t *dimCnt, + int32_t *dim, int32_t dimLen); + +/** + * @ingroup dnn + * @brief invert permutation forward computation + * @param [in] handle cce handle + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] beta bias factors + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccInvertPermutationForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, + const void *x, const void *beta, const ccTensorDescriptor_t outputDesc, + void *output); + +/** + * @ingroup dnn + * @brief get the workspace size of non max suppression + * @param [in] handle descriptor of handle + * @param [in] scoresDesc descriptor of input tensor scoresDesc + * @param [in] boxesDesc descriptor of input tensor boxesDesc + * @param [in|out] sizeInBytes point to workspace size + * @return ccStatus_t + */ +ccStatus_t ccGetNonMaxSuppressionWorkspaceSize(ccHandle_t handle, const ccTensorDescriptor_t scoresDesc, + const ccTensorDescriptor_t boxesDesc, uint32_t *sizeInBytes); + +/** + * @ingroup dnn + * @brief get the output dim of non max suppression + * @param [in] scoresDesc descriptor of input tensor scoresDesc + * @param [in] maxOutPutSize the max size of output + * @param [in|out] dimCnt point to the count of dim + * @param [in|out] dim[] the array of output dim + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetNonMaxSuppressionOutputDim(const ccTensorDescriptor_t scoresDesc, const int32_t maxOutPutSize, + int32_t *dimCnt, int32_t dim[], int32_t dimLen); + +/** + * @ingroup dnn + * @brief multinomial forward. + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] numSamples number of independent samples to draw for each row slice + * @param [in] seed1 sed to create a random seed for the distribution + * @param [in] seed2 sed to create a random seed for the distribution + * @param [in] workSpace work space for inter access + * @param [in] workSpaceSizeInBytes work space size + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccMultinomialForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + int32_t numSamples, int64_t seed1, int64_t seed2, void *workSpace, + uint32_t workSpaceSizeInBytes, const void *beta, const ccTensorDescriptor_t outputDesc, + void *output); +/** + * @ingroup dnn + * @brief get output dim of generated one-hot tensor. + * @param [in] indicesDesc Indices description of one-hot position. + * @param [in] depth On/off value description. + * @param [in] axis Data pointer of on/off value. + * @param [output] dimCnt Description of the generated one-hot tensor. + * @param [output] dim Data pointer of output. + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetOneHotOutputDim(const ccTensorDescriptor_t indicesDesc, int32_t depth, int32_t axis, int32_t *dimCnt, + int32_t *dim, int32_t dimLen); + +/** + * @ingroup dnn + * @brief generate an one-hot Tensor use given on/off value. + * @param [in] handle Stream handle. + * @param [in] alpha reserved. + * @param [in] indicesDesc Indices description of one-hot position. + * @param [in] indices Data pointer of indices. + * @param [in] onDesc On value description. + * @param [in] on Data pointer of on value. + * @param [in] offDesc Off value description. + * @param [in] off Data pointer of off value. + * @param [in] depth On/off value description. + * @param [in] axis Data pointer of on/off value. + * @param [in] beta reserved. + * @param [in] outputDesc Description of the generated one-hot tensor. + * @param [output] output Data pointer of output. + * @return ccStatus_t + */ +ccStatus_t ccOneHotForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t indicesDesc, + const void *indices, const ccTensorDescriptor_t onDesc, const void *on, + const ccTensorDescriptor_t offDesc, const void *off, const int32_t depth, const int32_t axis, + const void *beta, const ccTensorDescriptor_t outputDesc, void *output); +/** + * @ingroup dnn + * @brief get the workspaceSize of multinomial + * @param [in] xDesc descriptor of input tensor + * @param [in] numSamples number sample + * @param [out] sizeInBytes wor space size of byte + * @return ccStatus_t + */ +ccStatus_t ccGetMultinomialWorkspaceSize(const ccTensorDescriptor_t xDesc, uint32_t *sizeInBytes); +/** + * @ingroup dnn + * @brief get the output dimension info of multinomial + * @param [in] xDesc descriptor of input tensor + * @param [in] numSample number of independent samples to draw for each row slice + * @param [in|out] dimCnt point to the output dimCnt + * @param [in|out] dim arrays to save dims + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetMultinomialOutputDim(const ccTensorDescriptor_t xDesc, int32_t numSample, int32_t *dimCnt, + int32_t dim[], int32_t dimLen); +/** + * @ingroup dnn + * @brief get the output dimension info of BiasAddBackward + * @param [in] dyDesc descriptor of input tensor + * @param [in] out] n outputTensor [N]CHW + * @param [in|out] c outputTensor N[C]HW + * @param [in|out] h outputTensor NC[H]W + * @param [in|out] w outputTensor NCH[W] + * @return ccStatus_t + */ +ccStatus_t ccGetBiasAddBackwardOutputDim(const ccTensorDescriptor_t dyDesc, int32_t *n, int32_t *c, int32_t *h, + int32_t *w); + +/** + * @ingroup dnn + * @brief biasadd backward. + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] dyDesc descriptor of input data + * @param [in] dy input data in device memory + * @param [in] beta common scale factor + * @param [in] dbDesc descriptor of output data + * @param [in|out] db output data in device memory + * @return ccStatus_t + */ +#ifndef DAVINCI_LITE +ccStatus_t ccBiasAddBackward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t dyDesc, const void *dy, + const void *beta, const ccTensorDescriptor_t dbDesc, void *db); + +ccStatus_t ccMaxPoolWithArgmaxForward(ccHandle_t handle, const ccPoolingDescriptor_t poolingDesc, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t yDesc, void *y, const ccTensorDescriptor_t argMaskDesc, + void *argMask); +#endif + +ccStatus_t ccCreatePoolingMaskDescriptor(ccTensorDescriptor_t *poolingMaskDesc); + +ccStatus_t ccDestroyPoolingMaskDescriptor(ccTensorDescriptor_t *poolingMaskDesc); + +ccStatus_t ccSetPoolingMaskTensorDescriptor(ccTensorDescriptor_t poolingMaskDesc, ccTensorFormat_t format, + ccDataType_t dataType, int32_t n, int32_t c, int32_t h, int32_t w, + int32_t windowH, int32_t windowW); + +ccStatus_t ccGetPoolingMaskTensorSizeInBytes(ccTensorDescriptor_t poolingMaskDesc, uint32_t *size); + +/** + * @ingroup dnn + * @brief get the mask output dimension info of maxpooling training forward + * @param [in] pooling descriptor of convolution operator + * @param [in] xDesc descriptor of input tensor + * @param [in|out] n point to batch size + * @param [in|out] c point to channels + * @param [in|out] h point to height of feature map + * @param [in|out] w point to width of feature map + * @param [in|out] windowH point to height of window + * @param [in|out] windowW point to width of windowW + * @return ccStatus_t + */ +ccStatus_t ccGetPoolingMaskDim(const ccPoolingDescriptor_t poolingDesc, const ccTensorDescriptor_t xDesc, int32_t *n, + int32_t *c, int32_t *h, int32_t *w, int32_t *windowH, int32_t *windowW); + +#ifndef DAVINCI_LITE +ccStatus_t ccSoftmaxCrossEntropyLoss(ccHandle_t handle, ccSoftmaxAlgo_t algo, ccSoftmaxMode_t mode, + ccCrossEntropyMode_t ceMode, const void *alpha, const void *scale, + const ccTensorDescriptor_t logitsDesc, const void *logits, + const ccTensorDescriptor_t labelsDesc, const void *labels, const void *labelSmooth, + const void *beta, const ccTensorDescriptor_t lossDesc, void *loss); + +ccStatus_t ccSoftmaxCrossEntropyDx(ccHandle_t handle, ccSoftmaxAlgo_t algo, ccSoftmaxMode_t mode, + ccCrossEntropyMode_t ceMode, const void *alpha, const void *scale, + const ccTensorDescriptor_t logitsDesc, const void *logits, + const ccTensorDescriptor_t labelsDesc, const void *labels, const void *labelSmooth, + const void *beta, const ccTensorDescriptor_t dxDesc, void *dx); + +ccStatus_t ccAvgPoolingBackward(ccHandle_t handle, const ccPoolingDescriptor_t poolingDesc, const void *alpha, + const ccTensorDescriptor_t dyDesc, const void *dy, const void *beta, + const ccTensorDescriptor_t dxDesc, const void *dx); + +ccStatus_t ccTrainingAssignOp(ccHandle_t handle, const ccAssignOpMode_t assignOpDesc, const void *alpha, + const void *beta, const ccTensorDescriptor_t aDesc, void *a, + const ccTensorDescriptor_t bDesc, const void *b); + +/** + * @ingroup dnn + * @brief momentum optimizer for variable update + * @param [in] handle cce handle + * @param [in] inputDesc descriptor of input tensor: gradient,accumulation,variable + * @param [in] gradient gradient input + * @param [in|out] accumulation accumulation input and updated output + * @param [in|out] variable variable input and updated output + * @param [in] algo indicate whether need FP16 output + * @param [in] momentum scaler to control accumulation + * @param [in] learningRate scaler + * @param [in] lossScaleReciprocal scaler + * @param [in] workSpace additional memory address + * @param [in] workSpaceSizeInBytes additional memory size + * @param [out] variableUpdatedFP16Desc descriptor of FP16 output tensor: variableUpdatedFP16 + * @param [out] variableUpdatedFP16 variableUpdatedFP16 + * @return ccStatus_t + */ +ccStatus_t ccApplyMomentum(ccHandle_t handle, const ccTensorDescriptor_t inputDesc, const void *gradient, + void *accumulation, void *variable, const ccMomentumAlgo_t algo, const void *momentum, + const void *learningRate, const void *lossScaleReciprocal, void *workSpace, + const uint32_t workSpaceSizeInBytes, const ccTensorDescriptor_t variableUpdatedFP16Desc, + void *variableUpdatedFP16); + +ccStatus_t ccSsdClassifyLossTrain(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t labelDesc, + const void *label, const ccTensorDescriptor_t greaterConstDesc, + const void *greaterConst, const ccTensorDescriptor_t subConstDesc, + const void *subConst, const ccTensorDescriptor_t sparseDesc, const void *sparse, + const void *beta, const ccTensorDescriptor_t castoutDesc, const void *castout, + const ccTensorDescriptor_t muloutDesc, const void *mulout); + +#endif + +/** + * @ingroup dnn + * @brief get the workspace size of applymomentum + * @param [in] inputDesc descriptor of input tensor + * @return ccStatus_t + */ +ccStatus_t ccGetApplyMomentumWorkspaceSize(const ccTensorDescriptor_t inputDesc, uint32_t *sizeInBytes); +#ifndef DAVINCI_LITE +ccStatus_t ccHwck2FracZ(ccHandle_t handle, const ccFilterDescriptor_t xDesc, const void *x, + const ccFilterDescriptor_t yDesc, void *y); + +ccStatus_t ccFracZ2Hwck(ccHandle_t handle, const ccFilterDescriptor_t xDesc, const void *x, + const ccFilterDescriptor_t yDesc, void *y); +ccStatus_t ccAddNForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const int32_t inputNum, + const void *x[], const void *beta, void *workSpace, uint32_t workSpaceSizeInBytes, + const ccTensorDescriptor_t yDesc, void *y); +#endif +ccStatus_t ccGetAddNForwardWorkspaceSize(ccHandle_t handle, const ccTensorDescriptor_t xDesc, const int32_t inputNum, + const ccTensorDescriptor_t yDesc, uint32_t *sizeInBytes); +ccStatus_t ccGetAddNForwardOutputDim(const ccTensorDescriptor_t xDesc, int32_t *dimCnt, int32_t *dim, int32_t dimLen); +ccStatus_t ccAddTrainForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t wDesc, const void *w, const void *beta, void *workSpace, + uint32_t workSpaceSizeInBytes, const ccTensorDescriptor_t yDesc, void *y); +ccStatus_t ccGetAddTrainForwardWorkspaceSize(ccHandle_t handle, const ccTensorDescriptor_t xDesc, + const ccTensorDescriptor_t wDesc, const ccTensorDescriptor_t yDesc, + uint32_t *sizeInBytes); +ccStatus_t ccGetAddTrainForwardOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t wDesc, + int32_t *dimCnt, int32_t dim[], int32_t dimLen); +ccStatus_t ccMulTrainForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t wDesc, const void *w, const void *beta, void *workSpace, + uint32_t workSpaceSizeInBytes, const ccTensorDescriptor_t yDesc, void *y); +ccStatus_t ccGetMulTrainForwardWorkspaceSize(ccHandle_t handle, const ccTensorDescriptor_t xDesc, + const ccTensorDescriptor_t wDesc, const ccTensorDescriptor_t yDesc, + uint32_t *sizeInBytes); +ccStatus_t ccGetMulTrainForwardOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t wDesc, + int32_t *dimCnt, int32_t dim[], int32_t dimLen); + +/** + * @ingroup dnn + * @brief get workspace size + * @param [in] xDesc descriptor of input tensor + * @param [in|out] sizeInBytes workspace size + * @return ccStatus_t + */ +ccStatus_t ccGetRandomShuffleWorkspaceSize(const ccTensorDescriptor_t xDesc, uint32_t *sizeInBytes); + +/** + * @ingroup dnn + * @brief random shuffle forward computation + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] workspace temporary space + * @param [in] workspaceSizeInBytes temporary space size + * @param [in] seed random seed used to generate random number + * @param [in] seed2 random seed used to generate random number + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccRandomShuffleForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + void *workspace, const uint32_t workspaceSizeInBytes, const int64_t seed1, + const int64_t seed2, const void *beta, const ccTensorDescriptor_t outputDesc, + void *output); +/** + * @ingroup dnn + * @brief sin forward: + * data type only support float float16 double + * data format only support ND + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] input input data in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccSinForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *input, + const void *beta, const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief cos forward: + * data type only support float float16 double + * data format only support ND + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] input input data in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccCosForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *input, + const void *beta, const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief tan forward: + * data type only support float float16 double + * data format only support ND + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] input input data in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccTanForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *input, + const void *beta, const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief get the output dimension info of unstack + * @param [in] xDesc descriptor of input tensor + * @param [in] axis the axis to unstack along + * @param [in|out] dimCnt point to the output dimCnt + * @param [in|out] dim arrays to save dims + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetUnstackOutputDim(const ccTensorDescriptor_t xDesc, int32_t axis, int32_t *dimCnt, int32_t dim[], + int32_t dimLen); + +/** + * @ingroup dnn + * @brief unstack forward. + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data + * @param [in] x input data in device memory + * @param [in] num the length of the dimension axis + * @param [in] axis the axis to unstack along + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ + +ccStatus_t ccUnstackForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + int32_t num, int32_t axis, const void *beta, const ccTensorDescriptor_t outputDesc, + void *output[]); + +ccStatus_t ccResizeNearestNeighborCpuForward(ccHandle_t handle, const ccResizeNearestNeighborDescriptor_t resizeDesc, + const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const void *beta, const ccTensorDescriptor_t outputDesc, void *output); +/** + * @ingroup dnn + * @brief get the output dimension info of resize nearest neighbor + * @param [in] resizeDesc descriptor of resize + * @param [in] xDesc descriptor of input tensor + * @param [in|out] dimCnt point to the output dimCnt + * @param [in|out] dim arrays to save dims + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetResizeNearestNeighborOutputDim(const ccResizeNearestNeighborDescriptor_t resizeDesc, + const ccTensorDescriptor_t xDesc, int32_t *dimCnt, int32_t dim[], + int32_t dimLen); + +/** + * @ingroup dnn + * @brief create descriptor of ResizeNearestNeighbor + * @param [in|out] resizeDesc point to descriptor of ResizeNearestNeighbor attr + * @return ccStatus_t + */ +ccStatus_t ccCreateResizeNearestNeighborDescriptor(ccResizeNearestNeighborDescriptor_t *resizeDesc); + +/** + * @ingroup dnn + * @brief destroy descriptor of ResizeNearestNeighbor + * @param [in|out] resizeDesc point to descriptor of ResizeNearestNeighbor attr + * @return ccStatus_t + */ +ccStatus_t ccDestroyResizeNearestNeighborDescriptor(ccResizeNearestNeighborDescriptor_t *resizeDesc); + +/** + * @ingroup dnn + * @brief set descriptor of ResizeNearestNeighbor. + * @param [in|out] resizeDesc descriptor of resize nearest neighbor operator + * @param [in] alignCorners whether the centers of input and output are aligned + * @param [in] height height of output + * @param [in] width width of output + * @return ccStatus_t + */ +ccStatus_t ccSetResizeNearestNeighborDescriptor(ccResizeNearestNeighborDescriptor_t resizeDesc, bool alignCorners, + int32_t height, int32_t width); + +/** + * @ingroup dnn + * [ccGetPadV2OutputDim] + * @brief get the output dimension info of pad + * @param [in] xDesc descriptor of input tensor x + * @param [in] padDesc descriptor of input paddings + * @param [in|out] dimCnt point to the output dimCnt + * @param [in|out] dim arrays to save dims + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetPadV2OutputDim(const ccTensorDescriptor_t xDesc, const ccPadV2Descriptor_t padDesc, int32_t *dimCnt, + int32_t dim[], int32_t dimLen); + +ccStatus_t ccPadV2CpuForward(ccHandle_t handle, const ccPadV2Descriptor_t padDesc, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief create descriptor of parameters for padv2 function + * @param [in] point to descriptor of parameters for padv2 function + * @return ccStatus_t + */ +ccStatus_t ccCreatePadV2Descriptor(ccPadV2Descriptor_t *padDesc); + +/** + * @ingroup dnn + * @brief destroy descriptor of parameters for padv2 function + * @param [in] point to descriptor of parameters for padv2 function + * @return ccStatus_t + */ +ccStatus_t ccDestroyPadV2Descriptor(ccPadV2Descriptor_t *padDesc); + +/** + * @brief init descriptor for parameter of padv2 function + * @param [in|out] padDesc descriptor of pad + * @param [in] padShapeCnt padshape count + * @param [in] padShapeLow padshape low + * @param [in] padShapeHigh padshape high + * @param [in] padMode pad mode + * @param [in] padValue pad value ptr + * @param [in] padValueType pad value data type + * @return ccStatus_t + */ +ccStatus_t ccSetPadV2Descriptor(ccPadV2Descriptor_t padDesc, const int32_t padShapeCnt, const int32_t padShapeLow[], + const int32_t padShapeHigh[], const ccPadMode_t padMode, const void *padValue, + const ccDataType_t padValueType); +/** + * @ingroup dnn + * @brief create descriptor of batchToSpace + * @param [in|out] batchToSpaceDesc point to descriptor of batchToSpace + * @return ccStatus_t + */ +ccStatus_t ccCreateBatchToSpaceDescriptor(ccBatchToSpaceDescriptor_t *batchToSpaceDesc); + +/** + * @ingroup dnn + * @brief set batchToSpaceDesc + * @param [in|out] batchToSpaceDesc descriptor of batchToSpace + * @param [in] blockShape blockShape of batchToSpace + * @param [in] crops crops of batchToSpace + * @param [in] blockShapeLength blockShapeLength of batchToSpace + * @return ccStatus_t + */ +ccStatus_t ccSetBatchToSpaceDescriptor(ccBatchToSpaceDescriptor_t paramsDesc, const int32_t *blockShape, + const int32_t *crops, const int32_t blockShapeLength); + +/** + * @ingroup dnn + * @brief get batchToSpaceDesc + * @param [in|out] batchToSpaceDesc descriptor of batchToSpace + * @param [in] blockShape blockShape of batchToSpace + * @param [in] crops crops of batchToSpace + * @param [in] blockShapeLength blockShapeLength of batchToSpace + * @return ccStatus_t + */ +ccStatus_t ccGetBatchToSpaceDescriptor(const ccBatchToSpaceDescriptor_t paramsDesc, int32_t *blockShape, int32_t *crops, + int32_t *blockShapeLength); + +/** + * @ingroup dnn + * @brief destroy descriptor of batchToSpace + * @param [in] *batchToSpaceDesc descriptor of batchToSpace + * @return ccStatus_t + */ +ccStatus_t ccDestroyBatchToSpaceDescriptor(ccBatchToSpaceDescriptor_t *batchToSpaceDesc); + +/** + * @ingroup dnn + * @brief get the output dimension info of batch to space + * @param [in] xDesc descriptor of input tensor + * @param [in|out] dimCnt point to the output dimCnt + * @param [in|out] dim arrays to save dims + * @param [in| dimlen length of dim + * @return ccStatus_t + */ + +ccStatus_t ccGetBatchToSpaceOutputDim(const ccTensorDescriptor_t xDesc, + const ccBatchToSpaceDescriptor_t batchToSpaceDesc, int32_t *dimCnt, int32_t dim[], + int32_t dimLen); + +/** + * @ingroup dnn + * @brief batch to space forward computation + * @param [in] handle cce handle + * @param [in] paramsDesc descriptor of input params + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] beta bias factors + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ + +ccStatus_t ccBatchToSpaceForward(ccHandle_t handle, const ccBatchToSpaceDescriptor_t paramsDesc, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief create descriptor of spaceToBatch + * @param [in|out] spaceToBatchDesc point to descriptor of spaceToBatch + * @return ccStatus_t + */ +ccStatus_t ccCreateSpaceToBatchDescriptor(ccSpaceToBatchDescriptor_t *spaceToBatchDesc); + +/** + * @ingroup dnn + * @brief set spaceToBatchDesc + * @param [in|out] spaceToBatchDesc descriptor of spaceToBatch + * @param [in] blockShape blockShape of spaceToBatch + * @param [in] paddings paddings of spaceToBatch + * @param [in] blockShapeLength blockShapeLength of spaceToBatch + * @return ccStatus_t + */ +ccStatus_t ccSetSpaceToBatchDescriptor(ccSpaceToBatchDescriptor_t paramsDesc, const int32_t *blockShape, + const int32_t *paddings, const int32_t blockShapeLength); + +/** + * @ingroup dnn + * @brief get spaceToBatchDesc + * @param [in|out] spaceToBatchDesc descriptor of spaceToBatch + * @param [in] blockShape blockShape of spaceToBatch + * @param [in] paddings paddings of spaceToBatch + * @param [in] blockShapeLength blockShapeLength of spaceToBatch + * @return ccStatus_t + */ +ccStatus_t ccGetSpaceToBatchDescriptor(const ccSpaceToBatchDescriptor_t paramsDesc, int32_t *blockShape, + int32_t *paddings, int32_t *blockShapeLength); + +/** + * @ingroup dnn + * @brief destroy descriptor of spaceToBatch + * @param [in] *spaceToBatchDesc descriptor of spaceToBatch + * @return ccStatus_t + */ +ccStatus_t ccDestroySpaceToBatchDescriptor(ccSpaceToBatchDescriptor_t *spaceToBatchDesc); + +/** + * @ingroup dnn + * @brief get the output dimension info of space to batch + * @param [in] xDesc descriptor of input tensor + * @param [in|out] dimCnt point to the output dimCnt + * @param [in|out] dim arrays to save dims + * @param [in| dimlen length of dim + * @return ccStatus_t + */ + +ccStatus_t ccGetSpaceToBatchOutputDim(const ccTensorDescriptor_t xDesc, + const ccSpaceToBatchDescriptor_t spaceToBatchDesc, int32_t *dimCnt, int32_t dim[], + int32_t dimLen); + +/** + * @ingroup dnn + * @brief space to batch forward computation + * @param [in] handle cce handle + * @param [in] paramsDesc descriptor of input params + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] beta bias factors + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ + +ccStatus_t ccSpaceToBatchForward(ccHandle_t handle, const ccSpaceToBatchDescriptor_t paramsDesc, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +ccStatus_t ccTransFilterDesc2TensorDesc(ccFilterDescriptor_t wDesc, ccTensorDescriptor_t tensorDesc); + +/* + * @brief get the output dimension info of extractImagePatches + * @param [in] xDesc descriptor of input tensor x + * @param [in] ksizes ksizes array + * @param [in] strides strides array + * @param [in] rates rates array + * @param [in] padding padding type + * @param [in|out] dimCnt point to the output dimCnt + * @param [in|out] dim arrays to save dims + * @return ccStatus_t + */ +ccStatus_t ccGetExtractImagePatchesOutputDim(const ccTensorDescriptor_t xDesc, const ccIntArray_t *ksizes, + const ccIntArray_t *strides, const ccIntArray_t *rates, + const ccExtractImagePatchesPadType_t padding, int32_t *dimCnt, + int32_t dim[], const int32_t dimLen); + +/** + * @ingroup dnn + * @brief cum forward. + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data, dimCnt:1~8 + * @param [in] x input data in device memory + * @param [in] axisDesc scale factor, dimCnt:0 + * @param [in] axis which axis to cum calc, device memory + * @param [in] beta common scale factor + * @param [in] opType calc type, eg. sum, prod.... + * @param [in] exclusive cum flag, true or false + * @param [in] reverse cum flag, true or false + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccCumForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t axisDesc, const void *axis, const void *beta, const CumOpType opType, + const bool exclusive, const bool reverse, const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @ingroup dnn + * @brief ExtractImagePatches forward. + * @param [in] handle cce handle + * @param [in] ksizes ksizes array + * @param [in] strides strides array + * @param [in] rates rates array + * @param [in] padding padding type + * @param [in] alpha common scale factor + * @param [in] xDesc descriptor of input data x + * @param [in] x input data x in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccExtractImagePatchesForward(ccHandle_t handle, const ccIntArray_t *ksizes, const ccIntArray_t *strides, + const ccIntArray_t *rates, const ccExtractImagePatchesPadType_t padding, + const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const void *beta, const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @brief get argmax output dim info + * @param [in] argDesc argmaxmin descriptor + * @param [in] xDesc descriptor of input tensor + * @param [in|out] dimCnt output dim count + * @param [in|out] dim output dim + * @param [in| dimlen length of dim + * @return ccStatus_t + */ +ccStatus_t ccGetArgMaxOutputDim(const ccArgmaxminDescriptor_t argDesc, const ccTensorDescriptor_t xDesc, + int32_t *dimCnt, int32_t dim[], int32_t dimLen); + +/** + * @ingroup dnn + * @brief argmax forward computation + * @param [in] handle cce handle + * @param [in] argDesc argmaxmin descriptor + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] workSpace workspace pointer + * @param [in] workSpaceSizeInBytes workspace size in bytes + * @param [in] beta bias factors + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccArgMaxForward(ccHandle_t handle, const ccArgmaxminDescriptor_t argDesc, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, void *workSpace, + const uint32_t workSpaceSizeInBytes, const void *beta, const ccTensorDescriptor_t outputDesc, + void *output); + +/** + * @ingroup dnn + * @brief get the output dimension info of argmaxmin + * @param [in] argDesc descriptor of tagCcArgmaxmin + * @param [in] xDesc descriptor of input tensor + * @param [in|out] sizeInBytes workspace size + * @return ccStatus_t + */ +ccStatus_t ccGetArgMaxWorkspaceSize(const ccArgmaxminDescriptor_t argDesc, const ccTensorDescriptor_t xDesc, + uint32_t *sizeInBytes); + +/** + * @ingroup dnn + * @brief create descriptor of Argmaxmin + * @param [in|out] resizeDesc point to descriptor of Argmaxmin attr + * @return ccStatus_t + */ +ccStatus_t ccCreateArgmaxminDescriptor(ccArgmaxminDescriptor_t *argDesc); + +/** + * @ingroup dnn + * @brief destroy descriptor of Interp + * @param [in|out] resizeDesc point to descriptor of Argmaxmin attr + * @return ccStatus_t + */ +ccStatus_t ccDestroyArgmaxminDescriptor(ccArgmaxminDescriptor_t *argDesc); + +/** + * @ingroup dnn + * @brief destroy descriptor of Interp + * @param [in|out] argDesc descriptor of tagCcArgmaxmin + * @param [in] axisType + * @param [in] outMaxVal whether to return the maximum value + * @param [in] topK number that returns the maximum index or maximum value + * @param [in] axis Describes which axis of the input Tensor to reduce across + * @param [in] keepDims whether to keep reduced dim + * @param [in] reduceSize the num of elements to be reduce to get topK elements, reduceSize=-1 means the total num + * of elements in axis dimension + * @param [in] reduceStride the stride for reduce operation, reduceStride=1 means the layout of target data is + * continuous + * @return ccStatus_t + */ +ccStatus_t ccSetArgmaxminDescriptor(ccArgmaxminDescriptor_t argDesc, int32_t axisType, bool outMaxVal, int64_t topK, + int64_t axis, bool keepDims, int64_t reduceSize = -1, int64_t reduceDStride = 1); + +ccStatus_t ccArgMinForward(ccHandle_t handle, const ccArgmaxminDescriptor_t argDesc, const void *alpha, + const ccTensorDescriptor_t xDesc, const void *x, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +ccStatus_t ccGetArgMinOutputDim(const ccArgmaxminDescriptor_t argDesc, const ccTensorDescriptor_t xDesc, + int32_t *dimCnt, int32_t dim[], const int32_t dimLen); +/** + * @ingroup dnn + * @brief lsh projection forward computation + * @param [in] handle cce handle + * @param [in] alpha scaling factors + * @param [in] hashDesc descriptor of input tensor hashDesc + * @param [in] hash input data hash in device memory + * @param [in] weightDesc descriptor of input tensor weightDesc + * @param [in] weight input data weight in device memory + * @param [in] inputDesc descriptor of input tensor inputDesc + * @param [in] lookup input data lookup in device memory + * @param [in] type 1:SPARSE 2.DENSE + * @param [in] beta bias factors + * @param [in] workSpace workSpace data in device memory + * @param [in] workSpaceSizeInBytes workSpace length + * @param [in] outputDesc descriptor of output tensor + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccLshProjectionForward(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t hashDesc, + const void *hash, const ccTensorDescriptor_t weightDesc, const void *weight, + const ccTensorDescriptor_t inputDesc, const void *input, const LSHProjectionType type, + const void *beta, void *workSpace, const uint32_t workSpaceSizeInBytes, + const ccTensorDescriptor_t outputDesc, void *output); +/** + * @ingroup dnn + * @brief get the workspace size of lsh projection + * @param [in] inputDesc descriptor of input tensor input + * @param [in] hashDataType data type of hash + * @param [in|out] sizeInBytes workspace size + * @return ccStatus_t + */ +ccStatus_t ccGetLshProjectionForwardWorkspaceSize(const ccTensorDescriptor_t inputDesc, const ccDataType_t hashDataType, + uint32_t *sizeInBytes); +/** + * @ingroup dnn + * @brief get the output dimension info of LshProjection, + * @param [in] hashDesc descriptor of hash + * @param [in] type type of mode + * @param [in|out] dimCnt point to the output dimCnt + * @param [in|out] dim arrays to save dims + * @param [in] dimLen dim length + * @return ccStatus_t + */ +ccStatus_t ccGetLshProjectionOutputDim(const ccTensorDescriptor_t hashDesc, const LSHProjectionType type, + int32_t *dimCnt, int32_t dim[], const int32_t dimLen); +/** + * @ingroup dnn + * @brief get the weight dimension info of LshProjection, + * @param [in] inputDesc descriptor of input + * @param [in|out] dimCnt point to the weight dimCnt + * @param [in|out] dim arrays to save dims + * @param [in] dimLen dim length + * @return ccStatus_t + */ +ccStatus_t ccGetLshProjectionWeightDim(const ccTensorDescriptor_t inputDesc, int32_t *dimCnt, int32_t dim[], + const int32_t dimLen); + +/** + * @ingroup dnn + * @brief init descriptor for parameter of upsample function + * @param [in] handle cce handle + * @param [in] upsamplePara input para in host memory + * @param [in] alpha common scale factor + * @param [in] bottomDesc descriptor of input data bottomDesc + * @param [in] bottom input data bottom in device memory + * @param [in] bottomMaskDesc descriptor of input data bottomMaskDesc + * @param [in] bottomMask input data bottomMask in device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor of output data + * @param [in|out] output output data in device memory + * @return ccStatus_t + */ +ccStatus_t ccUpsampleForward(ccHandle_t handle, const ccUpsampleParaDescriptor_t upsamplePara, const void *alpha, + const ccTensorDescriptor_t bottomDesc, const void *bottom, + const ccTensorDescriptor_t bottomMaskDesc, const void *bottomMask, const void *beta, + const ccTensorDescriptor_t outputDesc, void *output); + +/** + * @brief creat descriptor for parameter of usample function + * @param [in|out] upsampleDesc descriptor of upsamplepara + * @return ccStatus_t + */ +ccStatus_t ccCreateUpsampleDescriptor(ccUpsampleParaDescriptor_t *upsampleDesc); + +/** + * @brief destroy descriptor for parameter of upsample function + * @param [in|out] upsampleDesc descriptor of upsamplepara + * @return ccStatus_t + */ +ccStatus_t ccDestroyUpsampleDescriptor(ccUpsampleParaDescriptor_t *upsampleDesc); + +/** + * @brief set descriptor for parameter of upsample function + * @param [in|out] upsampleDesc descriptor of upsamplepara + * @param [in] scale the scale of height and width + * @param [in] scaleHeight the scale of height + * @param [in] scaleWidth the scale of Width + * @param [in] upsampleHeight the height of output + * @param [in] upsampleWidth the width of output + * @param [in] padOutHeight pad value height + * @param [in] padOutWidth pad value width + * @return ccStatus_t + */ +ccStatus_t ccSetUpsampleDescriptor(ccUpsampleParaDescriptor_t upsampleDesc, const int32_t scale, + const int32_t scaleHeight, const int32_t scaleWidth, const int32_t upsampleHeight, + const int32_t upsampleWidth, const bool padOutHeight, const bool padOutWidth); +/** + * @ingroup dnn + * @brief get the output dimension info of upsample + * @param [in] upsamplePara para of upsample + * @param [in] bottomDesc descriptor of input bottom tensor + * @param [in|out] dimCnt point to the output dimCnt + * @param [in|out] dim arrays to save dims + * @param [in] dimLen the len of dim array + * @return ccStatus_t + */ +ccStatus_t ccGetUpsampleOutputDim(const ccUpsampleParaDescriptor_t upsamplePara, const ccTensorDescriptor_t bottomDesc, + int32_t *dimCnt, int32_t dim[], const int32_t dimLen); + +#ifndef DAVINCI_LITE +ccStatus_t ccMatmul(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t wDesc, const void *w, const ccTensorDescriptor_t biasDesc, + const void *bias, const ccFullConnectFwdAlgo_t algo, void *workSpace, + const uint32_t workSpaceSizeInBytes, const void *beta, const ccTensorDescriptor_t yDesc, void *y, + const bool transposeA, const bool transposeB); +ccStatus_t ccGetMatmulOutputDim(const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t wDesc, int32_t *n, + int32_t *c, int32_t *h, int32_t *w, bool transposeA, bool transposeB); +ccStatus_t ccGetMatmulWorkspaceSize(ccHandle_t handle, const ccFullConnectFwdAlgo_t algo, + const ccTensorDescriptor_t xDesc, const ccTensorDescriptor_t wDesc, + const ccTensorDescriptor_t yDesc, uint32_t *sizeInBytes, bool transposeA, + bool transposeB); +#endif + +/** + * @ingroup dnn + * @brief gather_v2 function + * @param [in] handle cce handle + * @param [in] alpha common scale factor + * @param [in] paramsDesc descriptor + * @param [in] params device memory + * @param [in] indicesDesc descriptor + * @param [in] indices device memory + * @param [in] axisDesc descriptor + * @param [in] axis device memory + * @param [in] beta common scale factor + * @param [in] outputDesc descriptor + * @param [in|out] output device memory + * @return ccStatus_t + */ +ccStatus_t ccGatherV2(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t paramsDesc, const void *params, + const ccTensorDescriptor_t indicesDesc, const void *indices, const ccTensorDescriptor_t axisDesc, + const void *axis, const void *beta, const ccTensorDescriptor_t outputDesc, const void *output); + +/** + * @ingroup dnn + * @brief memory_clear function + * @param [in] handle cce handle + * @param [in] addrSpaceSizeInBytes addr space size + * @param [in|out] addr device memory + * @return ccStatus_t + */ +ccStatus_t ccMemoryClear(ccHandle_t handle, const uint64_t addrSpaceSizeInBytes, const void *addr); + +/** + * @ingroup dnn + * @brief check input is overflow + * @param [in] handle cce handle + * @param [in] alpha scaling factors + * @param [in] xDesc descriptor of input tensor + * @param [in] x input data in device memory + * @param [in] yDesc descriptor of output tensor + * @param [in|out] y output data in device memory + * @param [in] beta scaling factors + * @return ccStatus_t + */ +ccStatus_t ccIsFinite(ccHandle_t handle, const void *alpha, const ccTensorDescriptor_t xDesc, const void *x, + const ccTensorDescriptor_t yDesc, const void *y, const void *beta); +}; // namespace cce + +#endif // DNN_OP_H__ diff --git a/third_party/fwkacllib/inc/cce/dnn_struct.hpp b/third_party/fwkacllib/inc/cce/dnn_struct.hpp new file mode 100644 index 00000000..96566074 --- /dev/null +++ b/third_party/fwkacllib/inc/cce/dnn_struct.hpp @@ -0,0 +1,23 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef DNN_STRUCT_HPP__ +#define DNN_STRUCT_HPP__ + +#include "dnn.h" +#include "dnn_struct_base.hpp" + +#endif // DNN_STRUCT_HPP__ diff --git a/third_party/fwkacllib/inc/cce/dnn_struct_base.hpp b/third_party/fwkacllib/inc/cce/dnn_struct_base.hpp new file mode 100644 index 00000000..dd75e9ea --- /dev/null +++ b/third_party/fwkacllib/inc/cce/dnn_struct_base.hpp @@ -0,0 +1,894 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef DNN_STRUCT_BASE_HPP__ +#define DNN_STRUCT_BASE_HPP__ + +#include "cce/cce_def.hpp" + +namespace cce { + +/** + * @ingroup dnn + * @brief max number of dimensions + */ +#define CC_DIM_MAX (8) + +/** + * @ingroup dnn + * @brief max number of dimensions when use NC1HWC0 format + */ +#define CC_REALDIM_MAX (4) + +/** + * @ingroup dnn + * @brief max input count of MscnnBoxOutput + */ +#define CC_MAX_INPUT_CNT (10) + +/** + * @ingroup dnn + * @brief image dimensions of aipp input + */ +#define CC_AIPP_IMG_DIM (2) + +/** + * @ingroup dnn + * @brief image channel number of aipp input + */ +#define CC_AIPP_IMG_CHN_NUM (4) + +/** + * @ingroup dnn + * @brief element number of aipp color space convertion matrix + */ +#define CC_AIPP_CSC_MATRIX_DIM (9) + +/** + * @ingroup dnn + * @brief element number of aipp color space convertion bias + */ +#define CC_AIPP_CSC_BIAS_DIM (3) + +/** + * @ingroup dnn + * @brief parameter number of op exp/log/pow + */ +#define PARAM_CNT_THREE (3) + +/** + * @ingroup dnn + * @brief parameter number of op nonmaxsuppression + */ +#define PARAM_CNT_TWO (2) +#define DIMCNT_NUMBER_ONE (1) +#define DIMCNT_NUMBER_TWO (2) +#define DIMCNT_NUMBER_FOUR (4) + +#define COMMON_FORMAT_NCHW_N_INDEX (0) +#define COMMON_FORMAT_NCHW_C_INDEX (1) +#define COMMON_FORMAT_NCHW_H_INDEX (2) +#define COMMON_FORMAT_NCHW_W_INDEX (3) + +/** + * @ingroup dnn + * @brief parameter number of op upsample + */ +#define UPSAMPLE_SCAL_DEFAULT_TWO (2) +#define UPSAMPLE_ILLEGAL_VALUE_1 (1) + +/** + * @ingroup dnn + * @brief struct define of StridedSlice required params. + */ + +typedef struct tagCcStridedSlice { + uint32_t dimCnt; + int32_t begin[CC_DIM_MAX]; + int32_t end[CC_DIM_MAX]; + int32_t strides[CC_DIM_MAX]; +} ccStridedSlice_t; + +/** + * @ingroup dnn + * @brief struct define of Strided_slice attrs + */ +typedef struct tagCcStridedSliceAttrs { + uint32_t beginMask; + uint32_t endMask; + uint32_t ellipsisMask; + uint32_t newAxisMask; + uint32_t shrinkAxisMask; +} ccStridedSliceAttrs_t; + +/** + * @ingroup dnn + * @brief params of batchToSpace + */ +typedef struct tagCcBatchToSpace { + int32_t blockShapeLength; + int32_t blockShape[CC_DIM_MAX]; + int32_t crops[2 * CC_DIM_MAX]; +} ccBatchToSpace_t; + +/** + * @ingroup dnn + * @brief params of spaceToBatch + */ +typedef struct tagCcSpaceToBatch { + int32_t blockShapeLength; + int32_t blockShape[CC_DIM_MAX]; + int32_t paddings[2 * CC_DIM_MAX]; +} ccSpaceToBatch_t; + +/** + * @ingroup dnn + * @brief struct define of tensor + */ +typedef struct tagCcTensor { + ccTensorFormat_t format; + ccDataType_t dataType; + int32_t dimCnt; + int32_t realDimCnt; + uint32_t dataSize; + int32_t dim[CC_DIM_MAX]; + int32_t stride[CC_DIM_MAX]; + ccVecQuantizePara_t vecQuantizePara; +} ccTensor_t; + +/** + * @ingroup dnn + * @brief struct define of filter tensor + */ +typedef struct tagCcFilter { + ccTensorFormat_t format; + ccDataType_t dataType; + int32_t dimCnt; + uint32_t dataSize; + int32_t dim[CC_DIM_MAX]; +} ccFilter_t; + +/** + * @ingroup dnn + * @brief struct define of convolution operator + */ +typedef struct tagCcConvolution { + ccConvolutionMode_t mode; + ccPaddingMode_t padMode; + int32_t dimCnt; + int32_t padding[2 * (CC_DIM_MAX - 2)]; + int32_t filterStride[CC_DIM_MAX - 2]; + int32_t dilation[CC_DIM_MAX - 2]; + int32_t group; + ccQuantizeDescriptor_t quantInfo; + ccConvolutionAipp_t aippInfo; + int32_t adj[CC_DIM_MAX - 2]; + int32_t targetShape[CC_DIM_MAX - 2]; + int32_t beforePadding[2 * (CC_DIM_MAX - 2)]; // pad before conv + uint32_t reluFlag; + int64_t concatBatchSize; +} ccConvolution_t; + +#define ccCorrelation_t ccConvolution_t +typedef struct tagCcFullConnection_t { + ccQuantizeDescriptor_t quantInfo; + uint32_t infoTabSize; + const void *infoTab; + bool reluFlag; + ccFullConnectFwdAlgo_t algo; +} ccFullConnection_t; + +typedef struct tagCcConcatFour2Five_t { + uint32_t branchNum; // how many branch for box or class + uint32_t classNum; // box branch's classNum is four, class branch's classNum is class number +} ccConcatFour2Five_t; + +typedef struct tagCcTransdata_t { + uint64_t scaleQAddr; + uint8_t scaleQValueMode; + uint64_t offsetQAddr; + uint8_t quantAlgo; + uint8_t quantize8bitFlag; +} ccTransdata_t; +/** + * @ingroup dnn + * @brief struct define of pooling operator + */ +typedef struct tagCcPooling { + ccPoolingMode_t mode; + ccPaddingMode_t padMode; + ccNanPropagation_t maxpoolingNanOpt; + int32_t dimCnt; + int32_t windowDim[CC_DIM_MAX - 2]; + int32_t padding[CC_DIM_MAX - 2]; + int32_t stride[CC_DIM_MAX - 2]; + int32_t dataMode; + int32_t ceilMode; + ccQuantizeDescriptor_t quantInfo; + ccPooingFwdAlgo_t algo; +} ccPooling_t; + +/** + * @ingroup dnn + * @brief struct define of activation operator + */ +typedef struct tagCcActivation { + ccActivationMode_t mode; + ccNanPropagation_t reluNanOpt; + double coef; /* ceiling for clipped RELU, alpha for ELU */ + ccActivationPara_u activationPara; +} ccActivation_t; + +/** + * @ingroup dnn + * @brief struct define of svdf operator + */ +typedef struct tagCcSvdf { + ccTensorFormat_t format; + ccDataType_t dataType; + uint32_t batches; + uint32_t features; + uint32_t rank; + uint32_t inputSize; + uint32_t memorySize; +} ccSvdf_t; + +/** + * @ingroup dnn + * @brief struct define of svdf operator + */ +typedef struct tagCcHashTableLookup { + ccTensorFormat_t format; + ccDataType_t lookupType; + ccDataType_t keyType; + ccDataType_t valueType; + ccDataType_t outputType; + ccDataType_t hitsType; + uint32_t lookups; + uint32_t keys; + uint32_t rows; + uint32_t features; + uint16_t valueScale; + uint16_t outputScale; + uint16_t valueOffset; + uint16_t outputOffset; +} ccHashTableLookup_t; + +/** + * @ingroup dnn + * @brief struct define of prelu operator + */ +typedef struct tagCcPRelu { + ccNanPropagation_t reluNanOpt; + int32_t slopeCount; + bool channelShared; +} ccPRelu_t; + +/** + * @ingroup dnn + * @brief struct define of crop operator + */ +typedef struct tagCcCrop { + int32_t startAxis; + int32_t offset[CC_DIM_MAX]; + int32_t offsetCnt; +} ccCrop_t; + +/** + * @ingroup dnn + * @brief struct define of SpatialTransformer operator + */ +typedef struct tagCcSpatialTransformer { + ccSamplerType_t samplerType; + ccDataType_t dataType; + int32_t dimCnt; + uint64_t dim[CC_DIM_MAX]; + uint64_t alignCorner; +} ccSpatialTransformer_t; + +/** + * @ingroup dnn + * @brief struct define of ShiftTransformer operator + */ +typedef struct tagCcShiftTransformer { + ccSamplerType_t samplerType; + double xPreDefined; + double yPreDefined; + bool xShift; + bool yShift; + int32_t gridH; + int32_t gridW; +} ccShiftTransformer_t; + +/** + * @ingroup dnn + * @brief struct define of FasterRcnnProposal operator + */ +typedef struct tagCcFasterRcnnProposal { + int32_t preNMStopK; + int32_t postNMStopK; + float nmsTresh; + float minSize; + float featStride; + float baseSize; + int32_t ratioCnt; + int32_t scaleCnt; + float *ratio; + float *scale; + int32_t imgH; + int32_t imgW; +} ccFasterRcnnProposal_t; + +/** + * @ingroup dnn + * @brief struct define of LRN operator + */ +typedef struct tagCcLRN { + ccLRNMode_t lrnMode; + int32_t lrnN; + double lrnAlpha; + double lrnBeta; + double lrnK; +} ccLRN_t; + +/** + * @ingroup dnn + * @brief struct define of instanceNorm + */ +typedef struct tagCcInstancenorm { + ccInstanceNormMode_t mode; + double epsilon; +} ccInstancenorm_t; + +/** + * @ingroup dnn + * @brief struct define of assignOp operator + */ +typedef struct tagCcAssignOp { + ccAssignOpMode_t assignOpMode; +} ccAssignOp_t; + +/** + * @ingroup dnn + * @brief struct define of arcSinCos operator + */ +typedef struct tagCcArcSinCos { + ccArcSinCosMode_t arcSinCosMode; +} ccArcSinCos_t; + +/** + * @ingroup dnn + * @brief struct define of Detectpostprocess operator + */ +typedef struct tagCcDetectpostprocess { + int32_t numClasses; + float confThreshold; + float nmsThreshold; + int32_t outTopK; + float bboxRegWeightsDx; + float bboxRegWeightsDy; + float bboxRegWeightsDw; + float bboxRegWeightsDh; +} ccDetectpostprocess_t; +/** + * @ingroup dnn + * @brief struct define of FasterRcnnDetectionOutput operator + */ +typedef struct tagCcFasterRcnnDetectionOutput { + int32_t numClasses; + float nmsThreshold; + float postConfThreshold; + int32_t imgH; + int32_t imgW; + int32_t batchSize; +} ccFasterRcnnDetectionOutput_t; + +/** + * @ingroup dnn + * @brief struct define of SsdDetectionOutput operator + */ +typedef struct tagCcSsdDetectionOutput { + int32_t numClasses; + int32_t backgroundLabelId; + double preConfThreshold; + int32_t preTopK; + double nmsThreshold; + double nmsEta; + ccBoxCodeType_t codeType; + int32_t outTopK; + bool shareLocation; + bool varianceEncodedInTarget; + uint32_t boxTypeNum; + float var[4]; + uint32_t variance_num; +} ccSsdDetectionOutput_t; + +/** + * @ingroup dnn + * @brief struct define of RefinedetDetectionOutput operator + */ +typedef struct tagCcRefinedetDetectionOutput { + int32_t numClasses; + int32_t backgroundLabelId; + double preConfThreshold; + int32_t preTopK; + double nmsThreshold; + double nmsEta; + ccBoxCodeType_t codeType; + int32_t outTopK; + bool shareLocation; + bool varianceEncodedInTarget; + uint32_t boxTypeNum; + float var[4]; + uint32_t variance_num; + double objectness_score; +} ccRefinedetDetectionOutput_t; + +/** + * @ingroup dnn + * @brief struct define of MsrGenerateRpnProposals operator + */ +typedef struct tagCcMsrGenerateRpnProposals { + int32_t preNmsTopK; + int32_t postNmsTopK; + float nmsThreshold; + float rpnMiniSize; + int32_t imgH; + int32_t imgW; + uint32_t boxTypeNum; + float scoreThreshold; +} ccMsrGenerateRpnProposals_t; + +/** + * @ingroup dnn + * @brief struct define of RetinaPostprocessor operator + */ +typedef struct tagCcRetinaPostprocessor { + int32_t numClasses; + int32_t maxDetections; + float nmsThreshold; + float scoreThreshold; + int32_t imgH; + int32_t imgW; + uint32_t boxTypeNum; + float mean[4]; + int32_t meanNum; + float std[4]; + int32_t stdNum; + int32_t outputNum; + bool ocrFlag; +} ccRetinaPostprocessor_t; + +/** + * @ingroup dnn + * @brief struct define of GenerateSsdAnchors operator + */ +typedef struct tagCcGenerateSsdAnchors { + int32_t featureMapShapeList[20]; + uint32_t featureMapShapeListSize; + int32_t boxSpecsNum[10]; + uint32_t boxSpecsNumSize; + float scales[10]; + uint32_t scalesNum; + float aspectRatios[10]; + uint32_t aspectRatiosNum; + int32_t baseAnchorSize[2]; + uint32_t baseAnchorSizeNum; + int32_t anchorStride[2]; + uint32_t anchorStrideNum; + int32_t anchorOffset[2]; + uint32_t anchorOffsetNum; + bool reduceBoxesInLowestLayer; + float minScale; + float maxScale; + int32_t imgH; + int32_t imgW; +} ccGenerateSsdAnchors_t; + +/** + * @ingroup dnn + * @brief struct define of MscnnBoxOutput operator + */ +typedef struct tagCcMscnnBoxOutput { + double fgThreshold; + double nmsThreshold; + ccNmsType_t nmsType; + int32_t fieldH[CC_MAX_INPUT_CNT]; + int32_t fieldW[CC_MAX_INPUT_CNT]; + int32_t downsampleRate[CC_MAX_INPUT_CNT]; + int32_t defaultBoxCnt; + double fieldWhr; + double fieldXyr; + int32_t maxNmsNum; + int32_t maxPostNmsNum; + double minSize; +} ccMscnnBoxOutput_t; + +/** + * @ingroup dnn + * @brief struct define of NMS operator + */ +typedef struct tagCcNms { + int32_t numClasses; + int32_t backgroundLabelId; + double preConfThreshold; + int32_t preTopK; + double nmsThreshold; + double nmsEta; + int32_t postTopK; + int32_t outTopK; + double postConfThreshold; + bool shareLocation; +} ccNms_t; + +/** + * @ingroup dnn + * @brief struct define of NMS/MultiClassNMS operator + */ +typedef struct tagCcMultiClassNms { + uint64_t numClasses; + float objThreshold; + float nmsThreshold; + float clsThreshold; + bool normal; + uint64_t coorType; +} ccCcMultiClassNms_t; + +/** + * @ingroup dnn + * @brief struct define of YoloDetectionOutput operator + */ +typedef struct tagCcYoloDetectionOutput { + ccYoloVersion_t yoloVersion; + uint32_t netH; + uint32_t netW; + uint32_t postTopK; + uint32_t classes; + float nmsThreshold; + float iouThreDecay; + float coorScaleFactor; + bool relative; + float objThreshold; + float clsThreshold; + uint32_t biasNum; + float *bias; +} ccYoloDetectionOutput_t; + +/** + * @ingroup dnn + * @brief struct define of GetRegionBox operator + */ +#ifndef CC_MAX_YOLO_BIAS_NUM +#define CC_MAX_YOLO_BIAS_NUM (16) +#endif + +typedef struct tagCcGetRegionBox { + uint32_t biasNum; + uint32_t H; + uint32_t W; + float bias[CC_MAX_YOLO_BIAS_NUM]; +} ccGetRegionBox_t; + +/** + * @ingroup dnn + * @brief struct define of CorrectBoxes operator + */ +typedef struct tagCorrectBoxes { + uint32_t netW; + uint32_t netH; + bool relative; +} ccCorrectBoxes_t; + +/** + * @ingroup dnn + * @brief struct define of ClsProb operator + */ +typedef struct tagClsProb { + float objThreshold; +} ccClsProb_t; + +/** + * @ingroup dnn + * @brief struct define of SsdPriorBox operator + */ +typedef struct tagCcSsdPriorBox { + ccBoxCodeType_t codeType; + double *minSize; + int32_t minSizeNum; + double *maxSize; + int32_t maxSizeNum; + double *aspectRatio; + int32_t aspectRatioNum; + double *variance; + int32_t varianceNum; + int32_t imgH; + int32_t imgW; + double stepH; + double stepW; + double offset; + bool flip; + bool clip; +} ccSsdPriorBox_t; + +/** + * @ingroup dnn + * @brief struct define of Yolo2Region operator + */ +typedef struct tagCcYolo2Region { + ccSoftmaxTree_t softmaxTree; + bool softmax; + bool background; + bool treeSoftmax; +} ccYolo2Region_t; + +/** + * @ingroup dnn + * @brief struct define of YoloRegion operator + */ +typedef struct tagCcYoloRegion { + ccSoftmaxTree_t softmaxTree; + bool softmax; + bool background; + bool treeSoftmax; + int32_t classes; + int32_t coords; + int32_t boxes; + ccYoloVersion_t yoloV; +} ccYoloRegion_t; + +/** + * @ingroup dnn + * @brief struct define of power operator + */ +typedef struct tagCcPower { + float scale; + float shift; + float power; +} ccPower_t; + +/** + * @ingroup dnn + * @brief struct define of exp operator + */ +typedef struct tagCcExp { + ccDataType_t dataType; + uint32_t paramCnt; +} ccExp_t; + +/** + * @ingroup dnn + * @brief struct define of exp operator + */ +typedef struct tagCcLog { + ccDataType_t dataType; + uint32_t paramCnt; +} ccLog_t; + +/** + * @ingroup dnn + * @brief struct define of pow operator + */ +typedef struct tagCcPow { + ccDataType_t dataType; + uint32_t paramCnt; +} ccPow_t; + +/** + * @ingroup dnn + * @brief struct define of padv2 operator + */ +typedef struct tagCcPadV2 { + ccPadMode_t padMode; + void *padValue; + ccDataType_t padValueType; + int32_t padDimCnt; + int32_t padShapeLow[CC_DIM_MAX]; + int32_t padShapeHigh[CC_DIM_MAX]; +} ccPadV2_t; + +/** + * @ingroup dnn + * @brief struct define of psROIPooling operator + */ +typedef struct tagCcPsRoiPooling { + ccPoolingMode_t poolingMode; + int32_t pooledH; + int32_t pooledW; + float spatialScale; + float padRatio; + int32_t groupSize; + int32_t outputDim; +} ccPsRoiPooling_t; + +/** + * @ingroup dnn + * @brief struct define of RoIAlign operator + */ +typedef struct tagCcRoiAlign { + int32_t pooledH; + int32_t pooledW; + float spatialScale; + int32_t samplingRatio; +} ccRoiAlign_t; + +/** + * @ingroup dnn + * @brief struct define of RoiInterpPooling operator + */ +typedef struct tagCcRoiInterpPooling { + int32_t pooledH; + int32_t pooledW; + int32_t poolKernelH; + int32_t poolKernelW; + int32_t pooledTailH; + int32_t pooledTailW; + float spatialScaleH; + float spatialScaleW; +} ccRoiInterpPooling_t; + +/** + * @ingroup dnn + * @brief struct define of DetectionFull3DOutput operator + */ +typedef struct tagCcDetectionFull3DOutput { + int32_t imageWidth; + int32_t imageHeight; + int32_t numAngleBins; + float trcMarginRatioX; + float trcMarginRatioY; + int32_t pitchRangeD; + int32_t pitchPresetD; + float mountHeight; + int32_t visiblenessBins; + float meanVisibleness; + bool discreteVisibleness; +} ccDetectionFull3DOutput_t; + +/** + * @ingroup dnn + * @brief struct define of MsrFastRcnnPredictions operator + */ +typedef struct tagMsrFastRcnnPredictions { + int32_t numClasses; // num of classes + float scoreThreshold; // the threshold of the score + double nmsThreshold; // the threshold of nms + int32_t postTopK; + int32_t outTopK; + int32_t imgH; // the height of image + int32_t imgW; // the width of image +} ccMsrFastRcnnPredictions_t; + +typedef struct tagCcResizeBilinear { + ccResizeOutputDimMode_t resizeOutputDimMode; + bool alignCorners; + int32_t zoom_factor; + int32_t shrink_factor; + int32_t height; + int32_t width; + int32_t pad_begin; + int32_t pad_end; +} ccResizeBilinear_t; + +typedef struct tagCcResizeNearestNeighbor { + bool alignCorners; + int32_t height; + int32_t width; +} ccResizeNearestNeighbor_t; + +typedef struct tagCcEltwise { + ccQuantize_t *quantInfo; + bool reluFlag; +} ccEltwise_t; + +typedef struct tagCcBatchNorm { + bool reluFlag; +} ccBatchNorm_t; + +typedef struct tagCcPad { + ccPadMode_t padMode; + float padValue; + int32_t htoppad; // padLow[0] + int32_t hbottompad; // padHigh[0] + int32_t wleftpad; // padLow[1] + int32_t wrightpad; // padHigh[1] +} ccPad_t; + +typedef struct tagCcSubCondition { + uint32_t BaseCondValue[4]; + ccCMPType_t condType[4]; + ccResultType_t resultType; +} ccSubCondition; + +typedef struct tagCcShapeClassifyCond { + uint32_t subConditionNum; + ccResultType_t resultType; + uint32_t true_value; + ccSubCondition subCond[2]; +} ccShapeClassifyCond; + +#ifndef CC_SHAPE_CLASSIFY_CONDITION_NUM +#define CC_SHAPE_CLASSIFY_CONDITION_NUM (8) +#endif + +typedef struct tagCcShapeClassify { + uint32_t shapeClassifyConditionNum; + uint32_t defaultValue; + ccShapeClassifyCond shapeClassifyCond[CC_SHAPE_CLASSIFY_CONDITION_NUM]; +} ccShapeClassify_t; + +/** + * @ingroup dnn + * @bref struct define of square operator + */ +typedef struct tagCcSquare { + ccSquareMode_t mode; +} ccSquare_t; + +/* + * @ingroup dnn + * @brief operation of segment reduction + */ +typedef enum { + CC_SEGMENT_REDUCTION_OP_SUM = 0, /**< sum */ + CC_SEGMENT_REDUCTION_OP_INVALID +} ccSegmentReductionOpType_t; + +typedef struct tagCcFillParam { + // The filler type. + ccFillOpType_t fillType; + ccDataType_t valueDatatype; + const void *value; // the value in constant fill + const void *min; // the min value in uniform fill + const void *max; // the max value in uniform fill + const void *mean; // the mean value in Gaussian fill + const void *std; // the std value in Gaussian fill + // the seed used to generate data in Gaussian and uniform fill + int64_t seed1; + int64_t seed2; +} ccFillParam_t; + +typedef struct tagNonMaxSuppression { + ccDataType_t dataType; + uint32_t paraCount; +} ccNonMaxSuppression_t; + +typedef struct tagCcArgmaxmin { + int32_t axisType; + bool outMaxVal; + int64_t topK; + int64_t reduceSize; + int64_t reduceStride; + int64_t axis; + bool keepDims; +} ccArgmaxmin_t; + +typedef struct tagUpsamplePara { + int32_t scale; + int32_t scaleHeight; + int32_t scaleWidth; + int32_t upsampleHeight; + int32_t upsampleWidth; + bool padOutHeight; + bool padOutWidth; +} ccUpsamplePara_t; + +typedef struct tagCcConcatFive2Four_t { + ccTransForLossMode_t mode; + uint32_t classNum; +} ccConcatFive2Four_t; + +}; // namespace cce +#endif // DNN_STRUCT_BASE_HPP__ diff --git a/third_party/fwkacllib/inc/cce/fwk_adpt_struct.h b/third_party/fwkacllib/inc/cce/fwk_adpt_struct.h new file mode 100644 index 00000000..5733d68f --- /dev/null +++ b/third_party/fwkacllib/inc/cce/fwk_adpt_struct.h @@ -0,0 +1,155 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef FWK_ADPT_STRUCT_H__ +#define FWK_ADPT_STRUCT_H__ + +#include + +namespace aicpu { +namespace FWKAdapter { + +// API RETURN CODE +enum FWKAdptAPIRetCode { + FWK_ADPT_SUCCESS = 0, // success + FWK_ADPT_NOT_INIT = 1, // not init + FWK_ADPT_ALLOC_FAILED = 2, // allocate memory failed + FWK_ADPT_PARAM_INVALID = 3, // invalid input param + FWK_ADPT_PARAM_PARSE_FAILED = 4, // parase input param failed + FWK_ADPT_NATIVE_ERROR = 5, // error code + FWK_ADPT_NOT_SUPPORT_OPTYPE = 6, // unsupport operate type + FWK_ADPT_INTERNAL_ERROR = 7, // adpter internal error + FWK_ADPT_NOT_SUPPORT_DATATYPE = 8, // unsupport input/output data type + FWK_ADPT_KERNEL_ALREADY_RUNING = 9, // kernel already runing, not support parallel run + FWK_ADPT_SESSION_NOT_EXIST = 10, // session id not exist + FWK_ADPT_SESSION_ALREADY_EXIST = 11, // session id alread exist for create session + FWK_ADPT_NATIVE_END_OF_SEQUENCE = 12, // end of sequence + FWK_ADPT_EXTEND_TYPE_NOT_EXIST = 13, // extend info type not exist + FWK_ADPT_UNKNOWN_ERROR = 99 // unknown error code +}; + +// FWKAdapter operate type +// Notice: add new operate type need check with OMM, and make sure append to the end line. +enum FWKOperateType { + FWK_ADPT_SESSION_CREATE = 0, + FWK_ADPT_KERNEL_RUN, + FWK_ADPT_KERNEL_DESTROY, + FWK_ADPT_SESSION_DESTROY, + FWK_ADPT_SINGLE_OP_RUN, + FWK_ADPT_KERNEL_RUN_NO_SESS, +}; + +// Extend Info type for task +enum FWKTaskExtInfoType { + FWK_ADPT_EXT_SHAPE_TYPE = 0, + FWK_ADPT_EXT_INPUT_SHAPE, + FWK_ADPT_EXT_OUTPUT_SHAPE, + FWK_ADPT_EXT_UPDATE_ADDR, + FWK_ADPT_EXT_OP_NAME, + FWK_ADPT_EXT_SESSION_INFO, + FWK_ADPT_EXT_BITMAP, + FWK_ADPT_EXT_TOPIC_TYPE, + FWK_ADPT_EXT_ASYNCWAIT, + FWK_ADPT_EXT_INVALID +}; + +enum FWKExtTopicType { + FWK_ADPT_TOPIC_DEVICE_ONLY = 0, + FWK_ADPT_TOPIC_DEVICE_FIRST, + FWK_ADPT_TOPIC_HOST_ONLY, + FWK_ADPT_TOPIC_HOST_FIRST, + FWK_ADPT_TOPIC_INVALID +}; + +enum FWKExtUpdateAddrType { + FWK_ADPT_UPDATE_NULL = 0, + FWK_ADPT_UPDATE_INPUT, + FWK_ADPT_UPDATE_OUTPUT, + FWK_ADPT_UPDATE_INPUT_OUTPUT +}; + +enum FWKExtWaitType { + FWK_ADPT_WAIT_TYPE_NULL = 0, + FWK_ADPT_WAIT_TYPE_EVENT, + FWK_ADPT_WAIT_TYPE_INVALID +}; + +#pragma pack(push, 1) +// API Parameter Structure +struct StrFWKKernel { + FWKOperateType opType; + uint64_t sessionID; // unique + + uint64_t stepIDAddr; // step id addr + uint64_t kernelID; // run kernel id, unique in session + uint64_t nodeDefLen; // nodeDef protobuf len + uint64_t nodeDefBuf; // NodeDef protobuf offset addr, need convert to void* + uint64_t funDefLibLen; // FunctionDefLibrary protobuf len + uint64_t funDefLibBuf; // FunctionDefLibrary protobuf addr which use in NodeDef, need convert to void* + + uint64_t inputOutputLen; // InputOutput shap protobuf len + uint64_t inputOutputBuf; // InputOutput shap protobuf addr, need convert to void* + uint64_t workspaceBaseAddr; // Workspace base addr, need convert to void* + uint64_t inputOutputAddr; // InputOutput addr, need convert to void* + + uint64_t extInfoLen; // extend info total length + uint64_t extInfoAddr; // extend info addr, ExtInfo structure +}; +#pragma pack(pop) + +typedef StrFWKKernel FWKOperateParam; + +// Extent info ShapeAndType +const uint32_t kMaxShapeDims = 8; +#pragma pack(push, 1) +struct ShapeAndType { + int32_t type; + int64_t dims[kMaxShapeDims]; +}; +#pragma pack(pop) + +// Extend info structure for extInfoAddr +const uint32_t kExtInfoHeadSize = 8; + +#pragma pack(push, 1) +struct ExtInfo { + int32_t infoType; // extend type + uint32_t infoLen; // length for infoMsg + char infoMsg[0]; // extend value +}; +#pragma pack(pop) + +#pragma pack(push, 1) +struct ResultSummary { + uint64_t shape_data_ptr; // shape data addr, need convert to void* + uint64_t shape_data_size; // num of dims + uint64_t raw_data_ptr; // raw data addr, need convert to void* + uint64_t raw_data_size; // size of raw data +}; +#pragma pack(pop) + +#pragma pack(push, 1) +struct AsyncWait { + uint8_t waitType; // wait type, FWK_ADPT_WAIT_TYPE_EVENT: event wait + uint32_t waitId; // wait id, GE refresh + uint32_t timeOut; // reserved + uint64_t reserved; +}; +#pragma pack(pop) +} // end namespace FWKAdapter +} // namespace aicpu + +#endif // FWK_ADPT_STRUCT_H__ diff --git a/third_party/fwkacllib/inc/cce/l2fusion_struct.hpp b/third_party/fwkacllib/inc/cce/l2fusion_struct.hpp new file mode 100644 index 00000000..fa5a95c9 --- /dev/null +++ b/third_party/fwkacllib/inc/cce/l2fusion_struct.hpp @@ -0,0 +1,56 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef L2FUSION_STRUCT_HPP_ +#define L2FUSION_STRUCT_HPP_ + +#include +#include +#include "runtime/kernel.h" + +#define L2_DYNAMIC_SPLIT_NUM + +using namespace std; + +namespace fusion { + +typedef struct tagL2Data { + uint32_t l2Index; + uint64_t l2Addr; + uint64_t l2PageNum; +} L2Data_t; + +typedef std::map L2DataMap_t; // the key is ddr addr +typedef std::pair L2DataPair_t; // the key is ddr addr + +typedef struct TagTaskL2Info { + string nodeName; + rtL2Ctrl_t l2ctrl; + + L2DataMap_t input; + L2DataMap_t output; + uint32_t isUsed; +} TaskL2Info_t; + +typedef std::map TaskL2InfoMap_t; // the key is nodeId +typedef std::pair TaskL2InfoPair_t; // the key is nodeId + +typedef std::map TaskL2InfoFEMap_t; // the key is nodeName +typedef std::pair TaskL2InfoFEPair_t; // the key is nodeName + +} // namespace fusion + +#endif // L2FUSION_STRUCT_HPP_ diff --git a/third_party/fwkacllib/inc/cce/optimizer/fusion_engine.h b/third_party/fwkacllib/inc/cce/optimizer/fusion_engine.h new file mode 100644 index 00000000..299998e3 --- /dev/null +++ b/third_party/fwkacllib/inc/cce/optimizer/fusion_engine.h @@ -0,0 +1,65 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef FUSION_ENGINE_HPP_ +#define FUSION_ENGINE_HPP_ + +#include "cce/cce.h" +#include "graph/compute_graph.h" +#include "proto/task.pb.h" + +#include +#include + +using namespace domi; +using namespace std; + +namespace fusion { +enum { + FUSION_STATUS_SUCCESS = 0, + FUSION_STATUS_FAIL = 1, +}; + +typedef struct { + uint64_t weightSize; + uint64_t memorySize; + uint8_t *dataMemBase; + uint8_t *weightMemBase; + uint32_t l2Enable; // 1 //1 - enable l2 buffer allocation, 0 - disable l2 buffer allocation + uint32_t fusionEnable; // 1 // 1 - enable buffer fusion, 0 - disable buffer fusion +} ModelRes; + +static const std::string SCOPE_ID_ATTR = "fusion_scope"; +static const std::string L2FUSION_DYNAMIC_CONVERGE_OP = "l2fusion_dynamic_converge_op"; +static const std::string L2FUSION_DYNAMIC_SPLIT_NUM = "l2fusion_dynamic_split_num"; +static const std::string FUSION_VIRTUAL_OP = "fusion_virtual_op"; +static const std::string FUSION_MULTI_BATCH_STRIDE = "fusion_multi_bathc_stride"; + +#define TVM_TYPE 1 + +typedef std::map> kScopeNodeMap_t; +typedef std::pair> kScopeNodePair_t; + +uint32_t BufferFusion(ge::ComputeGraphPtr origGraph, ge::ComputeGraphPtr fusionGraph, bool enable_l2dynamic = true); +uint32_t BufferFusionTrain(ge::ComputeGraphPtr origGraph, ge::ComputeGraphPtr fusionGraph); +uint32_t GraphFusion(ge::ComputeGraphPtr origGraph, ge::ComputeGraphPtr fusionGraph); +uint32_t FusionTaskBuild(cce::ccHandle_t ccHandle, ge::ComputeGraphPtr fusionGraph, ge::Buffer &buffer, + ModelRes &modelRes, std::vector &task_def_list_); +void FusionTaskBuildComplete(std::vector cchandleList); +uint32_t GraphFusionTrain(ge::ComputeGraphPtr origGraph, ge::ComputeGraphPtr fusionGraph); +} // namespace fusion + +#endif // FUSION_ENGINE_HPP_ diff --git a/third_party/fwkacllib/inc/cce/taskdown_api.h b/third_party/fwkacllib/inc/cce/taskdown_api.h new file mode 100644 index 00000000..2323aaa7 --- /dev/null +++ b/third_party/fwkacllib/inc/cce/taskdown_api.h @@ -0,0 +1,54 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef TASKDOWN_API_H_ +#define TASKDOWN_API_H_ + +#include +#include +#include "cce/cce.h" +#include "l2fusion_struct.hpp" +#include "taskdown_common.hpp" + +namespace cce { + +#define CC_FUSION_OP_MAX 32 + +typedef struct tagOpAddrsInfo { + void *addrPos; + uintptr_t addrData; +} ccOpAddrsInfo; + +#ifdef __cplusplus +extern "C" { +#endif + +ccStatus_t ccUpdateKernelArgs(ccOpContext &opContext, uint64_t dataBaseAddr, uint64_t weightBaseAddr, + uint64_t variableBaseAddr, void *argsAddr, uint64_t argsSize, void *l2ctrlAddr); + +#ifdef __cplusplus +} +#endif + +ccStatus_t ccGetKernelArgsAddrs(ccOpContext &opContext, void *argsAddr, uint64_t argsSize, void *l2ctrlAddr, + std::vector &opAddrsInfo); + +ccStatus_t ccSetKernelArgs(std::vector &dateInfo); + +ccStatus_t ccGetKernelTypeByOpId(uint32_t opId, ccKernelType &kernelType); + +} // namespace cce +#endif // TASKDOWN_API_H_ diff --git a/third_party/fwkacllib/inc/cce/taskdown_common.hpp b/third_party/fwkacllib/inc/cce/taskdown_common.hpp new file mode 100644 index 00000000..7954162e --- /dev/null +++ b/third_party/fwkacllib/inc/cce/taskdown_common.hpp @@ -0,0 +1,108 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef TASKDOWN_COMMON_H_ +#define TASKDOWN_COMMON_H_ + +#include +#include "cce/cce_def.hpp" +#include "common/attr_list.hpp" +#include "l2fusion_struct.hpp" + +namespace cce { + +#define CC_FUSION_OP_MAX 32 + +typedef enum tagccKernelType { + CCE_AI_CORE = 0, /* cce aicore */ + CCE_AI_CPU = 1, /* cce aicpu */ + TE = 2, /* te operator*/ + CUSTOMIZED = 3, /* customized operator */ + TE_AI_CORE = 4, /* te aicore operator*/ + TE_AI_CPU = 5, /* te aicpu operator */ + AI_CPU = 6, /* aicpu */ + CUST_AI_CPU = 7, /* custom aicpu*/ + HOST_CPU = 8, /* host cpu */ + INVALID = 10000 /* unknown kernel type */ +} ccKernelType; + +typedef struct tagOpContext { + ccKernelType kernelType; + uint32_t opId; + uint32_t kernelFuncId; + uint32_t opIndex; + uint32_t opCount; + uint32_t opIndex2[CC_FUSION_OP_MAX]; + bool isFlowtable; + uint16_t *argsOffset; + uint32_t argsCount; + uint64_t genDataBaseAddr; + uint64_t genDataBaseSize; + uint64_t genWeightBaseAddr; + uint64_t genWeightBaseSize; + uint64_t genVariableBaseAddr; + uint64_t genVariableBaseSize; + uint64_t l2ctrlSize; +} ccOpContext; + +typedef struct tagOpReadCount { + bool isEnable; + std::map tensorRc; +} ccOpReadCount; + +typedef enum tagTaskDownKernelIdMode { + CC_TASKDOWN_RESERVED = 0, + CC_TASKDOWN_ROIPOOLING, + CC_TASKDOWN_ROIPOOLING_PERF, + CC_TASKDOWN_ROIALIGN, + CC_TASKDOWN_ROIALIGN_PERF, + CC_TASKDOWN_FC, + CC_TASKDOWN_FC_COMPRESS, + CC_TASKDOWN_SOFTMAX_LOWEST, + CC_TASKDOWN_ROIALIGN_FP16, + CC_TASKDOWN_RESIZE_NEAREST_NEIGHBOR, + CC_TASKDOWN_RESIZE_NEAREST_NEIGHBOR_COMMON, +} ccTaskDownKernelIdMode_t; + +ccStatus_t GetStream(ccHandle_t handle, rtStream_t *streamId); + +ccStatus_t ccClearOpMap(ccHandle_t handle); + +ccStatus_t ccSetKernelOpMap(ccHandle_t handle); + +ccStatus_t ccSetKernelContext(ccHandle_t handle, uint32_t opId, AttrList &attrList, bool isFlowtable, + ccKernelType kernelType, void *pgraph); + +ccStatus_t ccGetKernelContext(rtStream_t streamId, ccOpContext &opContext); + +ccStatus_t ccGetKernelTypeByOpId(uint32_t opId, ccKernelType &kernelType); + +ccStatus_t ccSetStreamL2Map(ccHandle_t handle, fusion::TaskL2InfoMap_t &l2AllocRes); + +ccStatus_t ccGetStreamL2Map(rtStream_t streamId, uint32_t opIndex, fusion::TaskL2Info_t *&l2Data); + +ccStatus_t ccSetOpIndex(ccHandle_t handle, uint32_t opIndex); + +ccStatus_t ccGetOpIndex(ccHandle_t handle, uint32_t &opIndex); + +ccStatus_t ccGetOpIndexByStream(rtStream_t streamId, uint32_t &opIndex); + +ccStatus_t ccClearStreamL2Map(ccHandle_t handle); + +ccStatus_t ccGetKernelReadCount(rtStream_t streamId, ccOpReadCount &rc); + +} // namespace cce +#endif // TASKDOWN_COMMON_H_ From 9f12d87664b19ba03c60c09875628552d03abc4e Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Mon, 6 Dec 2021 18:57:35 +0800 Subject: [PATCH 47/59] update acl_prof --- inc/external/acl/acl_prof.h | 107 +++++++++++++++++++++++++----------- 1 file changed, 76 insertions(+), 31 deletions(-) diff --git a/inc/external/acl/acl_prof.h b/inc/external/acl/acl_prof.h index 3784d8c6..2ad13063 100644 --- a/inc/external/acl/acl_prof.h +++ b/inc/external/acl/acl_prof.h @@ -17,16 +17,26 @@ #ifndef INC_EXTERNAL_ACL_PROF_H_ #define INC_EXTERNAL_ACL_PROF_H_ +#if (defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)) +#define MSVP_PROF_API __declspec(dllexport) +#else +#define MSVP_PROF_API __attribute__((visibility("default"))) +#endif + #include "acl_base.h" #ifdef __cplusplus extern "C" { #endif -#define ACL_PROF_ACL_API 0x0001 -#define ACL_PROF_TASK_TIME 0x0002 -#define ACL_PROF_AICORE_METRICS 0x0004 -#define ACL_PROF_AICPU 0x0008 +#define ACL_PROF_ACL_API 0x0001ULL +#define ACL_PROF_TASK_TIME 0x0002ULL +#define ACL_PROF_AICORE_METRICS 0x0004ULL +#define ACL_PROF_AICPU 0x0008ULL +#define ACL_PROF_L2CACHE 0x0010ULL +#define ACL_PROF_HCCL_TRACE 0x0020ULL +#define ACL_PROF_TRAINING_TRACE 0x0040ULL +#define ACL_PROF_MSPROFTX 0x0080ULL /** * @deprecated please use aclprofGetOpTypeLen and aclprofGetOpTNameLen instead @@ -40,13 +50,20 @@ typedef enum { ACL_AICORE_MEMORY_BANDWIDTH = 2, ACL_AICORE_L0B_AND_WIDTH = 3, ACL_AICORE_RESOURCE_CONFLICT_RATIO = 4, + ACL_AICORE_MEMORY_UB = 5, ACL_AICORE_NONE = 0xFF } aclprofAicoreMetrics; +typedef enum { + ACL_STEP_START = 0, // step start + ACL_STEP_END = 1 // step end +} aclprofStepTag; + typedef struct aclprofConfig aclprofConfig; typedef struct aclprofStopConfig aclprofStopConfig; typedef struct aclprofAicoreEvents aclprofAicoreEvents; typedef struct aclprofSubscribeConfig aclprofSubscribeConfig; +typedef struct aclprofStepInfo aclprofStepInfo; /** * @ingroup AscendCL @@ -60,7 +77,7 @@ typedef struct aclprofSubscribeConfig aclprofSubscribeConfig; * * @see aclprofFinalize */ -ACL_FUNC_VISIBILITY aclError aclprofInit(const char *profilerResultPath, size_t length); +MSVP_PROF_API aclError aclprofInit(const char *profilerResultPath, size_t length); /** * @ingroup AscendCL @@ -71,7 +88,7 @@ ACL_FUNC_VISIBILITY aclError aclprofInit(const char *profilerResultPath, size_t * * @see aclprofInit */ -ACL_FUNC_VISIBILITY aclError aclprofFinalize(); +MSVP_PROF_API aclError aclprofFinalize(); /** * @ingroup AscendCL @@ -84,7 +101,7 @@ ACL_FUNC_VISIBILITY aclError aclprofFinalize(); * * @see aclprofStop */ -ACL_FUNC_VISIBILITY aclError aclprofStart(const aclprofConfig *profilerConfig); +MSVP_PROF_API aclError aclprofStart(const aclprofConfig *profilerConfig); /** * @ingroup AscendCL @@ -100,9 +117,9 @@ ACL_FUNC_VISIBILITY aclError aclprofStart(const aclprofConfig *profilerConfig); * * @see aclprofDestroyConfig */ -ACL_FUNC_VISIBILITY aclprofConfig *aclprofCreateConfig(uint32_t *deviceIdList, uint32_t deviceNums, - aclprofAicoreMetrics aicoreMetrics, - aclprofAicoreEvents *aicoreEvents, uint64_t dataTypeConfig); +MSVP_PROF_API aclprofConfig *aclprofCreateConfig(uint32_t *deviceIdList, uint32_t deviceNums, + aclprofAicoreMetrics aicoreMetrics, aclprofAicoreEvents *aicoreEvents, + uint64_t dataTypeConfig); /** * @ingroup AscendCL @@ -115,7 +132,7 @@ ACL_FUNC_VISIBILITY aclprofConfig *aclprofCreateConfig(uint32_t *deviceIdList, u * * @see aclprofCreateConfig */ -ACL_FUNC_VISIBILITY aclError aclprofDestroyConfig(const aclprofConfig *profilerConfig); +MSVP_PROF_API aclError aclprofDestroyConfig(const aclprofConfig *profilerConfig); /** * @ingroup AscendCL @@ -128,7 +145,7 @@ ACL_FUNC_VISIBILITY aclError aclprofDestroyConfig(const aclprofConfig *profilerC * * @see aclprofStart */ -ACL_FUNC_VISIBILITY aclError aclprofStop(const aclprofConfig *profilerConfig); +MSVP_PROF_API aclError aclprofStop(const aclprofConfig *profilerConfig); /** * @ingroup AscendCL @@ -142,7 +159,7 @@ ACL_FUNC_VISIBILITY aclError aclprofStop(const aclprofConfig *profilerConfig); * * @see aclprofModelUnSubscribe */ -ACL_FUNC_VISIBILITY aclError aclprofModelSubscribe(uint32_t modelId, const aclprofSubscribeConfig *profSubscribeConfig); +MSVP_PROF_API aclError aclprofModelSubscribe(uint32_t modelId, const aclprofSubscribeConfig *profSubscribeConfig); /** * @ingroup AscendCL @@ -155,7 +172,7 @@ ACL_FUNC_VISIBILITY aclError aclprofModelSubscribe(uint32_t modelId, const aclpr * * @see aclprofModelSubscribe */ -ACL_FUNC_VISIBILITY aclError aclprofModelUnSubscribe(uint32_t modelId); +MSVP_PROF_API aclError aclprofModelUnSubscribe(uint32_t modelId); /** * @ingroup AscendCL @@ -169,8 +186,8 @@ ACL_FUNC_VISIBILITY aclError aclprofModelUnSubscribe(uint32_t modelId); * * @see aclprofDestroySubscribeConfig */ -ACL_FUNC_VISIBILITY aclprofSubscribeConfig *aclprofCreateSubscribeConfig(int8_t timeInfoSwitch, - aclprofAicoreMetrics aicoreMetrics, void *fd); +MSVP_PROF_API aclprofSubscribeConfig *aclprofCreateSubscribeConfig(int8_t timeInfoSwitch, + aclprofAicoreMetrics aicoreMetrics, void *fd); /** * @ingroup AscendCL @@ -183,7 +200,7 @@ ACL_FUNC_VISIBILITY aclprofSubscribeConfig *aclprofCreateSubscribeConfig(int8_t * * @see aclprofCreateSubscribeConfig */ -ACL_FUNC_VISIBILITY aclError aclprofDestroySubscribeConfig(const aclprofSubscribeConfig *profSubscribeConfig); +MSVP_PROF_API aclError aclprofDestroySubscribeConfig(const aclprofSubscribeConfig *profSubscribeConfig); /** * @ingroup AscendCL @@ -194,7 +211,7 @@ ACL_FUNC_VISIBILITY aclError aclprofDestroySubscribeConfig(const aclprofSubscrib * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclprofGetOpDescSize(size_t *opDescSize); +MSVP_PROF_API aclError aclprofGetOpDescSize(size_t *opDescSize); /** * @ingroup AscendCL @@ -207,7 +224,7 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpDescSize(size_t *opDescSize); * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclprofGetOpNum(const void *opInfo, size_t opInfoLen, uint32_t *opNumber); +MSVP_PROF_API aclError aclprofGetOpNum(const void *opInfo, size_t opInfoLen, uint32_t *opNumber); /** * @ingroup AscendCL @@ -221,8 +238,7 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpNum(const void *opInfo, size_t opInfoLe * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclprofGetOpTypeLen(const void *opInfo, size_t opInfoLen, uint32_t index, - size_t *opTypeLen); +MSVP_PROF_API aclError aclprofGetOpTypeLen(const void *opInfo, size_t opInfoLen, uint32_t index, size_t *opTypeLen); /** * @ingroup AscendCL @@ -237,8 +253,8 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpTypeLen(const void *opInfo, size_t opIn * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoLen, uint32_t index, char *opType, - size_t opTypeLen); +MSVP_PROF_API aclError aclprofGetOpType(const void *opInfo, size_t opInfoLen, uint32_t index, char *opType, + size_t opTypeLen); /** * @ingroup AscendCL @@ -252,8 +268,7 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpType(const void *opInfo, size_t opInfoL * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclprofGetOpNameLen(const void *opInfo, size_t opInfoLen, uint32_t index, - size_t *opNameLen); +MSVP_PROF_API aclError aclprofGetOpNameLen(const void *opInfo, size_t opInfoLen, uint32_t index, size_t *opNameLen); /** * @ingroup AscendCL @@ -268,8 +283,8 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpNameLen(const void *opInfo, size_t opIn * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ACL_FUNC_VISIBILITY aclError aclprofGetOpName(const void *opInfo, size_t opInfoLen, uint32_t index, char *opName, - size_t opNameLen); +MSVP_PROF_API aclError aclprofGetOpName(const void *opInfo, size_t opInfoLen, uint32_t index, char *opName, + size_t opNameLen); /** * @ingroup AscendCL @@ -282,7 +297,7 @@ ACL_FUNC_VISIBILITY aclError aclprofGetOpName(const void *opInfo, size_t opInfoL * @retval start time(us) of specified op with timestamp * @retval 0 for failed */ -ACL_FUNC_VISIBILITY uint64_t aclprofGetOpStart(const void *opInfo, size_t opInfoLen, uint32_t index); +MSVP_PROF_API uint64_t aclprofGetOpStart(const void *opInfo, size_t opInfoLen, uint32_t index); /** * @ingroup AscendCL @@ -295,7 +310,7 @@ ACL_FUNC_VISIBILITY uint64_t aclprofGetOpStart(const void *opInfo, size_t opInfo * @retval end time(us) of specified op with timestamp * @retval 0 for failed */ -ACL_FUNC_VISIBILITY uint64_t aclprofGetOpEnd(const void *opInfo, size_t opInfoLen, uint32_t index); +MSVP_PROF_API uint64_t aclprofGetOpEnd(const void *opInfo, size_t opInfoLen, uint32_t index); /** * @ingroup AscendCL @@ -308,7 +323,7 @@ ACL_FUNC_VISIBILITY uint64_t aclprofGetOpEnd(const void *opInfo, size_t opInfoLe * @retval execution time(us) of specified op with timestamp * @retval 0 for failed */ -ACL_FUNC_VISIBILITY uint64_t aclprofGetOpDuration(const void *opInfo, size_t opInfoLen, uint32_t index); +MSVP_PROF_API uint64_t aclprofGetOpDuration(const void *opInfo, size_t opInfoLen, uint32_t index); /** * @ingroup AscendCL @@ -320,7 +335,37 @@ ACL_FUNC_VISIBILITY uint64_t aclprofGetOpDuration(const void *opInfo, size_t opI * @retval model id of subscription data * @retval 0 for failed */ -ACL_FUNC_VISIBILITY size_t aclprofGetModelId(const void *opInfo, size_t opInfoLen, uint32_t index); +MSVP_PROF_API size_t aclprofGetModelId(const void *opInfo, size_t opInfoLen, uint32_t index); + +/** + * @ingroup AscendCL + * @brief + * + * @param stepInfo [IN] pointer to stepInfo data + * @param aclprofstepTag [IN] start or end flag + * @param stream [IN] steam info + * + * @retval 0 for failed + */ +MSVP_PROF_API aclError aclprofGetStepTimestamp(aclprofStepInfo *stepInfo, aclprofStepTag tag, aclrtStream stream); + +/** + * @ingroup AscendCL + * @brief create pointer to aclprofStepInfo data + * + * + * @retval aclprofStepInfo pointer + */ +MSVP_PROF_API aclprofStepInfo *aclprofCreateStepInfo(); + +/** + * @ingroup AscendCL + * @brief destroy aclprofStepInfo pointer + * + * + * @retval void + */ +MSVP_PROF_API void aclprofDestroyStepInfo(aclprofStepInfo *stepinfo); #ifdef __cplusplus } From 4f1e23945406395698e886f1e78527883d88db64 Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Fri, 11 Feb 2022 16:57:41 +0800 Subject: [PATCH 48/59] upgrade Ascend package 11 Feb 22 --- inc/external/acl/acl_base.h | 14 + inc/external/acl/acl_op_compiler.h | 51 ++ inc/external/acl/acl_prof.h | 74 +++ inc/external/acl/acl_rt.h | 18 + inc/external/acl/error_codes/ge_error_codes.h | 65 +-- inc/external/acl/error_codes/rt_error_codes.h | 8 +- inc/external/acl/ops/acl_dvpp.h | 8 +- inc/external/ge/ge_api_error_codes.h | 67 +-- inc/external/ge/ge_api_types.h | 278 +++++------ inc/external/ge/ge_ir_build.h | 8 +- inc/external/runtime/rt_error_codes.h | 2 +- inc/framework/common/debug/ge_log.h | 16 +- inc/framework/common/debug/log.h | 12 +- inc/framework/common/file_constant_util.h | 10 +- inc/framework/common/fmk_error_codes.h | 4 +- inc/framework/common/ge_inner_error_codes.h | 81 ++-- inc/framework/common/ge_types.h | 42 +- inc/framework/common/helper/model_helper.h | 4 +- inc/framework/common/helper/om_file_helper.h | 42 +- inc/framework/common/l2_cache_optimize.h | 90 +--- inc/framework/common/op/attr_value_util.h | 140 +----- inc/framework/common/op/ge_op_utils.h | 87 +--- inc/framework/common/op_types.h | 20 +- inc/framework/common/profiling/ge_profiling.h | 6 +- inc/framework/common/profiling_definitions.h | 173 +++++++ inc/framework/common/scope_guard.h | 6 +- inc/framework/common/string_util.h | 39 +- inc/framework/common/taskdown_common.h | 37 +- inc/framework/common/types.h | 307 ++---------- inc/framework/common/util.h | 209 ++++---- inc/framework/engine/dnnengine.h | 15 +- inc/framework/executor/ge_executor.h | 126 +++-- inc/framework/generator/ge_generator.h | 18 +- inc/framework/memory/memory_api.h | 4 - inc/framework/memory/memory_assigner.h | 2 +- inc/framework/omg/omg.h | 8 +- inc/framework/omg/omg_inner_types.h | 40 +- inc/framework/omg/parser/model_parser.h | 7 + inc/framework/omg/parser/op_parser.h | 8 +- inc/framework/omg/parser/parser_factory.h | 6 +- inc/framework/omg/parser/parser_inner_ctx.h | 6 +- inc/framework/omg/version.h | 4 +- metadef | 2 +- .../aicpu/aicpu_schedule/aicpu_op_type_list.h | 114 ++--- .../inc/aicpu/common/aicpu_task_struct.h | 47 ++ third_party/fwkacllib/inc/cce/aicpu_engine.h | 1 - .../fwkacllib/inc/cce/fwk_adpt_struct.h | 16 +- third_party/fwkacllib/inc/hccl/base.h | 19 +- third_party/fwkacllib/inc/hccl/hcom.h | 66 --- third_party/fwkacllib/inc/mmpa/mmpa_api.h | 24 +- .../fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h | 24 +- .../inc/mmpa/sub_inc/mmpa_typedef_linux.h | 3 + .../inc/mmpa/sub_inc/mmpa_typedef_win.h | 169 +++---- .../fwkacllib/inc/mmpa/sub_inc/mmpa_win.h | 24 +- third_party/fwkacllib/inc/ops/OWNERS | 65 +++ third_party/fwkacllib/inc/ops/array_ops.h | 117 ++++- third_party/fwkacllib/inc/ops/ctc_ops.h | 12 +- third_party/fwkacllib/inc/ops/data_flow_ops.h | 45 ++ third_party/fwkacllib/inc/ops/deep_md.h | 156 +++++- .../inc/ops/elewise_calculation_ops.h | 14 +- third_party/fwkacllib/inc/ops/image_ops.h | 20 +- third_party/fwkacllib/inc/ops/math_ops.h | 2 +- .../inc/ops/matrix_calculation_ops.h | 83 +++- .../fwkacllib/inc/ops/nn_batch_norm_ops.h | 68 +++ .../fwkacllib/inc/ops/nn_calculation_ops.h | 46 +- third_party/fwkacllib/inc/ops/nn_detect_ops.h | 98 +++- third_party/fwkacllib/inc/ops/nn_norm_ops.h | 96 +++- .../fwkacllib/inc/ops/nn_pooling_ops.h | 6 +- .../fwkacllib/inc/ops/nonlinear_fuc_ops.h | 29 +- .../fwkacllib/inc/ops/npu_loss_scale_ops.h | 27 ++ third_party/fwkacllib/inc/ops/ocr_ops.h | 1 + third_party/fwkacllib/inc/ops/random_ops.h | 161 ++++++- third_party/fwkacllib/inc/ops/randomdsa_ops.h | 139 ++++++ third_party/fwkacllib/inc/ops/reduce_ops.h | 123 +++++ third_party/fwkacllib/inc/ops/rnn.h | 38 ++ third_party/fwkacllib/inc/ops/selection_ops.h | 130 ++++- .../fwkacllib/inc/ops/split_combination_ops.h | 24 + third_party/fwkacllib/inc/ops/vector_search.h | 39 +- third_party/fwkacllib/inc/runtime/base.h | 13 +- third_party/fwkacllib/inc/runtime/config.h | 24 +- third_party/fwkacllib/inc/runtime/context.h | 2 +- third_party/fwkacllib/inc/runtime/dev.h | 6 +- .../fwkacllib/inc/runtime/dvfsprofile.h | 4 +- third_party/fwkacllib/inc/runtime/event.h | 15 + third_party/fwkacllib/inc/runtime/kernel.h | 46 +- third_party/fwkacllib/inc/runtime/mem.h | 24 + third_party/fwkacllib/inc/runtime/rt_dfx.h | 10 + .../fwkacllib/inc/runtime/rt_ffts_plus.h | 3 +- .../fwkacllib/inc/runtime/rt_mem_queue.h | 65 ++- third_party/fwkacllib/inc/runtime/rt_model.h | 33 +- third_party/fwkacllib/inc/runtime/rt_stars.h | 21 +- .../fwkacllib/inc/runtime/rt_stars_define.h | 58 +++ third_party/fwkacllib/inc/tdt/data_common.h | 21 +- .../fwkacllib/inc/tdt/index_transform.h | 20 +- third_party/fwkacllib/inc/tdt/status.h | 22 +- .../fwkacllib/inc/tdt/tdt_host_interface.h | 20 +- third_party/fwkacllib/inc/tdt/tsd_client.h | 83 +++- .../fwkacllib/inc/toolchain/prof_acl_api.h | 61 ++- .../fwkacllib/inc/toolchain/prof_callback.h | 24 +- .../fwkacllib/inc/toolchain/prof_common.h | 449 ++++++++++++++++++ third_party/fwkacllib/inc/toolchain/slog.h | 237 ++++----- 101 files changed, 3653 insertions(+), 1818 deletions(-) create mode 100644 inc/framework/common/profiling_definitions.h create mode 100755 third_party/fwkacllib/inc/ops/OWNERS create mode 100644 third_party/fwkacllib/inc/ops/randomdsa_ops.h create mode 100644 third_party/fwkacllib/inc/toolchain/prof_common.h diff --git a/inc/external/acl/acl_base.h b/inc/external/acl/acl_base.h index 1f81b15a..c938d4fb 100644 --- a/inc/external/acl/acl_base.h +++ b/inc/external/acl/acl_base.h @@ -134,6 +134,7 @@ static const int ACL_ERROR_DRV_FAILURE = 500004; static const int ACL_ERROR_PROFILING_FAILURE = 500005; #define ACL_TENSOR_SHAPE_RANGE_NUM 2 +#define ACL_TENSOR_VALUE_RANGE_NUM 2 #define ACL_UNKNOWN_RANK 0xFFFFFFFFFFFFFFFE typedef enum { @@ -336,6 +337,19 @@ ACL_FUNC_VISIBILITY void aclDestroyTensorDesc(const aclTensorDesc *desc); ACL_FUNC_VISIBILITY aclError aclSetTensorShapeRange(aclTensorDesc *desc, size_t dimsCount, int64_t dimsRange[][ACL_TENSOR_SHAPE_RANGE_NUM]); +/** + * @ingroup AscendCL + * @brief set value range for aclTensorDesc + * + * @param desc [OUT] pointer to the data of aclTensorDesc + * @param valueCount [IN] the number of value + * @param valueRange [IN] the range of value + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclSetTensorValueRange(aclTensorDesc *desc, size_t valueCount, + int64_t valueRange[][ACL_TENSOR_VALUE_RANGE_NUM]); /** * @ingroup AscendCL * @brief get data type specified by the tensor description diff --git a/inc/external/acl/acl_op_compiler.h b/inc/external/acl/acl_op_compiler.h index b64b2bad..8480b89c 100644 --- a/inc/external/acl/acl_op_compiler.h +++ b/inc/external/acl/acl_op_compiler.h @@ -41,6 +41,8 @@ typedef enum { typedef enum aclCompileFlag { ACL_OP_COMPILE_DEFAULT, ACL_OP_COMPILE_FUZZ } aclOpCompileFlag; +typedef struct aclGraphDumpOption aclGraphDumpOption; + /** * @ingroup AscendCL * @brief compile op @@ -114,6 +116,55 @@ ACL_FUNC_VISIBILITY aclError aclSetCompileopt(aclCompileOpt opt, const char *val */ ACL_FUNC_VISIBILITY aclError aclopSetCompileFlag(aclOpCompileFlag flag); +/** + * @ingroup AscendCL + * @brief generate graph and dump + * + * @param opType [IN] op type + * @param numInputs [IN] number of inputs + * @param inputDesc [IN] pointer to array of input tensor descriptions + * @param inputs [IN] pointer to array of input buffers + * @param numOutputs [IN] number of outputs + * @param outputDesc [IN] pointer to array of output tensor descriptions + * @param outputs [IN] pointer to array of outputs buffers + * @param attr [IN] pointer to instance of aclopAttr. + * may pass nullptr if the op has no attribute + * @param engineType [IN] engine type + * @param graphDumpPath [IN] dump path, if the suffix is ".txt", it means file path, else it means directory path + * @param graphDumpOpt [IN] dump option, nullptr is supported + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclGenGraphAndDumpForOp( + const char *opType, int numInputs, const aclTensorDesc *const inputDesc[], const aclDataBuffer *const inputs[], + int numOutputs, const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], const aclopAttr *attr, + aclopEngineType engineType, const char *graphDumpPath, const aclGraphDumpOption *graphDumpOpt); + +/** + * @ingroup AscendCL + * @brief Create the graph dump option + * + * @retval null for failed + * @retval OtherValues success + * + * @see aclDestroyGraphDumpOpt + */ +ACL_FUNC_VISIBILITY aclGraphDumpOption *aclCreateGraphDumpOpt(); + +/** + * @ingroup AscendCL + * @brief Destroy graph dump option + * + * @param graphDumpOpt [IN] pointer to the graph dump option + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + * + * @see aclCreateGraphDumpOpt + */ +ACL_FUNC_VISIBILITY aclError aclDestroyGraphDumpOpt(const aclGraphDumpOption *graphDumpOpt); + #ifdef __cplusplus } #endif diff --git a/inc/external/acl/acl_prof.h b/inc/external/acl/acl_prof.h index 2ad13063..b2e1e1f7 100644 --- a/inc/external/acl/acl_prof.h +++ b/inc/external/acl/acl_prof.h @@ -37,6 +37,7 @@ extern "C" { #define ACL_PROF_HCCL_TRACE 0x0020ULL #define ACL_PROF_TRAINING_TRACE 0x0040ULL #define ACL_PROF_MSPROFTX 0x0080ULL +#define ACL_PROF_RUNTIME_API 0x0100ULL /** * @deprecated please use aclprofGetOpTypeLen and aclprofGetOpTNameLen instead @@ -367,6 +368,79 @@ MSVP_PROF_API aclprofStepInfo *aclprofCreateStepInfo(); */ MSVP_PROF_API void aclprofDestroyStepInfo(aclprofStepInfo *stepinfo); +/** + * @ingroup AscendCL + * @brief create pointer to aclprofstamp + * + * + * @retval aclprofStamp pointer + */ +MSVP_PROF_API void *aclprofCreateStamp(); + +/** + * @ingroup AscendCL + * @brief destory stamp pointer + * + * + * @retval void + */ +MSVP_PROF_API void aclprofDestroyStamp(void *stamp); + +/** + * @ingroup AscendCL + * @brief Record push timestamp + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +MSVP_PROF_API aclError aclprofPush(void *stamp); + +/** + * @ingroup AscendCL + * @brief Record pop timestamp + * + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +MSVP_PROF_API aclError aclprofPop(); + +/** + * @ingroup AscendCL + * @brief Record range start timestamp + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +MSVP_PROF_API aclError aclprofRangeStart(void *stamp, uint32_t *rangeId); + +/** + * @ingroup AscendCL + * @brief Record range end timestamp + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +MSVP_PROF_API aclError aclprofRangeStop(uint32_t rangeId); + +/** + * @ingroup AscendCL + * @brief set message to stamp + * + * + * @retval void + */ +MSVP_PROF_API aclError aclprofSetStampTraceMessage(void *stamp, const char *msg, uint32_t msgLen); + +/** + * @ingroup AscendCL + * @brief Record mark timestamp + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +MSVP_PROF_API aclError aclprofMark(void *stamp); + #ifdef __cplusplus } #endif diff --git a/inc/external/acl/acl_rt.h b/inc/external/acl/acl_rt.h index 7ea27cba..c5e8272c 100644 --- a/inc/external/acl/acl_rt.h +++ b/inc/external/acl/acl_rt.h @@ -44,6 +44,11 @@ typedef enum aclrtEventStatus { ACL_EVENT_STATUS_RESERVED = 2, } aclrtEventStatus; +typedef enum aclrtEventRecordedStatus { + ACL_EVENT_RECORDED_STATUS_NOT_READY = 0, + ACL_EVENT_RECORDED_STATUS_COMPLETE = 1, +} aclrtEventRecordedStatus; + typedef enum aclrtEventWaitStatus { ACL_EVENT_WAIT_STATUS_COMPLETE = 0, ACL_EVENT_WAIT_STATUS_NOT_READY = 1, @@ -503,8 +508,21 @@ ACL_FUNC_VISIBILITY aclError aclrtResetEvent(aclrtEvent event, aclrtStream strea * @retval ACL_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ +ACL_DEPRECATED_MESSAGE("aclrtQueryEvent is deprecated, use aclrtQueryEventStatus instead") ACL_FUNC_VISIBILITY aclError aclrtQueryEvent(aclrtEvent event, aclrtEventStatus *status); +/** + * @ingroup AscendCL + * @brief Queries an event's status + * + * @param event [IN] event to query + * @param status [OUT] event recorded status + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclrtQueryEventStatus(aclrtEvent event, aclrtEventRecordedStatus *status); + /** * @ingroup AscendCL * @brief Queries an event's wait-status diff --git a/inc/external/acl/error_codes/ge_error_codes.h b/inc/external/acl/error_codes/ge_error_codes.h index cafc5a64..027c83ea 100644 --- a/inc/external/acl/error_codes/ge_error_codes.h +++ b/inc/external/acl/error_codes/ge_error_codes.h @@ -32,42 +32,43 @@ #endif #include +#include #ifdef __cplusplus extern "C" { #endif -static const uint32_t ACL_ERROR_GE_PARAM_INVALID = 145000; -static const uint32_t ACL_ERROR_GE_EXEC_NOT_INIT = 145001; -static const uint32_t ACL_ERROR_GE_EXEC_MODEL_PATH_INVALID = 145002; -static const uint32_t ACL_ERROR_GE_EXEC_MODEL_ID_INVALID = 145003; -static const uint32_t ACL_ERROR_GE_EXEC_MODEL_DATA_SIZE_INVALID = 145006; -static const uint32_t ACL_ERROR_GE_EXEC_MODEL_ADDR_INVALID = 145007; -static const uint32_t ACL_ERROR_GE_EXEC_MODEL_QUEUE_ID_INVALID = 145008; -static const uint32_t ACL_ERROR_GE_EXEC_LOAD_MODEL_REPEATED = 145009; -static const uint32_t ACL_ERROR_GE_DYNAMIC_INPUT_ADDR_INVALID = 145011; -static const uint32_t ACL_ERROR_GE_DYNAMIC_INPUT_LENGTH_INVALID = 145012; -static const uint32_t ACL_ERROR_GE_DYNAMIC_BATCH_SIZE_INVALID = 145013; -static const uint32_t ACL_ERROR_GE_AIPP_BATCH_EMPTY = 145014; -static const uint32_t ACL_ERROR_GE_AIPP_NOT_EXIST = 145015; -static const uint32_t ACL_ERROR_GE_AIPP_MODE_INVALID = 145016; -static const uint32_t ACL_ERROR_GE_OP_TASK_TYPE_INVALID = 145017; -static const uint32_t ACL_ERROR_GE_OP_KERNEL_TYPE_INVALID = 145018; -static const uint32_t ACL_ERROR_GE_PLGMGR_PATH_INVALID = 145019; -static const uint32_t ACL_ERROR_GE_FORMAT_INVALID = 145020; -static const uint32_t ACL_ERROR_GE_SHAPE_INVALID = 145021; -static const uint32_t ACL_ERROR_GE_DATATYPE_INVALID = 145022; -static const uint32_t ACL_ERROR_GE_MEMORY_ALLOCATION = 245000; -static const uint32_t ACL_ERROR_GE_MEMORY_OPERATE_FAILED = 245001; -static const uint32_t ACL_ERROR_GE_INTERNAL_ERROR = 545000; -static const uint32_t ACL_ERROR_GE_LOAD_MODEL = 545001; -static const uint32_t ACL_ERROR_GE_EXEC_LOAD_MODEL_PARTITION_FAILED = 545002; -static const uint32_t ACL_ERROR_GE_EXEC_LOAD_WEIGHT_PARTITION_FAILED = 545003; -static const uint32_t ACL_ERROR_GE_EXEC_LOAD_TASK_PARTITION_FAILED = 545004; -static const uint32_t ACL_ERROR_GE_EXEC_LOAD_KERNEL_PARTITION_FAILED = 545005; -static const uint32_t ACL_ERROR_GE_EXEC_RELEASE_MODEL_DATA = 545006; -static const uint32_t ACL_ERROR_GE_COMMAND_HANDLE = 545007; -static const uint32_t ACL_ERROR_GE_GET_TENSOR_INFO = 545008; -static const uint32_t ACL_ERROR_GE_UNLOAD_MODEL = 545009; +static const uint32_t ACL_ERROR_GE_PARAM_INVALID = 145000U; +static const uint32_t ACL_ERROR_GE_EXEC_NOT_INIT = 145001U; +static const uint32_t ACL_ERROR_GE_EXEC_MODEL_PATH_INVALID = 145002U; +static const uint32_t ACL_ERROR_GE_EXEC_MODEL_ID_INVALID = 145003U; +static const uint32_t ACL_ERROR_GE_EXEC_MODEL_DATA_SIZE_INVALID = 145006U; +static const uint32_t ACL_ERROR_GE_EXEC_MODEL_ADDR_INVALID = 145007U; +static const uint32_t ACL_ERROR_GE_EXEC_MODEL_QUEUE_ID_INVALID = 145008U; +static const uint32_t ACL_ERROR_GE_EXEC_LOAD_MODEL_REPEATED = 145009U; +static const uint32_t ACL_ERROR_GE_DYNAMIC_INPUT_ADDR_INVALID = 145011U; +static const uint32_t ACL_ERROR_GE_DYNAMIC_INPUT_LENGTH_INVALID = 145012U; +static const uint32_t ACL_ERROR_GE_DYNAMIC_BATCH_SIZE_INVALID = 145013U; +static const uint32_t ACL_ERROR_GE_AIPP_BATCH_EMPTY = 145014U; +static const uint32_t ACL_ERROR_GE_AIPP_NOT_EXIST = 145015U; +static const uint32_t ACL_ERROR_GE_AIPP_MODE_INVALID = 145016U; +static const uint32_t ACL_ERROR_GE_OP_TASK_TYPE_INVALID = 145017U; +static const uint32_t ACL_ERROR_GE_OP_KERNEL_TYPE_INVALID = 145018U; +static const uint32_t ACL_ERROR_GE_PLGMGR_PATH_INVALID = 145019U; +static const uint32_t ACL_ERROR_GE_FORMAT_INVALID = 145020U; +static const uint32_t ACL_ERROR_GE_SHAPE_INVALID = 145021U; +static const uint32_t ACL_ERROR_GE_DATATYPE_INVALID = 145022U; +static const uint32_t ACL_ERROR_GE_MEMORY_ALLOCATION = 245000U; +static const uint32_t ACL_ERROR_GE_MEMORY_OPERATE_FAILED = 245001U; +static const uint32_t ACL_ERROR_GE_INTERNAL_ERROR = 545000U; +static const uint32_t ACL_ERROR_GE_LOAD_MODEL = 545001U; +static const uint32_t ACL_ERROR_GE_EXEC_LOAD_MODEL_PARTITION_FAILED = 545002U; +static const uint32_t ACL_ERROR_GE_EXEC_LOAD_WEIGHT_PARTITION_FAILED = 545003U; +static const uint32_t ACL_ERROR_GE_EXEC_LOAD_TASK_PARTITION_FAILED = 545004U; +static const uint32_t ACL_ERROR_GE_EXEC_LOAD_KERNEL_PARTITION_FAILED = 545005U; +static const uint32_t ACL_ERROR_GE_EXEC_RELEASE_MODEL_DATA = 545006U; +static const uint32_t ACL_ERROR_GE_COMMAND_HANDLE = 545007U; +static const uint32_t ACL_ERROR_GE_GET_TENSOR_INFO = 545008U; +static const uint32_t ACL_ERROR_GE_UNLOAD_MODEL = 545009U; #ifdef __cplusplus } // namespace ge diff --git a/inc/external/acl/error_codes/rt_error_codes.h b/inc/external/acl/error_codes/rt_error_codes.h index abfa30db..d16af89f 100644 --- a/inc/external/acl/error_codes/rt_error_codes.h +++ b/inc/external/acl/error_codes/rt_error_codes.h @@ -44,6 +44,7 @@ static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callbac static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type +static const int32_t ACL_ERROR_RT_WAIT_TIMEOUT = 107019; // wait timeout static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error @@ -61,6 +62,7 @@ static const int32_t ACL_ERROR_RT_OVER_LIMIT = 207012; // over limit static const int32_t ACL_ERROR_RT_QUEUE_EMPTY = 207013; // queue is empty static const int32_t ACL_ERROR_RT_QUEUE_FULL = 207014; // queue is full static const int32_t ACL_ERROR_RT_REPEATED_INIT = 207015; // repeated init +static const int32_t ACL_ERROR_RT_AIVEC_OVER_FLOW = 207016; // aivec over flow static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error @@ -99,6 +101,11 @@ static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // devic static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception +static const int32_t ACL_ERROR_RT_CDQ_BATCH_ABNORMAL = 507037; // cdq alloc batch abnormal +static const int32_t ACL_ERROR_RT_DIE_MODE_CHANGE_ERROR = 507038; // can not change die mode +static const int32_t ACL_ERROR_RT_DIE_SET_ERROR = 507039; // single die mode can not set die +static const int32_t ACL_ERROR_RT_INVALID_DIEID = 507040; // invalid die id +static const int32_t ACL_ERROR_RT_DIE_MODE_NOT_SET = 507041; // die mode not set static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error @@ -107,5 +114,4 @@ static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconn #ifdef __cplusplus } #endif - #endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/inc/external/acl/ops/acl_dvpp.h b/inc/external/acl/ops/acl_dvpp.h index b839ae48..6ab89c49 100644 --- a/inc/external/acl/ops/acl_dvpp.h +++ b/inc/external/acl/ops/acl_dvpp.h @@ -158,7 +158,13 @@ enum acldvppJpegFormat { ACL_JPEG_CSS_UNKNOWN = 1000 }; -enum acldvppChannelDescParamType { ACL_DVPP_CSC_MATRIX_UINT32 = 0, ACL_DVPP_MODE_UINT32, ACL_DVPP_CHANNEL_ID_UINT64 }; +enum acldvppChannelDescParamType { + ACL_DVPP_CSC_MATRIX_UINT32 = 0, + ACL_DVPP_MODE_UINT32, + ACL_DVPP_CHANNEL_ID_UINT64, + ACL_DVPP_CHANNEL_HEIGHT_UINT32, + ACL_DVPP_CHANNEL_WIDTH_UINT32 +}; enum aclvdecChannelDescParamType { ACL_VDEC_CSC_MATRIX_UINT32 = 0, diff --git a/inc/external/ge/ge_api_error_codes.h b/inc/external/ge/ge_api_error_codes.h index 5d2d6963..b5cfb115 100644 --- a/inc/external/ge/ge_api_error_codes.h +++ b/inc/external/ge/ge_api_error_codes.h @@ -20,15 +20,27 @@ #include #include #include "ge_error_codes.h" -#include "graph/types.h" +#include "ge_api_types.h" -namespace ge { #ifdef __GNUC__ #define ATTRIBUTED_DEPRECATED(replacement) __attribute__((deprecated("Please use " #replacement " instead."))) #else #define ATTRIBUTED_DEPRECATED(replacement) __declspec(deprecated("Please use " #replacement " instead.")) #endif +// Code compose(4 byte), runtime: 2 bit, type: 2 bit, level: 3 bit, sysid: 8 bit, modid: 5 bit, value: 12 bit +#define GE_ERRORNO(runtime, type, level, sysid, modid, name, value, desc) \ + constexpr ge::Status name = (static_cast(0xFFU & (static_cast(runtime))) << 30U) | \ + (static_cast(0xFFU & (static_cast(type))) << 28U) | \ + (static_cast(0xFFU & (static_cast(level))) << 25U) | \ + (static_cast(0xFFU & (static_cast(sysid))) << 17U) | \ + (static_cast(0xFFU & (static_cast(modid))) << 12U) | \ + (static_cast(0x0FFFU) & (static_cast(value))); \ + const ErrorNoRegisterar g_errorno_##name((name), (desc)); + +#define GE_ERRORNO_EXTERNAL(name, desc) const ErrorNoRegisterar g_errorno_##name((name), (desc)); + +namespace ge { class GE_FUNC_VISIBILITY StatusFactory { public: static StatusFactory *Instance() { @@ -56,7 +68,7 @@ class GE_FUNC_VISIBILITY StatusFactory { } std::string GetErrDesc(const uint32_t err) { - const auto iter_find = err_desc_.find(err); + const std::map::const_iterator iter_find = err_desc_.find(err); if (iter_find == err_desc_.end()) { return ""; } @@ -82,59 +94,10 @@ class GE_FUNC_VISIBILITY ErrorNoRegisterar { ~ErrorNoRegisterar() {} }; -// Code compose(4 byte), runtime: 2 bit, type: 2 bit, level: 3 bit, sysid: 8 bit, modid: 5 bit, value: 12 bit -#define GE_ERRORNO(runtime, type, level, sysid, modid, name, value, desc) \ - constexpr ge::Status name = (static_cast(0xFFU & (static_cast(runtime))) << 30U) | \ - (static_cast(0xFFU & (static_cast(type))) << 28U) | \ - (static_cast(0xFFU & (static_cast(level))) << 25U) | \ - (static_cast(0xFFU & (static_cast(sysid))) << 17U) | \ - (static_cast(0xFFU & (static_cast(modid))) << 12U) | \ - (static_cast(0x0FFFU) & (static_cast(value))); \ - const ErrorNoRegisterar g_##name##_errorno(name, desc); - -#define GE_ERRORNO_EXTERNAL(name, desc) const ErrorNoRegisterar g_##name##_errorno(name, desc); - -using Status = uint32_t; - // General error code GE_ERRORNO(0, 0, 0, 0, 0, SUCCESS, 0, "success"); GE_ERRORNO(0b11, 0b11, 0b111, 0xFFU, 0b11111, FAILED, 0xFFFU, "failed"); /*lint !e401*/ -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_PARAM_INVALID, "Parameter invalid."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_EXEC_NOT_INIT, "GE executor not initialized yet."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_EXEC_MODEL_PATH_INVALID, "Model file path invalid."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_EXEC_MODEL_ID_INVALID, "Model id invalid."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_EXEC_MODEL_DATA_SIZE_INVALID, "Data size of model invalid."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_EXEC_MODEL_ADDR_INVALID, "Model addr invalid."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_EXEC_MODEL_QUEUE_ID_INVALID, "Queue id of model invalid."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_EXEC_LOAD_MODEL_REPEATED, "The model loaded repeatedly."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_DYNAMIC_INPUT_ADDR_INVALID, "Dynamic input addr invalid."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_DYNAMIC_INPUT_LENGTH_INVALID, "Dynamic input size invalid."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_DYNAMIC_BATCH_SIZE_INVALID, "Dynamic batch size invalid."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_AIPP_BATCH_EMPTY, "AIPP batch parameter empty."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_AIPP_NOT_EXIST, "AIPP parameter not exist."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_AIPP_MODE_INVALID, "AIPP mode invalid."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_OP_TASK_TYPE_INVALID, "Task type invalid."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_OP_KERNEL_TYPE_INVALID, "Kernel type invalid."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_PLGMGR_PATH_INVALID, "Plugin path is invalid."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_FORMAT_INVALID, "Format is invalid."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_SHAPE_INVALID, "Shape is invalid."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_DATATYPE_INVALID, "Datatype is invalid."); - -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_MEMORY_ALLOCATION, "Memory allocation error."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_MEMORY_OPERATE_FAILED, "Failed to operate memory."); - -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_INTERNAL_ERROR, "Internal error."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_LOAD_MODEL, "Load model error."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_EXEC_LOAD_MODEL_PARTITION_FAILED, "Failed to load model partition."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_EXEC_LOAD_WEIGHT_PARTITION_FAILED, "Failed to load weight partition."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_EXEC_LOAD_TASK_PARTITION_FAILED, "Failed to load task partition."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_EXEC_LOAD_KERNEL_PARTITION_FAILED, "Failed to load op kernel partition."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_EXEC_RELEASE_MODEL_DATA, "Failed to release the model data."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_COMMAND_HANDLE, "Command handle error."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_GET_TENSOR_INFO, "Get tensor info error."); -GE_ERRORNO_EXTERNAL(ACL_ERROR_GE_UNLOAD_MODEL, "Load model error."); - } // namespace ge #endif // INC_EXTERNAL_GE_GE_API_ERROR_CODES_H_ diff --git a/inc/external/ge/ge_api_types.h b/inc/external/ge/ge_api_types.h index 52881020..93ebe284 100644 --- a/inc/external/ge/ge_api_types.h +++ b/inc/external/ge/ge_api_types.h @@ -28,96 +28,98 @@ namespace ge { // Option key: graph run mode -const char *const OPTION_GRAPH_RUN_MODE = "ge.graphRunMode"; -const char *const OPTION_DEVICE_TYPE = "ge.deviceType"; +const char_t *const OPTION_GRAPH_RUN_MODE = "ge.graphRunMode"; +const char_t *const OPTION_DEVICE_TYPE = "ge.deviceType"; // Option key: ome init -const char *const OPTION_EXEC_SESSION_ID = "ge.exec.sessionId"; -const char *const OPTION_EXEC_DEVICE_ID = "ge.exec.deviceId"; -const char *const OPTION_EXEC_JOB_ID = "ge.exec.jobId"; -const char *const OPTION_EXEC_IS_USEHCOM = "ge.exec.isUseHcom"; -const char *const OPTION_EXEC_IS_USEHVD = "ge.exec.isUseHvd"; -const char *const OPTION_EXEC_RANK_ID = "ge.exec.rankId"; -const char *const OPTION_EXEC_POD_NAME = "ge.exec.podName"; -const char *const OPTION_EXEC_DEPLOY_MODE = "ge.exec.deployMode"; -const char *const OPTION_EXEC_RANK_TABLE_FILE = "ge.exec.rankTableFile"; -const char *const GE_AICPU_FLAG = "ge.aicpuFlag"; -const char *const OPTION_EXEC_EXTERN_PLUGIN_PATH = "ge.soLoadPath"; +const char_t *const OPTION_EXEC_SESSION_ID = "ge.exec.sessionId"; +const char_t *const OPTION_EXEC_DEVICE_ID = "ge.exec.deviceId"; +const char_t *const OPTION_EXEC_JOB_ID = "ge.exec.jobId"; +const char_t *const OPTION_EXEC_IS_USEHCOM = "ge.exec.isUseHcom"; +const char_t *const OPTION_EXEC_IS_USEHVD = "ge.exec.isUseHvd"; +const char_t *const OPTION_EXEC_RANK_ID = "ge.exec.rankId"; +const char_t *const OPTION_EXEC_POD_NAME = "ge.exec.podName"; +const char_t *const OPTION_EXEC_DEPLOY_MODE = "ge.exec.deployMode"; +const char_t *const OPTION_EXEC_RANK_TABLE_FILE = "ge.exec.rankTableFile"; +const char_t *const GE_AICPU_FLAG = "ge.aicpuFlag"; +const char_t *const OPTION_EXEC_EXTERN_PLUGIN_PATH = "ge.soLoadPath"; // Dump flag and para -const char *const OPTION_EXEC_ENABLE_DUMP = "ge.exec.enableDump"; -const char *const OPTION_EXEC_DUMP_PATH = "ge.exec.dumpPath"; -const char *const OPTION_EXEC_DUMP_STEP = "ge.exec.dumpStep"; -const char *const OPTION_EXEC_DUMP_MODE = "ge.exec.dumpMode"; -const char *const OPTION_EXEC_ENABLE_DUMP_DEBUG = "ge.exec.enableDumpDebug"; -const char *const OPTION_EXEC_DUMP_DEBUG_MODE = "ge.exec.dumpDebugMode"; -const char *const OPTION_EXEC_ENABLE_INCRE_BUILD = "ge.exec.enableIncreBuild"; -const char *const OPTION_EXEC_INCRE_BUILD_CACHE_PATH = "ge.exec.increBuildCachePath"; -const char *const OPTION_EXEC_ENABLE_EXCEPTION_DUMP = "ge.exec.enable_exception_dump"; -const char *const OPTION_EXEC_ENABLE_SCOPE_FUSION_PASSES = "ge.exec.enableScopeFusionPasses"; -const char *const OPTION_EXEC_PROFILING_FPPONIT_OPTIONS = "ge.exec.profilingFpPointOptions"; -const char *const OPTION_EXEC_PROFILING_BPPONIT_OPTIONS = "ge.exec.profilingBpPointOptions"; +const char_t *const OPTION_EXEC_ENABLE_DUMP = "ge.exec.enableDump"; +const char_t *const OPTION_EXEC_DUMP_PATH = "ge.exec.dumpPath"; +const char_t *const OPTION_EXEC_DUMP_STEP = "ge.exec.dumpStep"; +const char_t *const OPTION_EXEC_DUMP_MODE = "ge.exec.dumpMode"; +const char_t *const OPTION_EXEC_ENABLE_DUMP_DEBUG = "ge.exec.enableDumpDebug"; +const char_t *const OPTION_EXEC_DUMP_DEBUG_MODE = "ge.exec.dumpDebugMode"; +const char_t *const OPTION_EXEC_ENABLE_INCRE_BUILD = "ge.exec.enableIncreBuild"; +const char_t *const OPTION_EXEC_INCRE_BUILD_CACHE_PATH = "ge.exec.increBuildCachePath"; +const char_t *const OPTION_EXEC_ENABLE_EXCEPTION_DUMP = "ge.exec.enable_exception_dump"; +const char_t *const OPTION_EXEC_ENABLE_SCOPE_FUSION_PASSES = "ge.exec.enableScopeFusionPasses"; +const char_t *const OPTION_EXEC_PROFILING_FPPONIT_OPTIONS = "ge.exec.profilingFpPointOptions"; +const char_t *const OPTION_EXEC_PROFILING_BPPONIT_OPTIONS = "ge.exec.profilingBpPointOptions"; // profiling flag -const char *const OPTION_EXEC_PROFILING_MODE = "ge.exec.profilingMode"; -const char *const OPTION_EXEC_PROFILING_OPTIONS = "ge.exec.profilingOptions"; +const char_t *const OPTION_EXEC_PROFILING_MODE = "ge.exec.profilingMode"; +const char_t *const OPTION_EXEC_PROFILING_OPTIONS = "ge.exec.profilingOptions"; // Hccl flag, if ge.exec.hcclFlag =1, it means load plugin for opskernel, else:ge.exec.hcclFlag =0 -const char *const OPTION_EXEC_HCCL_FLAG = "ge.exec.hcclFlag"; -const char *const OPTION_EXEC_ATOMIC_FLAG = "ge.exec.enable_atomic"; -const char *const OPTION_EXEC_DISABLE_REUSED_MEMORY = "ge.exec.disableReuseMemory"; -const char *const OPTION_EXEC_ENABLE_TAILING_OPTIMIZATION = "ge.exec.isTailingOptimization"; +const char_t *const OPTION_EXEC_HCCL_FLAG = "ge.exec.hcclFlag"; +const char_t *const OPTION_EXEC_ATOMIC_FLAG = "ge.exec.enable_atomic"; +const char_t *const OPTION_EXEC_DISABLE_REUSED_MEMORY = "ge.exec.disableReuseMemory"; +const char_t *const OPTION_EXEC_ENABLE_TAILING_OPTIMIZATION = "ge.exec.isTailingOptimization"; // Dynamic input flag. ge.exec.dynamicInput=1, means enable dynaimc input, // ge.exec.dynamicGraphExecuteMode, dynamic_execute[default] -const char *const OPTION_EXEC_DYNAMIC_INPUT = "ge.exec.dynamicInput"; -const char *const OPTION_EXEC_DYNAMIC_EXECUTE_MODE = "ge.exec.dynamicGraphExecuteMode"; -const char *const OPTION_EXEC_DATA_INPUTS_SHAPE_RANGE = "ge.exec.dataInputsShapeRange"; -const char *const OPTION_EXEC_ENABLE_COPY_OUTPUT_ADDR = "ge.exec.enableCopyOutputAddr"; +const char_t *const OPTION_EXEC_DYNAMIC_INPUT = "ge.exec.dynamicInput"; +const char_t *const OPTION_EXEC_DYNAMIC_EXECUTE_MODE = "ge.exec.dynamicGraphExecuteMode"; +const char_t *const OPTION_EXEC_DATA_INPUTS_SHAPE_RANGE = "ge.exec.dataInputsShapeRange"; +const char_t *const OPTION_EXEC_ENABLE_COPY_OUTPUT_ADDR = "ge.exec.enableCopyOutputAddr"; // Option key: memory init -const char *const GRAPH_MEMORY_MAX_SIZE = "ge.graphMemoryMaxSize"; -const char *const VARIABLE_MEMORY_MAX_SIZE = "ge.variableMemoryMaxSize"; +const char_t *const GRAPH_MEMORY_MAX_SIZE = "ge.graphMemoryMaxSize"; +const char_t *const VARIABLE_MEMORY_MAX_SIZE = "ge.variableMemoryMaxSize"; +const char_t *const OPTION_EXEC_REUSE_ZERO_COPY_MEMORY = "ge.exec.reuseZeroCopyMemory"; + namespace configure_option { -const char *const STREAM_NUM = "ge.streamNum"; -const char *const HEAD_STREAM = "ge.headStream"; -const char *const PERF_LEVEL = "ge.perfLevel"; -const char *const ENCRYPT_MODE = "ge.encryptMode"; -const char *const EK_FILE = "ge.ekFile"; -const char *const CERT_FILE = "ge.certFile"; -const char *const HW_KEY_FILE = "ge.hwKeyFile"; -const char *const PRIVATE_KEY_FILE = "ge.privateKeyFile"; -const char *const FRAMEWORK_TYPE = "ge.frameworkType"; -const char *const CALIBRATION_CONF_FILE = "ge.calibrationConfFile"; -const char *const INSERT_OP_FILE = "ge.insertOpFile"; -const char *const OUTPUT_NODE_NAME = "ge.outputNodeName"; -const char *const COMPRESS_FLAG = "ge.compressFlag"; -const char *const PRECISION_MODE = "ge.exec.precision_mode"; -const char *const SINGLE_OP_FLAG = "ge.exec.single_op"; -const char *const TRAIN_FLAG = "ge.trainFlag"; -const char *const RUN_FLAG = "ge.runFlag"; -const char *const LOCAL_FMKOP_FLAG = "ge.enabledLocalFmkop"; -const char *const TBE_PLUGIN_PATH_FLAG = "ge.TBE_plugin_path"; -const char *const DDK_VERSION_FLAG = "ge.DDK_version"; -const char *const GE_FE_FLAG = "ge.feFlag"; -const char *const STREAM_MAX_PARALLEL_NUM = "ge.streamMaxParallelNum"; -const char *const OUTPUT_DATATYPE = "ge.outputDatatype"; -const char *const OP_SELECT_IMPL_MODE = "ge.opSelectImplmode"; -const char *const OPTYPELIST_FOR_IMPLMODE = "ge.optypelistForImplmode"; -const char *const HCOM_PARALLEL = "ge.hcomParallel"; -const char *const AUTO_TUNE_MODE = "ge.autoTuneMode"; -const char *const SOC_VERSION = "ge.socVersion"; -const char *const CORE_TYPE = "ge.engineType"; -const char *const AICORE_NUM = "ge.aicoreNum"; -const char *const L1_FUSION = "ge.l1Fusion"; -const char *const BUFFER_OPTIMIZE = "ge.bufferOptimize"; -const char *const ENABLE_SMALL_CHANNEL = "ge.enableSmallChannel"; -const char *const ENABLE_COMPRESS_WEIGHT = "ge.enableCompressWeight"; -const char *const FUSION_SWITCH_FILE = "ge.fusionSwitchFile"; -const char *const SAVE_ORIGINAL_MODEL = "ge.saveOriginalModel"; -const char *const ORIGINAL_MODEL_FILE = "ge.originalModelFile"; -const char *const INPUT_FP16_NODES = "ge.INPUT_NODES_SET_FP16"; -const char *const OP_DEBUG_LEVEL = "ge.opDebugLevel"; -const char *const PERFORMANCE_MODE = "ge.performance_mode"; -const char *const SHAPE_GENERALIZED_BUILD_MODE = "ge.shape_generalized_build_mode"; -const char *const MODIFY_MIXLIST = "ge.exec.modify_mixlist"; -const char *const OP_PRECISION_MODE = "ge.exec.op_precision_mode"; +const char_t *const STREAM_NUM = "ge.streamNum"; +const char_t *const HEAD_STREAM = "ge.headStream"; +const char_t *const PERF_LEVEL = "ge.perfLevel"; +const char_t *const ENCRYPT_MODE = "ge.encryptMode"; +const char_t *const EK_FILE = "ge.ekFile"; +const char_t *const CERT_FILE = "ge.certFile"; +const char_t *const HW_KEY_FILE = "ge.hwKeyFile"; +const char_t *const PRIVATE_KEY_FILE = "ge.privateKeyFile"; +const char_t *const FRAMEWORK_TYPE = "ge.frameworkType"; +const char_t *const CALIBRATION_CONF_FILE = "ge.calibrationConfFile"; +const char_t *const INSERT_OP_FILE = "ge.insertOpFile"; +const char_t *const OUTPUT_NODE_NAME = "ge.outputNodeName"; +const char_t *const COMPRESS_FLAG = "ge.compressFlag"; +const char_t *const PRECISION_MODE = "ge.exec.precision_mode"; +const char_t *const SINGLE_OP_FLAG = "ge.exec.single_op"; +const char_t *const TRAIN_FLAG = "ge.trainFlag"; +const char_t *const RUN_FLAG = "ge.runFlag"; +const char_t *const LOCAL_FMKOP_FLAG = "ge.enabledLocalFmkop"; +const char_t *const TBE_PLUGIN_PATH_FLAG = "ge.TBE_plugin_path"; +const char_t *const DDK_VERSION_FLAG = "ge.DDK_version"; +const char_t *const GE_FE_FLAG = "ge.feFlag"; +const char_t *const STREAM_MAX_PARALLEL_NUM = "ge.streamMaxParallelNum"; +const char_t *const OUTPUT_DATATYPE = "ge.outputDatatype"; +const char_t *const OP_SELECT_IMPL_MODE = "ge.opSelectImplmode"; +const char_t *const OPTYPELIST_FOR_IMPLMODE = "ge.optypelistForImplmode"; +const char_t *const HCOM_PARALLEL = "ge.hcomParallel"; +const char_t *const AUTO_TUNE_MODE = "ge.autoTuneMode"; +const char_t *const SOC_VERSION = "ge.socVersion"; +const char_t *const CORE_TYPE = "ge.engineType"; +const char_t *const AICORE_NUM = "ge.aicoreNum"; +const char_t *const L1_FUSION = "ge.l1Fusion"; +const char_t *const BUFFER_OPTIMIZE = "ge.bufferOptimize"; +const char_t *const ENABLE_SMALL_CHANNEL = "ge.enableSmallChannel"; +const char_t *const ENABLE_COMPRESS_WEIGHT = "ge.enableCompressWeight"; +const char_t *const FUSION_SWITCH_FILE = "ge.fusionSwitchFile"; +const char_t *const SAVE_ORIGINAL_MODEL = "ge.saveOriginalModel"; +const char_t *const ORIGINAL_MODEL_FILE = "ge.originalModelFile"; +const char_t *const INPUT_FP16_NODES = "ge.INPUT_NODES_SET_FP16"; +const char_t *const OP_DEBUG_LEVEL = "ge.opDebugLevel"; +const char_t *const PERFORMANCE_MODE = "ge.performance_mode"; +const char_t *const SHAPE_GENERALIZED_BUILD_MODE = "ge.shape_generalized_build_mode"; +const char_t *const MODIFY_MIXLIST = "ge.exec.modify_mixlist"; +const char_t *const OP_PRECISION_MODE = "ge.exec.op_precision_mode"; } // namespace configure_option // Configure stream num by Session constructor options param, // its value should be int32_t type, default value is "1" @@ -227,7 +229,7 @@ const std::string OPTYPELIST_FOR_IMPLMODE = "ge.optypelistForImplmode"; const std::string HCOM_PARALLEL = "ge.hcomParallel"; // configure whether to use dynamic batch size -const char *const kDynamicBatchSize = "ge.dynamicBatchSize"; +const char_t *const kDynamicBatchSize = "ge.dynamicBatchSize"; // configure threshold of fusion data size for communication op const std::string FUSION_TENSOR_SIZE = "ge.fusionTensorSize"; @@ -236,10 +238,10 @@ const std::string INPUT_SHAPE = "ge.inputShape"; const std::string DYNAMIC_NODE_TYPE = "ge.dynamicNodeType"; // configure whether to use dynamic image size -const char *const kDynamicImageSize = "ge.dynamicImageSize"; +const char_t *const kDynamicImageSize = "ge.dynamicImageSize"; // Configure whether to use dynamic dims -const char *const kDynamicDims = "ge.dynamicDims"; +const char_t *const kDynamicDims = "ge.dynamicDims"; // Configure auto tune mode, this option only take effect while AUTO_TUNE_FLAG is Y, // example: GA|RL, support configure multiple, split by | @@ -275,29 +277,29 @@ const std::string SAVE_ORIGINAL_MODEL = "ge.saveOriginalModel"; // Save original model file name const std::string ORIGINAL_MODEL_FILE = "ge.originalModelFile"; -const char *const OPTION_GE_MAX_DUMP_FILE_NUM = "ge.maxDumpFileNum"; -const char *const OPTION_GE_MAX_DUMP_FILE_SIZE = "ge.maxDumpFileSize"; -const char *const OPTION_GE_MAX_DUMP_OP_NUM = "ge.maxDumpOpNum"; +const char_t *const OPTION_GE_MAX_DUMP_FILE_NUM = "ge.maxDumpFileNum"; +const char_t *const OPTION_GE_MAX_DUMP_FILE_SIZE = "ge.maxDumpFileSize"; +const char_t *const OPTION_GE_MAX_DUMP_OP_NUM = "ge.maxDumpOpNum"; // Configure for print op pass // Its value should be "0" or "1", default value is "1" -const char *const ENABLE_PRINT_OP_PASS = "ge.enablePrintOpPass"; +const char_t *const ENABLE_PRINT_OP_PASS = "ge.enablePrintOpPass"; // Configure operator compilation path // Its value should be file path, default value is "./" -const char *const DEBUG_DIR = "ge.debugDir"; +const char_t *const DEBUG_DIR = "ge.debugDir"; // Configure operator compiler cache path // Its value should be file path, default value is "./" -const char *const OP_COMPILER_CACHE_DIR = "ge.op_compiler_cache_dir"; +const char_t *const OP_COMPILER_CACHE_DIR = "ge.op_compiler_cache_dir"; // Configure operator compiler cache mode // Its value should be "disable", "enable" or "force", default value is "disable" -const char *const OP_COMPILER_CACHE_MODE = "ge.op_compiler_cache_mode"; +const char_t *const OP_COMPILER_CACHE_MODE = "ge.op_compiler_cache_mode"; // Configure whether to use single stream. // Its value should be "true" or "false", default value is "false" -const char *const ENABLE_SINGLE_STREAM = "ge.enableSingleStream"; +const char_t *const ENABLE_SINGLE_STREAM = "ge.enableSingleStream"; // Configure input fp16 nodes const std::string INPUT_FP16_NODES = "ge.INPUT_NODES_SET_FP16"; @@ -322,7 +324,7 @@ const std::string OP_BANK_UPDATE_FLAG = "ge.op_bank_update"; const std::string HCOM_MULTI_MODE = "ge.hcomMultiMode"; // atc and ir option -const char *const INPUT_SHAPE_RANGE = "input_shape_range"; +const char_t *const INPUT_SHAPE_RANGE = "input_shape_range"; // Configure express high compile performance or high execute performance // normal: no need to compile, used saved .o files directly @@ -338,7 +340,11 @@ const std::string MODIFY_MIXLIST = "ge.exec.modify_mixlist"; const std::string OP_PRECISION_MODE = "ge.exec.op_precision_mode"; -const char *const FILE_CONSTANT_PATH = "ge.exec.value_bins"; +const std::string OP_WAIT_TIMEOUT = "ge.exec.opWaitTimeout"; + +const std::string OP_EXECUTE_TIMEOUT = "ge.exec.opExecuteTimeout"; + +const char_t *const FILE_CONSTANT_PATH = "ge.exec.value_bins"; // Graph run mode enum GraphRunMode { PREDICTION = 0, TRAIN }; @@ -378,49 +384,49 @@ using RunAsyncCallback = std::function &)>; // for ir build namespace ir_option { -static const char *const INPUT_FORMAT = "input_format"; -static const char *const INPUT_SHAPE = "input_shape"; -static const char *const INPUT_SHAPE_RANGE = ge::INPUT_SHAPE_RANGE; -static const char *const OP_NAME_MAP = "op_name_map"; -static const char *const IS_DYNAMIC_INPUT = "is_dynamic_input"; -static const char *const IS_INPUT_ADJUST_HW_LAYOUT = "is_input_adjust_hw_layout"; -static const char *const IS_OUTPUT_ADJUST_HW_LAYOUT = "is_output_adjust_hw_layout"; -static const char *const ENABLE_SCOPE_FUSION_PASSES = "enable_scope_fusion_passes"; -static const char *const OUTPUT = "output"; -static const char *const DYNAMIC_BATCH_SIZE = kDynamicBatchSize; -static const char *const DYNAMIC_IMAGE_SIZE = kDynamicImageSize; -static const char *const DYNAMIC_DIMS = kDynamicDims; -static const char *const INSERT_OP_FILE = ge::INSERT_OP_FILE.c_str(); -static const char *const PRECISION_MODE = ge::PRECISION_MODE.c_str(); -static const char *const TUNE_DEVICE_IDS = ge::TUNE_DEVICE_IDS.c_str(); -static const char *const EXEC_DISABLE_REUSED_MEMORY = ge::OPTION_EXEC_DISABLE_REUSED_MEMORY; -static const char *const AUTO_TUNE_MODE = ge::AUTO_TUNE_MODE.c_str(); -static const char *const CORE_TYPE = ge::CORE_TYPE.c_str(); -static const char *const SOC_VERSION = ge::SOC_VERSION.c_str(); -static const char *const ENABLE_SINGLE_STREAM = ge::ENABLE_SINGLE_STREAM; -static const char *const AICORE_NUM = ge::AICORE_NUM.c_str(); -static const char *const FUSION_SWITCH_FILE = ge::FUSION_SWITCH_FILE.c_str(); -static const char *const ENABLE_SMALL_CHANNEL = ge::ENABLE_SMALL_CHANNEL.c_str(); -static const char *const OP_SELECT_IMPL_MODE = ge::OP_SELECT_IMPL_MODE.c_str(); -static const char *const OUTPUT_TYPE = ge::OUTPUT_DATATYPE.c_str(); -static const char *const BUFFER_OPTIMIZE = ge::BUFFER_OPTIMIZE.c_str(); -static const char *const ENABLE_COMPRESS_WEIGHT = ge::ENABLE_COMPRESS_WEIGHT.c_str(); -static const char *const COMPRESS_WEIGHT_CONF = "compress_weight_conf"; -static const char *const OUT_NODES = ge::OUTPUT_NODE_NAME.c_str(); -static const char *const INPUT_FP16_NODES = ge::INPUT_FP16_NODES.c_str(); -static const char *const LOG_LEVEL = "log"; -static const char *const OPTYPELIST_FOR_IMPLMODE = ge::OPTYPELIST_FOR_IMPLMODE.c_str(); -static const char *const DEBUG_DIR = ge::DEBUG_DIR; -static const char *const OP_COMPILER_CACHE_DIR = ge::OP_COMPILER_CACHE_DIR; -static const char *const OP_COMPILER_CACHE_MODE = ge::OP_COMPILER_CACHE_MODE; -static const char *const MDL_BANK_PATH = ge::MDL_BANK_PATH_FLAG.c_str(); -static const char *const OP_BANK_PATH = ge::OP_BANK_PATH_FLAG.c_str(); -static const char *const OP_BANK_UPDATE = ge::OP_BANK_UPDATE_FLAG.c_str(); -static const char *const OP_DEBUG_LEVEL = ge::OP_DEBUG_LEVEL.c_str(); -static const char *const PERFORMANCE_MODE = ge::PERFORMANCE_MODE.c_str(); -static const char *const SHAPE_GENERALIZED_BUILD_MODE = ge::SHAPE_GENERALIZED_BUILD_MODE.c_str(); -static const char *const MODIFY_MIXLIST = ge::MODIFY_MIXLIST.c_str(); -static const char *const OP_PRECISION_MODE = ge::OP_PRECISION_MODE.c_str(); +static const char_t *const INPUT_FORMAT = "input_format"; +static const char_t *const INPUT_SHAPE = "input_shape"; +static const char_t *const INPUT_SHAPE_RANGE = ge::INPUT_SHAPE_RANGE; +static const char_t *const OP_NAME_MAP = "op_name_map"; +static const char_t *const IS_DYNAMIC_INPUT = "is_dynamic_input"; +static const char_t *const IS_INPUT_ADJUST_HW_LAYOUT = "is_input_adjust_hw_layout"; +static const char_t *const IS_OUTPUT_ADJUST_HW_LAYOUT = "is_output_adjust_hw_layout"; +static const char_t *const ENABLE_SCOPE_FUSION_PASSES = "enable_scope_fusion_passes"; +static const char_t *const OUTPUT = "output"; +static const char_t *const DYNAMIC_BATCH_SIZE = kDynamicBatchSize; +static const char_t *const DYNAMIC_IMAGE_SIZE = kDynamicImageSize; +static const char_t *const DYNAMIC_DIMS = kDynamicDims; +static const char_t *const INSERT_OP_FILE = ge::INSERT_OP_FILE.c_str(); +static const char_t *const PRECISION_MODE = ge::PRECISION_MODE.c_str(); +static const char_t *const TUNE_DEVICE_IDS = ge::TUNE_DEVICE_IDS.c_str(); +static const char_t *const EXEC_DISABLE_REUSED_MEMORY = ge::OPTION_EXEC_DISABLE_REUSED_MEMORY; +static const char_t *const AUTO_TUNE_MODE = ge::AUTO_TUNE_MODE.c_str(); +static const char_t *const CORE_TYPE = ge::CORE_TYPE.c_str(); +static const char_t *const SOC_VERSION = ge::SOC_VERSION.c_str(); +static const char_t *const ENABLE_SINGLE_STREAM = ge::ENABLE_SINGLE_STREAM; +static const char_t *const AICORE_NUM = ge::AICORE_NUM.c_str(); +static const char_t *const FUSION_SWITCH_FILE = ge::FUSION_SWITCH_FILE.c_str(); +static const char_t *const ENABLE_SMALL_CHANNEL = ge::ENABLE_SMALL_CHANNEL.c_str(); +static const char_t *const OP_SELECT_IMPL_MODE = ge::OP_SELECT_IMPL_MODE.c_str(); +static const char_t *const OUTPUT_TYPE = ge::OUTPUT_DATATYPE.c_str(); +static const char_t *const BUFFER_OPTIMIZE = ge::BUFFER_OPTIMIZE.c_str(); +static const char_t *const ENABLE_COMPRESS_WEIGHT = ge::ENABLE_COMPRESS_WEIGHT.c_str(); +static const char_t *const COMPRESS_WEIGHT_CONF = "compress_weight_conf"; +static const char_t *const OUT_NODES = ge::OUTPUT_NODE_NAME.c_str(); +static const char_t *const INPUT_FP16_NODES = ge::INPUT_FP16_NODES.c_str(); +static const char_t *const LOG_LEVEL = "log"; +static const char_t *const OPTYPELIST_FOR_IMPLMODE = ge::OPTYPELIST_FOR_IMPLMODE.c_str(); +static const char_t *const DEBUG_DIR = ge::DEBUG_DIR; +static const char_t *const OP_COMPILER_CACHE_DIR = ge::OP_COMPILER_CACHE_DIR; +static const char_t *const OP_COMPILER_CACHE_MODE = ge::OP_COMPILER_CACHE_MODE; +static const char_t *const MDL_BANK_PATH = ge::MDL_BANK_PATH_FLAG.c_str(); +static const char_t *const OP_BANK_PATH = ge::OP_BANK_PATH_FLAG.c_str(); +static const char_t *const OP_BANK_UPDATE = ge::OP_BANK_UPDATE_FLAG.c_str(); +static const char_t *const OP_DEBUG_LEVEL = ge::OP_DEBUG_LEVEL.c_str(); +static const char_t *const PERFORMANCE_MODE = ge::PERFORMANCE_MODE.c_str(); +static const char_t *const SHAPE_GENERALIZED_BUILD_MODE = ge::SHAPE_GENERALIZED_BUILD_MODE.c_str(); +static const char_t *const MODIFY_MIXLIST = ge::MODIFY_MIXLIST.c_str(); +static const char_t *const OP_PRECISION_MODE = ge::OP_PRECISION_MODE.c_str(); // for interface: aclgrphBuildModel #ifdef __GNUC__ diff --git a/inc/external/ge/ge_ir_build.h b/inc/external/ge/ge_ir_build.h index 84f31145..d1d6ade9 100644 --- a/inc/external/ge/ge_ir_build.h +++ b/inc/external/ge/ge_ir_build.h @@ -98,10 +98,10 @@ GE_FUNC_VISIBILITY graphStatus aclgrphBuildModel(const ge::Graph &graph, * @retval GRAPH_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -ATTRIBUTED_DEPRECATED(GE_FUNC_VISIBILITY graphStatus aclgrphSaveModel(const char *, const ModelBufferData &)) +ATTRIBUTED_DEPRECATED(GE_FUNC_VISIBILITY graphStatus aclgrphSaveModel(const char_t *, const ModelBufferData &)) GE_FUNC_VISIBILITY graphStatus aclgrphSaveModel(const std::string &output_file, const ModelBufferData &model); -GE_FUNC_VISIBILITY graphStatus aclgrphSaveModel(const char *output_file, const ModelBufferData &model); +GE_FUNC_VISIBILITY graphStatus aclgrphSaveModel(const char_t *output_file, const ModelBufferData &model); /** * @ingroup AscendCL @@ -126,7 +126,7 @@ GE_FUNC_VISIBILITY graphStatus aclgrphGetIRVersion(int32_t *major_version, int32 * @retval GRAPH_SUCCESS The function is successfully executed. * @retval OtherValues Failure */ -GE_FUNC_VISIBILITY graphStatus aclgrphDumpGraph(const ge::Graph &graph, const char *file, const size_t len); +GE_FUNC_VISIBILITY graphStatus aclgrphDumpGraph(const ge::Graph &graph, const char_t *file, const size_t len); /** * @ingroup AscendCL @@ -150,7 +150,7 @@ GE_FUNC_VISIBILITY graphStatus aclgrphGenerateForOp(const AscendString &op_type, * @param cfg_path [IN] the config file path * @return graphStatus */ -GE_FUNC_VISIBILITY graphStatus aclgrphSetOpAttr(Graph &graph, aclgrphAttrType attr_type, const char *cfg_path); +GE_FUNC_VISIBILITY graphStatus aclgrphSetOpAttr(Graph &graph, aclgrphAttrType attr_type, const char_t *cfg_path); }; // namespace ge #endif // INC_EXTERNAL_GE_IR_BUILD_H_ diff --git a/inc/external/runtime/rt_error_codes.h b/inc/external/runtime/rt_error_codes.h index 8966f738..d16af89f 100644 --- a/inc/external/runtime/rt_error_codes.h +++ b/inc/external/runtime/rt_error_codes.h @@ -62,6 +62,7 @@ static const int32_t ACL_ERROR_RT_OVER_LIMIT = 207012; // over limit static const int32_t ACL_ERROR_RT_QUEUE_EMPTY = 207013; // queue is empty static const int32_t ACL_ERROR_RT_QUEUE_FULL = 207014; // queue is full static const int32_t ACL_ERROR_RT_REPEATED_INIT = 207015; // repeated init +static const int32_t ACL_ERROR_RT_AIVEC_OVER_FLOW = 207016; // aivec over flow static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error @@ -113,5 +114,4 @@ static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconn #ifdef __cplusplus } #endif - #endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/inc/framework/common/debug/ge_log.h b/inc/framework/common/debug/ge_log.h index b1bf929f..2cb56222 100644 --- a/inc/framework/common/debug/ge_log.h +++ b/inc/framework/common/debug/ge_log.h @@ -40,7 +40,7 @@ enum TraceStatus { TRACE_INIT = 0, TRACE_RUNNING, TRACE_WAITING, TRACE_STOP }; class GE_FUNC_VISIBILITY GeLog { public: - static const uint64_t GetTid() { + static uint64_t GetTid() { #ifdef __GNUC__ const uint64_t tid = static_cast(syscall(__NR_gettid)); #else @@ -56,11 +56,11 @@ inline bool IsLogEnable(const int32_t module_name, const int32_t log_level) { return (enable == 1); } -#define GELOGE(ERROR_CODE, fmt, ...) \ - do { \ - dlog_error(GE_MODULE_NAME, "%lu %s: ErrorNo: %u(%s) %s" fmt, GeLog::GetTid(), &__FUNCTION__[0], ERROR_CODE, \ - ((GE_GET_ERRORNO_STR(ERROR_CODE)).c_str()), ErrorManager::GetInstance().GetLogHeader().c_str(), \ - ##__VA_ARGS__); \ +#define GELOGE(ERROR_CODE, fmt, ...) \ + do { \ + dlog_error(GE_MODULE_NAME, "%lu %s: ErrorNo: %u(%s) %s" fmt, GeLog::GetTid(), &__FUNCTION__[0], (ERROR_CODE), \ + ((GE_GET_ERRORNO_STR(ERROR_CODE)).c_str()), ErrorManager::GetInstance().GetLogHeader().c_str(), \ + ##__VA_ARGS__); \ } while (false) #define GELOGW(fmt, ...) \ @@ -91,7 +91,7 @@ inline bool IsLogEnable(const int32_t module_name, const int32_t log_level) { #define GELOGT(VALUE, fmt, ...) \ do { \ - TraceStatus stat = VALUE; \ + TraceStatus stat = (VALUE); \ const char_t *const TraceStatStr[] = {"INIT", "RUNNING", "WAITING", "STOP"}; \ const int32_t idx = static_cast(stat); \ char_t *k = const_cast("status"); \ @@ -102,7 +102,7 @@ inline bool IsLogEnable(const int32_t module_name, const int32_t log_level) { #define GE_LOG_ERROR(MOD_NAME, ERROR_CODE, fmt, ...) \ do { \ - dlog_error(MOD_NAME, "%lu %s: ErrorNo: %u(%s) %s" fmt, GeLog::GetTid(), &__FUNCTION__[0], ERROR_CODE, \ + dlog_error((MOD_NAME), "%lu %s: ErrorNo: %u(%s) %s" fmt, GeLog::GetTid(), &__FUNCTION__[0], (ERROR_CODE), \ ((GE_GET_ERRORNO_STR(ERROR_CODE)).c_str()), ErrorManager::GetInstance().GetLogHeader().c_str(), \ ##__VA_ARGS__); \ } while (false) diff --git a/inc/framework/common/debug/log.h b/inc/framework/common/debug/log.h index 32e915eb..07affc3f 100644 --- a/inc/framework/common/debug/log.h +++ b/inc/framework/common/debug/log.h @@ -69,7 +69,7 @@ do { \ const ge::Status _chk_status = (expr); \ if (_chk_status != ge::SUCCESS) { \ - GELOGE((ge::FAILED), __VA_ARGS__); \ + GELOGE(_chk_status, __VA_ARGS__); \ } \ } while (false) @@ -213,9 +213,9 @@ // If expr is not RT_ERROR_NONE, print the log #define GE_CHK_RT(expr) \ do { \ - const rtError_t _rt_ret = (expr); \ - if (_rt_ret != RT_ERROR_NONE) { \ - GELOGE(ge::RT_FAILED, "Call rt api failed, ret: 0x%X", _rt_ret); \ + const rtError_t _rt_err = (expr); \ + if (_rt_err != RT_ERROR_NONE) { \ + GELOGE(ge::RT_FAILED, "Call rt api failed, ret: 0x%X", _rt_err); \ } \ } while (false) @@ -278,7 +278,7 @@ return (_status); \ } \ } while (false) - +namespace ge { template GE_FUNC_VISIBILITY std::string FmtToStr(const T &t) { std::string fmt; @@ -287,5 +287,5 @@ GE_FUNC_VISIBILITY std::string FmtToStr(const T &t) { fmt = st.str(); return fmt; } - +} // namespace ge #endif // INC_FRAMEWORK_COMMON_DEBUG_LOG_H_ diff --git a/inc/framework/common/file_constant_util.h b/inc/framework/common/file_constant_util.h index 1ea81960..e0763057 100644 --- a/inc/framework/common/file_constant_util.h +++ b/inc/framework/common/file_constant_util.h @@ -27,11 +27,6 @@ #include "graph/ge_tensor.h" namespace ge { -extern const int64_t kBlockSize; -extern const std::string kBinFileValues; -extern const std::string kBinIdValue; -extern const std::string kBinFilePathValue; - struct FileConstantInfo { std::string value_bin_file_id; std::string value_bin_file_path; @@ -47,14 +42,11 @@ void from_json(const nlohmann::json &j, OptionInfo &option_info); Status GetFilePathFromOption(std::map &file_id_and_path_map); -Status CopyOneWeightFromFile(const void *curr_dev_ptr, const std::string &value, const size_t file_constant_size, +Status CopyOneWeightFromFile(const void *const curr_dev_ptr, const std::string &value, const size_t file_constant_size, size_t &left_size); Status GetFilePath(const OpDescPtr &op_desc, const std::map &file_id_and_path_map, std::string &file_path); - -Status GetFileConstantElementTotalSize(const GeShape &shape, const DataType data_type, int64_t &mem_size, - const Format format = FORMAT_ND); } // namespace ge #endif // INC_FRAMEWORK_COMMON_FILE_CONSTANT_UTIL_H diff --git a/inc/framework/common/fmk_error_codes.h b/inc/framework/common/fmk_error_codes.h index 9f1719ac..1ecd96cb 100644 --- a/inc/framework/common/fmk_error_codes.h +++ b/inc/framework/common/fmk_error_codes.h @@ -44,7 +44,7 @@ // Each module uses the following four macros to define error codes: #define DECLARE_ERRORNO_OMG(name, value) DECLARE_ERRORNO(SYSID_FWK, MODID_OMG, (name), (value)) #define DECLARE_ERRORNO_OME(name, value) DECLARE_ERRORNO(SYSID_FWK, MODID_OME, (name), (value)) -#define DECLARE_ERRORNO_CALIBRATION(name, value) DECLARE_ERRORNO(SYSID_FWK, MODID_CALIBRATION, name, value) +#define DECLARE_ERRORNO_CALIBRATION(name, value) DECLARE_ERRORNO(SYSID_FWK, MODID_CALIBRATION, (name), (value)) #define DEF_ERRORNO(name, desc) const ErrorNoRegisterar g_##name##_errorno((name), (desc)); @@ -74,7 +74,7 @@ class GE_FUNC_VISIBILITY StatusFactory { class GE_FUNC_VISIBILITY ErrorNoRegisterar { public: - ErrorNoRegisterar(uint32_t err, const std::string &desc) { + ErrorNoRegisterar(const uint32_t err, const std::string &desc) { StatusFactory::Instance()->RegisterErrorNo(err, desc); } ~ErrorNoRegisterar() {} diff --git a/inc/framework/common/ge_inner_error_codes.h b/inc/framework/common/ge_inner_error_codes.h index 529f6cb4..fd80d2bd 100644 --- a/inc/framework/common/ge_inner_error_codes.h +++ b/inc/framework/common/ge_inner_error_codes.h @@ -22,17 +22,57 @@ #include #include "ge/ge_api_error_codes.h" +// Each module defines error codes using the following macros, name can not be modified to (name) +#define GE_ERRORNO_COMMON(name, value, desc) \ + GE_ERRORNO(ge::InnLogRuntime::RT_HOST, ge::InnErrorCodeType::ERROR_CODE, ge::InnErrorLevel::COMMON_LEVEL, \ + ge::InnSystemIdType::SYSID_GE, ge::InnSubModuleId::COMMON_MODULE, name, (value), (desc)) +#define GE_ERRORNO_CLIENT(name, value, desc) \ + GE_ERRORNO(ge::InnLogRuntime::RT_HOST, ge::InnErrorCodeType::ERROR_CODE, ge::InnErrorLevel::COMMON_LEVEL, \ + ge::InnSystemIdType::SYSID_GE, ge::InnSubModuleId::CLIENT_MODULE, name, (value), (desc)) +#define GE_ERRORNO_INIT(name, value, desc) \ + GE_ERRORNO(ge::InnLogRuntime::RT_HOST, ge::InnErrorCodeType::ERROR_CODE, ge::InnErrorLevel::COMMON_LEVEL, \ + ge::InnSystemIdType::SYSID_GE, ge::InnSubModuleId::INIT_MODULE, name, (value), (desc)) +#define GE_ERRORNO_SESSION(name, value, desc) \ + GE_ERRORNO(ge::InnLogRuntime::RT_HOST, ge::InnErrorCodeType::ERROR_CODE, ge::InnErrorLevel::COMMON_LEVEL, \ + ge::InnSystemIdType::SYSID_GE, ge::InnSubModuleId::SESSION_MODULE, name, (value), (desc)) +#define GE_ERRORNO_GRAPH(name, value, desc) \ + GE_ERRORNO(ge::InnLogRuntime::RT_HOST, ge::InnErrorCodeType::ERROR_CODE, ge::InnErrorLevel::COMMON_LEVEL, \ + ge::InnSystemIdType::SYSID_GE, ge::InnSubModuleId::GRAPH_MODULE, name, (value), (desc)) +#define GE_ERRORNO_ENGINE(name, value, desc) \ + GE_ERRORNO(ge::InnLogRuntime::RT_HOST, ge::InnErrorCodeType::ERROR_CODE, ge::InnErrorLevel::COMMON_LEVEL, \ + ge::InnSystemIdType::SYSID_GE, ge::InnSubModuleId::ENGINE_MODULE, name, (value), (desc)) +#define GE_ERRORNO_OPS(name, value, desc) \ + GE_ERRORNO(ge::InnLogRuntime::RT_HOST, ge::InnErrorCodeType::ERROR_CODE, ge::InnErrorLevel::COMMON_LEVEL, \ + ge::InnSystemIdType::SYSID_GE, ge::InnSubModuleId::OPS_MODULE, name, (value), (desc)) +#define GE_ERRORNO_PLUGIN(name, value, desc) \ + GE_ERRORNO(ge::InnLogRuntime::RT_HOST, ge::InnErrorCodeType::ERROR_CODE, ge::InnErrorLevel::COMMON_LEVEL, \ + ge::InnSystemIdType::SYSID_GE, ge::InnSubModuleId::PLUGIN_MODULE, name, (value), (desc)) +#define GE_ERRORNO_RUNTIME(name, value, desc) \ + GE_ERRORNO(ge::InnLogRuntime::RT_HOST, ge::InnErrorCodeType::ERROR_CODE, ge::InnErrorLevel::COMMON_LEVEL, \ + ge::InnSystemIdType::SYSID_GE, ge::InnSubModuleId::RUNTIME_MODULE, name, (value), (desc)) +#define GE_ERRORNO_EXECUTOR(name, value, desc) \ + GE_ERRORNO(ge::InnLogRuntime::RT_DEVICE, ge::InnErrorCodeType::ERROR_CODE, ge::InnErrorLevel::COMMON_LEVEL, \ + ge::InnSystemIdType::SYSID_GE, ge::InnSubModuleId::EXECUTOR_MODULE, name, (value), (desc)) +#define GE_ERRORNO_GENERATOR(name, value, desc) \ + GE_ERRORNO(ge::InnLogRuntime::RT_HOST, ge::InnErrorCodeType::ERROR_CODE, ge::InnErrorLevel::COMMON_LEVEL, \ + ge::InnSystemIdType::SYSID_GE, ge::InnSubModuleId::GENERATOR_MODULE, name, (value), (desc)) + +// Get error code description +#define GE_GET_ERRORNO_STR(value) ge::StatusFactory::Instance()->GetErrDesc(value) + +#define RT_ERROR_TO_GE_STATUS(RT_ERROR) static_cast(RT_ERROR) + namespace ge { // System ID -enum SystemIdType { SYSID_GE = 8 }; +enum class InnSystemIdType { SYSID_GE = 8 }; // Runtime location -enum LogRuntime { +enum class InnLogRuntime { RT_HOST = 0b01, RT_DEVICE = 0b10, }; // Sub model -enum SubModuleId { +enum class InnSubModuleId { COMMON_MODULE = 0, CLIENT_MODULE = 1, INIT_MODULE = 2, @@ -47,13 +87,13 @@ enum SubModuleId { }; // Error code type -enum ErrorCodeType { +enum class InnErrorCodeType { ERROR_CODE = 0b01, EXCEPTION_CODE = 0b10, }; // Error level -enum ErrorLevel { +enum class InnErrorLevel { COMMON_LEVEL = 0b000, SUGGESTION_LEVEL = 0b001, MINOR_LEVEL = 0b010, @@ -61,33 +101,6 @@ enum ErrorLevel { CRITICAL_LEVEL = 0b100, }; -// Each module defines error codes using the following macros, name can not be modified to (name) -#define GE_ERRORNO_COMMON(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, COMMON_MODULE, name, (value), (desc)) -#define GE_ERRORNO_CLIENT(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, CLIENT_MODULE, name, (value), (desc)) -#define GE_ERRORNO_INIT(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, INIT_MODULE, name, (value), (desc)) -#define GE_ERRORNO_SESSION(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, SESSION_MODULE, name, (value), (desc)) -#define GE_ERRORNO_GRAPH(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, GRAPH_MODULE, name, (value), (desc)) -#define GE_ERRORNO_ENGINE(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, ENGINE_MODULE, name, (value), (desc)) -#define GE_ERRORNO_OPS(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, OPS_MODULE, name, (value), (desc)) -#define GE_ERRORNO_PLUGIN(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, PLUGIN_MODULE, name, (value), (desc)) -#define GE_ERRORNO_RUNTIME(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, RUNTIME_MODULE, name, (value), (desc)) -#define GE_ERRORNO_EXECUTOR(name, value, desc) \ - GE_ERRORNO(RT_DEVICE, ERROR_CODE, COMMON_LEVEL, SYSID_GE, EXECUTOR_MODULE, name, (value), (desc)) -#define GE_ERRORNO_GENERATOR(name, value, desc) \ - GE_ERRORNO(RT_HOST, ERROR_CODE, COMMON_LEVEL, SYSID_GE, GENERATOR_MODULE, name, (value), (desc)) - -// Get error code description -#define GE_GET_ERRORNO_STR(value) ge::StatusFactory::Instance()->GetErrDesc(value) - // Common module error code definition GE_ERRORNO_COMMON(MEMALLOC_FAILED, 0, "Failed to allocate memory!"); // 1343225856 GE_ERRORNO_COMMON(PARAM_INVALID, 1, "Parameter's invalid!"); // 1343225857 @@ -313,10 +326,6 @@ GE_ERRORNO_GENERATOR(GE_GENERATOR_GRAPH_MANAGER_BUILD_GRAPH_FAILED, 3, "Graph ma GE_ERRORNO_GENERATOR(GE_GENERATOR_GRAPH_MANAGER_FINALIZE_FAILED, 4, "Graph manager finalize failed."); GE_ERRORNO_GENERATOR(GE_GENERATOR_GRAPH_MANAGER_SAVE_MODEL_FAILED, 5, "Graph manager save model failed."); -static inline Status TransRtErrorCode(const int32_t error_code) { - return static_cast(error_code); -} -#define RT_ERROR_TO_GE_STATUS(RT_ERROR) TransRtErrorCode(RT_ERROR) } // namespace ge #endif // INC_FRAMEWORK_COMMON_GE_INNER_ERROR_CODES_H_ diff --git a/inc/framework/common/ge_types.h b/inc/framework/common/ge_types.h index 868debe7..f1f6e54a 100644 --- a/inc/framework/common/ge_types.h +++ b/inc/framework/common/ge_types.h @@ -40,13 +40,13 @@ enum FrameworkType { CAFFE = 0, MINDSPORE = 1, TENSORFLOW = 3, - ANDROID_NN, - ONNX, + ANDROID_NN = 4, + ONNX = 5, }; enum class GraphStage : int64_t { GRAPH_STAGE_FUZZ = 0, GRAPH_STAGE_RESERVED }; -const char *const kGraphDumpStage = "DumpStage"; +const char_t *const kGraphDumpStage = "DumpStage"; const std::map kFwkTypeToStr = { {"0", "Caffe"}, {"1", "MindSpore"}, {"3", "TensorFlow"}, {"4", "Android_NN"}, {"5", "Onnx"}}; @@ -70,21 +70,42 @@ const std::string kTaskTypeAicore = "AI_CORE"; const std::string kTaskTypeAicpu = "AI_CPU"; const std::string kTaskTypeInvalid = "TASK_TYPE_INVALID"; const std::string kTaskTypeFftsPlus = "FFTS_PLUS"; +const std::string kEngineNameVectorCore = "VectorEngine"; + +const std::string kEngineNameHccl = "ops_kernel_info_hccl"; +const std::string kEngineNameRts = "DNN_VM_RTS_OP_STORE"; +const std::string kEngineNameHostCpu = "DNN_VM_HOST_CPU_OP_STORE"; +const std::string kEngineNameGeLocal = "DNN_VM_GE_LOCAL_OP_STORE"; +const std::string kEngineNameAiCpu = "aicpu_ascend_kernel"; +const std::string kEngineNameAiCpuTf = "aicpu_tf_kernel"; +const std::string kEngineNameAiCore = "AIcoreEngine"; +const std::string kAtomicOpType = "DynamicAtomicAddrClean"; + +const std::string kShapeTypeStatic = "static"; +const std::string kShapeTypeDynamic = "dynamic"; + +constexpr uint64_t kInferSessionId = 0U; +constexpr uint64_t kReleaseFlag = 1U; +constexpr uint32_t kInvalidModelId = 0xFFFFFFFFU; +constexpr size_t kNumTaskWithAtomicAddrCleanTask = 2U; // dynamic execute mode const char_t *const kLazyRecompile = "lazy_recompile"; +constexpr size_t kMaxHostMemInputLen = 64U; + // Data cache, including data address and length struct DataBuffer { - public: void *data; // Data address uint64_t length; // Data length bool isDataSupportMemShare = false; uint32_t placement = 0U; - DataBuffer(void *data_in, uint64_t data_len, bool is_support_mem_share, uint32_t placement = 0U) - : data(data_in), length(data_len), isDataSupportMemShare(is_support_mem_share), placement(placement) {} - DataBuffer() : data(nullptr), length(0UL), isDataSupportMemShare(false) {} + DataBuffer(void *const data_in, const uint64_t data_len, const bool is_support_mem_share = false, + const uint32_t data_placement = 0U) + : data(data_in), length(data_len), isDataSupportMemShare(is_support_mem_share), placement(data_placement) {} + + DataBuffer() : data(nullptr), length(0UL), isDataSupportMemShare(false), placement(0U) {} }; /// @@ -232,6 +253,9 @@ struct ModelInfo { class GE_FUNC_VISIBILITY ModelListener { public: virtual ~ModelListener() {} + ModelListener() = default; + ModelListener(const ModelListener &) = delete; + ModelListener &operator=(const ModelListener &) = delete; /// /// @brief Asynchronous callback interface /// @param [in] model_id Model ID of the callback @@ -241,7 +265,9 @@ class GE_FUNC_VISIBILITY ModelListener { virtual Status OnComputeDone(uint32_t model_id, uint32_t data_index, uint32_t result_code, std::vector &outputs) = 0; - virtual void SetCallback(const RunAsyncCallback &callback){}; + virtual void SetCallback(const RunAsyncCallback &callback) { + (void)callback; + } virtual uint32_t GetResultCode() { return 0U; diff --git a/inc/framework/common/helper/model_helper.h b/inc/framework/common/helper/model_helper.h index 8da856e1..4a098b1f 100644 --- a/inc/framework/common/helper/model_helper.h +++ b/inc/framework/common/helper/model_helper.h @@ -34,12 +34,13 @@ class GE_FUNC_VISIBILITY ModelHelper { ~ModelHelper(); Status SaveToOmModel(const GeModelPtr &ge_model, const SaveParam &save_param, const std::string &output_file, - ge::ModelBufferData &model); + ge::ModelBufferData &model) const; Status SaveToOmRootModel(const GeRootModelPtr &ge_root_model, const SaveParam &save_param, const std::string &output_file, ModelBufferData &model, const bool is_unknown_shape); Status SaveOriginalGraphToOmModel(const ge::Graph &graph, const std::string &output_file); Status LoadModel(const ge::ModelData &model_data); Status LoadRootModel(const ge::ModelData &model_data); + static void SetModelToGeModel(GeModelPtr &ge_model, Model &model); GeModelPtr GetGeModel(); GeRootModelPtr GetGeRootModel(); @@ -67,7 +68,6 @@ class GE_FUNC_VISIBILITY ModelHelper { Status GenerateGeModel(OmFileLoadHelper &om_load_helper); Status GenerateGeRootModel(OmFileLoadHelper &om_load_helper); Status LoadModelData(OmFileLoadHelper &om_load_helper); - void SetModelToGeModel(GeModelPtr &ge_model, Model &model) const; Status LoadModelData(OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model, const size_t mode_index) const; Status LoadWeights(OmFileLoadHelper &om_load_helper); Status LoadWeights(OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model, const size_t mode_index) const; diff --git a/inc/framework/common/helper/om_file_helper.h b/inc/framework/common/helper/om_file_helper.h index 45d61395..2d715486 100644 --- a/inc/framework/common/helper/om_file_helper.h +++ b/inc/framework/common/helper/om_file_helper.h @@ -21,25 +21,20 @@ #include #include "external/ge/ge_ir_build.h" -#include "framework/common/fmk_types.h" #include "framework/common/types.h" #include "framework/common/ge_types.h" -using ProcParam = struct PROC_PARAM; -using std::string; -using std::vector; - namespace ge { struct ModelPartition { ModelPartitionType type; - uint8_t *data = 0; - uint32_t size = 0; + const uint8_t *data = nullptr; + uint32_t size = 0U; }; struct OmFileContext { std::vector partition_datas_; - std::vector partition_table_; - uint32_t model_data_len_ = 0; + std::vector partition_table_; + uint32_t model_data_len_ = 0U; }; struct SaveParam { @@ -55,13 +50,13 @@ class GE_FUNC_VISIBILITY OmFileLoadHelper { public: Status Init(const ge::ModelData &model); - Status Init(uint8_t *model_data, const uint32_t model_data_size); + Status Init(uint8_t *const model_data, const uint32_t model_data_size); - Status Init(uint8_t *model_data, const uint32_t model_data_size, uint32_t model_num); + Status Init(uint8_t *const model_data, const uint32_t model_data_size, const uint32_t model_num); - Status GetModelPartition(ModelPartitionType type, ModelPartition &partition); + Status GetModelPartition(const ModelPartitionType type, ModelPartition &partition); - Status GetModelPartition(ModelPartitionType type, ModelPartition &partition, size_t model_index); + Status GetModelPartition(const ModelPartitionType type, ModelPartition &partition, const size_t model_index); OmFileContext context_; @@ -70,9 +65,9 @@ class GE_FUNC_VISIBILITY OmFileLoadHelper { private: Status CheckModelValid(const ge::ModelData &model) const; - Status LoadModelPartitionTable(uint8_t *model_data, const uint32_t model_data_size); + Status LoadModelPartitionTable(uint8_t *const model_data, const uint32_t model_data_size); - Status LoadModelPartitionTable(uint8_t *model_data, const uint32_t model_data_size, uint32_t model_num); + Status LoadModelPartitionTable(uint8_t *const model_data, const uint32_t model_data_size, const uint32_t model_num); bool is_inited_{false}; }; @@ -89,25 +84,24 @@ class GE_FUNC_VISIBILITY OmFileSaveHelper { ModelPartitionTable *GetPartitionTable(); - Status AddPartition(ModelPartition &partition); - - Status AddPartition(ModelPartition &partition, size_t cur_index); + Status AddPartition(const ModelPartition &partition); - const std::vector &GetModelPartitions() const; + Status AddPartition(const ModelPartition &partition, const size_t cur_index); - Status SaveModel(const SaveParam &save_param, const char *target_file, ge::ModelBufferData &model, - bool is_offline = true); + Status SaveModel(const SaveParam &save_param, const char_t *const output_file, ge::ModelBufferData &model, + const bool is_offline = true); - Status SaveModelToFile(const char *output_file, ge::ModelBufferData &model, bool is_offline = true); + Status SaveModelToFile(const char_t *const output_file, ge::ModelBufferData &model, const bool is_offline = true); std::vector model_contexts_; ModelFileHeader model_header_; OmFileContext context_; - ModelPartitionTable *GetPartitionTable(size_t cur_ctx_index); + ModelPartitionTable *GetPartitionTable(const size_t cur_ctx_index); - Status SaveRootModel(const SaveParam &save_param, const char *output_file, ModelBufferData &model, bool is_offline); + Status SaveRootModel(const SaveParam &save_param, const char_t *const output_file, ModelBufferData &model, + const bool is_offline); }; } // namespace ge #endif // INC_FRAMEWORK_COMMON_HELPER_OM_FILE_HELPER_H_ diff --git a/inc/framework/common/l2_cache_optimize.h b/inc/framework/common/l2_cache_optimize.h index 39bc1d13..478c1750 100644 --- a/inc/framework/common/l2_cache_optimize.h +++ b/inc/framework/common/l2_cache_optimize.h @@ -28,97 +28,13 @@ #include "framework/common/util.h" #include "graph/compute_graph.h" -using std::vector; - namespace ge { // Size of RC memory alignment, 2M -constexpr size_t ALIGN_SIZE = 2097152; - -constexpr uint32_t RC_VALUE_DEFAULT = 1; -constexpr uint32_t RC_VALUE_MAX = 32; - -// RC data type classification -enum RCType { - RC_DEFAULT, // Such as temporary workspace memory of operator, variable (including global and local variable) - RC_HCOM, // Output of gradient aggregation, RC value should be set to 0 - RC_L2LOSS, // Parameter of L2 loss operator, RC value should be set to 0 - RC_INPUTOUTPUT, // Input and output tensor of operator, RC value is returned by FE calculation - RC_WEIGHTS, // The weight, fp16, RC value used by FP/BP operator should be set to 1 or the actual access numbers - RC_DW, // The gradient data DW and RC value output by BP operator - // should be set to 1 or the actual access numbers - RC_ARGS // Args of FlowTable, actual access numbers -}; - -enum MemType { INPUT_TENSOR, OUTPUT_TENSOR, WEIGHT, WORKSPACE }; - -// Memory usage information < node, type, number > -struct NodeInfo { - std::string nodeName; - MemType memType; - size_t index; -}; - -// Memory block RC value -struct RCMemoryBlock { - RCType type; // RC type - size_t blockSize; // memory block size - size_t headOffset; // Start offset from base address - size_t tailOffset; // End offset from base address - uint32_t rcCount; // RC value - NodeInfo nodeInfo; // Input and output indexes of node objects to which RC belongs -}; - -// L2Cache optimizer -class GE_FUNC_VISIBILITY L2CacheOptimize { - public: - explicit L2CacheOptimize(ge::ComputeGraphPtr &graph); - ~L2CacheOptimize(); - - // Collect the information L2Cache Memory optimization - Status Gath(); - - private: - ge::ComputeGraphPtr graph_; - - // Save RC block information list - std::vector weightRCs; - std::vector opRCs; - - // Extract RC information generated by FE from compiled graph - void RetirveRCinfo(); - - // Take the maximum common divisor of RC values for the duplicate address - void Merge(std::vector &blocks); - - // The RC information is aligned with the 2m address - void Align(std::vector &blocks); - - // Weight of l2loss operator, output of gradient aggregation output, RC value set to 0 - void HandleOutputZeroRC(RCType type, ge::NodePtr node, std::vector &outputList, - std::vector &blocks); - - // Processing operator input Tensor's RC - void HandOPInput(ge::NodePtr node, std::vector &inputList, std::vector &blocks); - - // Processing operator output Tensor's RC - void HandOPoutput(ge::NodePtr node, std::vector &outputList, std::vector &blocks); +constexpr size_t ALIGN_SIZE = 2097152U; - // maximum common divisor - uint32_t Measure(uint32_t x, uint32_t y) { - if ((x == 0) || (y == 0)) return RC_VALUE_DEFAULT; - uint32_t z = y; - while (x % y != 0) { - z = x % y; - x = y; - y = z; - } - return z; - } +constexpr uint32_t RC_VALUE_DEFAULT = 1U; +constexpr uint32_t RC_VALUE_MAX = 32U; - bool Contain(const RCMemoryBlock &l_block, const RCMemoryBlock &r_block); - bool Cross(const RCMemoryBlock &l_block, const RCMemoryBlock &r_block); - bool Connect(const RCMemoryBlock &l_block, const RCMemoryBlock &r_block); -}; } // namespace ge #endif // INC_FRAMEWORK_COMMON_L2_CACHE_OPTIMIZE_H_ \ No newline at end of file diff --git a/inc/framework/common/op/attr_value_util.h b/inc/framework/common/op/attr_value_util.h index 27415df8..d749ae4f 100644 --- a/inc/framework/common/op/attr_value_util.h +++ b/inc/framework/common/op/attr_value_util.h @@ -34,143 +34,11 @@ #include #include #include - +#include "external/graph/types.h" #include "graph/debug/ge_attr_define.h" #include "proto/om.pb.h" -using domi::AttrDef; -using domi::AttrDef_ListValue; -using domi::ModelDef; -using domi::NamedAttrs; -using domi::OpDef; - namespace ge { -using AttrDefMap = ::google::protobuf::Map<::std::string, ::domi::AttrDef>; -using AttrDefPair = ::google::protobuf::MapPair; - -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, AttrDef &attr, OpDef *opdef); -// DEFINE_ADD_ATTR_VALUE -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, const std::string &value, AttrDefMap *attrs); -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, const char *value, AttrDefMap *attrs); -GE_FUNC_VISIBILITY void AddOpAttr(const char *key, const char *value, AttrDefMap *attrs); -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, const uint32_t value, AttrDefMap *attrs); -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, const int32_t value, AttrDefMap *attrs); -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, const int64_t value, AttrDefMap *attrs); -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, const float value, AttrDefMap *attrs); -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, const double value, AttrDefMap *attrs); -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, const bool value, AttrDefMap *attrs); - -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, const AttrDef_ListValue &value, AttrDefMap *attrs); - -// DEFINE_ADD_ATTR_VALUE -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, const std::string &value, OpDef *opdef); -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, const char *value, OpDef *opdef); -GE_FUNC_VISIBILITY void AddOpAttr(const char *key, const char *value, OpDef *opdef); -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, const uint32_t value, OpDef *opdef); -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, const int32_t value, OpDef *opdef); -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, const int64_t value, OpDef *opdef); -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, const float value, OpDef *opdef); -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, const double value, OpDef *opdef); -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, const bool value, OpDef *opdef); - -GE_FUNC_VISIBILITY void AddOpAttr(const std::string &key, const AttrDef_ListValue &value, OpDef *opdef); - -GE_FUNC_VISIBILITY void AddOpBytesAttr(const std::string &key, const void *value, size_t size, OpDef *opdef); - -// DEFINE_ADD_ATTR_VALUE_LIST -GE_FUNC_VISIBILITY void AddOpAttrList(const std::string &key, const double value, AttrDefMap *attrs); -GE_FUNC_VISIBILITY void AddOpAttrList(const std::string &key, const float value, AttrDefMap *attrs); -GE_FUNC_VISIBILITY void AddOpAttrList(const std::string &key, const uint32_t value, AttrDefMap *attrs); -GE_FUNC_VISIBILITY void AddOpAttrList(const std::string &key, const int32_t value, AttrDefMap *attrs); -GE_FUNC_VISIBILITY void AddOpAttrList(const std::string &key, const std::string value, AttrDefMap *attrs); -GE_FUNC_VISIBILITY void AddOpAttrList(const std::string &key, const double value, OpDef *opdef); -GE_FUNC_VISIBILITY void AddOpAttrList(const std::string &key, const float value, OpDef *opdef); -GE_FUNC_VISIBILITY void AddOpAttrList(const std::string &key, const uint32_t value, OpDef *opdef); -GE_FUNC_VISIBILITY void AddOpAttrList(const std::string &key, const int32_t value, OpDef *opdef); -GE_FUNC_VISIBILITY void AddOpAttrList(const std::string &key, const bool value, OpDef *opdef); -GE_FUNC_VISIBILITY void AddOpAttrList(const std::string &key, const int64_t value, OpDef *opdef); - -GE_FUNC_VISIBILITY void AddOpAttrList(const std::string &key, const std::string &value, OpDef *opdef); - -GE_FUNC_VISIBILITY bool GetOpAttr(const std::string &key, std::string *value, const OpDef *opdef); -GE_FUNC_VISIBILITY bool GetOpAttr(const std::string &key, int32_t *value, const OpDef *opdef); -GE_FUNC_VISIBILITY bool GetOpAttr(const std::string &key, int64_t *value, const OpDef *opdef); -GE_FUNC_VISIBILITY bool GetOpAttr(const std::string &key, uint32_t *value, const OpDef *opdef); -GE_FUNC_VISIBILITY bool GetOpAttr(const std::string &key, float *value, const OpDef *opdef); -GE_FUNC_VISIBILITY bool GetOpAttr(const std::string &key, double *value, const OpDef *opdef); -GE_FUNC_VISIBILITY bool GetOpAttr(const std::string &key, bool *value, const OpDef *opdef); -GE_FUNC_VISIBILITY bool GetOpAttr(const std::string &key, AttrDef_ListValue *value, const OpDef *opdef); - -GE_FUNC_VISIBILITY uint32_t GetOpAttrListSize(const std::string &key, std::string value, const OpDef *opdef); -GE_FUNC_VISIBILITY uint32_t GetOpAttrListSize(const std::string &key, int32_t value, const OpDef *opdef); -GE_FUNC_VISIBILITY uint32_t GetOpAttrListSize(const std::string &key, int64_t value, const OpDef *opdef); -GE_FUNC_VISIBILITY uint32_t GetOpAttrListSize(const std::string &key, uint32_t value, const OpDef *opdef); -GE_FUNC_VISIBILITY uint32_t GetOpAttrListSize(const std::string &key, float value, const OpDef *opdef); -GE_FUNC_VISIBILITY uint32_t GetOpAttrListSize(const std::string &key, double value, const OpDef *opdef); -GE_FUNC_VISIBILITY uint32_t GetOpAttrListSize(const std::string &key, bool value, const OpDef *opdef); - -GE_FUNC_VISIBILITY bool GetBytesAttr(const std::string &key, std::string *value, const OpDef *opdef); -GE_FUNC_VISIBILITY bool GetBytesAttr(const std::string &key, std::string *value, const ModelDef *model_def); - -GE_FUNC_VISIBILITY void AddModelAttr(const std::string &key, const std::string &value, ModelDef *model_def); -GE_FUNC_VISIBILITY void AddModelAttr(const std::string &key, const char *value, ModelDef *model_def); -GE_FUNC_VISIBILITY void AddModelAttr(const char *key, const char *value, ModelDef *model_def); -GE_FUNC_VISIBILITY void AddModelAttr(const std::string &key, const uint32_t value, ModelDef *model_def); -GE_FUNC_VISIBILITY void AddModelAttr(const std::string &key, const int32_t value, ModelDef *model_def); -GE_FUNC_VISIBILITY void AddModelAttr(const std::string &key, const int64_t value, ModelDef *model_def); -GE_FUNC_VISIBILITY void AddModelAttr(const std::string &key, const float value, ModelDef *model_def); -GE_FUNC_VISIBILITY void AddModelAttr(const std::string &key, const double value, ModelDef *model_def); -GE_FUNC_VISIBILITY void AddModelAttr(const std::string &key, const bool value, ModelDef *model_def); -GE_FUNC_VISIBILITY void AddModelAttr(const std::string &key, const void *value, size_t size, ModelDef *model_def); -GE_FUNC_VISIBILITY void AddModelAttr(const std::string &key, const AttrDef_ListValue &value, ModelDef *model_def); - -GE_FUNC_VISIBILITY void AddModelAttrList(const std::string &key, const double value, ModelDef *model_def); -GE_FUNC_VISIBILITY void AddModelAttrList(const std::string &key, const float value, ModelDef *model_def); -GE_FUNC_VISIBILITY void AddModelAttrList(const std::string &key, const uint32_t value, ModelDef *model_def); -GE_FUNC_VISIBILITY void AddModelAttrList(const std::string &key, const int32_t value, ModelDef *model_def); -GE_FUNC_VISIBILITY void AddModelAttrList(const std::string &key, const std::string &value, ModelDef *model_def); - -GE_FUNC_VISIBILITY bool GetModelAttr(const std::string &key, std::string *value, const ModelDef *model_def); -GE_FUNC_VISIBILITY bool GetModelAttr(const std::string &key, int32_t *value, const ModelDef *model_def); -GE_FUNC_VISIBILITY bool GetModelAttr(const std::string &key, int64_t *value, const ModelDef *model_def); -GE_FUNC_VISIBILITY bool GetModelAttr(const std::string &key, uint32_t *value, const ModelDef *model_def); -GE_FUNC_VISIBILITY bool GetModelAttr(const std::string &key, float *value, const ModelDef *model_def); -GE_FUNC_VISIBILITY bool GetModelAttr(const std::string &key, double *value, const ModelDef *model_def); -GE_FUNC_VISIBILITY bool GetModelAttr(const std::string &key, bool *value, const ModelDef *model_def); -GE_FUNC_VISIBILITY bool GetModelAttr(const std::string &key, AttrDef_ListValue *value, const ModelDef *model_def); - -GE_FUNC_VISIBILITY bool HasOpAttr(const OpDef *opdef, const std::string &attr_name); - -GE_FUNC_VISIBILITY void SetAttrDef(const std::string &value, AttrDef *out); -GE_FUNC_VISIBILITY void SetAttrDef(const char *value, AttrDef *out); -GE_FUNC_VISIBILITY void SetAttrDef(const uint32_t value, AttrDef *out); -GE_FUNC_VISIBILITY void SetAttrDef(const int32_t value, AttrDef *out); -GE_FUNC_VISIBILITY void SetAttrDef(const float value, AttrDef *out); -GE_FUNC_VISIBILITY void SetAttrDef(const double value, AttrDef *out); -GE_FUNC_VISIBILITY void SetAttrDef(const bool value, AttrDef *out); -GE_FUNC_VISIBILITY void SetAttrList(const std::string &value, AttrDef *out); -GE_FUNC_VISIBILITY void SetAttrList(const bool value, AttrDef *out); -GE_FUNC_VISIBILITY void SetAttrList(const float value, AttrDef *out); -GE_FUNC_VISIBILITY void SetAttrList(const double value, AttrDef *out); -GE_FUNC_VISIBILITY void SetAttrList(const uint32_t value, AttrDef *out); - -GE_FUNC_VISIBILITY bool GetAttrDefValue(const std::string &key, std::string *value, const AttrDefMap &attr); -GE_FUNC_VISIBILITY bool GetAttrDefValue(const std::string &key, int32_t *value, const AttrDefMap &attr); -GE_FUNC_VISIBILITY bool GetAttrDefValue(const std::string &key, int64_t *value, const AttrDefMap &attr); -GE_FUNC_VISIBILITY bool GetAttrDefValue(const std::string &key, uint32_t *value, const AttrDefMap &attr); -GE_FUNC_VISIBILITY bool GetAttrDefValue(const std::string &key, float *value, const AttrDefMap &attr); -GE_FUNC_VISIBILITY bool GetAttrDefValue(const std::string &key, double *value, const AttrDefMap &attr); -GE_FUNC_VISIBILITY bool GetAttrDefValue(const std::string &key, bool *value, const AttrDefMap &attr); -GE_FUNC_VISIBILITY bool GetAttrDefValue(const std::string &key, AttrDef_ListValue *value, const AttrDefMap &attr); -GE_FUNC_VISIBILITY bool GetAttrDefValue(const std::string &key, NamedAttrs *&value, AttrDefMap *attr); -GE_FUNC_VISIBILITY bool GetAttrDefValue(const std::string &key, const NamedAttrs *&value, const AttrDefMap &attr); - -GE_FUNC_VISIBILITY bool GetAttrDefListValue(const std::string &key, int32_t idx, int32_t *value, - const AttrDefMap &attr); -GE_FUNC_VISIBILITY bool GetAttrDefListValue(const std::string &key, int32_t idx, uint32_t *value, - const AttrDefMap &attr); -GE_FUNC_VISIBILITY bool GetAttrDefListValue(const std::string &key, int32_t idx, float *value, const AttrDefMap &attr); -GE_FUNC_VISIBILITY bool GetAttrDefListValue(const std::string &key, int32_t idx, double *value, const AttrDefMap &attr); -} // namespace ge - -#endif // INC_FRAMEWORK_COMMON_OP_ATTR_VALUE_UTIL_H_ +GE_FUNC_VISIBILITY void SetAttrDef(const std::string &value, domi::AttrDef *const out); +} +#endif // INC_FRAMEWORK_COMMON_OP_ATTR_VALUE_UTIL_H_ \ No newline at end of file diff --git a/inc/framework/common/op/ge_op_utils.h b/inc/framework/common/op/ge_op_utils.h index 8b28258a..53e72074 100644 --- a/inc/framework/common/op/ge_op_utils.h +++ b/inc/framework/common/op/ge_op_utils.h @@ -31,18 +31,16 @@ #include "proto/insert_op.pb.h" namespace ge { -using domi::Status; // Add Sub Mul GE_FUNC_VISIBILITY extern const uint32_t ADD_INPUT_NUM; -GE_FUNC_VISIBILITY extern const uint32_t SUB_INPUT_NUM; GE_FUNC_VISIBILITY extern const uint32_t MUL_INPUT_NUM; // Permute GE_FUNC_VISIBILITY extern const int32_t PERMUTE_ORDER_NUM; // Ssd PriroBox -GE_FUNC_VISIBILITY extern const double SSD_PRIORBOX_ASPECT_RATIO_VALUE; +GE_FUNC_VISIBILITY extern const float64_t SSD_PRIORBOX_ASPECT_RATIO_VALUE; GE_FUNC_VISIBILITY extern const uint32_t STRIDEDSLICE_INPUT_NUM; @@ -55,8 +53,8 @@ GE_FUNC_VISIBILITY extern const uint32_t SWITCH_DATA_INPUT; GE_FUNC_VISIBILITY extern const uint32_t SWITCH_PRED_INPUT; // Merge -GE_FUNC_VISIBILITY extern const uint32_t MERGE_DATA_OUTPUT; -GE_FUNC_VISIBILITY extern const uint32_t MERGE_INDEX_OUTPUT; +GE_FUNC_VISIBILITY extern const int32_t MERGE_DATA_OUTPUT; +GE_FUNC_VISIBILITY extern const int32_t MERGE_INDEX_OUTPUT; // FunctionOp GE_FUNC_VISIBILITY extern const uint32_t IF_COND_INPUT; @@ -66,86 +64,35 @@ GE_FUNC_VISIBILITY extern const uint32_t FOR_DELTA_INPUT; GE_FUNC_VISIBILITY extern const uint32_t FOR_DATA_INPUT; GE_FUNC_VISIBILITY extern const int32_t NORMAL_TENSOR_SIZE; - +/*lint -e148*/ class GE_FUNC_VISIBILITY OpUtils { public: - /// - /// @ingroup domi_ome - /// @brief Check whether check_value is in [min_enum_value, max_enum_value] - /// @return true Within - /// @return false out of range - // - static inline bool CheckEnumValid(int32_t check_value, int32_t min_enum_value, int32_t max_enum_value) { - return check_value < min_enum_value ? false : (check_value >= max_enum_value ? false : true); - } - - /// - /// @ingroup domi_omg - /// @brief Determine whether to manually calculate the tensor size based on the values of format and dim - /// @param [in] format, Format information of the tensor - /// @param [in] real_dim_cnt, Tensor dim - /// @return true Manually calculate the size based on dim and datatype - /// @return false skip - /// - static bool IsComputDimsSize(const int32_t format, const uint32_t real_dim_cnt); - /// /// @brief Extract AIPP parameters from AttrDefMap and splice them /// @param [in] aipp_attr attr of operator /// @param [out] aipp_params aipp parameters /// @return enum of tagCCAippInputFormat /// - static Status ConvertAippParams(const NamedAttrs &aipp_attr, domi::AippOpParams *aipp_params); - static Status TransferDim(const std::vector &dim, std::vector &dim_vector); + + static Status ConvertAippParams(const GeAttrValue::NamedAttrs &aipp_attr, domi::AippOpParams &aipp_params); template - static void SliceData(const std::vector &input, int64_t chunk_size, std::vector &output, - int64_t begin, int64_t out_dim, int64_t stride); + static void SliceData(const std::vector &input, const int64_t chunk_size, std::vector &output, + const int64_t begin, const int64_t out_dim, const int64_t stride); template - static Status SetDataByDataType(size_t out_size, const std::vector &chunk_input, - const std::vector &chunk_output, GeTensor *output); + static Status SetDataByDataType(const size_t out_size, const std::vector &chunk_input, + const std::vector &chunk_output, GeTensor *const output); template - static Status SetOutputSliceDataByDataType(void *data, int64_t data_size, const std::vector &input_dims, - const std::vector &begin, const std::vector &output_dims, - ge::GeTensor *output, const std::vector &stride); - static Status SetOutputSliceData(void *data, int64_t data_size, int32_t data_type, + static Status SetOutputSliceDataByDataType(void *const data, const int64_t data_size, + const std::vector &input_dims, const std::vector &begin, + const std::vector &output_dims, ge::GeTensor *const output, + const std::vector &stride); + static Status SetOutputSliceData(void *const data, const int64_t data_size, const int32_t data_type, const std::vector &input_dims, const std::vector &begin, - const std::vector &output_dims, ge::GeTensor *const output, + const std::vector &output_dims, GeTensor *const output, const std::vector &stride); - - /// - /// @ingroup domi_omg - /// @brief Convert the convolutional weight data from [h, w, c, k] to [k, c, h, w] - /// @param [in] input Weight data in HWCK format - /// @param [in] H value of H dimension - /// @param [in] W value of W dimension - /// @param [in] C value of C dimension - /// @param [in] K value of K dimension - /// @param [out] output Data pointer after conversion. The format is KCHW. - /// - static void TransDataHWCK2KCHW(const void *input, int64_t h, int64_t w, int64_t c, int64_t k, void **output); - /// - /// @ingroup domi_omg - /// @brief Converts the convolutional weight data from [k, c, h, w] to [h, w, c, k]. - /// @param [in] input Weight data in HWCK format - /// @param [in] K value of K dimension - /// @param [in] C value of C dimension - /// @param [in] H value of H dimension - /// @param [in] W value of W dimension - /// @param [out] output Data pointer after conversion. The format is HWCK - /// - static void TransDataKCHW2HWCK(const void *input, int64_t k, int64_t c, int64_t h, int64_t w, void *output); - - static std::vector GetWeights(const ge::Node &node); - static std::vector GetWeights(ge::ConstNodePtr node); - static std::vector MutableWeights(const ge::Node &node); - static std::vector MutableWeights(const ge::NodePtr node); - static Status SetWeights(ge::Node &node, const std::vector &weights); - static Status SetWeights(const ge::NodePtr node, const std::vector &weights); static Status GetShapeDataFromConstTensor(const ConstGeTensorPtr &tensor, const DataType type, std::vector &dims); - - private: - static uint32_t GetRealDimCnt(const GeTensorDesc &tensor_desc); }; +/*lint +e148*/ } // namespace ge #endif // INC_FRAMEWORK_COMMON_OP_GE_OP_UTILS_H_ diff --git a/inc/framework/common/op_types.h b/inc/framework/common/op_types.h index 4e4d4dda..2b7009e8 100644 --- a/inc/framework/common/op_types.h +++ b/inc/framework/common/op_types.h @@ -20,6 +20,8 @@ #include #include +#include "graph/types.h" + namespace ge { class GE_FUNC_VISIBILITY OpTypeContainer { public: @@ -30,12 +32,11 @@ class GE_FUNC_VISIBILITY OpTypeContainer { ~OpTypeContainer() = default; void Register(const std::string &op_type) { - op_type_list_.insert(op_type); + static_cast(op_type_list_.insert(op_type)); } bool IsExisting(const std::string &op_type) { - auto iter_find = op_type_list_.find(op_type); - return iter_find != op_type_list_.end(); + return op_type_list_.find(op_type) != op_type_list_.end(); } protected: @@ -47,20 +48,19 @@ class GE_FUNC_VISIBILITY OpTypeContainer { class GE_FUNC_VISIBILITY OpTypeRegistrar { public: - explicit OpTypeRegistrar(const std::string &op_type) { + explicit OpTypeRegistrar(const std::string &op_type) noexcept { OpTypeContainer::Instance()->Register(op_type); } ~OpTypeRegistrar() {} }; +} // namespace ge #define REGISTER_OPTYPE_DECLARE(var_name, str_name) \ - FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const char *var_name; + FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const char_t *var_name; #define REGISTER_OPTYPE_DEFINE(var_name, str_name) \ - const char *var_name = str_name; \ - const OpTypeRegistrar g_##var_name##_reg(str_name); - -#define IS_OPTYPE_EXISTING(str_name) (OpTypeContainer::Instance()->IsExisting(str_name)) -} // namespace ge + const char_t *var_name = str_name; \ + const ge::OpTypeRegistrar g_##var_name##_reg(str_name); +#define IS_OPTYPE_EXISTING(str_name) (ge::OpTypeContainer::Instance()->IsExisting(str_name)) #endif // INC_FRAMEWORK_COMMON_OP_TYPES_H_ diff --git a/inc/framework/common/profiling/ge_profiling.h b/inc/framework/common/profiling/ge_profiling.h index f0ecc5d1..16588830 100644 --- a/inc/framework/common/profiling/ge_profiling.h +++ b/inc/framework/common/profiling/ge_profiling.h @@ -24,10 +24,8 @@ /// @brief Output the profiling data of single operator in Pytorch, and does not support multithreading /// @return Status result /// -GE_FUNC_VISIBILITY ge::Status ProfSetStepInfo(uint64_t index_id, uint16_t tag_id, rtStream_t stream); +GE_FUNC_VISIBILITY ge::Status ProfSetStepInfo(const uint64_t index_id, const uint16_t tag_id, rtStream_t const stream); -GE_FUNC_VISIBILITY ge::Status ProfGetDeviceFormGraphId(uint32_t graph_id, uint32_t &device_id); - -GE_FUNC_VISIBILITY void ProfSetGraphIdToDeviceMap(uint32_t graph_id, uint32_t &device_id); +GE_FUNC_VISIBILITY ge::Status ProfGetDeviceFormGraphId(const uint32_t graph_id, uint32_t &device_id); #endif // INC_FRAMEWORK_COMMON_GE_PROFILING_H_ diff --git a/inc/framework/common/profiling_definitions.h b/inc/framework/common/profiling_definitions.h new file mode 100644 index 00000000..90f3823a --- /dev/null +++ b/inc/framework/common/profiling_definitions.h @@ -0,0 +1,173 @@ +/** + * Copyright 2021 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. + */ + +#ifndef AIR_CXX_PROFILING_DEFINITIONS_H +#define AIR_CXX_PROFILING_DEFINITIONS_H +#include +#include +#include +#include +#include "graph/profiler.h" +#include "external/ge/ge_api_types.h" +#include "toolchain/prof_callback.h" +namespace ge { +namespace profiling { +enum { + kAclCompileAndExecute, + kAclMatchOpModel, + kAclMatchStaticOpModel, + kAclMatchDynamicOpModel, + kAclExecuteAsync, + kAclLoadSingleOp, + kAclBuildOpModel, + kInferShape, + kTiling, + kUpdateShape, + kConstPrepare, + kInitHybridExecuteArgs, + kInitInferShapeContext, + kDestroyInferShapeContext, + kResetSubgraphExecutor, + kCommitInferShapeTask, + kDeviceToHost, + kPrepareTask, + kLaunchTask, + kCommitTilingTask, + kAtomic, + kKernelLaunchPrepare, + kRtKernelLaunch, + kOpExecute, + kAllocMem, + kCopyH2D, + + // Add new definitions here + kProfilingIndexEnd +}; +constexpr uint64_t kInvalidHashId = 0UL; + +class ProfilingContext { + public: + static bool IsDumpToStdEnabled(); + static ProfilingContext &GetInstance(); + ProfilingContext(); + ~ProfilingContext(); + + /* + * 还有一种思路是`IsEnabled`只判断profiler_是否为空指针,不再设置单独的enabled标记位,这样可以少一个标记位。 + * 但是这么做就意味着,profiler_实例在未使能profiling时,必须是空指针状态。 + * 为了性能考虑,profiling机制在编译和加载时,就会调用`RegisterString`,向profiler_注册字符串,后续执行时,只会使用注册好的index了。 + * 因此存在一种场景:编译时并未使能profiling(因为编译时间很长,使能profiling也无法真实反应执行时的耗时状态), + * 因此编译时注册字符串的动作并没有生效。在执行时,动态的打开了profiling,这种场景下,执行时无法拿到注册后字符串 + */ + bool IsEnabled() const noexcept { + return enabled_ && profiler_ != nullptr; + } + void SetEnable() noexcept { + enabled_ = true; + } + void SetDisable() noexcept { + enabled_ = false; + } + + void RecordCurrentThread(const int64_t element, const int64_t event, const EventType et, + const std::chrono::time_point time_point) { + if (IsEnabled()) { + profiler_->RecordCurrentThread(element, event, et, time_point); + } + } + + void RecordCurrentThread(const int64_t element, const int64_t event, const EventType et) { + RecordCurrentThread(element, event, et, std::chrono::system_clock::now()); + } + + const Profiler *GetProfiler() const { + return profiler_.get(); + } + + void Dump(std::ostream &out_stream) const { + if (IsEnabled()) { + profiler_->Dump(out_stream); + } else { + out_stream << "Profiling not enable, skip to dump" << std::endl; + } + } + + void DumpToStdOut() const { + Dump(std::cout); + } + + void Reset() { + if (IsEnabled()) { + profiler_->Reset(); + } + } + + int64_t RegisterString(const std::string &str); + int64_t RegisterStringHash(const uint64_t hash_id, const std::string &str); + void UpdateElementHashId(const MsprofReporterCallback reporter_callback); + static Status QueryHashId(const MsprofReporterCallback reporter_callback, const std::string &src_str, + uint64_t &hash_id); + size_t GetRegisterStringNum() const { + return strings_to_index_.size(); + } + + void Init(); + + private: + void UpdateHashByStr(const std::string &str, const uint64_t hash); + + private: + bool inited_; + bool enabled_; + int64_t str_index_; + std::unordered_map strings_to_index_; + std::mutex strings_to_index_mutex_; + std::unique_ptr profiler_; +}; + +class ScopeProfiler { + public: + ScopeProfiler(const int64_t element, const int64_t event) : element_(element), event_(event) { + if (ProfilingContext::GetInstance().IsEnabled()) { + start_trace_ = std::chrono::system_clock::now(); + } + } + ~ScopeProfiler() { + if (ProfilingContext::GetInstance().IsEnabled()) { + ProfilingContext::GetInstance().RecordCurrentThread(element_, event_, EventType::kEventStart, start_trace_); + ProfilingContext::GetInstance().RecordCurrentThread(element_, event_, EventType::kEventEnd); + } + } + void SetElement(const int64_t element) { + element_ = element; + } + + private: + std::chrono::time_point start_trace_; + int64_t element_; + int64_t event_; +}; +} // namespace profiling +} // namespace ge +#define PROFILING_START(element, event) \ + ge::profiling::ProfilingContext::GetInstance().RecordCurrentThread((element), (event), \ + ge::profiling::EventType::kEventStart) +#define PROFILING_END(element, event) \ + ge::profiling::ProfilingContext::GetInstance().RecordCurrentThread((element), (event), \ + ge::profiling::EventType::kEventEnd) +#define PROFILING_SCOPE(element, event) ge::profiling::ScopeProfiler profiler((element), (event)) +#define PROFILING_SCOPE_ELEMENT(element) profiler.SetElement((element)) +#endif // AIR_CXX_PROFILING_DEFINITIONS_H diff --git a/inc/framework/common/scope_guard.h b/inc/framework/common/scope_guard.h index 4ec4cfa7..ce9e4c51 100644 --- a/inc/framework/common/scope_guard.h +++ b/inc/framework/common/scope_guard.h @@ -25,9 +25,9 @@ /// MAKE_GUARD([&] { Release Resource 1 }) /// Acquire Resource 2 // MAKE_GUARD([&] { Release Resource 2 }) -#define GE_MAKE_GUARD(var, callback) const ScopeGuard const_guard_##var(callback) +#define GE_MAKE_GUARD(var, callback) const ::ge::ScopeGuard const_guard_##var(callback) -#define GE_DISMISSABLE_GUARD(var, callback) ScopeGuard make_guard_##var(callback) +#define GE_DISMISSABLE_GUARD(var, callback) ::ge::ScopeGuard make_guard_##var(callback) #define GE_DISMISS_GUARD(var) make_guard_##var.Dismiss() namespace ge { @@ -44,7 +44,7 @@ class GE_FUNC_VISIBILITY ScopeGuard { if (on_exit_scope_ != nullptr) { try { on_exit_scope_(); - } catch (std::bad_function_call &e) { + } catch (std::bad_function_call &) { } catch (...) { } } diff --git a/inc/framework/common/string_util.h b/inc/framework/common/string_util.h index 21f09ffd..c369d04f 100644 --- a/inc/framework/common/string_util.h +++ b/inc/framework/common/string_util.h @@ -39,13 +39,14 @@ #include #include #include +#include "graph/types.h" namespace ge { class GE_FUNC_VISIBILITY StringUtils { public: static std::string &Ltrim(std::string &s) { #if __cplusplus >= 201103L - (void)s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int32_t c) { return std::isspace(c) == 0; })); + (void)s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](const int32_t c) { return std::isspace(c) == 0; })); #else (void)s.erase(s.begin(), std::find_if(s.begin(), s.end(), std::not1(std::ptr_fun(std::isspace)))); #endif @@ -54,7 +55,8 @@ class GE_FUNC_VISIBILITY StringUtils { // lint -esym(551,*) static std::string &Rtrim(std::string &s) { /*lint !e618*/ #if __cplusplus >= 201103L - (void)s.erase(std::find_if(s.rbegin(), s.rend(), [](int32_t c) { return std::isspace(c) == 0; }).base(), s.end()); + (void)s.erase(std::find_if(s.rbegin(), s.rend(), [](const int32_t c) { return std::isspace(c) == 0; }).base(), + s.end()); #else (void)s.erase(std::find_if(s.rbegin(), s.rend(), std::not1(std::ptr_fun(std::isspace))).base(), s.end()); @@ -79,7 +81,7 @@ class GE_FUNC_VISIBILITY StringUtils { /// @param [in] delim separator /// @return string array after segmentation /// - static std::vector> Split(const std::string &str, char delim) { + static std::vector> Split(const std::string &str, const char_t delim) { std::vector> elems; if (str.empty()) { @@ -94,8 +96,8 @@ class GE_FUNC_VISIBILITY StringUtils { elems.push_back(item); } - auto str_size = str.size(); - if ((str_size > 0) && (str[str_size - 1] == delim)) { + const auto str_size = str.size(); + if ((str_size > 0U) && (str[str_size - 1U] == delim)) { elems.emplace_back(""); } @@ -107,13 +109,13 @@ class GE_FUNC_VISIBILITY StringUtils { /// @param [in] s path name /// @return file name /// - static std::string GetFileName(std::string &s) { + static std::string GetFileName(const std::string &s) { if (s.empty()) { return ""; } - std::vector files = StringUtils::Split(s, '/'); + const std::vector files = StringUtils::Split(s, '/'); - return files.empty() ? "" : files[files.size() - 1]; + return files.empty() ? "" : files[files.size() - 1U]; } /// /// @ingroup domi_common @@ -125,12 +127,13 @@ class GE_FUNC_VISIBILITY StringUtils { /// @return string after replacement /// static std::string ReplaceAll(std::string str, const std::string &old_value, const std::string &new_value) { - std::string::size_type cur_pos = 0; - std::string::size_type old_length = old_value.length(); - std::string::size_type new_length = new_value.length(); + std::string::size_type cur_pos = 0U; + const std::string::size_type old_length = old_value.length(); + const std::string::size_type new_length = new_value.length(); // cycle replace for (; cur_pos != std::string::npos; cur_pos += new_length) { - if ((cur_pos = str.find(old_value, cur_pos)) != std::string::npos) { + cur_pos = str.find(old_value, cur_pos); + if (cur_pos != std::string::npos) { (void)str.replace(cur_pos, old_length, new_value); } else { break; @@ -148,7 +151,7 @@ class GE_FUNC_VISIBILITY StringUtils { /// @return if the value is a prefix, true is returned. Otherwise, false is returned /// static bool StartWith(const std::string &str, const std::string str_x) { - return ((str.size() >= str_x.size()) && (str.compare(0, str_x.size(), str_x) == 0)); + return ((str.size() >= str_x.size()) && (str.compare(0U, str_x.size(), str_x) == 0)); } /// @@ -159,14 +162,14 @@ class GE_FUNC_VISIBILITY StringUtils { /// @param [in] ... format Filling Content /// @return formatted string /// - static std::string FormatString(const char *format, ...) { - const uint32_t MAX_BUFFER_LEN = 1024; // the stack memory plint check result must be less than 1024 + static std::string FormatString(const char_t *const format, ...) { + const uint32_t MAX_BUFFER_LEN = 1024U; // the stack memory plint check result must be less than 1024 va_list args; va_start(args, format); - char buffer[MAX_BUFFER_LEN] = {0}; - int32_t ret = vsnprintf_s(buffer, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, format, args); + char_t buffer[MAX_BUFFER_LEN] = {}; + const int32_t ret = vsnprintf_s(&buffer[0], MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1U, format, args); va_end(args); - return ret > 0 ? buffer : ""; + return (ret > 0) ? buffer : ""; } }; } // namespace ge diff --git a/inc/framework/common/taskdown_common.h b/inc/framework/common/taskdown_common.h index 331bf486..159072b8 100644 --- a/inc/framework/common/taskdown_common.h +++ b/inc/framework/common/taskdown_common.h @@ -23,7 +23,7 @@ namespace ge { const int32_t CC_FUSION_OP_MAX = 32; -typedef enum tagCcStatus { +enum class ccStatus_t { CC_STATUS_SUCCESS = 0, /**< succ */ CC_STATUS_NOT_INITIALIZED = 1, /**< not init */ CC_STATUS_ALLOC_FAILED = 2, /**< alloc mem failed */ @@ -33,10 +33,10 @@ typedef enum tagCcStatus { CC_STATUS_RUNTIME_ERROR = 6, /**< runtime error */ CC_STATUS_NOT_SUPPORTED = 7, /**< unsupport error */ CC_STATUS_INVALID_VALUE = 7, /**< invalid value error for blas*/ - CC_STATUS_RESERVED /**< just for check */ -} ccStatus_t; + CC_STATUS_RESERVED = 8, /**< just for check */ +}; -typedef enum tagccKernelType { +enum class ccKernelType { CCE_AI_CORE = 0, /* cce aicore */ CCE_AI_CPU = 1, /* cce aicpu */ TE = 2, /* te operator*/ @@ -47,9 +47,9 @@ typedef enum tagccKernelType { CUST_AI_CPU = 7, /* custom aicpu*/ HOST_CPU = 8, /* host cpu */ INVALID = 10000 /* unknown kernel type */ -} ccKernelType; +}; -typedef struct tagOpContext { +using ccOpContext = struct tagOpContext { ccKernelType kernelType; uint32_t opId; uint32_t kernelFuncId; @@ -66,7 +66,28 @@ typedef struct tagOpContext { uint64_t genVariableBaseAddr; uint64_t genVariableBaseSize; uint64_t l2ctrlSize; -} ccOpContext; -} // namespace ge +}; + +enum class tagOpTensorFormat { OP_TENSOR_FORMAT_NC1HWC0 = 0, OP_TENSOR_FORMAT_ND, OP_TENSOR_FORMAT_RESERVED }; +enum class tagOpDataType { + OP_DATA_FLOAT = 0, /**< float type */ + OP_DATA_HALF, /**< fp16 type */ + OP_DATA_INT8, /**< int8 type */ + OP_DATA_INT32, /**< int32 type */ + OP_DATA_UINT8, /**< uint8 type */ + OP_DATA_HALF_UINT16_PROPOSAL, /**< mixed type for proposal */ + OP_DATA_RESERVED +}; + +// AICPU Tensor +using ccAICPUTensor = struct tagOpTensor { + // real dim info + tagOpTensorFormat format; + tagOpDataType data_type; + int32_t dim_cnt; + int32_t mm; + int32_t dim[8]; +}; +} // namespace ge #endif // INC_FRAMEWORK_COMMON_TASKDOWN_COMMON_H_ diff --git a/inc/framework/common/types.h b/inc/framework/common/types.h index e5681ba6..475def7f 100644 --- a/inc/framework/common/types.h +++ b/inc/framework/common/types.h @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -44,32 +43,17 @@ FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string OP_DEB FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string OP_DEBUG_ALL; // Profile-related constants -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string OME_PROFILE; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string CCE_PROFILE; -FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string RTS_PROFILE; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string PROFILE_MODEL_ID; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string MODEL_ATTR_TASKS; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string MODEL_ATTR_TASK_GEN_BASE_ADDR; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string MODEL_ATTR_TASK_GEN_WEIGHT_ADDR; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string MODEL_ATTR_FUSION_MODEL_DEF; - FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint64_t ALLOC_MEMORY_MAX_SIZE; // Max size of 8 GB. -template -static std::pair flip_pair(const std::pair &p) { - return std::pair(p.second, p.first); -} - -template -static std::map flip_map(std::map src) { - std::map dst; - std::transform(src.begin(), src.end(), std::inserter(dst, dst.begin()), flip_pair); - return dst; -} - REGISTER_OPTYPE_DECLARE(DATA, "Data"); REGISTER_OPTYPE_DECLARE(AIPPDATA, "AippData"); +REGISTER_OPTYPE_DECLARE(QUEUE_DATA, "QueueData"); REGISTER_OPTYPE_DECLARE(CONVOLUTION, "Convolution"); REGISTER_OPTYPE_DECLARE(CORRELATION, "Correlation"); REGISTER_OPTYPE_DECLARE(CORRELATIONV2, "Correlation_V2"); @@ -140,6 +124,8 @@ REGISTER_OPTYPE_DECLARE(SQUEEZE, "Squeeze"); REGISTER_OPTYPE_DECLARE(UNSQUEEZE, "Unsqueeze"); REGISTER_OPTYPE_DECLARE(SQUEEZEV2, "SqueezeV2"); REGISTER_OPTYPE_DECLARE(UNSQUEEZEV2, "UnsqueezeV2"); +REGISTER_OPTYPE_DECLARE(SQUEEZEV3, "SqueezeV3"); +REGISTER_OPTYPE_DECLARE(UNSQUEEZEV3, "UnsqueezeV3"); REGISTER_OPTYPE_DECLARE(STRIDEDSLICE, "StridedSlice"); REGISTER_OPTYPE_DECLARE(RANGE, "Range"); REGISTER_OPTYPE_DECLARE(RPNPROPOSALS, "GenerateRpnProposals"); @@ -438,6 +424,7 @@ REGISTER_OPTYPE_DECLARE(MODELEXIT, "ModelExit"); REGISTER_OPTYPE_DECLARE(SEND, "Send"); REGISTER_OPTYPE_DECLARE(RECV, "Recv"); REGISTER_OPTYPE_DECLARE(ENDOFSEQUENCE, "EndOfSequence"); +REGISTER_OPTYPE_DECLARE(STARTOFSEQUENCE, "StartOfSequence"); REGISTER_OPTYPE_DECLARE(LABELSET, "LabelSet"); REGISTER_OPTYPE_DECLARE(LABELGOTO, "LabelGoto"); @@ -461,8 +448,6 @@ REGISTER_OPTYPE_DECLARE(ELU_GRAD, "EluGrad"); REGISTER_OPTYPE_DECLARE(ADD_V2, "AddV2"); REGISTER_OPTYPE_DECLARE(DATAFORMATDIMMAP, "DataFormatDimMap"); REGISTER_OPTYPE_DECLARE(DATAFORMATVECPERMUTE, "DataFormatVecPermute"); -REGISTER_OPTYPE_DECLARE(BESSELI0e, "BesselI0e"); -REGISTER_OPTYPE_DECLARE(BESSELI1e, "BesselI1e"); REGISTER_OPTYPE_DECLARE(DEQUANTIZE, "Dequantize"); REGISTER_OPTYPE_DECLARE(APPLYADADELTA, "ApplyAdadelta"); REGISTER_OPTYPE_DECLARE(APPLYADAGRAD, "ApplyAdagrad"); @@ -516,29 +501,11 @@ REGISTER_OPTYPE_DECLARE(GETDYNAMICDIMS, "GetDynamicDims"); // profiling training trace node REGISTER_OPTYPE_DECLARE(PROFILINGTRAININGTRACE, "ProfilingTrainingTrace"); -enum InputMode { INPUT = 0, CONST_INPUT }; - -// Definition of the processing status enum of the process module -enum ModelProcessState { - INIT_STATE = 0, // init status - WAIT_EVENT_STATE, // Wait for the event status - IND_RSLT_STATE, // The model execution result is being output to the high level - STOPPED_STATE, // Model execution completed. The model enters this state after Model Manager::Stop - RESERVED_STATE, // reserved -}; - -// Indicates the enun definition of the execution mode of the access module -enum SysMode { - INFERENCE = 0, // Normal, that is, Inference mode - DEBUG, // Debug mode - TIME, // Model execution time mode, including the execution time of each OP - STOP, // STOP mode - RESET, // RESET mode - PERFORMANCE, // Impact of enabling the performance model: 1. The input data of the model is considered ready and does - // not need to be converted - ANDROID_DEBUG, // Exports Android platform computing data - RESERVED, // reserved -}; +// Stack series +REGISTER_OPTYPE_DECLARE(STACK, "Stack"); +REGISTER_OPTYPE_DECLARE(STACKPUSH, "StackPush"); +REGISTER_OPTYPE_DECLARE(STACKPOP, "StackPop"); +REGISTER_OPTYPE_DECLARE(STACKCLOSE, "StackClose"); // @brief encryption type of the model file enum ModelEncryptType { @@ -577,22 +544,22 @@ FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t MODEL_FIL /// /// @brief model name length /// -static constexpr uint32_t MODEL_NAME_LENGTH = 32; +constexpr uint32_t MODEL_NAME_LENGTH = 32U; /// /// @brief length of user-defined information /// -static constexpr uint32_t USER_DEFINE_INFO_LENGTH = 32; +constexpr uint32_t USER_DEFINE_INFO_LENGTH = 32U; /// /// @brief length of the model file signature /// -static constexpr uint32_t MODEL_FILE_CHECKSUM_LENGTH = 64; +constexpr uint32_t MODEL_FILE_CHECKSUM_LENGTH = 64U; /// /// @brief length of the reserved field in the model file header /// -static constexpr uint32_t MODEL_FILE_RESERVED_LENGTH = 75; +constexpr uint32_t MODEL_FILE_RESERVED_LENGTH = 75U; // DATA node type FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string DATA_TYPE; @@ -617,7 +584,7 @@ FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string OP_TYP FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string OP_CONF_DELIMITER; // dim default size value -static const int32_t DIM_DEFAULT_SIZE = 4; +constexpr int32_t DIM_DEFAULT_SIZE = 4; // dim extension default value FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const int32_t DIM_DEFAULT_VALUE; @@ -650,34 +617,35 @@ FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint32_t STREAM_SW FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string NODE_NAME_GLOBAL_STEP; -static const uint32_t PLATFORM_VERSION_LEN = 20; +constexpr uint32_t PLATFORM_VERSION_LEN = 20U; // Definition of the file header of the model file struct ModelFileHeader { - uint32_t magic = MODEL_FILE_MAGIC_NUM; // magic number of DOMI - uint32_t headsize = MODEL_FILE_HEAD_LEN; // length of the model header. The value is fixed at 256 - uint32_t version = MODEL_VERSION; // version 1.0 - uint8_t checksum[MODEL_FILE_CHECKSUM_LENGTH] = {0}; // signature - uint32_t length = 0; // Ciphertext length. In the non-encryption model, the length is the plaintext length. - uint8_t is_encrypt = ModelEncryptType::UNENCRYPTED; // whether encrypted 0:not encrypt, 1:encrypt - uint8_t is_checksum = ModelCheckType::CHECK; // whether to check the checksum - uint8_t modeltype = 0; // 0:IR model 1:standard model 2: OM Tiny model - uint8_t genmode = 0; // 0:offline generate 1:online generate - uint8_t name[MODEL_NAME_LENGTH] = {0}; // Model name, which contains 32 characters - uint32_t ops = 0; // Computing power (Kops) - uint8_t userdefineinfo[USER_DEFINE_INFO_LENGTH] = {0}; // User-defined information. The value contains 32 characters - uint32_t om_ir_version = 0; - uint32_t model_num = 0; - uint8_t platform_version[PLATFORM_VERSION_LEN] = {0}; - uint8_t platform_type = {0}; - uint8_t reserved[MODEL_FILE_RESERVED_LENGTH] = {0}; // Reserved field 75 + uint32_t magic = MODEL_FILE_MAGIC_NUM; // magic number of DOMI + uint32_t headsize = MODEL_FILE_HEAD_LEN; // length of the model header. The value is fixed at 256 + uint32_t version = MODEL_VERSION; // version 1.0 + uint8_t checksum[MODEL_FILE_CHECKSUM_LENGTH] = {0U}; // signature + uint32_t length = 0U; // Ciphertext length. In the non-encryption model, the length is the plaintext length. + uint8_t is_encrypt = + static_cast(ModelEncryptType::UNENCRYPTED); // whether encrypted 0:not encrypt, 1:encrypt + uint8_t is_checksum = static_cast(ModelCheckType::CHECK); // whether to check the checksum + uint8_t modeltype = 0U; // 0:IR model 1:standard model 2: OM Tiny model + uint8_t genmode = 0U; // 0:offline generate 1:online generate + uint8_t name[MODEL_NAME_LENGTH] = {0U}; // Model name, which contains 32 characters + uint32_t ops = 0U; // Computing power (Kops) + uint8_t userdefineinfo[USER_DEFINE_INFO_LENGTH] = {0U}; // User-defined information. The value contains 32 characters + uint32_t om_ir_version = 0U; + uint32_t model_num = 0U; + uint8_t platform_version[PLATFORM_VERSION_LEN] = {0U}; + uint8_t platform_type = {0U}; + uint8_t reserved[MODEL_FILE_RESERVED_LENGTH] = {0U}; // Reserved field 75 }; -static constexpr uint8_t TARGET_TYPE_LTTE_8BIT = 0; -static constexpr uint8_t TARGET_TYPE_MINI_8BIT = 1; +constexpr uint8_t TARGET_TYPE_LTTE_8BIT = 0U; +constexpr uint8_t TARGET_TYPE_MINI_8BIT = 1U; // number of partitions in the current model -static constexpr uint32_t PARTITION_SIZE = 5; +constexpr uint32_t PARTITION_SIZE = 5U; enum ModelPartitionType { MODEL_DEF = 0, WEIGHTS_DATA, TASK_INFO, TBE_KERNELS, CUST_AICPU_KERNELS }; @@ -692,22 +660,9 @@ struct ModelPartitionTable { ModelPartitionMemInfo partition[0]; }; -#define SIZE_OF_MODEL_PARTITION_TABLE(table) (sizeof(ModelPartitionTable) + sizeof(ModelPartitionMemInfo) * (table).num) - -// Filter format -typedef enum tagDomiFilterFormat { - DOMI_FILTER_KCHW, // KCHW - DOMI_FILTER_HWCK, // HWCK - DOMI_FILTER_RESERVED -} domiFilterFormat_t; - -// Const data trans type -typedef enum tagDomiConstDataTransType { - DOMI_CONST_DATA_NOT_CHANGE = 0, // No action is required - DOMI_CONST_DATA_TRANS_MATMUL, // The const input to MatMul and needs to be transposed - DOMI_CONST_DATA_RESERVED -} domiConstDataTransType_t; - +inline uint64_t SizeOfModelPartitionTable(const ModelPartitionTable &table) { + return sizeof(ModelPartitionTable) + (sizeof(ModelPartitionMemInfo) * static_cast(table.num)); +} // mode of activation typedef enum tagDomiActivationMode { DOMI_ACTIVATION_SIGMOID = 0, // sigmoid @@ -727,190 +682,6 @@ typedef enum tagDomiActivationMode { DOMI_ACTIVATION_RESERVED } domiActivationMode_t; -// mode of batchnorm -typedef enum tagDomiBatchNormMode { - DOMI_BATCHNORM_PER_ACTIVATION = 0, // bnScale, bnBias tensor dims are 1xCxHxW - DOMI_BATCHNORM_SPATIAL, // bnScale, bnBias tensor dims are 1xCx1x1 - DOMI_BATCHNORM_RESERVED -} domiBatchNormMode_t; - -// eltwise mode -typedef enum tagDomiEltwiseMode { - DOMI_ELTWISE_PROD = 0, // prod - DOMI_ELTWISE_SUM, // sum - DOMI_ELTWISE_MAX, // max - DOMI_ELTWISE_RESERVED -} domiEltwiseMode_t; - -// mode of padding -typedef enum tagDomiPaddingMode { - DOMI_PADDING_CEIL = 0, // Default padding mode - DOMI_PADDING_DIRECTASSIGN, // Default padding mode: NOTSET - DOMI_PADDING_VALID, // VALID padding mode - DOMI_PADDING_SAME, // Padding values of 0 are always used - DOMI_PADDING_CEIL_NEW, // Padding values of 0 are always used - DOMI_PADDING_VALID_NEW, // Padding values of 0 are always used - DOMI_PADDING_SAME_NEW, // Padding values of 0 are always used - DOMI_PADDING_RESERVED -} domiPaddingMode_t; - -// algorithm of convolution forward -typedef enum tagDomiConvolutionFwdAlgo { - DOMI_CONVOLUTION_FWD_ALGO_GEMM = 0, // matrix gemm algo - DOMI_CONVOLUTION_FWD_ALGO_WINOGRAD, // Winograd Transform algo - DOMI_CONVOLUTION_FWD_ALGO_GEMM_ACCU_FLOAT32, // accumulate in L0c with FP32 - DOMI_CONVOLUTION_FWD_ALGO_RESERVED -} domiConvolutionFwdAlgo_t; - -typedef enum tagDomiFullConnectFwdAlgo { - DOMI_FULLCONNECT_FWD_ALGO_HALF = 0, // accumulate in L0c with FP16 - DOMI_FULLCONNECT_FWD_ALGO_FLOAT32 // accumulate in L0c with FP32 -} domiFullConnectFwdAlgo_t; - -typedef enum tagDomiPooingFwdAlgo { - DOMI_POOLING_FWD_ALGO_HALF = 0, // accumulate in L0c with FP16 - DOMI_POOLING_FWD_ALGO_FLOAT32 // accumulate in L0c with FP32 -} domiPooingFwdAlgo_t; - -// mode of convolution -typedef enum tagDomiConvolutionMode { - DOMI_CONV_CONVOLUTION = 0, // math convolution - DOMI_CONV_CROSS_CORRELATION, // cross-correlation convolution - DOMI_CONV_DECONVOLUTION, // deconvolution, also named transposed convolution - DOMI_CONV_MODE_DEPTHWISE, // depthwise convolution - DOMI_CONV_MODE_RESERVED -} domiConvolutionMode_t; - -// softmax mode -typedef enum tagDomiSoftmaxMode { - DOMI_SOFTMAX_MODE_INSTANCE = 0, // compute the softmax over all C, H, W for each N - DOMI_SOFTMAX_MODE_CHANNEL, // compute the softmax over all C for each H, W, N - DOMI_SOFTMAX_MODE_HEIGHT, // compute the softmax over all H for each N, C, W - DOMI_SOFTMAX_MODE_WIDTH, // compute the softmax over all W for each N, C, H - DOMI_SOFTMAX_MODE_RESERVED -} domiSoftmaxMode_t; - -// softmax algorithm -typedef enum tagDomiSoftmaxAlgo { - DOMI_SOFTMAX_FAST = 0, // straightforward implementation - DOMI_SOFTMAX_ACCURATE, // subtract max from every point to avoid overflow - DOMI_SOFTMAX_LOG, // perform the Log softmax operation to avoid overflow - DOMI_SOFTMAX_ACCURATE_FP32, - DOMI_SOFTMAX_RESERVED -} domiSoftmaxAlgo_t; - -// algorithm of convolution backward -typedef enum tagDomiConvolutionBwdAlgo { - DOMI_CONVOLUTION_BWD_ALGO_GEMM = 0, // matrix gemm algo - DOMI_CONVOLUTION_BWD_ALGO_WINOGRAD, // Winograd Transform algo - DOMI_CONVOLUTION_BWD_ALGO_RESERVED -} domiConvolutionBwdAlgo_t; - -// mode of pooling -typedef enum tagDomiPoolingMode { - DOMI_POOLING_MAX = 0, // max pooling - DOMI_POOLING_AVG, // average pooling - DOMI_POOLING_L2, // L2 pooling - DOMI_POOLING_RESERVED -} domiPoolingMode_t; - -// propagate Nan -typedef enum tagDomiNanPropagation { - DOMI_NAN_NOT_PROPAGATE = 0, // Nan numbers are not propagated - DOMI_NAN_PROPAGATE, // Nan numbers are propagated - DOMI_NAN_PROPAGATE_RESERVED -} domiNanPropagation_t; - -// mode of cropandresize -typedef enum tagDomiCropAndResizeMode { - DOMI_RESIZE_METHOD_BILINEAR = 0, // resize bilinear - DOMI_RESIZE_METHOD_NEAREST, // resize nearest - DOMI_RESIZE_RESERVED -} domiCropAndResizeMode_t; - -// yolo version -typedef enum tagDomiYoloVersion { DOMI_YOLO_V2 = 1, DOMI_YOLO_V3, DOMI_YOLO_TRSERVED } domiYoloVersion_t; - -typedef enum tagDomiRNNScopePassType { - DOMI_STATIC_BIDIRECTIONAL_RNN_GENERAL_PASS = 0, - DOMI_DYNAMIC_BIDIRECTIONAL_RNN_GENERAL_PASS, - DOMI_DYNAMIC_BIDIRECTIONAL_RNN_BIDAF_PASS -} domiRNNScopePassType; - -// RNNDataLayout -typedef enum tagDomiRNNDataLayout { - DOMI_RNN_ND_TBX = 0, // data[max_time,batch_size,Xt] - DOMI_RNN_ND_BTX, // data[batch_size,max_time,Xt] - DOMI_RNN_5D_TX1BX, // data[max_time,Xt,1,batch_size,Xt] - DOMI_RNN_5D_BX1TX, // dataa[batch_size,Xt,1,max_time,Xt] - DOMI_RNN_4DTBX1, - DOMI_ENN_DL_RESERVED -} domiRNNDataLayout_t; - -// RNNInputMode -typedef enum tagDomiRNNInputMode { DOMI_RNN_LINEAR_INPUT = 0, DOMI_RNN_SKIP_INPUT } domiRNNInputMode_t; - -// RNNDirectionMode -typedef enum tagDomiRNNDirectionMode { DOMI_RNN_UNIDIRECTIONAL = 0, DOMI_RNN_BIDIRECTIONAL } domiDirectionMode_t; - -typedef enum tagDomiPoolingCeilMode { DOMI_POOLING_FLOOR = 0, DOMI_POOLING_CEIL } domiPoolingCeilMode_t; - -// RNNMode -typedef enum tagDomiRNNActivationMode { - DOMI_RNN_ACTIVATION_SIGMOID = 0, // sigmoid - DOMI_RNN_ACTIVATION_TANH, // tanh - DOMI_RNN_ACTIVATION_RELU, // ReLU - DOMI_RNN_ACTIVATION_RELU1, // ReLU1 - DOMI_RNN_ACTIVATION_RELU6, // ReLU6 - DOMI_RNN_ACTIVATION_RESERVED -} domiRNNActivationMode_t; - -typedef enum tagDomiRNNLSTMOutMode { - DOMI_RNN_LSTM_OUT_SEPARATE = 0, - DOMI_RNN_LSTM_OUT_CONCAT, - DOMI_RNN_LSTM_OUT_RESERVED -} domiRNNLSTMOutPutMode_t; -typedef enum tagDomiRNNLSTMStateOutMode { - DOMI_RNN_LSTM_STATE_OUT_SEPARATE = 0, - DOMI_RNN_LSTM_STATE_OUT_CONCAT_ALL, - DOMI_RNN_LSTM_STATE_OUT_RESERVED -} domiRNNLSTMStateOutMode_t; - -typedef enum tagDomiRNNMode { - DOMI_RNN_RELU = 0, - DOMI_RNN_TANH, - DOMI_LSTM, - DOMI_GRU, - DOMI_RNN_MODE_RESERVED -} domiRNNMode_t; - -typedef enum tagDomiResizeBilinearMode { - DOMI_RESIZE_OUTPUT_DIM_BY_ZOOM_FACTOR = 0, // Output dimension specified by zoom factor - DOMI_RESIZE_OUTPUT_DIM_BY_SHRINK_FACTOR, // specified by shrink factor - DOMI_RESIZE_OUTPUT_DIM_EXPLICIT, // specified explicitly - DOMI_RESIZE_OUTPUT_DIM_RESERVED -} domiResizeOutputDimMode_t; - -#pragma pack(1) // single-byte alignment -// DUMP file struct -struct FileHeader { - int32_t Version; // version - int32_t Output_Offset; // output offset address - char Reserved[24] = {0}; // 24 bytes reserved -}; - -struct BasicInfo { - struct FileHeader header; // file header - int32_t stream_id; // stread id - uint64_t start_time; // start time - uint64_t end_time; // end time - uint32_t input_size; // input memory size - uint32_t output_size; // output memory size - uint32_t weight_size; // weight Memory Size - uint32_t workspace_size; // workspace - uint32_t total_size; // total memory size -}; -#pragma pack() // Cancels single-byte alignment enum class MemorySizeCalcType { NORMAL = 0, ALWAYS_EMPTY }; } // namespace ge diff --git a/inc/framework/common/util.h b/inc/framework/common/util.h index fac7e4ca..ca662242 100644 --- a/inc/framework/common/util.h +++ b/inc/framework/common/util.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef INC_FRAMEWORK_COMMON_UTIL_H_ -#define INC_FRAMEWORK_COMMON_UTIL_H_ +#ifndef AIR_INC_FRAMEWORK_COMMON_UTIL_H_ +#define AIR_INC_FRAMEWORK_COMMON_UTIL_H_ #include #include @@ -24,13 +24,16 @@ #include #include +#include "external/graph/types.h" +#include "external/register/register.h" #include "framework/common/debug/log.h" #include "framework/common/scope_guard.h" #include "framework/common/ge_inner_error_codes.h" +#include "graph/detail/attributes_holder.h" #define GE_CHECK_POSITIVE_SIZE_RANGE(size) \ do { \ - if (size <= 0) { \ + if ((size) <= 0) { \ GELOGE(ge::FAILED, "param[%s] is not a positive number", #size); \ return PARAM_INVALID; \ } \ @@ -46,15 +49,19 @@ // new ge marco // Encapsulate common resource releases -#define GE_MAKE_GUARD_RTMEM(var) \ - GE_MAKE_GUARD(var, [&] { \ - if (var) GE_CHK_RT(rtFreeHost(var)); \ - }); +#define GE_MAKE_GUARD_RTMEM(var) \ + GE_MAKE_GUARD(var, [&] { \ + if ((var) != nullptr) { \ + GE_CHK_RT(rtFreeHost(var)); \ + } \ + }) -#define GE_MAKE_GUARD_RTSTREAM(var) \ - GE_MAKE_GUARD(var, [&] { \ - if (var) GE_CHK_RT(rtStreamDestroy(var)); \ - }); +#define GE_MAKE_GUARD_RTSTREAM(var) \ + GE_MAKE_GUARD(var, [&] { \ + if ((var) != nullptr) { \ + GE_CHK_RT(rtStreamDestroy(var)); \ + } \ + }) // For propagating errors when calling a function. #define GE_RETURN_IF_ERROR(expr) \ @@ -115,7 +122,7 @@ // Check if the parameter is null. If yes, return PARAM_INVALID and record the error #define GE_CHECK_NOTNULL(val) \ do { \ - if (val == nullptr) { \ + if ((val) == nullptr) { \ REPORT_INNER_ERROR("E19999", "Param:%s is nullptr, check invalid", #val); \ GELOGE(ge::FAILED, "[Check][Param:%s]null is invalid.", #val); \ return ge::PARAM_INVALID; \ @@ -125,7 +132,7 @@ // Check if the parameter is null. If yes, just return and record the error #define GE_CHECK_NOTNULL_JUST_RETURN(val) \ do { \ - if (val == nullptr) { \ + if ((val) == nullptr) { \ GELOGE(ge::FAILED, "param[%s] must not be null.", #val); \ return; \ } \ @@ -134,7 +141,7 @@ // Check whether the parameter is null. If so, execute the exec_expr expression and record the error log #define GE_CHECK_NOTNULL_EXEC(val, exec_expr) \ do { \ - if (val == nullptr) { \ + if ((val) == nullptr) { \ GELOGE(ge::FAILED, "param[%s] must not be null.", #val); \ exec_expr; \ } \ @@ -143,7 +150,7 @@ // Check whether the parameter is null. If yes, return directly and record the error log #define GE_RT_VOID_CHECK_NOTNULL(val) \ do { \ - if (val == nullptr) { \ + if ((val) == nullptr) { \ GELOGE(ge::FAILED, "param[%s] must not be null.", #val); \ return; \ } \ @@ -152,7 +159,7 @@ // Check if the parameter is null. If yes, return false and record the error log #define GE_RT_FALSE_CHECK_NOTNULL(val) \ do { \ - if (val == nullptr) { \ + if ((val) == nullptr) { \ GELOGE(ge::FAILED, "param[%s] must not be null.", #val); \ return false; \ } \ @@ -161,7 +168,7 @@ // Check if the parameter is out of bounds #define GE_CHECK_SIZE(size) \ do { \ - if (size == 0) { \ + if ((size) == 0U) { \ GELOGE(ge::FAILED, "param[%s] is out of range", #size); \ return ge::PARAM_INVALID; \ } \ @@ -170,7 +177,7 @@ // Check if the value on the left is greater than or equal to the value on the right #define GE_CHECK_GE(lhs, rhs) \ do { \ - if (lhs < rhs) { \ + if ((lhs) < (rhs)) { \ GELOGE(ge::FAILED, "param[%s] is less than[%s]", #lhs, #rhs); \ return ge::PARAM_INVALID; \ } \ @@ -179,7 +186,7 @@ // Check if the value on the left is less than or equal to the value on the right #define GE_CHECK_LE(lhs, rhs) \ do { \ - if (lhs > rhs) { \ + if ((lhs) > (rhs)) { \ GELOGE(ge::FAILED, "param[%s] is greater than[%s]", #lhs, #rhs); \ return ge::PARAM_INVALID; \ } \ @@ -187,102 +194,37 @@ #define GE_DELETE_NEW_SINGLE(var) \ do { \ - if (var != nullptr) { \ - delete var; \ - var = nullptr; \ + if ((var) != nullptr) { \ + delete (var); \ + (var) = nullptr; \ } \ } while (false) #define GE_DELETE_NEW_ARRAY(var) \ do { \ - if (var != nullptr) { \ - delete[] var; \ - var = nullptr; \ + if ((var) != nullptr) { \ + delete[](var); \ + (var) = nullptr; \ } \ } while (false) #define GE_FREE_RT_LOG(addr) \ do { \ - if (addr != nullptr) { \ + if ((addr) != nullptr) { \ const rtError_t error = rtFree(addr); \ if (error != RT_ERROR_NONE) { \ GELOGE(RT_FAILED, "Call rtFree failed, error: %#x", error); \ } \ - addr = nullptr; \ + (addr) = nullptr; \ } \ } while (false) +namespace ge { /** * @ingroup domi_common * @brief version of om.proto file */ -static constexpr int32_t OM_PROTO_VERSION = 2; - -/** - * Finding an Integer Ceiling Value Without Precision Loss - */ -#define CEIL(N, n) (((N) + (n)-1) / (n)) - -namespace ge { -using google::protobuf::Message; - -/// -/// @ingroup domi_common -/// @brief Reads the proto structure from an array. -/// @param [in] data proto data to be read -/// @param [in] size proto data size -/// @param [out] proto Memory for storing the proto file -/// @return true success -/// @return false fail -/// -GE_FUNC_VISIBILITY bool ReadProtoFromArray(const void *data, int32_t size, Message *proto); - -/// -/// @ingroup domi_proto -/// @brief Reads the proto file in the text format. -/// @param [in] file path of proto file -/// @param [out] message Memory for storing the proto file -/// @return true success -/// @return false fail -/// -GE_FUNC_VISIBILITY bool ReadProtoFromText(const char *file, google::protobuf::Message *message); - -/// -/// @ingroup: domi_common -/// @brief: get length of file -/// @param [in] input_file: path of file -/// @return long: File length. If the file length fails to be obtained, the value -1 is returned. -/// -GE_FUNC_VISIBILITY extern long GetFileLength(const std::string &input_file); - -/// -/// @ingroup domi_common -/// @brief Reads all data from a binary file. -/// @param [in] file_name path of file -/// @param [out] buffer Output memory address, which needs to be released by the caller. -/// @param [out] length Output memory size -/// @return false fail -/// @return true success -/// -GE_FUNC_VISIBILITY bool ReadBytesFromBinaryFile(const char *const file_name, char **buffer, int32_t &length); - -GE_FUNC_VISIBILITY bool ReadBytesFromBinaryFile(const char *file_name, std::vector &buffer); - -/// -/// @ingroup domi_common -/// @brief Recursively Creating a Directory -/// @param [in] directory_path Path, which can be a multi-level directory. -/// @return 0 success -/// @return -1 fail -/// -GE_FUNC_VISIBILITY extern int32_t CreateDirectory(const std::string &directory_path); - -/// -/// @ingroup domi_common -/// @brief Obtains the current time string. -/// @return Time character string in the format : %Y%m%d%H%M%S, eg: 20171011083555 -/// -GE_FUNC_VISIBILITY std::string CurrentTimeInStr(); +constexpr int32_t OM_PROTO_VERSION = 2; /// /// @ingroup domi_common @@ -294,7 +236,7 @@ template GE_FUNC_VISIBILITY std::string ToString(std::vector &v) { std::stringstream ss; ss << "["; - for (T x : v) { + for (const T x : v) { ss << x; ss << ", "; } @@ -314,7 +256,7 @@ template GE_FUNC_VISIBILITY std::string ToString(const google::protobuf::RepeatedField &rpd_field) { std::stringstream ss; ss << "["; - for (T x : rpd_field) { + for (const T x : rpd_field) { ss << x; ss << ", "; } @@ -343,6 +285,63 @@ GE_FUNC_VISIBILITY std::string ToString(const google::protobuf::RepeatedPtrField return str_ret; } +/// +/// @ingroup domi_common +/// @brief Reads the proto structure from an array. +/// @param [in] data proto data to be read +/// @param [in] size proto data size +/// @param [out] proto Memory for storing the proto file +/// @return true success +/// @return false fail +/// +GE_FUNC_VISIBILITY bool ReadProtoFromArray(const void *const data, const int32_t size, + google::protobuf::Message *const proto); + +/// +/// @ingroup domi_proto +/// @brief Reads the proto file in the text format. +/// @param [in] file path of proto file +/// @param [out] message Memory for storing the proto file +/// @return true success +/// @return false fail +/// +GE_FUNC_VISIBILITY bool ReadProtoFromText(const char_t *const file, google::protobuf::Message *const message); + +/// +/// @ingroup: domi_common +/// @brief: get length of file +/// @param [in] input_file: path of file +/// @return int64_t: File length. If the file length fails to be obtained, the value -1 is returned. +/// +GE_FUNC_VISIBILITY extern int64_t GetFileLength(const std::string &input_file); + +/// +/// @ingroup domi_common +/// @brief Reads all data from a binary file. +/// @param [in] file_name path of file +/// @param [out] buffer Output memory address, which needs to be released by the caller. +/// @param [out] length Output memory size +/// @return false fail +/// @return true success +/// +GE_FUNC_VISIBILITY bool ReadBytesFromBinaryFile(const char_t *const file_name, char_t **const buffer, int32_t &length); + +/// +/// @ingroup domi_common +/// @brief Recursively Creating a Directory +/// @param [in] directory_path Path, which can be a multi-level directory. +/// @return 0 success +/// @return -1 fail +/// +GE_FUNC_VISIBILITY extern int32_t CreateDirectory(const std::string &directory_path); + +/// +/// @ingroup domi_common +/// @brief Obtains the current time string. +/// @return Time character string in the format : %Y%m%d%H%M%S, eg: 20171011083555 +/// +GE_FUNC_VISIBILITY std::string CurrentTimeInStr(); + /// /// @ingroup domi_common /// @brief Obtains the absolute time (timestamp) of the current system. @@ -366,7 +365,7 @@ GE_FUNC_VISIBILITY uint32_t GetCurrentSecondTimestap(); /// @param [in] b /// @return false: true: The result is within the normal int64 range. /// -GE_FUNC_VISIBILITY bool CheckInt64MulOverflow(int64_t a, int64_t b); +GE_FUNC_VISIBILITY bool CheckInt64MulOverflow(const int64_t a, const int64_t b); /// /// @ingroup domi_common @@ -374,7 +373,7 @@ GE_FUNC_VISIBILITY bool CheckInt64MulOverflow(int64_t a, int64_t b); /// @param [in] path of input file /// @param [out] Absolute path of a file. If the absolute path cannot be obtained, an empty string is returned /// -GE_FUNC_VISIBILITY std::string RealPath(const char *path); +GE_FUNC_VISIBILITY std::string RealPath(const char_t *path); /// /// @ingroup domi_common @@ -401,17 +400,9 @@ GE_FUNC_VISIBILITY bool CheckOutputPathValid(const std::string &file_path, const /// @param [in] str file path /// @param [out] result /// -GE_FUNC_VISIBILITY bool ValidateStr(const std::string &str, const std::string &mode); +GE_FUNC_VISIBILITY bool ValidateStr(const std::string &file_path, const std::string &mode); -/// -/// @ingroup domi_common -/// @brief Check path invalid -/// @param [in] path, path to be checked -/// @param [in] length, length of path -/// @return 0 success -/// @return -1 fail -/// -GE_FUNC_VISIBILITY Status CheckPath(const char *path, size_t length); +GE_FUNC_VISIBILITY Status ConvertToInt32(const std::string &str, int32_t &val); } // namespace ge -#endif // INC_FRAMEWORK_COMMON_UTIL_H_ +#endif // AIR_INC_FRAMEWORK_COMMON_UTIL_H_ diff --git a/inc/framework/engine/dnnengine.h b/inc/framework/engine/dnnengine.h index 84d5705a..63c2d9de 100644 --- a/inc/framework/engine/dnnengine.h +++ b/inc/framework/engine/dnnengine.h @@ -26,11 +26,11 @@ #include "graph/types.h" namespace ge { -enum PriorityEnum { +enum class PriorityEnum { COST_0 = 0, - COST_1, - COST_2, - COST_3, + COST_1 = 1, + COST_2 = 2, + COST_3 = 3, COST_9 = 9, COST_10 = 10, }; @@ -38,7 +38,7 @@ enum PriorityEnum { struct DNNEngineAttribute { std::string engine_name; std::vector mem_type; - uint32_t compute_cost; + PriorityEnum compute_cost; enum RuntimeType runtime_type; // HOST, DEVICE // If engine input format must be specific, set this attribute, else set FORMAT_RESERVED Format engine_input_format; @@ -53,10 +53,11 @@ class GE_FUNC_VISIBILITY DNNEngine { engine_attribute_ = attrs; } virtual ~DNNEngine() = default; - Status Initialize(const std::map &options) { + Status Initialize(const std::map &options) const { + (void)options; return SUCCESS; } - Status Finalize() { + Status Finalize() const { return SUCCESS; } void GetAttributes(DNNEngineAttribute &attr) const { diff --git a/inc/framework/executor/ge_executor.h b/inc/framework/executor/ge_executor.h index c5df77df..2929d26b 100644 --- a/inc/framework/executor/ge_executor.h +++ b/inc/framework/executor/ge_executor.h @@ -32,18 +32,19 @@ namespace ge { class SingleOp; class DynamicSingleOp; +class GeRootModel; struct RunModelData { uint32_t index; // Data index uint32_t modelId; - std::vector blobs; // All input/output data buffer - uint32_t timestamp; // Data creation time - uint32_t timeout; // Processing timeout - uint64_t request_id = 0; // Request ID - uint64_t dynamic_batch_size = 0; // Dynamic batch size scene, set dynamic size, not supported by default:0 - uint64_t dynamic_image_height = 0; // Dynamic image size scene, set image height, not supported by default:0 - uint64_t dynamic_image_width = 0; // Dynamic image size scene, set image width, not supported by default:0 - std::vector dynamic_dims; // Dynamic dims scene, set dynamic dims, not supported by default:empty + std::vector blobs; // All input/output data buffer + uint32_t timestamp; // Data creation time + uint32_t timeout; // Processing timeout + uint64_t request_id = 0UL; // Request ID + uint64_t dynamic_batch_size = 0UL; // Dynamic batch size scene, set dynamic size, not supported by default:0 + uint64_t dynamic_image_height = 0UL; // Dynamic image size scene, set image height, not supported by default:0 + uint64_t dynamic_image_width = 0UL; // Dynamic image size scene, set image width, not supported by default:0 + std::vector dynamic_dims; // Dynamic dims scene, set dynamic dims, not supported by default:empty }; class GE_FUNC_VISIBILITY GeExecutor { @@ -69,11 +70,11 @@ class GE_FUNC_VISIBILITY GeExecutor { /// static Status FinalizeEx(); - Status UnloadModel(uint32_t modelId); + Status UnloadModel(const uint32_t model_id); // Get input and output descriptor - Status GetModelDescInfo(uint32_t model_id, std::vector &input_desc, std::vector &output_desc, - bool new_model_desc = false); + Status GetModelDescInfo(const uint32_t model_id, std::vector &input_desc, + std::vector &output_desc, const bool new_model_desc = false); /// /// @ingroup ge @@ -84,7 +85,8 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [in] batch_size: batch size entered by user in dynamic multi-batch scenario /// @return execute result /// - Status SetDynamicBatchSize(uint32_t model_id, void *dynamic_input_addr, uint64_t length, uint64_t batch_size); + Status SetDynamicBatchSize(const uint32_t model_id, void *const dynamic_input_addr, const uint64_t length, + const uint64_t batch_size); /// /// @ingroup ge @@ -96,8 +98,8 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [in] image_width: image width entered by user in dynamic multi-resolution scenario /// @return execute result /// - Status SetDynamicImageSize(uint32_t model_id, void *dynamic_input_addr, uint64_t length, uint64_t image_height, - uint64_t image_width); + Status SetDynamicImageSize(const uint32_t model_id, void *const dynamic_input_addr, const uint64_t length, + const uint64_t image_height, const uint64_t image_width); /// /// @ingroup ge @@ -109,7 +111,7 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [in] dynamic_dims: array of dynamic dimensions /// @return execute result /// - Status SetDynamicDims(uint32_t model_id, void *dynamic_input_addr, uint64_t length, + Status SetDynamicDims(const uint32_t model_id, void *const dynamic_input_addr, const uint64_t length, const std::vector &dynamic_dims); /// @@ -120,7 +122,7 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [out] cur_dynamic_dims: current dynamic dims /// @return execute result /// - Status GetCurDynamicDims(uint32_t model_id, const std::vector &dynamic_dims, + Status GetCurDynamicDims(const uint32_t model_id, const std::vector &dynamic_dims, std::vector &cur_dynamic_dims); /// @@ -131,7 +133,8 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [out] dynamic_type /// @return execute result /// - Status GetDynamicBatchInfo(uint32_t model_id, std::vector> &batch_info, int32_t &dynamic_type); + Status GetDynamicBatchInfo(const uint32_t model_id, std::vector> &batch_info, + int32_t &dynamic_type); /// /// @ingroup ge @@ -140,7 +143,7 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [out] batch_info /// @return execute result /// - Status GetCombinedDynamicDims(uint32_t model_id, std::vector> &batch_info); + Status GetCombinedDynamicDims(const uint32_t model_id, std::vector> &batch_info); /// /// @ingroup ge @@ -149,7 +152,7 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [out] user_designate_shape_order /// @return execute result /// - Status GetUserDesignateShapeOrder(uint32_t model_id, std::vector &user_designate_shape_order); + Status GetUserDesignateShapeOrder(const uint32_t model_id, std::vector &user_designate_shape_order); Status GetCurShape(const uint32_t model_id, std::vector &batch_info, int32_t &dynamic_type); @@ -163,18 +166,18 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [in] aippParms: kAippDynamicPara by user in dynamic aipp /// @return execute result /// - Status SetDynamicAippData(uint32_t model_id, void *dynamic_input_addr, uint64_t length, + Status SetDynamicAippData(const uint32_t model_id, void *const dynamic_input_addr, const uint64_t length, const std::vector &aipp_batch_para, - const kAippDynamicPara &aippParms); + const kAippDynamicPara &aipp_parms); - Status GetAIPPInfo(uint32_t model_id, uint32_t index, AippConfigInfo &aipp_info); + Status GetAIPPInfo(const uint32_t model_id, const uint32_t index, AippConfigInfo &aipp_info); - Status GetOpAttr(uint32_t model_id, const std::string &op_name, const std::string &attr_name, + Status GetOpAttr(const uint32_t model_id, const std::string &op_name, const std::string &attr_name, std::string &attr_value); - Status GetModelAttr(uint32_t model_id, std::vector &dynamic_output_shape_info); + Status GetModelAttr(const uint32_t model_id, std::vector &dynamic_output_shape_info); - Status GetAippType(uint32_t model_id, uint32_t index, InputAippType &type, size_t &aipp_index); + Status GetAippType(const uint32_t model_id, const uint32_t index, InputAippType &type, size_t &aipp_index); Status CommandHandle(const Command &command); @@ -188,7 +191,7 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @return SUCCESS /// @return FAILED /// - Status GetMaxUsedMemory(uint32_t model_id, uint32_t &max_size); + Status GetMaxUsedMemory(const uint32_t model_id, uint32_t &max_size); /// /// @ingroup ge @@ -210,8 +213,8 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [out] uint32_t &model_id: Corresponding identification after model loading /// @return SUCCESS handle successfully / others handle failed /// - Status LoadModelFromData(uint32_t &model_id, const ModelData &model_data, void *dev_ptr, size_t mem_size, - void *weight_ptr, size_t weight_size); + Status LoadModelFromData(uint32_t &model_id, const ModelData &model_data, void *const dev_ptr, const size_t mem_size, + void *const weight_ptr, const size_t weight_size); /// /// @ingroup ge @@ -225,6 +228,18 @@ class GE_FUNC_VISIBILITY GeExecutor { Status LoadModelWithQ(uint32_t &model_id, const ModelData &model_data, const std::vector &input_queue_ids, const std::vector &output_queue_ids); + /// + /// @ingroup ge + /// @brief Load task list from ModelData with queue. + /// @param [out] model_id: model id allocate from manager. + /// @param [in] root_model: Instance of GeRootModel. + /// @param [in] input_queue_ids: input queue ids create from user. + /// @param [in] output_queue_ids: input queue ids create from user. + /// @return: 0 for success / others for fail + /// + Status LoadModelWithQ(uint32_t &model_id, const std::shared_ptr &root_model, + const std::vector &input_queue_ids, const std::vector &output_queue_ids); + /// /// @ingroup ge /// @brief Synchronous execution of offline model(Do not create thread) @@ -235,8 +250,17 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [out] domi::OutputData *output_data: Model output data /// @return SUCCESS handle successfully / others handle failed /// - Status ExecModel(uint32_t model_id, void *stream, const RunModelData &input_data, RunModelData &output_data, - bool async_mode = false); + Status ExecModel(const uint32_t model_id, void *const stream, const RunModelData &input_data, + RunModelData &output_data, const bool async_mode = false); + + /// + /// @ingroup ge + /// @brief Load task list from root_model without input queue or output queue. + /// @param [out] model_id: model id allocate from manager. + /// @param [in] root_model: Instance of GeRootModel. + /// @return: 0 for success / others for fail + /// + Status LoadModelWithoutQ(uint32_t &model_id, const std::shared_ptr &root_model) const; /// /// @ingroup ge @@ -250,9 +274,9 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [out] std::vector &output_desc: description of model output data /// @return SUCCESS handle successfully / others handle failed /// - Status ExecModel(uint32_t model_id, void *stream, const RunModelData &run_input_data, + Status ExecModel(const uint32_t model_id, void *const stream, const RunModelData &run_input_data, const std::vector &input_desc, RunModelData &run_output_data, - std::vector &output_desc, bool async_mode = false); + std::vector &output_desc, const bool async_mode = false); /// /// @ingroup ge @@ -273,36 +297,38 @@ class GE_FUNC_VISIBILITY GeExecutor { /// @param [out] size_t &weight_size Weight memory space size /// @return SUCCESS handle successfully / others handle failed /// - Status GetMemAndWeightSize(const void *model_data, size_t model_size, size_t &mem_size, size_t &weight_size); + Status GetMemAndWeightSize(const void *const model_data, const size_t model_size, size_t &mem_size, + size_t &weight_size); - static Status LoadSingleOp(const std::string &modelName, const ModelData &modelData, void *stream, - SingleOp **single_op); + static Status LoadSingleOp(const std::string &model_name, const ModelData &model_data, void *const stream, + SingleOp **const single_op); - static Status LoadSingleOpV2(const std::string &modelName, const ModelData &modelData, void *stream, - SingleOp **single_op, const uint64_t model_id); + static Status LoadSingleOpV2(const std::string &model_name, const ModelData &model_data, void *const stream, + SingleOp **const single_op, const uint64_t model_id); - static Status ExecuteAsync(SingleOp *executor, const std::vector &inputs, + static Status ExecuteAsync(SingleOp *const executor, const std::vector &inputs, std::vector &outputs); - static Status LoadDynamicSingleOp(const std::string &model_name, const ModelData &modelData, void *stream, - DynamicSingleOp **single_op); + static Status LoadDynamicSingleOp(const std::string &model_name, const ModelData &model_data, void *const stream, + DynamicSingleOp **const single_op); - static Status LoadDynamicSingleOpV2(const std::string &model_name, const ModelData &modelData, void *stream, - DynamicSingleOp **single_op, const uint64_t model_id); + static Status LoadDynamicSingleOpV2(const std::string &model_name, const ModelData &model_data, void *const stream, + DynamicSingleOp **const single_op, const uint64_t model_id); - static Status ExecuteAsync(DynamicSingleOp *executor, const std::vector &input_desc, + static Status ExecuteAsync(DynamicSingleOp *const executor, const std::vector &input_desc, const std::vector &inputs, std::vector &output_desc, std::vector &outputs); - static Status ReleaseSingleOpResource(void *stream); + static Status ReleaseSingleOpResource(void *const stream); - static Status GetDeviceIdByModelId(uint32_t model_id, uint32_t &device_id); + static Status GetDeviceIdByModelId(const uint32_t model_id, uint32_t &device_id); - Status GetBatchInfoSize(uint32_t model_id, size_t &shape_count); - Status GetOrigInputInfo(uint32_t model_id, uint32_t index, OriginInputInfo &orig_input_info); - Status GetAllAippInputOutputDims(uint32_t model_id, uint32_t index, std::vector &input_dims, - std::vector &output_dims); - Status GetOpDescInfo(uint32_t device_id, uint32_t stream_id, uint32_t task_id, OpDescInfo &op_desc_info); + Status GetBatchInfoSize(const uint32_t model_id, size_t &shape_count); + Status GetOrigInputInfo(const uint32_t model_id, const uint32_t index, OriginInputInfo &orig_input_info); + Status GetAllAippInputOutputDims(const uint32_t model_id, const uint32_t index, + std::vector &input_dims, std::vector &output_dims); + Status GetOpDescInfo(const uint32_t device_id, const uint32_t stream_id, const uint32_t task_id, + OpDescInfo &op_desc_info); private: static std::atomic_bool is_inited_; diff --git a/inc/framework/generator/ge_generator.h b/inc/framework/generator/ge_generator.h index b49fa53b..8213c115 100644 --- a/inc/framework/generator/ge_generator.h +++ b/inc/framework/generator/ge_generator.h @@ -31,6 +31,8 @@ #include "framework/omg/omg_inner_types.h" namespace ge { +const std::string kAttrSupportDynamicShape = "support_dynamicshape"; + class GeRootModel; class GE_FUNC_VISIBILITY GeGenerator { public: @@ -103,8 +105,8 @@ class GE_FUNC_VISIBILITY GeGenerator { /// @param [in] graph_name: graph name. /// @param [out] graph: graph of single op. /// @return SUCCESS or FAILED - Status BuildSingleOpGraph(OpDescPtr &op_desc, const InOutTensorRef &inputs_outputs, std::string graph_name, - Graph &graph, std::vector> &inputs_name_type); + Status BuildSingleOpGraph(const OpDescPtr &op_desc, const InOutTensorRef &inputs_outputs, std::string graph_name, + Graph &graph, std::vector> &inputs_name_type) const; Status BuildOriginalGraphInfo(OpDescPtr &op_desc, const std::vector &inputs, const std::vector &outputs, const std::string &model_file_name, bool is_offline, int32_t compile_flag, GraphStage graph_stage, Graph &graph, @@ -116,20 +118,20 @@ class GE_FUNC_VISIBILITY GeGenerator { ge::ModelBufferData &model, bool is_offline = true); Status BuildSingleOp(OpDescPtr &op_desc, const std::vector &inputs, const std::vector &outputs, const std::string &model_file_name, OpEngineType engine_type, ModelBufferData &model_buff, - ComputeGraphPtr &compute_graph, bool is_offline = true, int32_t compile_flag = 0, + ComputeGraphPtr &comp_graph, bool is_offline = true, int32_t compile_flag = 0, GraphStage graph_stage = GraphStage::GRAPH_STAGE_RESERVED); bool CheckNoAicore(const ComputeGraphPtr &graph); - void RemoveConst(const std::vector &inputs, std::vector &outputs); - Status CheckForSingleOp(OpDescPtr &op_desc, const std::vector &inputs, - const std::vector &outputs); - Status InferFormatForSingleOp(OpDescPtr &op_desc, Graph &graph); + void RemoveConst(const std::vector &inputs, std::vector &outputs) const; + Status CheckForSingleOp(const OpDescPtr &op_desc, const std::vector &inputs, + const std::vector &outputs) const; + Status InferFormatForSingleOp(const OpDescPtr &op_desc, const Graph &graph) const; using GeRootModelPtr = std::shared_ptr; Status SetModelNameForDump(const GeRootModelPtr &ge_root_model); Status CreateGeneralizedBuildAttrs(const GeRootModelPtr &ge_root_model, const std::vector &inputs, const std::vector &outputs, const std::vector> &inputs_name_type, - std::vector &generalized_build_attrs); + std::vector &generalized_build_attrs) const; class Impl; diff --git a/inc/framework/memory/memory_api.h b/inc/framework/memory/memory_api.h index a04a1ebe..30ade3b7 100644 --- a/inc/framework/memory/memory_api.h +++ b/inc/framework/memory/memory_api.h @@ -17,11 +17,7 @@ #ifndef INC_FRAMEWORK_MEMORY_MEMORY_API_H_ #define INC_FRAMEWORK_MEMORY_MEMORY_API_H_ -#include -#include - #include "external/ge/ge_api_error_codes.h" -#include "graph/types.h" #include "runtime/mem.h" namespace ge { diff --git a/inc/framework/memory/memory_assigner.h b/inc/framework/memory/memory_assigner.h index 1ccbd785..be615426 100644 --- a/inc/framework/memory/memory_assigner.h +++ b/inc/framework/memory/memory_assigner.h @@ -33,7 +33,7 @@ class GE_FUNC_VISIBILITY MemoryAssigner { MemoryAssigner &operator=(const MemoryAssigner &) = delete; - Status AssignMemory(bool is_loop_graph, std::map &mem_offset, size_t &zero_copy_mem_size); + Status AssignMemory(std::map &mem_offset, size_t &zero_copy_mem_size); private: ge::ComputeGraphPtr compute_graph_; diff --git a/inc/framework/omg/omg.h b/inc/framework/omg/omg.h index 029b7a24..cab51e0d 100644 --- a/inc/framework/omg/omg.h +++ b/inc/framework/omg/omg.h @@ -64,7 +64,7 @@ GE_FUNC_VISIBILITY Status InitDomiOmgContext(const std::string &input_shape, con GE_FUNC_VISIBILITY Status ParseGraph(ge::Graph &graph, const std::map &atc_params, const char *model_file, const char *weights_file, domi::FrameworkType type, const char *op_conf = nullptr, const char *target = nullptr, - RunMode run_mode = GEN_OM_MODEL, bool is_dynamic_input = false); + RunMode run_mode = RunMode::GEN_OM_MODEL, bool is_dynamic_input = false); /** * @ingroup domi_omg @@ -89,15 +89,15 @@ GE_FUNC_VISIBILITY Status ConvertPbtxtToJson(const char *model_file, const char GE_FUNC_VISIBILITY Status ConvertFwkModelToJson(domi::FrameworkType framework, const char *model_file, const char *json_file); -GE_FUNC_VISIBILITY void GetGroupName(ge::proto::ModelDef &model); +GE_FUNC_VISIBILITY void GetGroupName(ge::proto::ModelDef &model_def); -GE_FUNC_VISIBILITY void FindParserSo(const std::string &path, std::vector &fileList, +GE_FUNC_VISIBILITY void FindParserSo(const std::string &path, std::vector &file_list, std::string &caffe_parser_path); GE_FUNC_VISIBILITY Status DumpInfershapeJson(const ge::Graph &graph, const char *json_file); GE_FUNC_VISIBILITY Status SetOutputNodeInfo(ge::Graph &graph, const std::string &output_type, - const std::string &output_format); + const std::string &output); GE_FUNC_VISIBILITY Status GetOutputLeaf(ge::NodePtr node, std::vector> &output_nodes_info); diff --git a/inc/framework/omg/omg_inner_types.h b/inc/framework/omg/omg_inner_types.h index 3f7b5db1..1addd326 100644 --- a/inc/framework/omg/omg_inner_types.h +++ b/inc/framework/omg/omg_inner_types.h @@ -31,12 +31,7 @@ using domi::DOMI_TENSOR_ND; using domi::DOMI_TENSOR_RESERVED; using domi::domiTensorFormat_t; -using domi::FRAMEWORK_RESERVED; -using domi::FrameworkType; -using std::map; -using std::string; using std::unordered_map; -using std::vector; namespace ge { /** @@ -51,36 +46,13 @@ enum RunMode { DISPLAY_OM_INFO = 6 // display model info }; -/// -/// @ingroup domi_omg -/// @brief high-precision mode -/// -enum HighPrecisionMode { - // the FP16 high-precision function is disabled in common mode - HIGH_PRECISION_DEFAULT = 0, - - // high-precision mode, enabling FP16 high-precision mode (Convolution/FullConnect/AvgPooling are involved) - HIGH_PRECISION_FP16 = 1 -}; - -/// -/// @ingroup domi_omg -/// @brief description buffer data -/// -struct OMGBufferData { - void *data; - uint32_t length; -}; - struct OmgContext { - OmgContext() { - format = DOMI_TENSOR_ND; - } - domiTensorFormat_t format; + OmgContext() : format(domi::DOMI_TENSOR_ND) {} + domi::domiTensorFormat_t format; // format of the input specified by the command line - std::unordered_map input_nodes_format_map; - std::vector output_formats; + std::unordered_map input_nodes_format_map; + std::vector output_formats; // user-designate input dims std::vector>> user_input_dims; @@ -107,9 +79,9 @@ struct OmgContext { // net data nodes tensor names(caffe or onnx) std::vector data_tensor_names; // preferential format used by the entire network - domiTensorFormat_t net_format = DOMI_TENSOR_RESERVED; + domi::domiTensorFormat_t net_format = domi::DOMI_TENSOR_RESERVED; domi::FrameworkType type = domi::FRAMEWORK_RESERVED; - RunMode run_mode = ONLY_PRE_CHECK; + RunMode run_mode = RunMode::ONLY_PRE_CHECK; bool train_flag = false; std::string output_type; diff --git a/inc/framework/omg/parser/model_parser.h b/inc/framework/omg/parser/model_parser.h index a0415d73..96a5a018 100644 --- a/inc/framework/omg/parser/model_parser.h +++ b/inc/framework/omg/parser/model_parser.h @@ -108,6 +108,8 @@ class GE_FUNC_VISIBILITY ModelParser { * @return Others failed */ virtual domi::Status ToJson(const char *model_file, const char *json_file) { + (void)model_file; + (void)json_file; return domi::SUCCESS; } @@ -130,6 +132,8 @@ class GE_FUNC_VISIBILITY ModelParser { * @return Others failed */ virtual domi::Status ParseProto(const std::string &serialized_proto, ge::ComputeGraphPtr &graph) { + (void)serialized_proto; + (void)graph; return UNSUPPORTED; } @@ -144,6 +148,9 @@ class GE_FUNC_VISIBILITY ModelParser { */ virtual domi::Status ParseProtoWithSubgraph(const std::string &serialized_proto, GetGraphCallbackV2 callback, ge::ComputeGraphPtr &graph) { + (void)serialized_proto; + (void)callback; + (void)graph; return UNSUPPORTED; } }; diff --git a/inc/framework/omg/parser/op_parser.h b/inc/framework/omg/parser/op_parser.h index 04731ff3..b511a8b0 100644 --- a/inc/framework/omg/parser/op_parser.h +++ b/inc/framework/omg/parser/op_parser.h @@ -50,7 +50,7 @@ class GE_FUNC_VISIBILITY OpParser { * @return SUCCESS * @return FAILED */ - virtual domi::Status ParseParams(const Message *op_src, ge::OpDescPtr &op_desc) = 0; + virtual domi::Status ParseParams(const google::protobuf::Message *op_src, ge::OpDescPtr &op_desc) = 0; /** * @ingroup domi_omg @@ -60,7 +60,7 @@ class GE_FUNC_VISIBILITY OpParser { * @return SUCCESS * @return FAILED */ - virtual domi::Status ParseParams(const Message *op_src, ge::Operator &op_dest) = 0; + virtual domi::Status ParseParams(const google::protobuf::Message *op_src, ge::Operator &op_dest) = 0; /** * @ingroup domi_omg @@ -70,7 +70,7 @@ class GE_FUNC_VISIBILITY OpParser { * @return SUCCESS * @return FAILED */ - virtual domi::Status ParseWeights(const Message *op_src, ge::NodePtr &node) = 0; + virtual domi::Status ParseWeights(const google::protobuf::Message *op_src, ge::NodePtr &node) = 0; /** * @ingroup domi_omg @@ -80,7 +80,7 @@ class GE_FUNC_VISIBILITY OpParser { * @return SUCCESS * @return FAILED */ - virtual domi::Status GetFormat(const Message *op_src, domi::domiTensorFormat_t &format) { + virtual domi::Status GetFormat(const google::protobuf::Message *op_src, domi::domiTensorFormat_t &format) { (void)op_src; // Indicates that the op does not provide a value for format format = domi::DOMI_TENSOR_RESERVED; diff --git a/inc/framework/omg/parser/parser_factory.h b/inc/framework/omg/parser/parser_factory.h index 7ae286df..cd5faa73 100644 --- a/inc/framework/omg/parser/parser_factory.h +++ b/inc/framework/omg/parser/parser_factory.h @@ -24,13 +24,11 @@ #include "framework/omg/omg_inner_types.h" #include "framework/omg/parser/parser_types.h" -using Status = domi::Status; - namespace domi { class WeightsParser; class ModelParser; -typedef std::shared_ptr (*MODEL_PARSER_CREATOR_FUN)(void); +using MODEL_PARSER_CREATOR_FUN = std::shared_ptr (*)(void); // Create modelparser for different frameworks class GE_FUNC_VISIBILITY ModelParserFactory { @@ -82,7 +80,7 @@ class GE_FUNC_VISIBILITY ModelParserRegisterar { } \ ModelParserRegisterar g_##type##_Model_Parser_Creator(type, Creator_##type##_Model_Parser) -typedef std::shared_ptr (*WEIGHTS_PARSER_CREATOR_FUN)(void); +using WEIGHTS_PARSER_CREATOR_FUN = std::shared_ptr (*)(void); // Create weightsparser for different frameworks class GE_FUNC_VISIBILITY WeightsParserFactory { diff --git a/inc/framework/omg/parser/parser_inner_ctx.h b/inc/framework/omg/parser/parser_inner_ctx.h index 969a94f8..5cf0d00b 100644 --- a/inc/framework/omg/parser/parser_inner_ctx.h +++ b/inc/framework/omg/parser/parser_inner_ctx.h @@ -29,8 +29,8 @@ namespace ge { struct ParserContext { // format of the input specified by the command line - std::unordered_map input_nodes_format_map; - std::vector output_formats; + std::unordered_map input_nodes_format_map; + std::vector output_formats; // user-designate input dims std::vector>> user_input_dims; std::map> input_dims; @@ -58,7 +58,7 @@ struct ParserContext { bool train_flag = false; domi::domiTensorFormat_t format = domi::DOMI_TENSOR_ND; domi::FrameworkType type = domi::FRAMEWORK_RESERVED; - RunMode run_mode = GEN_OM_MODEL; + RunMode run_mode = RunMode::GEN_OM_MODEL; // save caffe custom proto path, used by caffe parse std::string custom_proto_path; // save caffe proto path, used by caffe parse diff --git a/inc/framework/omg/version.h b/inc/framework/omg/version.h index 156fbc5c..53f155fa 100644 --- a/inc/framework/omg/version.h +++ b/inc/framework/omg/version.h @@ -19,8 +19,6 @@ #include #include -#include -#include #include "framework/common/debug/log.h" #include "framework/common/string_util.h" @@ -34,7 +32,7 @@ class GE_FUNC_VISIBILITY PlatformVersionManager { static Status GetPlatformVersion(std::string &ver) { ver = "1.11.z"; const std::vector version_splits = StringUtils::Split(ver, '.'); - GE_IF_BOOL_EXEC(version_splits.size() < 3, GELOGW("Read platform version error!"); return FAILED;); + GE_IF_BOOL_EXEC(version_splits.size() < 3U, GELOGW("Read platform version error!"); return FAILED;); GELOGI("Read current platform version: %s.", ver.c_str()); return SUCCESS; diff --git a/metadef b/metadef index 1d99928b..0a233571 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit 1d99928bfcb02e45acc7db73e3ee57304ff1131a +Subproject commit 0a2335712484f85cd44a0f2402eac6932b22b40a diff --git a/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h b/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h index 2a10859c..37a2e412 100644 --- a/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h +++ b/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h @@ -1,57 +1,57 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef AICPU_OP_TYPE_LIST_H_ -#define AICPU_OP_TYPE_LIST_H_ - -extern "C" { -enum OpKernelType { - TF_KERNEL, - CPU_KERNEL -}; - -enum ReturnCode { - OP_TYPE_NOT_SUPPORT, - FORMAT_NOT_SUPPORT, - DTYPE_NOT_SUPPORT -}; - -#pragma pack(push, 1) -//One byte alignment -struct SysOpInfo { - uint64_t opLen; - uint64_t opType; - OpKernelType kernelsType; -}; - -struct SysOpCheckInfo { - uint64_t opListNum; - uint64_t offSetLen; - uint64_t sysOpInfoList; - uint64_t opParamInfoList; -}; - -struct SysOpCheckResp { - uint64_t opListNum; - bool isWithoutJson; - uint64_t returnCodeList; - uint64_t sysOpInfoList; - uint64_t opParamInfoList; -}; -#pragma pack(pop) -} - -#endif // AICPU_OP_TYPE_LIST_H_ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2019-2020. All rights reserved. + * + * 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. + */ + +#ifndef AICPU_OP_TYPE_LIST_H_ +#define AICPU_OP_TYPE_LIST_H_ + +extern "C" { +enum OpKernelType { + TF_KERNEL, + CPU_KERNEL +}; + +enum ReturnCode { + OP_TYPE_NOT_SUPPORT, + FORMAT_NOT_SUPPORT, + DTYPE_NOT_SUPPORT +}; + +#pragma pack(push, 1) +// One byte alignment +struct SysOpInfo { + uint64_t opLen; + uint64_t opType; + OpKernelType kernelsType; +}; + +struct SysOpCheckInfo { + uint64_t opListNum; + uint64_t offSetLen; + uint64_t sysOpInfoList; + uint64_t opParamInfoList; +}; + +struct SysOpCheckResp { + uint64_t opListNum; + bool isWithoutJson; + uint64_t returnCodeList; + uint64_t sysOpInfoList; + uint64_t opParamInfoList; +}; +#pragma pack(pop) +} + +#endif // AICPU_OP_TYPE_LIST_H_ diff --git a/third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h b/third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h index 72e21f6f..ceae0f0f 100644 --- a/third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h +++ b/third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h @@ -29,6 +29,53 @@ struct AicpuParamHead uint32_t extInfoLength; // extInfo struct Length uint64_t extInfoAddr; // extInfo address }; + +enum class AicpuConfigMsgType { + AICPU_CONFIG_MSG_TYPE_BUF_FREE = 0, /* free buf */ + AICPU_CONFIG_MSG_TYPE_BUF_RESET = 1, /* reset buf */ + AICPU_CONFIG_MSG_TYPE_BUF_SET_ADDR = 2, /* set buf addr to aicpu */ +}; + +enum class AicpuErrMsgType { + ERR_MSG_TYPE_NULL = 0, + ERR_MSG_TYPE_AICORE = 1, + ERR_MSG_TYPE_AICPU = 2, +}; + +typedef struct tagAicpuConfigMsg { + uint8_t msgType; + uint8_t reserved1; + uint16_t bufLen; + uint32_t offset; + uint64_t bufAddr; + uint32_t tsId; + uint32_t reserved2; +} AicpuConfigMsg; + +typedef struct tagAicoreErrMsgInfo { + uint8_t errType; + uint8_t version; + uint8_t reserved1[2]; /* reserved1, 4 byte alignment */ + uint32_t errorCode; + uint32_t modelId; + uint32_t taskId; + uint32_t streamId; + uint64_t transactionId; + uint8_t reserved2[228]; /* the total byte is 256, reserved2 len = 256 - other lens */ +} AicoreErrMsgInfo; + +typedef struct tagAicpuErrMsgInfo { + uint8_t errType; + uint8_t version; + uint8_t reserved1[2]; /* reserved1, 4 byte alignment */ + uint32_t errorCode; + uint32_t modelId; + uint32_t streamId; + uint64_t transactionId; + char opName[64]; /* op name str */ + char errDesc[128]; /* err msg desc info */ + uint8_t reserved2[40]; /* the total byte is 256, reserved2 len = 256 - other lens */ +} AicpuErrMsgInfo; #pragma pack(pop) } // namespace aicpu diff --git a/third_party/fwkacllib/inc/cce/aicpu_engine.h b/third_party/fwkacllib/inc/cce/aicpu_engine.h index bc2e415f..042d952b 100644 --- a/third_party/fwkacllib/inc/cce/aicpu_engine.h +++ b/third_party/fwkacllib/inc/cce/aicpu_engine.h @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #ifndef AICPU_ENGINE_H__ #define AICPU_ENGINE_H__ diff --git a/third_party/fwkacllib/inc/cce/fwk_adpt_struct.h b/third_party/fwkacllib/inc/cce/fwk_adpt_struct.h index 5733d68f..ec92a036 100644 --- a/third_party/fwkacllib/inc/cce/fwk_adpt_struct.h +++ b/third_party/fwkacllib/inc/cce/fwk_adpt_struct.h @@ -21,7 +21,7 @@ namespace aicpu { namespace FWKAdapter { - +using char_t = char; // API RETURN CODE enum FWKAdptAPIRetCode { FWK_ADPT_SUCCESS = 0, // success @@ -63,6 +63,8 @@ enum FWKTaskExtInfoType { FWK_ADPT_EXT_BITMAP, FWK_ADPT_EXT_TOPIC_TYPE, FWK_ADPT_EXT_ASYNCWAIT, + FWK_ADPT_EXT_UNKNOWN_SHAPE_INPUT_INDEX, + FWK_ADPT_EXT_UNKNOWN_SHAPE_OUTPUT_INDEX, FWK_ADPT_EXT_INVALID }; @@ -113,7 +115,7 @@ struct StrFWKKernel { typedef StrFWKKernel FWKOperateParam; // Extent info ShapeAndType -const uint32_t kMaxShapeDims = 8; +const uint32_t kMaxShapeDims = 8U; #pragma pack(push, 1) struct ShapeAndType { int32_t type; @@ -122,13 +124,13 @@ struct ShapeAndType { #pragma pack(pop) // Extend info structure for extInfoAddr -const uint32_t kExtInfoHeadSize = 8; +const uint32_t kExtInfoHeadSize = 8U; #pragma pack(push, 1) struct ExtInfo { int32_t infoType; // extend type uint32_t infoLen; // length for infoMsg - char infoMsg[0]; // extend value + char_t infoMsg[0]; // extend value }; #pragma pack(pop) @@ -143,9 +145,9 @@ struct ResultSummary { #pragma pack(push, 1) struct AsyncWait { - uint8_t waitType; // wait type, FWK_ADPT_WAIT_TYPE_EVENT: event wait - uint32_t waitId; // wait id, GE refresh - uint32_t timeOut; // reserved + uint8_t waitType; // wait type, FWk_ADPT_WAIT_TPYE_EVENT: event wait + uint32_t waitId; // wait id, GE refresh + uint32_t timeOut; // reserved uint64_t reserved; }; #pragma pack(pop) diff --git a/third_party/fwkacllib/inc/hccl/base.h b/third_party/fwkacllib/inc/hccl/base.h index aa43c82a..4dd9e023 100644 --- a/third_party/fwkacllib/inc/hccl/base.h +++ b/third_party/fwkacllib/inc/hccl/base.h @@ -94,13 +94,13 @@ enum HcclEventType { HCCL_EVENT_RESERVED /**< reserved */ }; -const u32 TAG_MAX_LEN = 127; // ×î´óµÄtag ³¤¶È +const u32 TAG_MAX_LEN = 127; // tag using TagAttr = struct TagAttrDef { - char name[TAG_MAX_LEN + 1]; // tag±êʶ - // tag±êʶµÄ½ÓÊÕÊý¾Ý£¬µ÷ÓÃÕßÊÇ·ñ»áÖ÷¶¯µ÷ÓýÓÊÕ½Ó¿Ú£¬0 = ·ñ, 1 = »á(Ô¤Áô£¬Ôݲ»Ö§³Ö)¡£ - // ¶ÔÓÚactiveRecv = 0£¬µ±½ÓÊÕ²àÊÕµ½Êý¾Ý»òÕß·¢ËÍÇëÇóʱ£¬Ö÷¶¯Í¨Öªµ÷ÓÃÕß¡£ + char name[TAG_MAX_LEN + 1]; // tagʶ + // tagʶĽݣǷýսӿڣ0 = , 1 = (Ԥݲ֧) + // activeRecv = 0ղյݻ߷ʱ֪ͨߡ uint32_t activeRecv; - uint32_t sendCredit; // ÅäÖøÃtagÔÊÐíinflightµÄsend¸öÊý + uint32_t sendCredit; // øtaginflightsend uint32_t eventId; }; @@ -188,6 +188,15 @@ struct HcomGatherAllToAllVParams { const char *group; // not used now }; +typedef enum workMode { +HCCL_MODE_NORMAL = 0, // ֧κProbe any֧־ȷprobe +HCCL_MODE_ANY = 1 // ֧ANY_SOURCE + ANY_TAGprobe +} WorkMode; + +typedef struct tagCommAttr { + WorkMode mode; // ͨڵprobeģʽ + uint32_t deviceId = 0; +} CommAttr; #ifdef __cplusplus } #endif // __cplusplus diff --git a/third_party/fwkacllib/inc/hccl/hcom.h b/third_party/fwkacllib/inc/hccl/hcom.h index bf1f395b..cdc8d840 100644 --- a/third_party/fwkacllib/inc/hccl/hcom.h +++ b/third_party/fwkacllib/inc/hccl/hcom.h @@ -126,72 +126,6 @@ extern HcclResult HcomSetGradFusionByIndex(const char *group, u32 segmentNum, co * @return HcclResult */ extern HcclResult HcomSetGradFusionBySize(const char *group, u32 segmentNum, const float *sizeList); - -/** - * @brief Initialize hcom executor. - * - * @param void - * @return HcclResult - */ -HcclResult HcomExecInitialize(); - -/** - * @brief Finalize hcom executor. - * - * @param void - * @return HcclResult - */ -HcclResult HcomExecFinalize(); - -/** - * @brief Put collective communication operation into hcom executor. - * - * @param opInfo information about collective communication operation. - * @param callback callback after collective communication operation. - * @return HcclResult - */ -HcclResult HcomExecEnqueueOperation(HcomOperation opInfo, std::function callback); - -/** - * @brief Put remote access operation into hcom executor. - * - * @param remoteAccessType operation type (read or write). - * @param addrInfos address information about collective communication operation. - * @param callback callback after collective communication operation. - * @return HcclResult - */ -HcclResult HcomExecEnqueueRemoteAccess(const std::string& remoteAccessType, - const std::vector& addrInfos, - std::function callback); - -/** - * @brief Put alltoallv communication operation into hcom executor. - * - * @param params information about alltoallv communication operation. - * @param callback callback after collective communication operation. - * @return HcclResult - */ -HcclResult HcomExecEnqueueAllToAllV(HcomAllToAllVParams params, std::function callback); - -/** - * @brief Put agther alltoallv communication operation into hcom executor. - * - * @param params information about agther alltoallv communication operation. - * @param callback callback after collective communication operation. - * @return HcclResult - */ -HcclResult HcomExecEnqueueGatherAllToAllV(HcomGatherAllToAllVParams params, - std::function callback); - -/** - * @brief Register memories and init resources for remote access. - * - * @param addrList memory addresses for remote access. - * @param count number of remote memory addresses. - * @return HcclResult - */ -extern HcclResult HcomRegRemoteAccessMem(const MemRegisterAddr* addrList, u32 count); - #ifdef __cplusplus } #endif // __cplusplus diff --git a/third_party/fwkacllib/inc/mmpa/mmpa_api.h b/third_party/fwkacllib/inc/mmpa/mmpa_api.h index c48aaa63..f7eb7435 100644 --- a/third_party/fwkacllib/inc/mmpa/mmpa_api.h +++ b/third_party/fwkacllib/inc/mmpa/mmpa_api.h @@ -1,18 +1,12 @@ -/** - * Copyright 2019-2020 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. - */ +/* +* @file mmpa_api.h +* +* Copyright (C) Huawei Technologies Co., Ltd. 2019-2021. All Rights Reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ #ifndef _MMPA_API_H_ #define _MMPA_API_H_ diff --git a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h index 46fb6e21..fa72aed2 100644 --- a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h +++ b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_linux.h @@ -1,18 +1,12 @@ -/** - * Copyright 2019-2020 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. - */ +/* +* @file mmpa_linux.h +* +* Copyright (C) Huawei Technologies Co., Ltd. 2019-2021. All Rights Reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ #ifndef MMPA_LINUX_MMPA_LINUX_H #define MMPA_LINUX_MMPA_LINUX_H diff --git a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_linux.h b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_linux.h index 9df5b9ce..9c6f6499 100644 --- a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_linux.h +++ b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_linux.h @@ -79,6 +79,9 @@ typedef long LONG; #define MMPA_THREAD_SCHED_OTHER SCHED_OTHER #define MMPA_THREAD_MIN_STACK_SIZE PTHREAD_STACK_MIN +#define MMPA_PATH_SEPARATOR_STR "/" +#define MMPA_PATH_SEPARATOR_CHAR '/' + #define MM_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER #define MMPA_MAX_NI 19 diff --git a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_win.h b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_win.h index 1627d7a9..9f8a72cd 100644 --- a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_win.h +++ b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_typedef_win.h @@ -1,83 +1,86 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef MMPA_TYPEDEF_WIN_H -#define MMPA_TYPEDEF_WIN_H - -#ifdef __cplusplus -#if __cplusplus -extern "C" { -#endif // __cpluscplus -#endif // __cpluscplus - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - -#define EN_OK 0 -#define EN_ERR 1 -#define EN_ERROR (-1) -#define EN_INVALID_PARAM (-2) -#define EN_TIMEOUT (-3) - -#define HANDLE_INVALID_VALUE (-1) -#define INVALID_SOCKET_HANDLE INVALID_SOCKET -#define MMPA_MEM_MAX_LEN (0x7fffffff) -#define MMPA_PROCESS_ERROR (0x7fffffff) - -#define MMPA_ONE_THOUSAND 1000 -#define MMPA_COMPUTER_BEGIN_YEAR 1900 -#define SUMMER_TIME_OR_NOT (-1) -#define MMPA_ZERO 0 -#define MMPA_VALUE_ONE 1 -#define MMPA_SOCKET_MAIN_EDITION 2 -#define MMPA_SOCKET_SECOND_EDITION 0 -#define MMPA_PIPE_BUF_SIZE 1024 -#define MMPA_MAX_SCANDIR_COUNT 1024 -#define MAX_IOVEC_SIZE 32 -#define MMPA_PIPE_COUNT 2 -#define MMPA_THREADNAME_SIZE 16 -#define MMPA_MIN_OS_NAME_SIZE (MAX_COMPUTERNAME_LENGTH + 1) -#define MMPA_MIN_OS_VERSION_SIZE 64 - -#define MMPA_MAX_NI 19 -#define MMPA_MIDDLE_NI 5 -#define MMPA_LOW_NI (-5) -#define MMPA_MIN_NI (-20) -#define MMPA_MAX_FILE 128 - -#define MMPA_MAX_THREAD_PIO 99 -#define MMPA_MIDDLE_THREAD_PIO 66 -#define MMPA_LOW_THREAD_PIO 33 -#define MMPA_MIN_THREAD_PIO 1 - -#define MMPA_THREAD_SCHED_RR 0 -#define MMPA_THREAD_SCHED_FIFO 0 -#define MMPA_THREAD_SCHED_OTHER 0 -#define MMPA_THREAD_MIN_STACK_SIZE 0 - -#define MM_MUTEX_INITIALIZER NULL - -#ifdef __cplusplus -#if __cplusplus -} -#endif // __cpluscplus -#endif // __cpluscplus -#endif // _MMPA_TYPEDEF_WIN_H_ +/** + * Copyright 2019-2020 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. + */ + +#ifndef MMPA_TYPEDEF_WIN_H +#define MMPA_TYPEDEF_WIN_H + +#ifdef __cplusplus +#if __cplusplus +extern "C" { +#endif // __cpluscplus +#endif // __cpluscplus + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#define EN_OK 0 +#define EN_ERR 1 +#define EN_ERROR (-1) +#define EN_INVALID_PARAM (-2) +#define EN_TIMEOUT (-3) + +#define HANDLE_INVALID_VALUE (-1) +#define INVALID_SOCKET_HANDLE INVALID_SOCKET +#define MMPA_MEM_MAX_LEN (0x7fffffff) +#define MMPA_PROCESS_ERROR (0x7fffffff) + +#define MMPA_ONE_THOUSAND 1000 +#define MMPA_COMPUTER_BEGIN_YEAR 1900 +#define SUMMER_TIME_OR_NOT (-1) +#define MMPA_ZERO 0 +#define MMPA_VALUE_ONE 1 +#define MMPA_SOCKET_MAIN_EDITION 2 +#define MMPA_SOCKET_SECOND_EDITION 0 +#define MMPA_PIPE_BUF_SIZE 1024 +#define MMPA_MAX_SCANDIR_COUNT 1024 +#define MAX_IOVEC_SIZE 32 +#define MMPA_PIPE_COUNT 2 +#define MMPA_THREADNAME_SIZE 16 +#define MMPA_MIN_OS_NAME_SIZE (MAX_COMPUTERNAME_LENGTH + 1) +#define MMPA_MIN_OS_VERSION_SIZE 64 + +#define MMPA_MAX_NI 19 +#define MMPA_MIDDLE_NI 5 +#define MMPA_LOW_NI (-5) +#define MMPA_MIN_NI (-20) +#define MMPA_MAX_FILE 128 + +#define MMPA_PATH_SEPARATOR_STR "\\" +#define MMPA_PATH_SEPARATOR_CHAR '\\' + +#define MMPA_MAX_THREAD_PIO 99 +#define MMPA_MIDDLE_THREAD_PIO 66 +#define MMPA_LOW_THREAD_PIO 33 +#define MMPA_MIN_THREAD_PIO 1 + +#define MMPA_THREAD_SCHED_RR 0 +#define MMPA_THREAD_SCHED_FIFO 0 +#define MMPA_THREAD_SCHED_OTHER 0 +#define MMPA_THREAD_MIN_STACK_SIZE 0 + +#define MM_MUTEX_INITIALIZER NULL + +#ifdef __cplusplus +#if __cplusplus +} +#endif // __cpluscplus +#endif // __cpluscplus +#endif // _MMPA_TYPEDEF_WIN_H_ diff --git a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h index 699fe815..e03131f2 100644 --- a/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h +++ b/third_party/fwkacllib/inc/mmpa/sub_inc/mmpa_win.h @@ -1,18 +1,12 @@ -/** - * Copyright 2019-2020 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. - */ +/* +* @file mmpa_win.h +* +* Copyright (C) Huawei Technologies Co., Ltd. 2019-2021. All Rights Reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ #ifndef MMPA_WIN_MMPA_WIN_H #define MMPA_WIN_MMPA_WIN_H diff --git a/third_party/fwkacllib/inc/ops/OWNERS b/third_party/fwkacllib/inc/ops/OWNERS new file mode 100755 index 00000000..f95df23c --- /dev/null +++ b/third_party/fwkacllib/inc/ops/OWNERS @@ -0,0 +1,65 @@ +approvers: +- gegenhua +- qiaohairong +reviewers: +- chuqingxi +- wang-jintang +- luanma_bl +- chen-kang30 +- li-xulong +- Allan_Yu +- minshen +- pan-jixing +- yl_wang +- lijie176 +- mabing726 +- miao-fangzheng +- huang-qiang002 +- su-yueming +- chenpeng-hw +- wang_jianle +- luanma_bl +- LDLD0524 +- wywismygod2020 +- lipeiyang3699 +- koala-zhang +- zhu-jingjing +- zhaozhihui5 +- simbaliuxx +- lyxyz +- zhou-qilong +- block0219 +- hanfuwei +- xchu42 +- sheng-nan +- yangjing88 +- alexlak +- xig514 +- jellylj +- brightlyking +- liuzhenyuhw +- djh602 +- wangjiangben_hw +- li1jie +- clinglai +- liujun2014 +- soupkey +- wu-shengji +- cimeng +- ccl_ligang +- xiaozhedeng +- granpad7 +- tc1qaz +- Ronnie_zheng +- xiexianhu +- zhouyujoe +- zhaoping12 +- tanshengshun +- fanqirui +- xu-binglin +- yangyang016 +- zhangzhongzt +- gegenhua +- qiaohairong +options: + no_parent_owners: true \ No newline at end of file diff --git a/third_party/fwkacllib/inc/ops/array_ops.h b/third_party/fwkacllib/inc/ops/array_ops.h index d56ac5bb..7928db15 100644 --- a/third_party/fwkacllib/inc/ops/array_ops.h +++ b/third_party/fwkacllib/inc/ops/array_ops.h @@ -745,6 +745,28 @@ REG_OP(UnsqueezeV2) .ATTR(axis, ListInt, {}) .OP_END_FACTORY_REG(UnsqueezeV2) + +/** +*@brief Inserts a dimension of 1 into a tensor's shape. Only the tensor shape +is changed, but the data is not changed. \n + +*@par Inputs: +*x: A tensor. +*axes: A list of int64, which indicates the dimensions to be inserted. \n + +*@par Outputs: +*y: Reshape tensor with same data as input. \n + +*@par Third-party framework compatibility +*Compatible with the Onnx operator Unsqueeze in V13. \n +*/ + +REG_OP(UnsqueezeV3) + .INPUT(x, TensorType::ALL()) + .INPUT(axes, ListInt) + .OUTPUT(y, TensorType::ALL()) + .OP_END_FACTORY_REG(UnsqueezeV3) + /** *@brief Reshapes a tensor. Only the tensor shape is changed, without changing the data. \n @@ -821,6 +843,28 @@ REG_OP(SqueezeV2) .ATTR(axis, ListInt, {}) .OP_END_FACTORY_REG(SqueezeV2) +/** +*@brief Removes dimensions of size 1 from the shape of a tensor according to axes. \n + +*@par Inputs: +*x: A tensor. +*axes: An optional list of int64. If not specified, squeezes all dimensions of +size 1. If specified, only squeezes the dimensions listed. It is an error to +squeeze a dimension that is not 1. \n + +*@par Outputs: +*y: Reshape tensor with same data as input. \n + +*@par Third-party framework compatibility +*Compatible with the onnx operator Squeeze in V13. \n +*/ + +REG_OP(SqueezeV3) + .INPUT(x, TensorType::ALL()) + .OPTIONAL_INPUT(axes, ListInt) + .OUTPUT(y, TensorType::ALL()) + .OP_END_FACTORY_REG(SqueezeV3) + /** *@brief Returns an integer representing the rank of input tensor. The rank of a tensor is the number of indices required to uniquely select each element of the tensor, that is, the dimension size of the tensor. \n @@ -1273,7 +1317,7 @@ REG_OP(SortV2) * @par Inputs: * One inputs, including: * @li x: A Tensor. Must be one of the following types: -* float16, float32, int32, int8 ,uint8. \n +* float16, float32, int32, int8, uint8, bool. \n * @li shape: A Tensor to specify the shape that the input tensor expanded to. \n * @par Outputs: @@ -1284,9 +1328,9 @@ REG_OP(SortV2) */ REG_OP(Expand) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32,DT_INT64, DT_INT8, DT_UINT8, DT_BOOL})) .INPUT(shape, TensorType({DT_INT16, DT_INT32, DT_INT64})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32,DT_INT64, DT_INT8, DT_UINT8, DT_BOOL})) .OP_END_FACTORY_REG(Expand) /** @@ -1342,13 +1386,37 @@ REG_OP(NonZeroWithValue) .ATTR(dtype, Type, DT_INT32) .OP_END_FACTORY_REG(NonZeroWithValue) + + +/** +*@Returns a tensor with updated shape from NonZeroWithValue. \n + +*@par Inputs: +*value: A Tensor. The output of NonZeroWithValue. \n +*index: A Tensor. The output of NonZeroWithValue. \n +*count: A Tensor. The type is INT32, means count for non_zero ele in input. \n + +* out_value: A Tensor. Has the same type as "value" . \n +* out_index: A Tensor. Has the same type as "index". \n +*/ +REG_OP(NonZeroWithValueShape) + .INPUT(value, TensorType({DT_DOUBLE, DT_FLOAT, DT_FLOAT16, DT_INT8, DT_UINT8, DT_INT16, + DT_UINT16, DT_INT32, DT_UINT32, DT_INT64, DT_UINT64, DT_BOOL})) + .INPUT(index, TensorType({DT_INT32})) + .INPUT(count, TensorType({DT_INT32})) + .OUTPUT(out_value, TensorType({DT_DOUBLE, DT_FLOAT, DT_FLOAT16, DT_INT8, DT_UINT8, DT_INT16, + DT_UINT16, DT_INT32, DT_UINT32, DT_INT64, DT_UINT64, DT_BOOL})) + .OUTPUT(out_index, TensorType({DT_INT32})) + .OP_END_FACTORY_REG(NonZeroWithValueShape) + + /** * @brief Expand the input tensor to a compatible shape. \n * @par Inputs: * One inputs, including: * x: A Tensor. Must be one of the following types: -* float16, float32, int32, int8 ,uint8. \n +* float16, float32, int32, int8, uint8, bool. \n * @par Attributes: * shape: A required listInt to specify the shape that the input tensor expanded to. \n @@ -1362,8 +1430,8 @@ REG_OP(NonZeroWithValue) */ REG_OP(ExpandD) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8, DT_BOOL})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8, DT_BOOL})) .REQUIRED_ATTR(shape, ListInt) .OP_END_FACTORY_REG(ExpandD) @@ -1404,6 +1472,43 @@ REG_OP(UpdateTensorDesc) DT_INT64, DT_UINT64, DT_INT16, DT_UINT16, DT_DOUBLE})) .REQUIRED_ATTR(shape, ListInt) .OP_END_FACTORY_REG(UpdateTensorDesc) + +/** +*@brief Queue data for other operators. \n +*@par Attributes: +*index: Index of the input tensor.The data type must be int32 or int64. +Assume that net has three data nodes, one should be set 0, another should +be set 1, and the left should be set 2. \n +*queue_name: queue name +*output_types: types of outputs data +*output_shapes: shapes of outputs data +*@par Outputs: +*y: A DT_UINT8 tensor. \n +*/ +REG_OP(QueueData) + .OUTPUT(y, TensorType({DT_UINT8})) + .ATTR(index, Int, 0) + .ATTR(queue_name, String, "") + .ATTR(output_types, ListType, {}) + .ATTR(output_shapes, ListListInt, {{}, {}}) + .OP_END_FACTORY_REG(QueueData) + +/** +* @brief Ensures that the tensor's shape matches the expected shape. \n +* @par Inputs: +* x: A Tensor. \n +* @par Attributes: +* shape: The shape that needs to be checked \n +* @par Outputs: +* y: A tensor. \n +*/ +REG_OP(EnsureShape) + .INPUT(input, TensorType({DT_INT8,DT_UINT8,DT_INT16,DT_UINT16,DT_INT32,DT_INT64,DT_FLOAT16, \ + DT_FLOAT,DT_DOUBLE})) + .OUTPUT(output, TensorType({DT_INT8,DT_UINT8,DT_INT16,DT_UINT16,DT_INT32,DT_INT64,DT_FLOAT16, \ + DT_FLOAT,DT_DOUBLE})) + .REQUIRED_ATTR(shape, ListInt) + .OP_END_FACTORY_REG(EnsureShape) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_ARRAY_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/ctc_ops.h b/third_party/fwkacllib/inc/ops/ctc_ops.h index 6e908091..bf50b24d 100644 --- a/third_party/fwkacllib/inc/ops/ctc_ops.h +++ b/third_party/fwkacllib/inc/ops/ctc_ops.h @@ -146,7 +146,7 @@ REG_OP(CTCBeamSearchDecoder) *@li log_probs: Tensor of size (T, N, C), where T =input length, N =batch size, and C = number of classes (including blank). It represent the logarithmized probabilities of the outputs. -*@li targets: Tensor of size (N, S), where S= max target length. +*@li targets: Tensor of size (N, S) or sum(target_lengths), where S = max target length. It represent the target sequences. *@li input_lengths: Tuple or tensor of size (N). It represent the lengths of the inputs. *@li target_lengths: Tuple or tensor of size (N). It represent lengths of the targets. @@ -159,11 +159,12 @@ REG_OP(CTCBeamSearchDecoder) *@li blank : Blank label. Default 0. *@li reduction: Specifies the reduction to apply to the output. Default: 'mean'. *@li zero_infinity : Whether to zero infinite losses and the associated gradients. +*@li label_max : The max length of targets. *@par Third-party framework compatibility * Compatible with Pytorch CTCLoss operator. -*@par Restrictions: +*@attention Constraints: *The limit of Label’s length is 1K. */ REG_OP(CTCLossV2) @@ -176,6 +177,7 @@ REG_OP(CTCLossV2) .ATTR(blank, Int, 0) .ATTR(reduction, String, "mean") .ATTR(zero_infinity, Bool, false) + .ATTR(label_max, Int, 0) .OP_END_FACTORY_REG(CTCLossV2) /** @@ -186,7 +188,7 @@ REG_OP(CTCLossV2) *@li log_probs: Tensor of size (T, N, C), where T =input length, N =batch size, and C = number of classes (including blank). It represent the logarithmized probabilities of the outputs. -*@li targets: Tensor of size (N, S), where S= max target length. +*@li targets: Tensor of size (N, S) or sum(target_lengths), where S = max target length. It represent the target sequences. *@li input_lengths: Tuple or tensor of size (N). It represent the lengths of the inputs. *@li target_lengths: Tuple or tensor of size (N). It represent lengths of the targets. @@ -200,11 +202,12 @@ REG_OP(CTCLossV2) *@li blank : Blank label. Default 0. *@li reduction: Specifies the reduction to apply to the output. Default: 'mean'. *@li zero_infinity : Whether to zero infinite losses and the associated gradients. +*@li label_max : The max length of targets. *@par Third-party framework compatibility * Compatible with Pytorch CTCLoss operator. -*@par Restrictions: +*@attention Constraints: *The limit of Label’s length is 1K. */ REG_OP(CTCLossV2Grad) @@ -219,6 +222,7 @@ REG_OP(CTCLossV2Grad) .ATTR(blank, Int, 0) .ATTR(reduction, String, "mean") .ATTR(zero_infinity, Bool, false) + .ATTR(label_max, Int, 0) .OP_END_FACTORY_REG(CTCLossV2Grad) } // namespace ge diff --git a/third_party/fwkacllib/inc/ops/data_flow_ops.h b/third_party/fwkacllib/inc/ops/data_flow_ops.h index 3034730d..91a59327 100644 --- a/third_party/fwkacllib/inc/ops/data_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/data_flow_ops.h @@ -2398,6 +2398,32 @@ REG_OP(DynamicGetNext) .ATTR(_getnext_inputs_shape_range, String, "") .OP_END_FACTORY_REG(DynamicGetNext) +/** +@brief DynamicGetNextV2, dynamic get next data +* @par Inputs: +*x: the iterator, all types are available +* @par Outputs: +* y: the date in iterator, all types are available +* @par Attributes: +* output_types: types of all outputs +* output_shapes: shapes of all outputs +*_dynamic_graph_execute_mode: dynamic graph execution mode, +value is one of lazy_recompile and dynamic_execute +*_getnext_inputs_shape_range: shape ranges of outputs, +it works where _dynamic_graph_execute_mode is dynamic_execute +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ + +REG_OP(DynamicGetNextV2) + .DYNAMIC_OUTPUT(y, TensorType::ALL()) + .ATTR(output_types, ListType, {}) + .ATTR(channel_name, String, "") + .ATTR(output_shapes, ListListInt, {{}, {}}) + .ATTR(_dynamic_graph_execute_mode, String, "lazy_recompile") + .ATTR(_getnext_inputs_shape_range, String, "") + .OP_END_FACTORY_REG(DynamicGetNextV2) + /** *@brief AdpGetNext *@par Outputs: @@ -2433,5 +2459,24 @@ REG_OP(GetNextV2) .ATTR(output_shapes, ListListInt, {{}, {}}) .ATTR(channel_name, String, "") .OP_END_FACTORY_REG(GetNextV2) + +/** +*@brief GetNextFromQueue +*@par Inputs: +*x: the data, only support uint8 +*@par Outputs: +*y: the data in iterator, all types are available +*@par Attributes: +*output_types: types of all outputs +*output_shapes: shapes of all outputs +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(GetNextFromQueue) + .INPUT(x, TensorType({DT_UINT8})) + .DYNAMIC_OUTPUT(y, TensorType::ALL()) + .ATTR(output_types, ListType, {}) + .ATTR(output_shapes, ListListInt, {{}, {}}) + .OP_END_FACTORY_REG(GetNextFromQueue) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_DATA_FLOW_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/deep_md.h b/third_party/fwkacllib/inc/ops/deep_md.h index fadfe128..ef335f33 100644 --- a/third_party/fwkacllib/inc/ops/deep_md.h +++ b/third_party/fwkacllib/inc/ops/deep_md.h @@ -1,5 +1,5 @@ /** - * Copyright 2021 Huawei Technologies Co., Ltd + * CCopyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -24,6 +24,87 @@ #include "graph/operator_reg.h" namespace ge { + +/** +* @brief Calculate TabulateFusion. \n +* +* @par Inputs: +* Five inputs, including: +* @li table: A Tensor. Must be one of the following types: float16, float32, float64. +* @li table_info: A Tensor. Must be one of the following types: float16, float32, float64. +* @li em_x: A Tensor. Must be one of the following types: float16, float32, float64. +* @li em: A Tensor. Must be one of the following types: float16, float32, float64. \n +* +* @par Outputs: +* descriptor: A Tensor. Must be one of the following types: float16, float32, float64. \n +* +* @par Attributes: +* Three attributes, including: +* @li last_layer_size: int value. +* @li split_count: int value. +* @li split_index: int value. \n +* +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(TabulateFusion) + .INPUT(table, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(table_info, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(em_x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(em, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(descriptor, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .REQUIRED_ATTR(last_layer_size, Int) + .ATTR(split_count, Int, 1) + .ATTR(split_index, Int, 0) + .OP_END_FACTORY_REG(TabulateFusion) + +/** +* @brief Calculate ProdEnvMatA. \n +* +* @par Inputs: +* @li coord: A Tensor. Must be one of the following types: float32, float64. +* @li type: A Tensor. Must be one of the following types: int32. +* @li natoms: A Tensor. Must be one of the following types: int32. +* @li box: A Tensor. Must be one of the following types: float32, float64. +* @li mesh: A Tensor. Must be one of the following types: int32. +* @li davg: A Tensor. Must be one of the following types: float32, float64. +* @li dstd: A Tensor. Must be one of the following types: float32, float64. +* +* @par Outputs: +* descrpt: A Tensor. Must be one of the following types: float32, float64. +* descrpt_deriv: A Tensor. Must be one of the following types: float32, float64. +* rij: A Tensor. Must be one of the following types: float32, float64. +* nlist: A Tensor. Must be one of the following types: int32. \n +* +* @par Attributes: +* @li rcut_a: A Float. +* @li rcut_r: A Float. +* @li rcut_r_smth: A Float. +* @li sel_a: A ListInt. +* @li split_count: A Int. +* @li split_index: A Int.\n +* +*/ +REG_OP(ProdEnvMatA) + .INPUT(coord, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(type, TensorType({DT_INT32})) + .INPUT(natoms, TensorType({DT_INT32})) + .INPUT(box, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(mesh, TensorType({DT_INT32})) + .INPUT(davg, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(dstd, TensorType({DT_FLOAT, DT_DOUBLE})) + .OUTPUT(descrpt, TensorType({DT_FLOAT, DT_DOUBLE})) + .OUTPUT(descrpt_deriv, TensorType({DT_FLOAT, DT_DOUBLE})) + .OUTPUT(rij, TensorType({DT_FLOAT, DT_DOUBLE})) + .OUTPUT(nlist, TensorType({DT_INT32})) + .ATTR(rcut_a, Float, 1.0) + .ATTR(rcut_r, Float, 1.0) + .ATTR(rcut_r_smth, Float, 1.0) + .ATTR(sel_a, ListInt, {}) + .ATTR(sel_r, ListInt, {}) + .ATTR(split_count, Int, 1) + .ATTR(split_index, Int, 0) + .OP_END_FACTORY_REG(ProdEnvMatA) /** * @brief Calculate ProdForceSeA. \n * @@ -53,7 +134,80 @@ REG_OP(ProdForceSeA) .OUTPUT(atom_force, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) .REQUIRED_ATTR(n_a_sel, Int) .REQUIRED_ATTR(n_r_sel, Int) + .ATTR(split_count, Int, 1) + .ATTR(split_index, Int, 0) .OP_END_FACTORY_REG(ProdForceSeA) + +/** +* @brief Calculate ProdVirialSeA. \n +* +* @par Inputs: +* Five inputs, including: +* @li net_deriv: A Tensor. Must be one of the following types: float16, float32, float64. +* @li in_deriv: A Tensor. Must be one of the following types: float16, float32, float64. +* @li rij: A Tensor. Must be one of the following types: float16, float32, float64. +* @li nlist: A Tensor. dtype is int32. +* @li natoms: A Tensor. dtype is int32. \n +* +* @par Outputs: +* Two outputs, including: +* @li virial: A Tensor. Must be one of the following types: float16, float32, float64. +* @li atom_virial: A Tensor. Must be one of the following types: float16, float32, float64. \n +* +* @par Attributes: +* Two attributes, including: +* @li n_a_sel: Int value. +* @li n_r_sel: Int value. +* @li split_count: Int value. +* @li split_index: Int value. \n +*/ +REG_OP(ProdVirialSeA) + .INPUT(net_deriv, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(in_deriv, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(rij, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(nlist, TensorType({DT_INT32})) + .INPUT(natoms, TensorType({DT_INT32})) + .OUTPUT(virial, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(atom_virial, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .REQUIRED_ATTR(n_a_sel, Int) + .REQUIRED_ATTR(n_r_sel, Int) + .ATTR(split_count, Int, 1) + .ATTR(split_index, Int, 0) + .OP_END_FACTORY_REG(ProdVirialSeA) + +/** +* @brief Calculate TabulateFusionGrad. \n +* +* @par Inputs: +* Five inputs, including: +* @li table: A Tensor. Must be one of the following types: float16, float32, float64. +* @li table_info: A Tensor. Must be one of the following types: float16, float32, float64. +* @li em_x: A Tensor. Must be one of the following types: float16, float32, float64. +* @li em: A Tensor. Must be one of the following types: float16, float32, float64. +* @li dy: A Tensor. Must be one of the following types: float16, float32, float64. +* @li descriptor: A Tensor. Must be one of the following types: float16, float32, float64. \n +* +* @par Outputs: +* @li dy_dem_x: A Tensor. Must be one of the following types: float16, float32, float64. +* @li dy_dem: A Tensor. Must be one of the following types: float16, float32, float64. \n +* +* @par Attributes: +* Two attributes, including: +* @li split_count: A Scalar. +* @li split_index: A Scalar. \n +*/ +REG_OP(TabulateFusionGrad) + .INPUT(table, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(table_info, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(em_x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(em, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(dy, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(descriptor, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(dy_dem_x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(dy_dem, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .ATTR(split_count, Int, 1) + .ATTR(split_index, Int, 0) + .OP_END_FACTORY_REG(TabulateFusionGrad) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_DEEP_MD_H_ diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index be201579..1cd89c69 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -331,7 +331,7 @@ REG_OP(Sub) *@par Inputs: *One input, including: \n -*x: A Tensor. Must be one of the following types: float16, float32, double, int32, int64. \n +*x: A Tensor. Must be one of the following types: float16, float32, double, int8, int16, int32, int64. \n *@par Outputs: *y: A Tensor. Has the same type as "x". \n @@ -340,8 +340,10 @@ REG_OP(Sub) *Compatible with the TensorFlow operator Abs. */ REG_OP(Abs) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64})) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT8, DT_INT16, + DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT8, DT_INT16, + DT_INT32, DT_INT64})) .OP_END_FACTORY_REG(Abs) /** @@ -3821,6 +3823,10 @@ REG_OP(CosineSimilarity) * @li max_grad_norm: A Tensor. Datatype is same as exp_avg. Shape (1, ).\n * @li global_grad_norm: A Tensor. Datatype is same as exp_avg. Shape (1, ).\n * @li weight_decay: A Tensor. Datatype is same as exp_avg. Shape (1, ).\n +* @li step_size: A Optional Tensor. Datatype is same as exp_avg. Shape (1, ).\n + +* @par Attributes: +* @li adam_mode: An optional bool. Defaults to "adam". \n *@par Outputs: *three inputs, including: @@ -3840,9 +3846,11 @@ REG_OP(ApplyAdamV2) .INPUT(max_grad_norm, TensorType({ DT_FLOAT, DT_FLOAT16 })) .INPUT(global_grad_norm, TensorType({ DT_FLOAT, DT_FLOAT16 })) .INPUT(weight_decay, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .OPTIONAL_INPUT(step_size, TensorType({ DT_FLOAT, DT_FLOAT16 })) .OUTPUT(var, TensorType({ DT_FLOAT, DT_FLOAT16 })) .OUTPUT(m, TensorType({ DT_FLOAT, DT_FLOAT16 })) .OUTPUT(v, TensorType({ DT_FLOAT, DT_FLOAT16 })) + .ATTR(adam_mode, String, "adam") .OP_END_FACTORY_REG(ApplyAdamV2) } // namespace ge diff --git a/third_party/fwkacllib/inc/ops/image_ops.h b/third_party/fwkacllib/inc/ops/image_ops.h index dc3a96b6..bf0846c2 100644 --- a/third_party/fwkacllib/inc/ops/image_ops.h +++ b/third_party/fwkacllib/inc/ops/image_ops.h @@ -132,7 +132,7 @@ nearest neighbor sampling to a common output size specified by crop_size . \n *@li x:A Tensor. Must be one of the following types:uint8, uint16, int8, int16, int32, int64, float16, float, double. A 4-D tensor of shape [batch, image_height, image_width, depth]. The format must be NHWC. -*@li boxes: A Tensor of type float. A 2-D tensor of shape [num_boxes, 4]. +*@li boxes: A Tensor. Must be one of the following types: float16, float. A 2-D tensor of shape [num_boxes, 4]. *@li box_index: A Tensor of type int32. A 1-D tensor of shape [num_boxes] with int32 values in [0, batch). *@li crop_size: A Tensor of type int32. A 1-D tensor of 2 elements, crop_size @@ -146,7 +146,7 @@ extrapolation, when applicable. NearestNeighbor . \n *@par Outputs: -*y:A Tensor of type float. The format must be NHWC. \n +*y: A Tensor. Must be one of the following types: float16, float. The format must be NHWC. \n *@attention Constraints: *Input images must be a 4-D tensor . \n @@ -158,10 +158,10 @@ NearestNeighbor . \n REG_OP(CropAndResize) .INPUT(x, TensorType({DT_UINT8, DT_UINT16, DT_INT8, \ DT_INT16, DT_INT32, DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) - .INPUT(boxes, TensorType({DT_FLOAT})) + .INPUT(boxes, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(box_index, TensorType({DT_INT32})) .INPUT(crop_size, TensorType({DT_INT32})) - .OUTPUT(y, TensorType({DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(extrapolation_value, Float, 0) .ATTR(method, String, "bilinear") .OP_END_FACTORY_REG(CropAndResize) @@ -175,7 +175,7 @@ REG_OP(CropAndResize) *Input images must be a 5HD tensor. Inputs include: *@li x:A Tensor. Must be one of the following types:float16, float. A 5HD tensor of shape * [batch, C1, image_height, image_width, C0]. -*@li boxes: A Tensor of type float. A 2-D tensor of shape [num_boxes, 4]. +*@li boxes: A Tensor. Must be one of the following types: float16, float. A 2-D tensor of shape [num_boxes, 4]. *@li box_index: A Tensor of type int32. A 1-D tensor of shape [num_boxes] with int32 values in [0, batch) . \n *@par Attributes: @@ -184,7 +184,7 @@ REG_OP(CropAndResize) *@li method: An optional string from: '"bilinear"'. Defaults to "bilinear" . \n *@par Outputs: -*y:A Tensor of type float . \n +*y: A Tensor. Must be one of the following types: float16, float. \n *@attention Constraints: *Input images must be a 5HD tensor . \n @@ -197,9 +197,9 @@ REG_OP(CropAndResize) */ REG_OP(CropAndResizeD) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(boxes, TensorType({DT_FLOAT})) + .INPUT(boxes, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(box_index, TensorType({DT_INT32})) - .OUTPUT(y, TensorType({DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .REQUIRED_ATTR(crop_size, ListInt) .ATTR(extrapolation_value, Float, 0) .ATTR(method, String, "bilinear") @@ -888,10 +888,10 @@ Defaults to false . \n *@li half_pixel_centers: An optional bool. Defaults to False . \n *@par Outputs: -*y: 4-D with shape [batch, new_height, new_width, channels] . \n +*y: A Tensor with the same type and format as input "images" . \n *@par Third-party framework compatibility -*Compatible with tensorflow ResizeNearestNeighborV2 operator. +*Compatible with tensorflow ResizeNearestNeighbor operator. */ REG_OP(ResizeNearestNeighborV2) diff --git a/third_party/fwkacllib/inc/ops/math_ops.h b/third_party/fwkacllib/inc/ops/math_ops.h index d3e8c0bf..f6e2df88 100644 --- a/third_party/fwkacllib/inc/ops/math_ops.h +++ b/third_party/fwkacllib/inc/ops/math_ops.h @@ -378,7 +378,7 @@ to each component of an element of this dataset. REG_OP(GetNext) .DYNAMIC_OUTPUT(y, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, DT_INT32, DT_INT64, DT_UINT32, DT_UINT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_BOOL})) - .ATTR(output_types, ListInt, {}) + .ATTR(output_types, ListType, {}) .ATTR(output_shapes, ListListInt, {}) .ATTR(output_num, Int, 1) .ATTR(channel_name, String, "") diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index 0d9a8424..e8931120 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -213,9 +213,9 @@ REG_OP(GEMM) */ REG_OP(BatchMatMul) - .INPUT(x1, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) - .INPUT(x2, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .INPUT(x1, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_BF16})) + .INPUT(x2, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_BF16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_BF16})) .ATTR(adj_x1, Bool, false) .ATTR(adj_x2, Bool, false) .OP_END_FACTORY_REG(BatchMatMul) @@ -246,11 +246,11 @@ REG_OP(BatchMatMul) */ REG_OP(BatchMatMulV2) - .INPUT(x1, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8, DT_INT4})) - .INPUT(x2, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8, DT_INT4})) - .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .INPUT(x1, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8, DT_INT4, DT_BF16})) + .INPUT(x2, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT8, DT_INT4, DT_BF16})) + .OPTIONAL_INPUT(bias, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_BF16})) .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8, DT_INT4})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_BF16})) .ATTR(adj_x1, Bool, false) .ATTR(adj_x2, Bool, false) .ATTR(offset_x, Int, 0) @@ -505,17 +505,17 @@ REG_OP(ScatterElements) * Three inputs, including: *@li var: An ND Tensor . -*Must be one of the following types: float16, float32, int32, int8, uint8 -*@li indices: An ND Tensor of type int32 or int64 - +*Must be one of the following types: float16, float, int32, int8, uint8 +*@li indices: An ND Tensor . \n -*@li updates: An Tensor. format:NCHW, NHWC . +*Must be one of the following types: int32 or int64 +*@li updates: An ND Tensor . -*Must be one of the following types: float16, float32, int32, int8, uint8 +*Must be one of the following types: float16, float, int32, int8, uint8 *@par Attributes: -* use_locking: An optional bool. Defaults to "False". If "True", the operation -* will be protected by a lock . \n +*use_locking: An optional bool. Defaults to "False". If "True", +* the operation will be protected by a lock . \n *@par Outputs: *var: A Tensor. Has the same type and format as input "var" . \n @@ -792,13 +792,13 @@ REG_OP(DiagPart) * Four inputs, including: *@li x: A Tensor of type float16, int8. *@li w: A weight matrix of type float16, int8. -*@li b: A Tensor of type float16, int32, float32. -*@li offset_w: A Tensor of type int8 . \n +*@li b: An optional Tensor of type float16, int32, float32. +*@li offset_w: An optional Tensor of type int8. Reserved. Only None Supported. \n *@par Attributes: -*@li num_output: Reserved. +*@li num_output: Required. An int, output neuron number. Reserved. *@li transpose: A bool, specifying weight whether to transpose input w, either "true" or "false". Defaults to "false". -*@li axis: Optional. A int, 1 or 2, specifying which dimension the input "K" starts from. Defaults to 1. +*@li axis: Optional. An int, 1 or 2, specifying which dimension the input "K" starts from. Defaults to 1. * The product of the subsequent dimensions starting form first dimension or the second dimension is "K". *@li offset_x: An optional integer for quantized FullyConnection. *The negative offset added to the input image for int8 type. Ensure offset_x within the @@ -814,11 +814,11 @@ REG_OP(DiagPart) * Yes */ REG_OP(FullyConnection) - .INPUT(x, TensorType({DT_FLOAT16, DT_INT8, DT_INT4})) - .INPUT(w, TensorType({DT_FLOAT16, DT_INT8, DT_INT4})) - .OPTIONAL_INPUT(b, TensorType({DT_FLOAT16, DT_INT32,DT_FLOAT32})) + .INPUT(x, TensorType({DT_FLOAT16, DT_INT8, DT_INT4, DT_FLOAT32, DT_BF16})) + .INPUT(w, TensorType({DT_FLOAT16, DT_INT8, DT_INT4, DT_FLOAT32, DT_BF16})) + .OPTIONAL_INPUT(b, TensorType({DT_FLOAT16, DT_INT32,DT_FLOAT32, DT_BF16})) .OPTIONAL_INPUT(offset_w, TensorType({DT_INT8, DT_INT4})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_INT32,DT_FLOAT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_INT32,DT_FLOAT32, DT_BF16})) .REQUIRED_ATTR(num_output, Int) .ATTR(transpose, Bool, false) .ATTR(axis, Int, 1) @@ -1360,6 +1360,45 @@ REG_OP(FillDiagonal) .ATTR(wrap, Bool, false) .OP_END_FACTORY_REG(FillDiagonal) +/** +*@brief: Returns the sum of the elements of the diagonal of the input 2-D matrix. \n + +*@par Inputs: +*x: A Tensor. Must be one of the following types: +* float16, float. \n + +*@par Outputs: +*y: A Tensor. Has the same type as "x" . \n + +*@par Third-party framework compatibility +* Compatible with the Pytorch operator Trace. +*/ + +REG_OP(Trace) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(Trace) + +/** +*@brief Computes the generalized inverse of any matrix. \n + +*@par Inputs: +* @li x: input matrix. Must be one of the following types: +* double, float. \n + +*@par Attributes: +* @li rcond: An optional float >= 0 or inf. Defaults to 1e-15. \n + +*@par Outputs: +* y: A Tensor with the same type and shape of x's transpose. \n + +*/ +REG_OP(Pinverse) + .INPUT(x, TensorType({ DT_FLOAT, DT_DOUBLE })) + .OUTPUT(y, TensorType({ DT_FLOAT, DT_DOUBLE })) + .ATTR(rcond, Float, 1e-15) + .OP_END_FACTORY_REG(Pinverse) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATRIX_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h index 398c6568..7a28a738 100644 --- a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h @@ -142,6 +142,74 @@ REG_OP(BatchNorm) .ATTR(is_training, Bool, true) .OP_END_FACTORY_REG(BatchNorm) +/** +* @brief After the mean and reciprocal of standard deviation(invert_std) are separately calculated on each device, +* the mena and reciprocal of standard deviation(invert_std) data on each device are normlized, +* a total mean and reciprocal of standard deviation(invert_std) are returned, and running_var are updated. + +* @par Inputs: +* include: +* @li mean_all: A Tensor. The mean of each device. Must be one of the following types: float16, float32. +* @li invert_std_all: A Tensor. Reciprocal of the variances of each device. Must be one of the following types: float16, float32. +* @li count_all: A Tensor. Number of data for each device. Must be one of the following types: float16, float32. +* @li mean_broadcast: A Tensor. The overall average and broadcast. Must be one of the following types: float16, float32. +* @li count_sum: A Tensor. General statistics. Must be one of the following types: float16, float32. +* @li running_var: A Tensor. Runtime variance. Must be one of the following types: float16, float32. \n + +* @par Attributes: +* Two Attributes, including: +* @li momentum: A optional float. Defaults to 0.01. \n +* @li epsilon: An optional float. Defaults to 0.00001. \n + +* @par Outputs: +* include: +* @li invert_std: A Tensor. It's inverse of total variance. +* @li running_var_update: A Tensor. It's moving variance of each device after the update. \n + +* @par Third-party framework compatibility +* ReduceMeanWithCount and SyncBatchNormGatherStatsWithCounts and SyncBNTrainingUpdate +* compatible with the Pytorch operator BatchNormGatherStatsWithCounts. +*/ +REG_OP(SyncBatchNormGatherStatsWithCounts) + .INPUT(mean_all, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(invert_std_all, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(count_all, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(mean_broadcast, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(count_sum, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(running_var, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(invert_std, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(running_var_update, TensorType({DT_FLOAT, DT_FLOAT16})) + .ATTR(momentum, Float, 0.1) + .ATTR(epsilon, Float, 0.001) + .OP_END_FACTORY_REG(SyncBatchNormGatherStatsWithCounts) + +/** +* @brief update running_mean. + +* @par Inputs: +* include: +* @li mean: A Tensor. The mean of each device. Must be one of the following types: float16, float32. +* @li running_mean: A Tensor. Runtime Mean. Must be one of the following types: float16, float32. \n + +* @par Attributes: +* One Attribute, including: +* @li momentum: A optional float. Defaults to 0.01. \n + +* @par Outputs: +* include: +* @li running_mean_update: A Tensor. It's moving mean of each device after the update. \n + +* @par Third-party framework compatibility +* ReduceMeanWithCount and SyncBatchNormGatherStatsWithCounts and SyncBNTrainingUpdate +* compatible with the Pytorch operator BatchNormGatherStatsWithCounts. +*/ +REG_OP(SyncBNTrainingUpdate) + .INPUT(mean, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(running_mean, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(running_mean_update, TensorType({DT_FLOAT, DT_FLOAT16})) + .ATTR(momentum, Float, 0.1) + .OP_END_FACTORY_REG(SyncBNTrainingUpdate) + /** *@brief part of SyncBatchNormBackward . \n diff --git a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h index 6f58f028..5cabd4db 100644 --- a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h @@ -134,9 +134,9 @@ REG_OP(DepthwiseConv2DBackpropFilter) * instead. */ REG_OP(DepthwiseConv2DBackpropFilterD) - .INPUT(input, TensorType({float16})) - .INPUT(out_backprop, TensorType({float16})) - .OUTPUT(filter_grad, TensorType({float32})) + .INPUT(input, TensorType({DT_FLOAT16, DT_FLOAT32, DT_BF16})) + .INPUT(out_backprop, TensorType({DT_FLOAT16, DT_FLOAT32, DT_BF16})) + .OUTPUT(filter_grad, TensorType({DT_FLOAT32})) .REQUIRED_ATTR(filter_size, ListInt) .REQUIRED_ATTR(strides, ListInt) .ATTR(dilations, ListInt, {1, 1, 1, 1}) @@ -764,7 +764,7 @@ REG_OP(Conv2DBackpropFilterD) | | float32 | float32 | float32 | float32 |\n | | int8 | int8 | int32 | int32 |\n | Format | NCHW | NCHW | ND | NCHW |\n -| | NHWC | HWCN | | NHWC |\n +| | NHWC | HWCN | ND | NHWC |\n *\n * For float32 type, the actual calculation on the chip is based on * float16. @@ -1650,5 +1650,43 @@ REG_OP(Dilation) .ATTR(padding_value, Float, 0.0) .OP_END_FACTORY_REG(Dilation) +/** +*@brief Computes the post-cube processing output with the expected input +*@par Inputs: + * Ten inputs: + * x1: A Tensor of type float16, bfloat16, float32, int32 + * x2: A Tensor of type float16, int8, int4 + * quant_scale_0: A Tensor of type uint64 + * relu_weight_0: A Tensor of type float32 + * clip_value_0: A Tensor of type float16, int8, int4 + * quant_scale_1: A Tensor of type uint64 + * relu_weight_1: A Tensor of type float32 + * clip_value_1: A Tensor of type float16 + * anti_quant_scale: A Tensor of type float16 + * anti_quant_offset: A Tensor of type int8, int4 +*@par Attributes: + * @li fusion_op_list: A list of String. + * @li unit_list: A list of String + * @li eltwise_mode: An optional string from "ADD", "SUB" and "". +*@par Outputs: + * output: A Tensor. A Tensor of type float16, bfloat16, float32, int32, int8, int4. +*/ +REG_OP(FixPipe) + .INPUT(x1, TensorType({DT_FLOAT16, DT_BF16, DT_FLOAT, DT_INT32})) + .OPTIONAL_INPUT(x2, TensorType({DT_FLOAT16, DT_INT8, DT_INT4})) + .OPTIONAL_INPUT(quant_scale_0, TensorType({DT_UINT64})) + .OPTIONAL_INPUT(relu_weight_0, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(clip_value_0, TensorType({DT_FLOAT16, DT_INT8, DT_INT4})) + .OPTIONAL_INPUT(quant_scale_1, TensorType({DT_UINT64})) + .OPTIONAL_INPUT(relu_weight_1, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(clip_value_1, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(anti_quant_scale, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(anti_quant_offset, TensorType({DT_INT8, DT_INT4})) + .OUTPUT(output, TensorType({DT_FLOAT16, DT_BF16, DT_FLOAT, DT_INT32, DT_INT8, DT_INT4})) + .REQUIRED_ATTR(fusion_op_list, ListString) + .REQUIRED_ATTR(unit_list, ListString) + .ATTR(eltwise_mode, String, "") + .OP_END_FACTORY_REG(FixPipe) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_detect_ops.h b/third_party/fwkacllib/inc/ops/nn_detect_ops.h index 108a20a7..2ccb184f 100644 --- a/third_party/fwkacllib/inc/ops/nn_detect_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_detect_ops.h @@ -1179,6 +1179,8 @@ REG_OP(SPP) * the index of the input feature map, "x1", "y1", "x2", or "y2" must be * greater than or equal to "0.0". * roi_max_num must be less than or equal to 6000 and must be divided by 16. +* The input data of the rois cannot exceed the width and height range of the x, +* otherwise, the accuracy of the output result may not be as expected. *@li roi_actual_num: A optional tensor of type int32, with shape [batch, 8], specifying * the number of ROIs per batch . \n @@ -2076,7 +2078,7 @@ REG_OP(GIoUGrad) * trans: An optional attr, true for 'xyxyt', false for 'xywht'. *@par Outputs: -* overlaps: A 3D Tensor of type float16 or float32 with shape [B, N, K]. +* overlaps: A 3D Tensor of type float32 with shape [B, N, K]. *@attention Constraints: * In each batch, the invalid box cannot appear before the valid box. @@ -2087,6 +2089,100 @@ REG_OP(RotatedOverlaps) .OUTPUT(overlaps, TensorType({DT_FLOAT})) .ATTR(trans, Bool, false) .OP_END_FACTORY_REG(RotatedOverlaps) + +/** +*@brief RotatedIou . \n + +*@par Inputs: +*@li boxes : data of grad increment, a 3D Tensor of type float32 with +* shape (B, 5, N). "N" indicates the number of boxes, and the value +* "5" refers to [x1, y1, x2, y2, theta] or [x, y, w, h, theta]. +*@li query_boxes: Bounding boxes, a 3D Tensor of type float32 with +* shape (B, 5, K). "K" indicates the number of boxes, and the value +* "5" refers to [x1, y1, x2, y2, theta] or [x, y, w, h, theta]. + +*@par Attributes: +*@li trans: An optional attr, true for 'xyxyt', false for 'xywht'. +*@li mode: An optional attr, a character string with the value range of ['iou', 'iof'], +* only support 'iou' now. +*@li is_cross: Cross calculation when it is True, and one-to-one calculation when it is False. +*@li v_threshold: An optional attr, provide condition relaxation for intersection calculation. +*@li e_threshold: An optional attr, provide condition relaxation for intersection calculation. + +*@par Outputs: +* iou: A 3D Tensor of float32 with shape [B, N, K]. + +*@attention Constraints: +* In each batch, the invalid box cannot appear before the valid box. +*/ +REG_OP(RotatedIou) + .INPUT(boxes, TensorType({DT_FLOAT})) + .INPUT(query_boxes, TensorType({DT_FLOAT})) + .OUTPUT(iou, TensorType({DT_FLOAT})) + .ATTR(trans, Bool, false) + .ATTR(mode, String, "iou") + .ATTR(is_cross, Bool, true) + .ATTR(v_threshold, Float, 0) + .ATTR(e_threshold, Float, 0) + .OP_END_FACTORY_REG(RotatedIou) + +/** +*@brief RotatedBoxEncode. \n + +*@par Inputs: +* Two inputs, including: +*@li anchor_box: A 3D Tensor of float32 (float16) with shape (B, 5, N). +* "B" indicates the number of batch size +* "N" indicates the number of bounding boxes, and the value "5" refers to +* "x0", "x1", "y0", "y1" and "angle". +*@li gt_box: A 3D Tensor of float32 (float16) with shape (B, 5, N). +* "B" indicates the number of batch size +* "N" indicates the number of bounding boxes, and the value "5" refers to +* "x0", "x1", "y0", "y1" and "angle". \n + +*@par Attributes: +*@li weight: A float list for "x0", "x1", "y0", "y1" and "angle", +* defaults to [1.0, 1.0, 1.0, 1.0, 1.0]. + +*@par Outputs: +*@li y: A 3D Tensor of type float32 (float16) with shape (B, 5, N), +* specifying the variations between all anchor boxes and ground truth boxes. +*/ +REG_OP(RotatedBoxEncode) + .INPUT(anchor_box, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(gt_box, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(weight, ListFloat, {1.0, 1.0, 1.0, 1.0, 1.0}) + .OP_END_FACTORY_REG(RotatedBoxEncode) + +/** +*@brief RotatedBoxDecode. \n + +*@par Inputs: +* Two inputs, including: +*@li anchor_box: A 3D Tensor of float32 (float16) with shape (B, 5, N). +* "B" indicates the number of batch size +* "N" indicates the number of bounding boxes, and the value "5" refers to +* "x0", "x1", "y0", "y1" and "angle". +*@li deltas: A 3D Tensor of float32 (float16) with shape (B, 5, N). +* "B" indicates the number of batch size +* "N" indicates the number of bounding boxes, and the value "5" refers to +* "x0", "x1", "y0", "y1" and "angle". \n + +*@par Attributes: +*@li weight: A float list for "x0", "x1", "y0", "y1" and "angle", +* defaults to [1.0, 1.0, 1.0, 1.0, 1.0]. + +*@par Outputs: +*@li y: A 3D Tensor of type float32 (float16) with shape (B, 5, N), +* specifying the variations between all anchor boxes and ground truth boxes. +*/ +REG_OP(RotatedBoxDecode) + .INPUT(anchor_box, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(deltas, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(weight, ListFloat, {1.0, 1.0, 1.0, 1.0, 1.0}) + .OP_END_FACTORY_REG(RotatedBoxDecode) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_DETECT_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index 9ce7abfd..38e513db 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -1487,25 +1487,51 @@ REG_OP(Roll) .OP_END_FACTORY_REG(Roll) /** - *@brief Calculate the loss. Creates a criterion that optimizes a two-class classification - logistic loss between input_x and input_y (containing 1 or -1). \n +* @brief Roll the tensor along the given dimension(s). - *@par Inputs: - *Tow inputs, including: +* @par Inputs: +* One inputs, including: +* x: A tensor + +* @par Attributes: +* @li shift: The number of places by which the elements of the tensor are shifted. \n +* @li axes: Axis along which to roll. \n + +* @par Outputs: +* y: A Tensor with the same type and shape of x's. \n + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Roll. \n +*/ +REG_OP(RollV2) + .INPUT(input, TensorType({DT_INT8,DT_UINT8,DT_INT16,DT_UINT16,DT_INT32,DT_INT64,DT_FLOAT16, \ + DT_FLOAT,DT_DOUBLE})) + .INPUT(shift, TensorType({DT_INT32,DT_INT64})) + .INPUT(axes, TensorType({DT_INT32,DT_INT64})) + .OUTPUT(output, TensorType({DT_INT8,DT_UINT8,DT_INT16,DT_UINT16,DT_INT32,DT_INT64,DT_FLOAT16, \ + DT_FLOAT,DT_DOUBLE})) + .OP_END_FACTORY_REG(RollV2) + +/** + * @brief Calculate the loss. Creates a criterion that optimizes a two-class classification + * logistic loss between input_x and input_y (containing 1 or -1). \n + + * @par Inputs: + * Tow inputs, including: * @li input_x: A tensor. Must be one of the following types: * float16, float32. \n * @li input_y: A tensor. Must be one of the following types: * float16, float32. \n - *@par Attributes: - *reduction: An optional string.Defaults to "mean". \n + * @par Attributes: + * reduction: An optional string.Defaults to "mean". \n - *@par Outputs: - *output_z: while reduction == "none", A Tensor with the same type and shape of input_x's. \n + * @par Outputs: + * output_z: while reduction == "none", A Tensor with the same type and shape of input_x's. \n * while reduction == "sum" or "mean", A Tensor with the same type of input_x , shape of which is (1,) - *@par Third-party framework compatibility - *Compatible with the Pytorch operator SoftMarginLoss. \n + * @par Third-party framework compatibility + * Compatible with the Pytorch operator SoftMarginLoss. \n */ REG_OP(SoftMarginLoss) .INPUT(input_x, TensorType({DT_FLOAT, DT_FLOAT16})) @@ -1624,18 +1650,18 @@ REG_OP(MultilabelMarginLoss) .OP_END_FACTORY_REG(MultilabelMarginLoss) /** -*@brief Performs batch normalization . \n -*@par Inputs: +* @brief Performs batch normalization . \n +* @par Inputs: * Two inputs -*@li input_x: A Tensor. Support float32. shape (n, c, d). -*@li seq_len: A Tensor. Each batch normalize data num. Support Int32. Shape (n, ). \n -*@par Attributes: -*@li normalize_type: Str. Support "per_feature" or "all_features". -*@li epsilon: An optional float32, specifying the small value added to -variance to avoid dividing by zero. Defaults to "0.00001" . \n -*@par Outputs: +* @li input_x: A Tensor. Support float32. shape (n, c, d). +* @li seq_len: A Tensor. Each batch normalize data num. Support Int32. Shape (n, ). \n +* @par Attributes: +* @li normalize_type: Str. Support "per_feature" or "all_features". +* @li epsilon: An optional float32, specifying the small value added to +* variance to avoid dividing by zero. Defaults to "0.00001" . \n +* @par Outputs: * One outputs -*@li output_y: A Tensor for the normalized "x".Support float32. shape (n, c, d).\n +* @li output_y: A Tensor for the normalized "x".Support float32. shape (n, c, d).\n */ REG_OP(NormalizeBatch) .INPUT(input_x, TensorType({ DT_FLOAT })) @@ -1644,6 +1670,36 @@ REG_OP(NormalizeBatch) .REQUIRED_ATTR(normalize_type, String) .ATTR(epsilon, Float, 0.00001) .OP_END_FACTORY_REG(NormalizeBatch) + +/** +*@brief GroupNorm and Reul operator +* calculating: x, gamma, beta +* y = relu(gamma*((x - mean) / np.sqrt(variance + 0.001)) + beta) + +* @par Inputs: +* Three inputs, including: +* @li x: A Tensor. Must be one of the following types: float16, float32. +* @li gamma: A Tensor. Must be one of the following types: float16, float32. +* @li beta: A Tensor. Must be one of the following types: float16, float32 . \n + +* @par Attributes: +* @li num_groups: A require attribute, the type is int32. +* @li eps: A optional attribute, the type is float32. Defaults to 0.00001. \n + +* @par Outputs: +* One outputs, including: +* @li y: A Tensor. Must be one of the following types: float16, float32. +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use/ +*/ +REG_OP(GroupNormRelu) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(gamma, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(beta, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .REQUIRED_ATTR(num_groups, Int) + .ATTR(eps, Float, 0.00001) + .OP_END_FACTORY_REG(GroupNormRelu) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_NORM_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h index ee599a76..1c689ee9 100644 --- a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h @@ -1747,7 +1747,8 @@ included in the sample.\n *@par Third-party framework compatibility *Compatible with the Pytorch operator SubSample. -*@par Restrictions: + +*@attention Constraints: *Warning: This operator can be integrated only by MaskRcnn. Please do not use it directly. */ REG_OP(SubSample) @@ -1776,7 +1777,8 @@ included in the sample.\n *@par Third-party framework compatibility *Compatible with the Pytorch operator SubSampleLabels. -*@par Restrictions: + +*@attention Constraints: *Warning: This operator can be integrated only by MaskRcnn. Please do not use it directly. */ REG_OP(SubSampleLabels) diff --git a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h index d5960395..fc61815e 100644 --- a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h +++ b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h @@ -25,7 +25,8 @@ namespace ge { /** -*@brief Computes the for the gelu of "x" . \n +*@brief The GELU activation function is x*Φ(x), +* where Φ(x) the standard Gaussian cumulative distribution function. \n *@par Inputs: *One input, including: @@ -144,7 +145,7 @@ REG_OP(GeluGrad) .OP_END_FACTORY_REG(GeluGrad) /** -*@brief Computes the for the fast_gelu of "x" . \n +*@brief The FastGelu activation function is x*e^(0.851*x)*(x-|x|)/(1+e^(-1.702|x|)). \n *@par Inputs: *One input, including: @@ -159,7 +160,23 @@ REG_OP(FastGelu) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .OP_END_FACTORY_REG(FastGelu) +/** +*@brief The FastGeluV2 activation function is x*(sgn(x)*[(a/2)*(clip(|x|,max=-b)+b)^2+0.5]+0.5), +* where sgn(x) function is (x+0.000000000001)/|(x+0.000000000001)|. \n + +*@par Inputs: +*One input, including: +*x: A Tensor. Must be one of the following types: float16, float32 +*@par Outputs: +*y: A Tensor. Has the same type as "x". +*@par Third-party framework compatibility +*Compatible with the TensorFlow operator FastGeluV2 +*/ +REG_OP(FastGeluV2) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(FastGeluV2) /** *@brief Computes the gradient for the fast_gelu of "x" . \n @@ -623,9 +640,7 @@ REG_OP(Elu) *x: A float16, float32, for the input data type . \n *@par Attributes: -*@li alpha1: A float32. Defines at which negative value the ELU saturates. Defaults to "1.0" . -*@li alpha2: A float32. Defines at which negative value the ELU saturates. Defaults to "1.0" . -*@li alpha3: A float32. Defines at which positive value the ELU saturates. Defaults to "1.0" . \n +*li alpha: A float32. Defines at which negative value the ELU saturates. Defaults to "1.0" . *@par Outputs: *y: A float16, float32, for the normalized result . \n @@ -641,9 +656,7 @@ REG_OP(Elu) REG_OP(Celu) .INPUT(x, TensorType({DT_FLOAT,DT_FLOAT16})) .OUTPUT(y, TensorType({DT_FLOAT,DT_FLOAT16})) - .ATTR(alpha1, Float, 1.0) - .ATTR(alpha2, Float, 1.0) - .ATTR(alpha3, Float, 1.0) + .ATTR(alpha, Float, 1.0) .OP_END_FACTORY_REG(Celu) /** diff --git a/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h b/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h index f36d2935..1bdfb2c7 100644 --- a/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h +++ b/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h @@ -117,6 +117,33 @@ REG_OP(NPUGetFloatStatus) .INPUT(addr, TensorType{DT_FLOAT}) .OUTPUT(data, TensorType({DT_FLOAT})) .OP_END_FACTORY_REG(NPUGetFloatStatus) + + +/** +*@brief Set the value of global workspace to 0. \n + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(NPUClearFloatStatusV2) + .OP_END_FACTORY_REG(NPUClearFloatStatusV2) + +/** +*@brief Set the value of global workspace to 0. \n + +*@par Inputs: +*addr: A nested structure of Tensors of type float32 . \n + +*@par Outputs: +*data: A Tensor of type float32. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(NPUGetFloatStatusV2) + .DYNAMIC_INPUT(addr, TensorType{DT_FLOAT}) + .OUTPUT(data, TensorType({DT_FLOAT})) + .OP_END_FACTORY_REG(NPUGetFloatStatusV2) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NPU_LOSS_SCALE_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/ocr_ops.h b/third_party/fwkacllib/inc/ops/ocr_ops.h index a5755659..efaa7aa7 100644 --- a/third_party/fwkacllib/inc/ops/ocr_ops.h +++ b/third_party/fwkacllib/inc/ops/ocr_ops.h @@ -81,6 +81,7 @@ REG_OP(OCRRecognitionPreHandle) .OUTPUT(imgs, TensorType({DT_UINT8})) .OUTPUT(imgs_relation, TensorType({DT_INT32})) .OUTPUT(imgs_lang, TensorType({DT_INT32})) + .OUTPUT(imgs_piece_fillers, TensorType({DT_INT32})) .ATTR(batch_size, Int, 8) .ATTR(data_format, String, "NHWC") .ATTR(pad_mode, String, "REPLICATE") diff --git a/third_party/fwkacllib/inc/ops/random_ops.h b/third_party/fwkacllib/inc/ops/random_ops.h index ad7f9003..57631d14 100644 --- a/third_party/fwkacllib/inc/ops/random_ops.h +++ b/third_party/fwkacllib/inc/ops/random_ops.h @@ -59,6 +59,65 @@ REG_OP(Multinomial) .ATTR(seed2, Int, 0) .OP_END_FACTORY_REG(Multinomial) +/** +*@brief Creates a multinomial distribution. \n + +*@par Inputs: +*Inputs include: +* @li q: A Tensor. Must be one of the following types: float, double. +1-D Tensor with shape [num_classes]. +* @li j: A Tensor. Must be one of the following types: int64. +1-D Tensor with shape [num_classes]. +* @li num_samples: A Tensor of type int32. 0-D. Number of independent samples to draw for each row slice . \n + +*@par Attributes: +*@li output_dtype: An optional type from: int32, int64. Defaults to int64. +*@li seed: An optional int. Defaults to 0. +*@li seed2: An optional int. Defaults to 0. \n + +*@par Outputs: +*y: A Tensor of type int32 or int64. \n + +*@attention Constraints: +*The implementation for MultinomialAliasDraw on Ascend uses AICPU, with bad performance. + +*@par Third-party framework compatibility +*@li compatible with torch _multinomial_alias_draw operator. +*/ +REG_OP(MultinomialAliasDraw) + .INPUT(q, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(j, TensorType({DT_INT64})) + .OUTPUT(y, TensorType({DT_INT64})) + .REQUIRED_ATTR(num_samples, Int) + .ATTR(seed, Int, 0) + .OP_END_FACTORY_REG(MultinomialAliasDraw) + +/** +*@brief Prepares for MultinomialAliasDraw to create a multinomial distribution. \n + +*@par Inputs: +*Inputs include: +* @li probs: A Tensor. Must be one of the following types: float, double. +1-D Tensor with shape [num_classes]. \n + +*@par Outputs: +*j: A Tensor. Must be one of the following types: int64. +1-D Tensor with shape [num_classes]. +*q: A Tensor. Must be one of the following types: float, double. +1-D Tensor with shape [num_classes]. \n + +*@attention Constraints: +*The implementation for MultinomialAliasSetup on Ascend uses AICPU, with bad performance. + +*@par Third-party framework compatibility +*@li compatible with torch _multinomial_alias_setup operator. +*/ +REG_OP(MultinomialAliasSetup) + .INPUT(probs, TensorType({DT_FLOAT, DT_DOUBLE})) + .OUTPUT(j, TensorType({DT_INT64})) + .OUTPUT(q, TensorType({DT_FLOAT, DT_DOUBLE})) + .OP_END_FACTORY_REG(MultinomialAliasSetup) + /** *@brief Outputs random values from a normal distribution . \n @@ -173,6 +232,27 @@ REG_OP(Randperm) .ATTR(dtype, Type, DT_INT64) .OP_END_FACTORY_REG(Randperm) +/** +*@brief Fills a tensor with elements drawn from the poisson distribution. \n + +*@par Inputs: +*x: A Tensor. Must be one of the following types: float16, float. \n + +*@par Attributes: +*@li seed: An optional int. Defaults to 0. \n + +*@par Outputs: +*y: A Tensor list with same type as "x" . \n + +*@par Third-party framework compatibility +*@ Compatible with the Pytorch operator Poisson. +*/ +REG_OP(Poisson) + .INPUT(x, TensorType({ DT_FLOAT16,DT_FLOAT })) + .OUTPUT(y, TensorType({ DT_FLOAT16,DT_FLOAT })) + .ATTR(seed, Int, 0) + .OP_END_FACTORY_REG(Poisson) + /** *@brief Outputs random values from the Poisson distribution(s) described by rate . \n @@ -446,6 +526,34 @@ REG_OP(DropOutGenMaskV3) .ATTR(seed2, Int, 0) .OP_END_FACTORY_REG(DropOutGenMaskV3) + +/** +*@brief Generate stateless random bit mask for dropout . \n + +*@par Inputs: +include: +*@li shape:The shape of the output tensor. +*@li prob:0-D. Number of bit 1 . \n +*@li seed:If either seed or seed2 are set to be non-zero, the random number +*generator is seeded by the given seed. Otherwise, it is seeded by a random seed. +*@li seed2:A second seed to avoid seed collision . \n + +*@par Outputs: +*y:Output (1-D) random number using uint data format . \n + +*@attention Constraints: +*The output is aligned with 128 bits + +*@see StatelessDropOutGenMask() +*/ +REG_OP(StatelessDropOutGenMask) + .INPUT(shape, TensorType({ DT_INT32, DT_INT64 })) + .INPUT(prob, TensorType({ DT_FLOAT16, DT_FLOAT })) + .INPUT(seed, TensorType({ DT_INT32, DT_INT64 })) + .INPUT(seed1, TensorType({ DT_INT32, DT_INT64 })) + .OUTPUT(y, TensorType({ DT_UINT8 })) + .OP_END_FACTORY_REG(StatelessDropOutGenMask) + /** *@brief Generates values in an interval . \n @@ -698,11 +806,62 @@ REG_OP(Uniform) *@attention Constraints: * Compatible with the Caffe operator ContinuationIndicator. */ - REG_OP(ContinuationIndicator) .REQUIRED_ATTR(time_step, Int) .REQUIRED_ATTR(batch_size, Int) .OUTPUT(y, TensorType({DT_FLOAT})) .OP_END_FACTORY_REG(ContinuationIndicator) + +/** +*@brief Outputs random values from the Exponential distribution(s) described by rate . \n + +*@par Inputs: +*Inputs include: +* @li x: A Tensor. Must be one of the following types: half, float32, float64. \n + +*@par Attributes: +*@li lambda: An optional float. Defaults to 1. +*@li seed: An optional int. Defaults to 0.The random number generator is seeded by the given seed. + Otherwise, it is seeded by a random seed. \n + +*@par Outputs: +*y: A Tensor of type dtype float16, float, double. \n + +*@attention Constraints: +*The implementation for Exponential on Ascend uses AICPU, with bad performance. + +*@par Third-party framework compatibility +*@li compatible with tensorflow Exponential operator. +*/ +REG_OP(Exponential) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .ATTR(lambda, Float, 1) + .ATTR(seed, Int, 0) + .OP_END_FACTORY_REG(Exponential) + +/** +*@brief Fills a tensor with elements drawn from the geometric distribution. \n + +*@par Inputs: +*x: A Tensor. Must be one of the following types: float16, float. \n + +*@par Attributes: +*@li p: The probability of experimental success in Bernoulli's experiment. +*@li seed: An optional int. Defaults to 0. \n + +*@par Outputs: +*y: A Tensor list with same type as "x" . \n + +*@par Third-party framework compatibility +*@ Compatible with the Pytorch operator Geometric. +*/ +REG_OP(Geometric) + .INPUT(x, TensorType({ DT_FLOAT16,DT_FLOAT })) + .OUTPUT(y, TensorType({ DT_FLOAT16,DT_FLOAT })) + .REQUIRED_ATTR(p, Float) + .ATTR(seed, Int, 0) + .OP_END_FACTORY_REG(Geometric) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_RANDOM_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/randomdsa_ops.h b/third_party/fwkacllib/inc/ops/randomdsa_ops.h new file mode 100644 index 00000000..4574bb5d --- /dev/null +++ b/third_party/fwkacllib/inc/ops/randomdsa_ops.h @@ -0,0 +1,139 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. + * + * 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. + */ + +/*! + * \file randomdsa_ops.h + * \brief + */ +#ifndef OPS_BUILT_IN_OP_PROTO_INC_RANDOMDSA_OPS_H_ +#define OPS_BUILT_IN_OP_PROTO_INC_RANDOMDSA_OPS_H_ + +#include +#include "graph/operator_reg.h" +#include "graph/operator.h" + +namespace ge { +/** +* @brief Generate DSA random bit mask for dropout. \n + +* @par Inputs: +include: +* @li count:The shape of the input tensor. +* @li seed:If seed is set to be non-zero, the random number +* generator is seeded by the given seed. Otherwise, it is seeded by a random seed +* @li dropout:0-D. Number of bit 1 . \n + +* @par Attributes: +* @li random_algorithm:The default value is "Philox". \n + +* @par Outputs: +* y:Output (1-D) random number using uint data format . \n + +* @see DSAGenBitMask() +*/ +REG_OP(DSAGenBitMask) + .INPUT(count, TensorType({DT_INT64})) + .INPUT(seed, TensorType({DT_UINT64})) + .INPUT(dropout, TensorType({DT_FLOAT16, DT_FLOAT, DT_BF16})) + .OUTPUT(out, TensorType({DT_UINT8})) + .ATTR(random_algorithm, String, "Philox") + .OP_END_FACTORY_REG(DSAGenBitMask) + +/** +* @brief Generate DSA truncatenormal data in random. \n + +* @par Inputs: +include: +* @li count: The shape of the input tensor. +* @li seed: If seed is set to be non-zero, the random number +* generator is seeded by the given seed. Otherwise, it is seeded by a random seed +* @li mean: A Tensor. Must be one of the following types: float16, float32, double +* @li stdev: A Tensor. Must be one of the following types: float16, float32, double. \n + +* @par Attributes: +* @li random_algorithm:The default value is "Philox". \n + +* @par Outputs: +* y:Output (1-D) random number using float and bf data format . \n + +* @see DSARandomTruncatedNormal() +*/ +REG_OP(DSARandomTruncatedNormal) + .INPUT(count, TensorType({DT_INT64})) + .INPUT(seed, TensorType({DT_UINT64})) + .INPUT(mean, TensorType({DT_FLOAT16, DT_FLOAT, DT_BF16})) + .INPUT(stdev, TensorType({DT_FLOAT16, DT_FLOAT, DT_BF16})) + .OUTPUT(out, TensorType({DT_FLOAT16, DT_FLOAT32, DT_BF16})) + .ATTR(random_algorithm, String, "Philox") + .OP_END_FACTORY_REG(DSARandomTruncatedNormal) + +/** +* @brief Generate DSA normal data in random. \n + +* @par Inputs: +include: +* @li count: The shape of the input tensor. +* @li seed: If seed is set to be non-zero, the random number +* generator is seeded by the given seed. Otherwise, it is seeded by a random seed +* @li mean: A Tensor. Must be one of the following types: float16, float32, double +* @li stdev: A Tensor. Must be one of the following types: float16, float32, double. \n + +* @par Attributes: +* @li random_algorithm:The default value is "Philox". \n + +* @par Outputs: +* y:Output (1-D) random number using float and bf data format . \n + +* @see DSARandomNormal() +*/ +REG_OP(DSARandomNormal) + .INPUT(count, TensorType({DT_INT64})) + .INPUT(seed, TensorType({DT_UINT64})) + .INPUT(mean, TensorType({DT_FLOAT16, DT_FLOAT, DT_BF16})) + .INPUT(stdev, TensorType({DT_FLOAT16, DT_FLOAT, DT_BF16})) + .OUTPUT(out, TensorType({DT_FLOAT16, DT_FLOAT32, DT_BF16})) + .ATTR(random_algorithm, String, "Philox") + .OP_END_FACTORY_REG(DSARandomNormal) + +/** +* @brief Generate DSA uniform data in random. \n + +* @par Inputs: +include: +* @li count: The shape of the input tensor. +* @li seed: If seed is set to be non-zero, the random number +* generator is seeded by the given seed. Otherwise, it is seeded by a random seed +* @li low: A Tensor. Must be one of the following types: int, float, bf +* @li high: A Tensor. Must be one of the following types: int, float, bf. \n + +* @par Attributes: +* @li random_algorithm:The default value is "Philox". \n + +* @par Outputs: +* y:Output (1-D) random number using float int and bf data format . \n + +* @see DSARandomUniform() +*/ +REG_OP(DSARandomUniform) + .INPUT(count, TensorType({DT_INT64})) + .INPUT(seed, TensorType({DT_UINT64})) + .INPUT(low, TensorType({DT_BF16, DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT64, DT_UINT32, DT_UINT64})) + .INPUT(high, TensorType({DT_BF16, DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT64, DT_UINT32, DT_UINT64})) + .OUTPUT(out, TensorType({DT_BF16, DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT64, DT_UINT32, DT_UINT64})) + .ATTR(random_algorithm, String, "Philox") + .OP_END_FACTORY_REG(DSARandomUniform) +} +#endif // OPS_BUILT_IN_OP_PROTO_INC_RANDOMDSA_OPS_H diff --git a/third_party/fwkacllib/inc/ops/reduce_ops.h b/third_party/fwkacllib/inc/ops/reduce_ops.h index fa572b66..6fa95abc 100644 --- a/third_party/fwkacllib/inc/ops/reduce_ops.h +++ b/third_party/fwkacllib/inc/ops/reduce_ops.h @@ -515,6 +515,34 @@ REG_OP(ReduceSumD) .ATTR(keep_dims, Bool, false) .OP_END_FACTORY_REG(ReduceSumD) +/** +*@brief Calculate the total mean based on the mean of each device . \n + +*@par Inputs: +* Three inputs, including: +*@li x: A Tensor. Must be one of the following types: float16, float32 . +*@li count: A Tensor. Must be one of the following types: float16, float32 . +*@li count_sum: A Tensor. Must be one of the following types: float16, float32 . \n + +*@par Attributes: +*@li axes: A required 1D list or tuple of int32 or int64. Specifies the dimensions to reduce. +*@li keepdims: An optional bool. If "true", retains reduced dimensions with length 1. Defaults to "false" . \n + +*@par Outputs: +*y: The reduced tensor. Has the same type and format as input "x" . \n + +*@par Third-party framework compatibility +* Compatible with the TensorFlow operator Sum. +*/ +REG_OP(ReduceMeanWithCount) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(count, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(count_sum, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .REQUIRED_ATTR(axes, ListInt) + .ATTR(keep_dims, Bool, false) + .OP_END_FACTORY_REG(ReduceMeanWithCount) + /** *@brief Calculates the "logical sum" of elements of a tensor in a dimension . \n @@ -1326,6 +1354,101 @@ REG_OP(ReduceMeanVariance) .ATTR(axes, ListInt, {}) .ATTR(keep_dims, Bool, true) .OP_END_FACTORY_REG(ReduceMeanVariance) + +/** +* @brief Calculates the standard deviation or the variance of Tensors with the average value. + +* @par Inputs: +* Two inputs, including: +* @li x: A Tensor. Must be one of the following types: float16, float32. \n +* @li mean: A Tensor. It's the mean of X. Has the same shape and type as "x" \n + +* @par Attributes: +* Four Attributes, including: +* @li dim: An listint. \n +* @li if_std: An optional bool. Defaults to "False" +* If "True", Calculate the standard deviation +* If "False", Calculate the variance +* @li unbiased: An optional bool. Defaults to "True". +* If "True", Use Bessel Correction. +* If "False", Do not use Bessel Correction. \n +* @li keepdim: An optional bool. Defaults to "False". +* If "True", Keep the original tensor dimension. +* If "False", Do not keep the original tensor dimension. \n + +* @par Outputs: +* @li output_var: A Tensor. It's the standard deviation or the variance of X. Has the same type as "x". + +* @par Third-party framework compatibility +* Compatible with the Pytorch operator Var_mean. +*/ +REG_OP(ReduceStdV2Update) + .INPUT(x, TensorType({DT_FLOAT,DT_FLOAT16})) + .INPUT(mean, TensorType({DT_FLOAT,DT_FLOAT16})) + .OUTPUT(output_var, TensorType({DT_FLOAT,DT_FLOAT16})) + .REQUIRED_ATTR(dim, ListInt) + .ATTR(if_std, Bool, false) + .ATTR(unbiased, Bool, true) + .ATTR(keepdim, Bool, false) + .OP_END_FACTORY_REG(ReduceStdV2Update) + +/** +*@brief Computes the log and sum and exp of elements across dimensions of a tensor. +* Reduces "x" along the dimensions given in "axes". +* Unless "keep_dims" is true, the rank of the tensor is reduced by 1 for each +* entry in "axes". If "keep_dims" is true, the reduced dimensions +* are retained with length 1. +* +*@par Inputs: +* Two inputs, including: +*@li x: A Tensor. Must be one of the following types: +* float32, float16, int32, int64, uint32, uint64, double +*@li axes: A 1D list or tuple of int32 or int64. Specifies the dimensions to reduce . \n +* +*@par Attributes: +*keep_dims: An optional bool. If "true", retains reduced dimensions with length 1. Defaults to "false" . \n +* +*@par Outputs: +*y: The reduced tensor. Has the same type and format as input "x" . \n +* +*@par Third-party framework compatibility +* Compatible with the Onnx operator ReduceLogSumExp. +*/ +REG_OP(ReduceLogSumExp) + .INPUT(x, TensorType::NumberType()) + .INPUT(axes, TensorType::IndexNumberType()) + .OUTPUT(y, TensorType::NumberType()) + .ATTR(keep_dims, Bool, false) + .OP_END_FACTORY_REG(ReduceLogSumExp) + +/** +*@brief Computes the log and sum of elements across dimensions of a tensor. +* Reduces "x" along the dimensions given in "axes". +* Unless "keep_dims" is true, the rank of the tensor is reduced by 1 for each +* entry in "axes". If "keep_dims" is true, the reduced dimensions +* are retained with length 1. +* +*@par Inputs: +* Two inputs, including: +*@li x: A Tensor. Must be one of the following types: +* float32, float16, int32, int64, uint32, uint64, double +*@li axes: A 1D list or tuple of int32 or int64. Specifies the dimensions to reduce . \n +* +*@par Attributes: +*keep_dims: An optional bool. If "true", retains reduced dimensions with length 1. Defaults to "false" . \n +* +*@par Outputs: +*y: The reduced tensor. Has the same type and format as input "x" . \n +* +*@par Third-party framework compatibility +* Compatible with the Onnx operator ReduceLogSum. +*/ +REG_OP(ReduceLogSum) + .INPUT(x, TensorType::NumberType()) + .INPUT(axes, TensorType::IndexNumberType()) + .OUTPUT(y, TensorType::NumberType()) + .ATTR(keep_dims, Bool, false) + .OP_END_FACTORY_REG(ReduceLogSum) } //namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_REDUCE_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/rnn.h b/third_party/fwkacllib/inc/ops/rnn.h index b374fa5c..43951402 100644 --- a/third_party/fwkacllib/inc/ops/rnn.h +++ b/third_party/fwkacllib/inc/ops/rnn.h @@ -1280,6 +1280,44 @@ REG_OP(EmbeddingBag) .ATTR(sparse, Bool, false) .ATTR(include_last_offset, Bool, false) .OP_END_FACTORY_REG(EmbeddingBag) +/** + * @brief:LSTMP calculation + * @par Inputs: + * eight inputs: + * @li x:A required Tensor(seq, batch, dim). Must be one of the following types: float16, float32. + * @li real_mask:A optional Tensor(seq, batch). Must be one of the following types: float16, float32. + * @li init_h:A optional Tensor(batch, state). Must be one of the following types: float16, float32. + * @li init_c:A optional Tensor(batch, hidden). Must be one of the following types: float16, float32. + * @li wx:A required Tensor(4*hidden, dim). Must be one of the following types: float16, float32. + * @li wr:A required Tensor(4*hidden, state). Must be one of the following types: float16, float32. + * @li bias:A optional Tensor(hidden). Must be one of the following types: float16, float32. The format must be ND. + * @li project: A optional Tensor. Must be one of the following types: float16, float32. + * + * @par Outputs: + *three outputs: + *@li y:A Tensor. Must be one of the following types: float16, float32. + *@li output_h:A Tensor. Must be one of the following types: float16, float32. + *@li output_c:A Tensor. Must be one of the following types: float16, float32. + * + *@par Attributes: + *time_major:An bool identifying the time major in the op. Default to false. + * @par Restrictions: + * Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(LSTMP) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(wx, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(bias, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(wr, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(project, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(real_mask, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(init_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(time_major, Bool, false) + .OP_END_FACTORY_REG(LSTMP) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_RNN_H_ diff --git a/third_party/fwkacllib/inc/ops/selection_ops.h b/third_party/fwkacllib/inc/ops/selection_ops.h index b09d08b0..2cc8fd1d 100644 --- a/third_party/fwkacllib/inc/ops/selection_ops.h +++ b/third_party/fwkacllib/inc/ops/selection_ops.h @@ -259,13 +259,39 @@ REG_OP(GatherV2D) *@par Third-party framework compatibility *Compatible with the PyTorch operator Gather. */ - REG_OP(GatherElements) - .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT64})) + .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT8,DT_INT16,DT_INT32, + DT_INT64,DT_UINT8,DT_UINT16,DT_UINT32,DT_UINT64})) + .INPUT(index, TensorType({DT_INT32,DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT16,DT_FLOAT,DT_INT8,DT_INT16,DT_INT32, + DT_INT64,DT_UINT8,DT_UINT16,DT_UINT32,DT_UINT64})) + .ATTR(dim, Int, 0) + .OP_END_FACTORY_REG(GatherElements) + +/** +*@Gathers values along an axis specified by dim . \n + +*@par Inputs: +*@li x: A Tensor. Must be one of the following types: float32, float64, int32, uint8, int16, int8, +* int64, uint16, float16, uint32, uint64, bool. +*@li dim: A Tensor. Must be one of the following types: int32, int64. +*@li index: A Tensor. Must be one of the following types: int32, int64 . \n + + +*@par Outputs: +* y: A Tensor. Has the same type as "x" . \n + +*@par Third-party framework compatibility +*Compatible with the PyTorch operator Gather. +*/ +REG_OP(GatherD) + .INPUT(x, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, DT_INT32, DT_UINT32 + DT_INT64, DT_UINT64, DT_BOOL, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(dim, TensorType({DT_INT32, DT_INT64})) .INPUT(index, TensorType({DT_INT32, DT_INT64})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT64})) .ATTR(dim, Int, 0) - .OP_END_FACTORY_REG(GatherElements) + .OP_END_FACTORY_REG(GatherD) /** *@brief Extracts a strided slice of a tensor. Roughly speaking, this op @@ -360,9 +386,9 @@ REG_OP(StridedSlice) * Warning: THIS FUNCTION IS DEPRECATED. Please use StridedSlice instead. */ REG_OP(StridedSliceD) - .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_UINT8, DT_INT8, + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT64, DT_UINT8, DT_INT8, DT_BOOL})) - .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_UINT8, DT_INT8, + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT64, DT_UINT8, DT_INT8, DT_BOOL})) .REQUIRED_ATTR(begin, ListInt) .REQUIRED_ATTR(end, ListInt) @@ -700,6 +726,27 @@ REG_OP(SegmentMax) .OUTPUT(y, TensorType::RealNumberType()) .OP_END_FACTORY_REG(SegmentMax) +/** +*@brief Computes the sum along segments of a tensor . \n + +*@par Inputs: +*Two inputs, including: +* @li x: A Tensor of type NumberType. +* @li segment_ids: A Tensor of type IndexNumberType, whose shape is a prefix +* of "x.shape". + +*@par Outputs: +*y: A Tensor of type NumberType . \n + +*@par Third-party framework compatibility +* Compatible with the TensorFlow operator SegmentSum. +*/ +REG_OP(SegmentSum) + .INPUT(x, TensorType::NumberType()) + .INPUT(segment_ids, TensorType::IndexNumberType()) + .OUTPUT(y, TensorType::NumberType()) + .OP_END_FACTORY_REG(SegmentSum) + /** *@brief: Computes the maximum along segments of a tensor. *Computes a tensor such that output[i]=(data[i]) where max is over j @@ -929,6 +976,49 @@ REG_OP(TopKD) * @brief Finds values and indices of the "k" largest elements for the last * dimension . \n +* @par Inputs: +* Two inputs, including: +* @li x: A 1D or higher tensor of type BasicType, with the last dimension +* at least "k". +* @li k: A 0D Tensor of type int32. +* Number of top elements to look for along the last dimension (along each row +* for matrices) . +* @li assist_seq: A 1D tensor of type float16. +* with size of 2N, which "N" is the last dimension. +* The first N numbers is indices, and the next N numbers is deviation of casting +* int32 to float16. \n + +* @par Attributes: +* @li sorted: An optional bool. Defaults to true. +* If true, the resulting "k" elements will be sorted by the values in descending +* order. +* @li dim: An optional int. Defaults to -1. For reserved use. +* @li largest: An optional bool. Defaults to true. For reserved use. \n + +* @par Outputs: +* @li values: A Tensor, specifying the sorted data. Has the same type as +* "input". +* @li indices: A Tensor of type int32, specifying the indices of sorted data . \n + +* @see TopK() +* @par Third-party framework compatibility +* @li Compatible with the TensorFlow operator TopKV2. +*/ +REG_OP(TopKV2D) + .INPUT(x, TensorType::RealNumberType()) + .INPUT(k, TensorType({DT_INT32})) + .INPUT(assist_seq, TensorType({DT_FLOAT16})) + .OUTPUT(values, TensorType::RealNumberType()) + .OUTPUT(indices, TensorType({DT_INT32})) + .ATTR(sorted, Bool, true) + .ATTR(dim, Int, -1) + .ATTR(largest, Bool, true) + .OP_END_FACTORY_REG(TopKV2D) + +/** +* @brief Finds values and indices of the "k" largest elements for the last +* dimension . \n + * @par Inputs: * Two inputs, including: * @li x: A 1D or higher tensor of type BasicType, with the last dimension @@ -2340,7 +2430,7 @@ REG_OP(AddRowRanges) *@par Outputs: *y: A ND Tensor of float32/float16/int32/int8 with shapes 1-D (D,), 2-D(N, D), 3-D(N, C, D) -* @par Restrictions: +*@attention Constraints: * Warning: input shape's length must not be bigger than 1024 * 1024 * 1024. */ REG_OP(MaskedFillRange) @@ -2442,6 +2532,34 @@ REG_OP(StridedSliceV3) .OPTIONAL_INPUT(strides, TensorType::IndexNumberType()) .OUTPUT(y, TensorType::BasicType()) .OP_END_FACTORY_REG(StridedSliceV3) + +/** +*@brief MovingSumWithSigmoid. + +*@par Inputs: +*Four inputs, including: +* @li alpha: A Tensor. Must be one of the following types: float32, float16. +* @li energy: A Tensor. Must be one of the following types: float32, float16. +* @li beam_size: A Tensor of type int32. +* @li frame_size: A Tensor of type int32. \n + +*@par Outputs: +* y: A Tensor. Has the same type as "alpha". \n +* +* @par Attributes: +* window_size: A int. +* +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(MovingSumWithSigmoid) + .INPUT(alpha, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(energy, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(beam_size, TensorType({DT_INT32})) + .INPUT(frame_size, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(window_size, Int) + .OP_END_FACTORY_REG(MovingSumWithSigmoid) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_SELECTION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/split_combination_ops.h b/third_party/fwkacllib/inc/ops/split_combination_ops.h index 08726080..7d181545 100644 --- a/third_party/fwkacllib/inc/ops/split_combination_ops.h +++ b/third_party/fwkacllib/inc/ops/split_combination_ops.h @@ -381,6 +381,30 @@ REG_OP(ConcatOffsetD) .REQUIRED_ATTR(concat_dim, Int) .REQUIRED_ATTR(N, Int) .OP_END_FACTORY_REG(ConcatOffsetD) + +/** +*@brief Compute combinations of length of the given tensor. \n + +*@par Inputs: +*x: A list of 1D Tensor objects. \n + +*@par Attributes: +*@li r: An optional int indicates number of elements to combine. Defaults to 2. +*@li with_replacement: An optional bool indicates whether to allow duplication +*in combination. Defaults to "False". \n + +*@par Outputs: +*y: A Tensor list with same type as "x" . \n + +*@par Third-party framework compatibility +*@ Compatible with the Pytorch operator Combinations. +*/ +REG_OP(Combinations) + .INPUT(x, TensorType::ALL()) + .OUTPUT(y, TensorType::ALL()) + .ATTR(r, Int, 2) + .ATTR(with_replacement, Bool, false) + .OP_END_FACTORY_REG(Combinations) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_SPLIT_COMBINATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/vector_search.h b/third_party/fwkacllib/inc/ops/vector_search.h index 1e8c574b..ab4daa70 100644 --- a/third_party/fwkacllib/inc/ops/vector_search.h +++ b/third_party/fwkacllib/inc/ops/vector_search.h @@ -1,5 +1,5 @@ /** - * Copyright 2021 Huawei Technologies Co., Ltd + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -154,43 +154,6 @@ REG_OP(CalcBucketsLimitAndOffset) .OUTPUT(buckets_offset, TensorType({DT_INT32, DT_INT64})) .REQUIRED_ATTR(total_limit, Int) .OP_END_FACTORY_REG(CalcBucketsLimitAndOffset) - -/** -* @brief Calculate ProdVirialSeA. \n -* -* @par Inputs: -* Five inputs, including: -* @li net_deriv: A Tensor. Must be one of the following types: float16, float32, float64. -* @li in_deriv: A Tensor. Must be one of the following types: float16, float32, float64. -* @li rij: A Tensor. Must be one of the following types: float16, float32, float64. -* @li nlist: A Tensor. dtype is int32. -* @li natoms: A Tensor. dtype is int32. \n -* -* @par Outputs: -* Two outputs, including: -* @li virial: A Tensor. Must be one of the following types: float16, float32, float64. -* @li atom_virial: A Tensor. Must be one of the following types: float16, float32, float64. \n -* -* @par Attributes: -* Two attributes, including: -* @li n_a_sel: A Scalar. -* @li n_r_sel: A Scalar. \n -* -* @par Restrictions: -* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. -*/ -REG_OP(ProdVirialSeA) - .INPUT(net_deriv, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) - .INPUT(in_deriv, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) - .INPUT(rij, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) - .INPUT(nlist, TensorType({DT_INT32})) - .INPUT(natoms, TensorType({DT_INT32})) - .OUTPUT(virial, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) - .OUTPUT(atom_virial, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) - .REQUIRED_ATTR(n_a_sel, Int) - .REQUIRED_ATTR(n_r_sel, Int) - .ATTR(nall, Int, 28328) - .OP_END_FACTORY_REG(ProdVirialSeA) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_VECTOR_SEARCH_H_ diff --git a/third_party/fwkacllib/inc/runtime/base.h b/third_party/fwkacllib/inc/runtime/base.h index aa98ed9a..c9779326 100644 --- a/third_party/fwkacllib/inc/runtime/base.h +++ b/third_party/fwkacllib/inc/runtime/base.h @@ -98,11 +98,11 @@ typedef struct rtExceptionInfo { uint32_t tid; uint32_t deviceid; uint32_t retcode; -} rtExceptionInfo; +} rtExceptionInfo_t; typedef void (*rtErrorCallback)(rtExceptionType); -typedef void (*rtTaskFailCallback)(rtExceptionInfo *exceptionInfo); +typedef void (*rtTaskFailCallback)(rtExceptionInfo_t *exceptionInfo); typedef void (*rtDeviceStateCallback)(uint32_t devId, bool isOpen); @@ -429,6 +429,15 @@ RTS_API rtError_t rtLabelCreateExV2(rtLabel_t *lbl, rtModel_t mdl, rtStream_t st * @return RT_ERROR_INVALID_VALUE for input null ptr */ RTS_API rtError_t rtGetTaskIdAndStreamID(uint32_t *taskId, uint32_t *streamId); + +/** + * @ingroup dvrt_base + * @brief get max model num + * @param [out] max model num + * @param [in] null + * @return RT_ERROR_NONE for ok + */ +RTS_API rtError_t rtGetMaxModelNum(uint32_t *maxModelCount); #if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/runtime/config.h b/third_party/fwkacllib/inc/runtime/config.h index c83c1521..3881ac5c 100644 --- a/third_party/fwkacllib/inc/runtime/config.h +++ b/third_party/fwkacllib/inc/runtime/config.h @@ -22,7 +22,8 @@ typedef enum tagRtArchType { ARCH_BEGIN = 0, ARCH_V100 = ARCH_BEGIN, ARCH_V200 = 1, - ARCH_END = 2, + ARCH_V300 = 2, + ARCH_END = 3, } rtArchType_t; typedef enum tagRtChipType { @@ -34,7 +35,8 @@ typedef enum tagRtChipType { CHIP_DC = 4, CHIP_CLOUD_V2 = 5, CHIP_NO_DEVICE = 6, - CHIP_END = 7, + CHIP_MINI_V3 = 7, + CHIP_END = 8, } rtChipType_t; typedef enum tagRtAicpuScheType { @@ -74,7 +76,8 @@ typedef enum tagRtPlatformType { PLATFORM_DC = 5, PLATFORM_CLOUD_V2 = 6, PLATFORM_LHISI_SD3403 = 7, - PLATFORM_END = 8, + PLATFORM_MINI_V3 = 8, + PLATFORM_END = 9, } rtPlatformType_t; typedef enum tagRtCubeFracMKNFp16 { @@ -140,6 +143,12 @@ typedef enum tagRTTaskTimeoutType { RT_TIMEOUT_TYPE_OP_EXECUTE, } rtTaskTimeoutType_t; +typedef enum tagRtFloatOverflowMode { + RT_OVERFLOW_MODE_SATURATION = 0, + RT_OVERFLOW_MODE_INFNAN, + RT_OVERFLOW_MODE_UNDEF, +} rtFloatOverflowMode_t; + /** * @ingroup * @brief get AI core count @@ -180,6 +189,15 @@ RTS_API rtError_t rtGetAiCoreMemoryRates(rtAiCoreMemoryRates_t *aiCoreMemoryRate */ RTS_API rtError_t rtGetMemoryConfig(rtMemoryConfig_t *memoryConfig); +/** + * @ingroup + * @brief get float overflow mode + * @param [out] floatOverflowMode + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtGetFloatOverflowMode(rtFloatOverflowMode_t * const floatOverflowMode); + /** * @ingroup * @brief get l2 buffer Info,virtual baseaddr,Size diff --git a/third_party/fwkacllib/inc/runtime/context.h b/third_party/fwkacllib/inc/runtime/context.h index e920a939..378470c7 100644 --- a/third_party/fwkacllib/inc/runtime/context.h +++ b/third_party/fwkacllib/inc/runtime/context.h @@ -140,7 +140,7 @@ RTS_API rtError_t rtSetGroup(int32_t groupId); * @param [in] groupid count * @return RT_ERROR_NONE for ok, errno for failed */ -RTS_API rtError_t rtGetGroupInfo(int32_t groupId, rtGroupInfo_t *groupInfo, uint32_t count); +RTS_API rtError_t rtGetGroupInfo(int32_t groupId, rtGroupInfo_t *groupInfo, uint32_t cnt); /** * @ingroup diff --git a/third_party/fwkacllib/inc/runtime/dev.h b/third_party/fwkacllib/inc/runtime/dev.h index e5b741c7..bce6625b 100644 --- a/third_party/fwkacllib/inc/runtime/dev.h +++ b/third_party/fwkacllib/inc/runtime/dev.h @@ -94,11 +94,11 @@ typedef enum tagGetDevMsgType { /** * @ingroup dvrt_dev * @brief get total device number. - * @param [in|out] count the device number + * @param [in|out] cnt the device number * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtGetDeviceCount(int32_t *count); +RTS_API rtError_t rtGetDeviceCount(int32_t *cnt); /** * @ingroup dvrt_dev * @brief get device ids @@ -338,7 +338,7 @@ RTS_API rtError_t rtSetTSDevice(uint32_t tsId); * @return RT_ERROR_NONE for ok * @return RT_ERROR_DRV_ERR for can not get run mode */ -RTS_API rtError_t rtGetRunMode(rtRunMode *mode); +RTS_API rtError_t rtGetRunMode(rtRunMode *runMode); /** * @ingroup dvrt_dev diff --git a/third_party/fwkacllib/inc/runtime/dvfsprofile.h b/third_party/fwkacllib/inc/runtime/dvfsprofile.h index 7cb8c8a6..2813d73b 100644 --- a/third_party/fwkacllib/inc/runtime/dvfsprofile.h +++ b/third_party/fwkacllib/inc/runtime/dvfsprofile.h @@ -23,11 +23,11 @@ typedef enum dvfsProfileMode { /** * @ingroup dvrt_dvfsprofile * @brief Set the performance mode of the device - * @param [in] mode dvfsProfileMode + * @param [in] profMode dvfsProfileMode * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtSetDvfsProfile(DvfsProfileMode mode); +RTS_API rtError_t rtSetDvfsProfile(DvfsProfileMode profMode); /** * @ingroup dvrt_dvfsprofile diff --git a/third_party/fwkacllib/inc/runtime/event.h b/third_party/fwkacllib/inc/runtime/event.h index 024ff3e3..6bd47992 100644 --- a/third_party/fwkacllib/inc/runtime/event.h +++ b/third_party/fwkacllib/inc/runtime/event.h @@ -19,6 +19,11 @@ typedef enum rtEventWaitStatus { EVENT_STATUS_MAX = 2, } rtEventWaitStatus_t; +typedef enum rtEventStatus { + RT_EVENT_INIT = 0, + RT_EVENT_RECORDED = 1, +} rtEventStatus_t; + /** * @ingroup event_flags * @brief event op bit flags @@ -115,6 +120,16 @@ RTS_API rtError_t rtEventQuery(rtEvent_t evt); */ RTS_API rtError_t rtEventQueryWaitStatus(rtEvent_t evt, rtEventWaitStatus_t *status); +/** + * @ingroup dvrt_event + * @brief Queries an event's status + * @param [in] evt event to query + * @param [in out] rtEventStatus_t status + * @return RT_EVENT_RECORDED for recorded + * @return RT_EVENT_INIT for not recorded + */ +RTS_API rtError_t rtEventQueryStatus(rtEvent_t evt, rtEventStatus_t *status); + /** * @ingroup dvrt_event * @brief computes the elapsed time between events. diff --git a/third_party/fwkacllib/inc/runtime/kernel.h b/third_party/fwkacllib/inc/runtime/kernel.h index 08860ccd..1c3f571b 100644 --- a/third_party/fwkacllib/inc/runtime/kernel.h +++ b/third_party/fwkacllib/inc/runtime/kernel.h @@ -287,13 +287,13 @@ RTS_API rtError_t rtDependencyRegister(void *mHandle, void *sHandle); * @param [in] binHandle device binary handle * @param [in] stubFunc stub function * @param [in] stubName stub function name - * @param [in] devFunc device function description. symbol name or address - * offset, depending binary type. + * @param [in] kernelInfoExt kernel Info extension. device function description or tiling key, + * depending static shape or dynmaic shape. * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtFunctionRegister(void *binHandle, const void *stubFunc, const char_t *stubName, - const void *devFunc, uint32_t funcMode); + const void *kernelInfoExt, uint32_t funcMode); /** * @ingroup rt_kernel @@ -354,7 +354,8 @@ RTS_API rtError_t rtKernelLaunch(const void *stubFunc, uint32_t blockDim, void * * @ingroup rt_kernel * @brief launch kernel with handle to device * @param [in] hdl program - * @param [in] devFunc device function description. + * @param [in] kernelInfoExt kernel Info extension. device function description or tiling key, + * depending static shape or dynmaic shape. * @param [in] blockDim block dimentions * @param [in] args argments address for kernel function * @param [in] argsSize argements size @@ -364,7 +365,7 @@ RTS_API rtError_t rtKernelLaunch(const void *stubFunc, uint32_t blockDim, void * * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtKernelLaunchWithHandle(void *hdl, const void *devFunc, uint32_t blockDim, +RTS_API rtError_t rtKernelLaunchWithHandle(void *hdl, const void *kernelInfoExt, uint32_t blockDim, void *args, uint32_t argsSize, rtSmDesc_t *smDesc, rtStream_t stream_, const void *kernelInfo); @@ -497,6 +498,28 @@ RTS_API rtError_t rtDumpAddrSet(rtModel_t mdl, void *addr, uint32_t dumpSize, ui */ RTS_API rtError_t rtDatadumpInfoLoad(const void *dumpInfo, uint32_t length); +/** + * @ingroup rt_kernel + * @brief launch npu get float status task + * @param [in] outputAddr pointer to op output addr + * @param [in] outputSize op output size + * @param [in] checkMode check mode + * @param [in] stm associated stream + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtNpuGetFloatStatus(void *outputAddr, uint64_t outputSize, uint32_t checkMode, rtStream_t stm); + +/** + * @ingroup rt_kernel + * @brief launch npu clear float status task + * @param [in] checkMode check mode + * @param [in] stm associated stream + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtNpuClearFloatStatus(uint32_t checkMode, rtStream_t stm); + #ifndef __CLANG_CCE_RUNTIME_H__ #define __CLANG_CCE_RUNTIME_H__ /** @@ -519,13 +542,13 @@ RTS_API rtError_t rtConfigureCall(uint32_t numBlocks, rtSmDesc_t *smDesc, rtStre /** * @ingroup rt_kernel * @brief setup argment for next rtLaunch in current thread - * @param [in] arg argment address for kernel function + * @param [in] args argment address for kernel function * @param [in] size argment size * @param [in] offset argment table offset * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtSetupArgument(const void *arg, uint32_t size, uint32_t offset); +RTS_API rtError_t rtSetupArgument(const void *args, uint32_t size, uint32_t offset); /** * @ingroup rt_kernel @@ -544,11 +567,11 @@ RTS_API rtError_t rtLaunch(const void *stubFunc); * @param [in] ptr host memory * @param [in] size host memory size * @param [in] flag reserved. set to 0 - * @param [out] arg returned arg. used for next kernel's arg. + * @param [out] args returned arg. used for next kernel's arg. * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtKernelConfigTransArg(const void *ptr, uint64_t size, uint32_t flag, void **arg); +RTS_API rtError_t rtKernelConfigTransArg(const void *ptr, uint64_t size, uint32_t flag, void **args); /** * @ingroup rt_kernel @@ -675,7 +698,8 @@ RTS_API rtError_t rtKernelLaunchWithTiling(const void *stubFunc, uint32_t blockD * @ingroup rt_kernel * @brief launch kernel with handle and tiling data to device * @param [in] hdl program - * @param [in] devFunc device function description. + * @param [in] kernelInfoExt kernel Info extension. device function description or tiling key, + * depending static shape or dynmaic shape. * @param [in] blockDim block dimentions * @param [in] argsInfo argments info address for kernel function * @param [in] smDesc shared memory description @@ -684,7 +708,7 @@ RTS_API rtError_t rtKernelLaunchWithTiling(const void *stubFunc, uint32_t blockD * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtKernelLaunchWithHandleAndTiling(void *hdl, const void *devFunc, uint32_t blockDim, +RTS_API rtError_t rtKernelLaunchWithHandleAndTiling(void *hdl, const void *kernelInfoExt, uint32_t blockDim, rtArgsWithTiling_t *argsInfo, rtSmDesc_t *smDesc, rtStream_t stm, const void* kernelInfo); #if defined(__cplusplus) diff --git a/third_party/fwkacllib/inc/runtime/mem.h b/third_party/fwkacllib/inc/runtime/mem.h index c086da10..7f3a4bc7 100644 --- a/third_party/fwkacllib/inc/runtime/mem.h +++ b/third_party/fwkacllib/inc/runtime/mem.h @@ -341,6 +341,20 @@ RTS_API rtError_t rtInvalidCache(void *base, size_t len); */ RTS_API rtError_t rtMemcpy(void *dst, uint64_t destMax, const void *src, uint64_t cnt, rtMemcpyKind_t kind); +/** + * @ingroup dvrt_mem + * @brief host task memcpy + * @param [in] dst destination address pointer + * @param [in] destMax length of destination address memory + * @param [in] src source address pointer + * @param [in] cnt the number of byte to copy + * @param [in] kind memcpy type + * @param [in] stm task stream + * @return RT_ERROR_NONE for ok, errno for failed + */ +RTS_API rtError_t rtMemcpyHostTask(void * const dst, const uint64_t destMax, const void * const src, + const uint64_t cnt, rtMemcpyKind_t kind, rtStream_t stm); + /** * @ingroup dvrt_mem * @brief asynchronized memcpy @@ -424,6 +438,16 @@ RTS_API rtError_t rtAiCoreMemorySizes(rtAiCoreMemorySize_t *aiCoreMemorySize); */ RTS_API rtError_t rtSetAiCoreMemorySizes(rtAiCoreMemorySize_t *aiCoreMemorySize); +/** + * @ingroup dvrt_mem + * @brief Specifies how memory is use + * @param [in] devPtr memory pointer + * @param [in] count memory count + * @param [in] advise reserved, set to 1 + * @return RT_ERROR_NONE for ok + * @return others for error + */ +RTS_API rtError_t rtMemAdvise(void *devPtr, uint64_t count, uint32_t advise); /** * @ingroup dvrt_mem * @brief set memory with uint32_t value diff --git a/third_party/fwkacllib/inc/runtime/rt_dfx.h b/third_party/fwkacllib/inc/runtime/rt_dfx.h index f96c0859..71215f80 100644 --- a/third_party/fwkacllib/inc/runtime/rt_dfx.h +++ b/third_party/fwkacllib/inc/runtime/rt_dfx.h @@ -28,6 +28,16 @@ extern "C" { */ RTS_API rtError_t rtSetTaskTag(const char_t *taskTag); +/** + * @brief set aicpu device attribute. + * it is used for aicpu device to be aware of enviroment config + * @param [in] key attrubute key. + * @param [in] val attrubute value. + * @return RT_ERROR_NONE for ok + * @return other failed + */ +RTS_API rtError_t rtSetAicpuAttr(const char_t *key, const char_t *val); + #if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h b/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h index 18b25d36..4978d5fa 100644 --- a/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h +++ b/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h @@ -25,7 +25,8 @@ typedef struct tagFftsPlusTaskInfo { #pragma pack(pop) -RTS_API rtError_t rtGetAddrAndPrefCntWithHandle(void *hdl, const void *devFunc, void **addr, uint32_t *prefetchCnt); +RTS_API rtError_t rtGetAddrAndPrefCntWithHandle(void *hdl, const void *kernelInfoExt, void **addr, + uint32_t *prefetchCnt); RTS_API rtError_t rtFftsPlusTaskLaunch(rtFftsPlusTaskInfo_t *fftsPlusTaskInfo, rtStream_t stm); diff --git a/third_party/fwkacllib/inc/runtime/rt_mem_queue.h b/third_party/fwkacllib/inc/runtime/rt_mem_queue.h index 49a272f0..2ed9fd08 100644 --- a/third_party/fwkacllib/inc/runtime/rt_mem_queue.h +++ b/third_party/fwkacllib/inc/runtime/rt_mem_queue.h @@ -184,6 +184,13 @@ typedef enum rtGroupType { RT_GRP_TYPE_BIND_DP_CPU_EXCLUSIVE /* Bound to a AICPU, intra-group threads are mutex awakened */ } rtGroupType_t; +typedef struct tagInitFlowGwInfo { + const char_t *groupName; + uint64_t schedPolicy; + uint64_t reschedInterval; + char_t rsv[128]; +} rtInitFlowGwInfo_t; + /** * @ingroup rt_mem_queue * @brief init queue schedule @@ -193,6 +200,15 @@ typedef enum rtGroupType { */ RTS_API rtError_t rtMemQueueInitQS(int32_t devId, const char_t *grpName); +/** + * @ingroup rt_mem_queue + * @brief init flow gateway + * @param [in] devId the logical device id + * @param [in] initInfo Initialization parameters + * @return RT_ERROR_NONE for ok + */ +RTS_API rtError_t rtMemQueueInitFlowGw(int32_t devId, const rtInitFlowGwInfo_t * const initInfo); + /** * @ingroup rt_mem_queue * @brief create mbuf queue @@ -222,24 +238,24 @@ RTS_API rtError_t rtMemQueueInit(int32_t devId); /** * @ingroup rt_mem_queue - * @brief enqueu mbuf + * @brief enqueue memBuf * @param [in] devId the logical device id * @param [in] qid queue id - * @param [in] mbuf enqueue mbuf + * @param [in] memBuf enqueue memBuf * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMemQueueEnQueue(int32_t devId, uint32_t qid, void *mbuf); +RTS_API rtError_t rtMemQueueEnQueue(int32_t devId, uint32_t qid, void *memBuf); /** * @ingroup rt_mem_queue - * @brief enqueu mbuf + * @brief dequeue memBuf * @param [in] devId the logical device id * @param [in] qid queue id - * @param [out] mbuf dequeue mbuf + * @param [out] memBuf dequeue memBuf * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMemQueueDeQueue(int32_t devId, uint32_t qid, void **mbuf); +RTS_API rtError_t rtMemQueueDeQueue(int32_t devId, uint32_t qid, void **memBuf); /** * @ingroup rt_mem_queue @@ -350,47 +366,56 @@ RTS_API rtError_t rtMbufInit(rtMemBuffCfg_t *cfg); /** * @ingroup rt_mem_queue * @brief alloc buff -* @param [out] buff: buff addr alloced +* @param [out] memBuf: buff addr alloced * @param [in] size: The amount of memory space requested * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMbufAlloc(rtMbufPtr_t *mbuf, uint64_t size); +RTS_API rtError_t rtMbufAlloc(rtMbufPtr_t *memBuf, uint64_t size); /** * @ingroup rt_mem_queue * @brief free buff -* @param [in] buff: buff addr to be freed +* @param [in] memBuf: buff addr to be freed * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMbufFree(rtMbufPtr_t mbuf); +RTS_API rtError_t rtMbufFree(rtMbufPtr_t memBuf); + +/** +* @ingroup rt_mem_queue +* @brief set Data len of Mbuf +* @param [in] memBuf: Mbuf addr +* @param [in] len: data len +* @return RT_ERROR_NONE for success, others for fail +*/ +RTS_API rtError_t rtMbufSetDataLen(rtMbufPtr_t memBuf, uint64_t len); /** * @ingroup rt_mem_queue * @brief get Data addr of Mbuf -* @param [in] mbuf: Mbuf addr +* @param [in] memBuf: Mbuf addr * @param [out] buf: Mbuf data addr * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMbufGetBuffAddr(rtMbufPtr_t mbuf, void **buf); +RTS_API rtError_t rtMbufGetBuffAddr(rtMbufPtr_t memBuf, void **buf); /** * @ingroup rt_mem_queue * @brief get total Buffer size of Mbuf -* @param [in] mbuf: Mbuf addr +* @param [in] memBuf: Mbuf addr * @param [out] totalSize: total buffer size of Mbuf * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMbufGetBuffSize(rtMbufPtr_t mbuf, uint64_t *totalSize); +RTS_API rtError_t rtMbufGetBuffSize(rtMbufPtr_t memBuf, uint64_t *totalSize); /** * @ingroup rt_mem_queue * @brief Get the address and length of its user_data from the specified Mbuf -* @param [in] mbuf: Mbuf addr +* @param [in] memBuf: Mbuf addr * @param [out] priv: address of its user_data * @param [out] size: length of its user_data * @return RT_ERROR_NONE for ok */ -RTS_API rtError_t rtMbufGetPrivInfo (rtMbufPtr_t mbuf, void **priv, uint64_t *size); +RTS_API rtError_t rtMbufGetPrivInfo(rtMbufPtr_t memBuf, void **priv, uint64_t *size); // mem group typedef struct { @@ -573,6 +598,14 @@ RTS_API rtError_t rtQueueSubF2NFEvent(int32_t devId, uint32_t qId, uint32_t grou */ RTS_API rtError_t rtQueueSubscribe(int32_t devId, uint32_t qId, uint32_t groupId, int32_t type); +/** +* @ingroup rtBufEventTrigger +* @brief buf event trigger +* @param [in] name, group name +* @return 0 for success, others for fail +*/ +RTS_API rtError_t rtBufEventTrigger(const char_t *name); + #if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/runtime/rt_model.h b/third_party/fwkacllib/inc/runtime/rt_model.h index 2807a705..f550887d 100644 --- a/third_party/fwkacllib/inc/runtime/rt_model.h +++ b/third_party/fwkacllib/inc/runtime/rt_model.h @@ -44,6 +44,11 @@ typedef enum tagModelTaskType { RT_MODEL_TASK_PROFILER_TRACE_EX, RT_MODEL_TASK_FFTS_TASK, RT_MODEL_TASK_FFTS_PLUS_TASK, + RT_MODEL_TASK_DSA_TASK, + RT_MODEL_TASK_CMO, + RT_MODEL_TASK_BARRIER, + RT_MODEL_TASK_NPU_GET_FLOAT_STATUS, + RT_MODEL_TASK_NPU_CLEAR_FLOAT_STATUS, } rtModelTaskType_t; typedef enum tagModelStreamType { @@ -115,9 +120,9 @@ typedef struct tagKernelTaskInfo { uint16_t argsCount; uint16_t argsSize; uint16_t reserved; - char_t *stubFunc; + const char_t *stubFunc; uint8_t *smDesc; - uint8_t *args; + const uint8_t *args; uint16_t *argsOffset; } rtKernelTaskInfo_t; @@ -126,17 +131,17 @@ typedef struct tagAllKernelTaskInfo { uint16_t argsCount; uint16_t argsSize; uint16_t reserved; - void *devfunc; + const void *kernelInfoExt; void *handle; uint8_t *smDesc; - uint8_t *args; + const uint8_t *args; uint16_t *argsOffset; } rtAllKernelTaskInfo_t; typedef struct tagKernelTaskInfoEx { uint32_t flags; uint32_t argsSize; - void *args; + const void *args; uint32_t reserved[6]; } rtKernelTaskInfoEx_t; @@ -198,9 +203,9 @@ typedef struct tagProfilerTraceExTaskInfo { } rtProfilerTraceEx_t; typedef struct tagrtMemcpyAsyncTaskInfo { - void *dst; + const void *dst; uint64_t destMax; - void *src; + const void *src; uint64_t count; uint32_t kind; uint32_t reserved; @@ -212,9 +217,9 @@ typedef struct tagrtNotifyTaskInfo { } rtNotifyTaskInfo_t; typedef struct tagrtReduceAsyncTaskInfo { - void *dst; + const void *dst; uint64_t destMax; - void *src; + const void *src; uint64_t count; uint32_t kind; uint32_t type; @@ -481,6 +486,16 @@ RTS_API rtError_t rtDebugRegister(rtModel_t mdl, uint32_t flag, const void *addr */ RTS_API rtError_t rtDebugUnRegister(rtModel_t mdl); +/** + * @ingroup rt_model + * @brief set model group id + * @param [in] mdl model + * @param [in] schGrpId groupId (0,4) 0:default invalid value 1-4 valid value Maximum support 4 groups + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtModelSetSchGroupId(rtModel_t mdl, const int16_t schGrpId); + #if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/runtime/rt_stars.h b/third_party/fwkacllib/inc/runtime/rt_stars.h index a9c91897..b778550f 100644 --- a/third_party/fwkacllib/inc/runtime/rt_stars.h +++ b/third_party/fwkacllib/inc/runtime/rt_stars.h @@ -7,7 +7,7 @@ #define CCE_RUNTIME_RT_STARS_H #include "base.h" - +#include "rt_stars_define.h" #if defined(__cplusplus) extern "C" { #endif @@ -80,6 +80,25 @@ RTS_API rtError_t rtCdqEnQueue(const char_t *queName, uint32_t cdqeIndex, void * RTS_API rtError_t rtCdqEnQueuePtrMode(const char_t *queName, uint32_t cdqeIndex, const void *ptrAddr, rtStream_t stm); +/** + * @ingroup rt_stars + * @brief launch common cmo task on the stream. + * @param [in] taskInfo cmo task info + * @param [in] stm launch task on the stream + * @param [in] flag flag + * @return RT_ERROR_NONE for ok, others failed + */ +RTS_API rtError_t rtCmoTaskLaunch(rtCmoTaskInfo_t *taskInfo, rtStream_t stm, uint32_t flag); + +/** + * @ingroup rt_stars + * @brief launch barrier cmo task on the stream. + * @param [in] taskInfo barrier task info + * @param [in] stm launch task on the stream + * @param [in] flag flag + * @return RT_ERROR_NONE for ok, others failed + */ +RTS_API rtError_t rtBarrierTaskLaunch(rtBarrierTaskInfo_t *taskInfo, rtStream_t stm, uint32_t flag); #if defined(__cplusplus) } diff --git a/third_party/fwkacllib/inc/runtime/rt_stars_define.h b/third_party/fwkacllib/inc/runtime/rt_stars_define.h index 260809af..4920ef00 100644 --- a/third_party/fwkacllib/inc/runtime/rt_stars_define.h +++ b/third_party/fwkacllib/inc/runtime/rt_stars_define.h @@ -32,6 +32,37 @@ typedef struct tagStarsSqeHeader { uint16_t taskId; } rtStarsSqeHeader_t; +typedef struct tagStarsDsaSqe { + // 0-7 bytes + rtStarsSqeHeader_t sqeHeader; + // 8-11 bytes + uint32_t start : 1; + uint32_t functionType : 3; + uint32_t dataType : 3; + uint32_t algoType : 3; + uint32_t paramVldBitmap : 5; + uint32_t paramAddrValBitmap : 7; + uint32_t reserved0 : 10; + // 12-15 bytes + uint16_t sqeIndex; + uint8_t kernelCredit; + uint8_t reserved1; + // 16-31 bytes + uint32_t dsaCfgResultAddrLow; + uint32_t dsaCfgResultAddrHigh; + uint32_t dsaCfgStateAddrLow; + uint32_t dsaCfgStateAddrHigh; + // 32-47 bytes + uint32_t dsaCfgParamAddrLow; + uint32_t dsaCfgParamAddrHigh; + uint32_t dsaCfgSeedLow; + uint32_t dsaCfgSeedHigh; + // 48-63 bytes + uint32_t dsaCfgNumberLow; + uint32_t dsaCfgNumberHigh; + uint32_t reserved2[2]; +} rtStarsDsaSqe_t; + // ffts+ type typedef enum tagFftsPlusType { RT_FFTS_PLUS_TYPE_RES1 = 2, // Reserved @@ -83,6 +114,33 @@ typedef struct tagFftsPlusSqe { uint32_t reserved16[4]; } rtFftsPlusSqe_t; +typedef struct tagCmoTaskInfo { + uint8_t qos; + uint8_t partId; + uint8_t pmg; + uint8_t reserved; + uint16_t cmoType; + uint16_t opCode; + uint16_t numInner; + uint16_t numOuter; + uint32_t logicId; + uint32_t lengthInner; + uint64_t sourceAddr; + uint32_t striderOuter; + uint32_t striderInner; +} rtCmoTaskInfo_t; + +typedef struct tagBarrierCmoInfo { + uint16_t cmoType; // 0 is barrier, 1 is invalid, Prefetch is 2, Write_back is 3, FE/GE only use invalid type. + uint32_t logicId; +} rtBarrierCmoInfo_t; + +#define RT_CMO_MAX_BARRIER_NUM 6U // 6U is max support +typedef struct tagBarrierTaskInfo { + uint8_t logicIdNum; + rtBarrierCmoInfo_t cmoInfo[RT_CMO_MAX_BARRIER_NUM]; +} rtBarrierTaskInfo_t; + #pragma pack(pop) #if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) diff --git a/third_party/fwkacllib/inc/tdt/data_common.h b/third_party/fwkacllib/inc/tdt/data_common.h index 7b1d631b..a9b347c4 100644 --- a/third_party/fwkacllib/inc/tdt/data_common.h +++ b/third_party/fwkacllib/inc/tdt/data_common.h @@ -1,21 +1,14 @@ /** - * Copyright 2019-2020 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. - */ +* @file data_common.h +* +* Copyright (C) Huawei Technologies Co., Ltd. 2019-2020. All Rights Reserved. +* +* This program is used to data structure +*/ #ifndef HOST_INNER_INC_DATA_COMMON_H_ #define HOST_INNER_INC_DATA_COMMON_H_ +#include namespace tdt { #ifndef TDT_DATA_TYPE diff --git a/third_party/fwkacllib/inc/tdt/index_transform.h b/third_party/fwkacllib/inc/tdt/index_transform.h index a62e0185..a5af2c83 100644 --- a/third_party/fwkacllib/inc/tdt/index_transform.h +++ b/third_party/fwkacllib/inc/tdt/index_transform.h @@ -1,18 +1,10 @@ /** - * Copyright 2019-2020 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. - */ +* @file index_transform.h +* +* Copyright (C) Huawei Technologies Co., Ltd. 2018-2019. All Rights Reserved. +* +* This program is used to get logical device id by phy device id. +*/ #ifndef INC_TDT_INDEX_TRANSFORM_H #define INC_TDT_INDEX_TRANSFORM_H diff --git a/third_party/fwkacllib/inc/tdt/status.h b/third_party/fwkacllib/inc/tdt/status.h index dc9e670f..b78eee75 100644 --- a/third_party/fwkacllib/inc/tdt/status.h +++ b/third_party/fwkacllib/inc/tdt/status.h @@ -1,18 +1,10 @@ -/** - * Copyright 2019-2020 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. - */ +/** +* @file status.h +* +* Copyright (C) Huawei Technologies Co., Ltd. 2019-2020. All Rights Reserved. +* +* This program is used to describe status +*/ #ifndef INC_TDT_STATUS_H_ #define INC_TDT_STATUS_H_ diff --git a/third_party/fwkacllib/inc/tdt/tdt_host_interface.h b/third_party/fwkacllib/inc/tdt/tdt_host_interface.h index 3e7d11ee..ea23211c 100644 --- a/third_party/fwkacllib/inc/tdt/tdt_host_interface.h +++ b/third_party/fwkacllib/inc/tdt/tdt_host_interface.h @@ -1,18 +1,10 @@ /** - * Copyright 2019-2020 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. - */ +* @file tdt_host_interface.h +* +* Copyright (C) Huawei Technologies Co., Ltd. 2019-2020. All Rights Reserved. +* +* This program is used to host server +*/ #ifndef HOST_INNER_INC_TDT_HOST_INTERFACE_H_ #define HOST_INNER_INC_TDT_HOST_INTERFACE_H_ diff --git a/third_party/fwkacllib/inc/tdt/tsd_client.h b/third_party/fwkacllib/inc/tdt/tsd_client.h index 36fc500e..406ab1c3 100644 --- a/third_party/fwkacllib/inc/tdt/tsd_client.h +++ b/third_party/fwkacllib/inc/tdt/tsd_client.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright (c) Hisilicon Technologies Co., Ltd. 2018-2021. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,17 +14,22 @@ * limitations under the License. */ -#ifndef TDT_HOST_INNER_INC_TSD_CLIENT_H_ -#define TDT_HOST_INNER_INC_TSD_CLIENT_H_ +#ifndef TDT_HOST_INNER_INC_TSD_CLIENT_H +#define TDT_HOST_INNER_INC_TSD_CLIENT_H #include #include #include #include -#include "tdt/status.h" -#include "tdt/data_common.h" +#include "tsd/status.h" #include "toolchain/prof_callback.h" +#ifdef WIN_TSD +#define TDT_LIB_EXPORT __declspec(dllexport) +#else +#define TDT_LIB_EXPORT __attribute__((visibility("default"))) +#endif + #ifdef __cplusplus extern "C" { #endif // __cplusplus @@ -50,7 +55,51 @@ extern "C" { * @li tsd_client.h: Header file where the interface declaration is located. * @li data_common.h: Header file where 'TDT_StatusT' defined */ -TDT_LIB_EXPORT TDT_StatusT TsdOpen(const uint32_t logicDeviceId, const uint32_t rankSize); +TDT_LIB_EXPORT uint32_t TsdOpen(const uint32_t logicDeviceId, const uint32_t rankSize); + +/** +* @ingroup Open +* @brief Used for the Framework process to communicate with the TSDDaemon process in 1981, +* and notify TSD to complete the initialization of other processes +* +* @par Function +* Used for the Framework process to communicate with the TSDDaemon process, +* and notify TSD to complete the initialization of other processes +* +* @param logicDeviceId [IN] type #unsigned int. Logic device ID +* @param rankSize [IN] type #unsigned int. The rankSize of the training. +* The default value is 1. When rankSize is greater than 1, +* HCCP will be pulled to perform set communication related operations. +* @param deviceMode [IN] type unsigned int. The device running mode of aicpuSd, +* it include chipMode and DieMode +* @retval TDT_OK Success +* @retval OtherValues Failure +* +* @par Dependency +* @li data_common.h: Header file where 'TDT_StatusT' defined +*/ +TDT_LIB_EXPORT uint32_t TsdOpenEx(const uint32_t logicDeviceId, const uint32_t rankSize, const uint32_t deviceMode); + +/** +* @ingroup InitialQs +* @brief Used for the Framework process to communicate with the TSDDaemon process, +* and notify TSD to complete the initialization of QS processes +* +* @par Function +* Used for the Framework process to communicate with the TSDDaemon process, +* and notify TSD to complete the initialization of other processes +* +* @param logicDeviceId [IN] type #unsigned int. Logic device ID +* @param groupName [IN] type #char pointer. qs group name send by host process +* @retval TDT_OK Success +* @retval OtherValues Failure +* +* @par Dependency +* @li libtsdclient.so: Library to which the interface belongs. +* @li tsd_client.h: Header file where the interface declaration is located. +* @li data_common.h: Header file where 'TDT_StatusT' defined +*/ +TDT_LIB_EXPORT uint32_t TsdInitQs(const uint32_t logicDeviceId, const char_t * const groupName = nullptr); /** * @ingroup Close @@ -64,11 +113,12 @@ TDT_LIB_EXPORT TDT_StatusT TsdOpen(const uint32_t logicDeviceId, const uint32_t * @retval OtherValues Failure * * @par Dependency + * @li libtsdclient.so: Library to which the interface belongs. * @li tsd_client.h: Header file where the interface declaration is located. * @li data_common.h: Header file where 'TDT_StatusT' defined */ -TDT_LIB_EXPORT TDT_StatusT TsdClose(const uint32_t logicDeviceId); +TDT_LIB_EXPORT uint32_t TsdClose(const uint32_t logicDeviceId); /** * @ingroup UpdateProfilingMode @@ -86,7 +136,7 @@ TDT_LIB_EXPORT TDT_StatusT TsdClose(const uint32_t logicDeviceId); * @li tsd_client.h: Header file where the interface declaration is located. * @li data_common.h: Header file where 'TDT_StatusT' defined */ -TDT_LIB_EXPORT TDT_StatusT UpdateProfilingMode(const uint32_t logicDeviceId, const uint32_t flag); +TDT_LIB_EXPORT uint32_t UpdateProfilingMode(const uint32_t logicDeviceId, const uint32_t flag); /** * @ingroup TsdSetMsprofReporterCallback @@ -105,9 +155,22 @@ TDT_LIB_EXPORT TDT_StatusT UpdateProfilingMode(const uint32_t logicDeviceId, con * @li data_common.h: Header file where 'TDT_StatusT' defined * @li prof_callback.h: Headerfile where 'MsprofReporterCallback' defined */ -TDT_LIB_EXPORT TDT_StatusT TsdSetMsprofReporterCallback(MsprofReporterCallback callback); +TDT_LIB_EXPORT uint32_t TsdSetMsprofReporterCallback(const MsprofReporterCallback callback); +/** +* @ingroup TsdSetAttr +* @brief used to set tsd attr +* +* @par key +* key set for tsd attr,now only support RunMode +* +* @par value +* value set to run correspond mode, PROCESS_MODE or THREAD_MODE +* @retval TDT_OK Success +* @retval OtherValues Failure +*/ +TDT_LIB_EXPORT uint32_t TsdSetAttr(const char * const attrKey, const char * const attrValue); #ifdef __cplusplus } #endif // __cplusplus -#endif // TDT_HOST_INNER_INC_TSD_CLIENT_H_ +#endif // TDT_HOST_INNER_INC_TSD_CLIENT_H diff --git a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h index 8ecd5f14..15baae46 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h +++ b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h @@ -1,17 +1,8 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. + * Description: handle perf data + * Author: xp + * Create: 2019-10-13 */ #ifndef MSPROFILER_API_PROF_ACL_API_H_ @@ -25,6 +16,8 @@ #define PROF_L2CACHE 0x00000010ULL #define PROF_HCCL_TRACE 0x00000020ULL #define PROF_TRAINING_TRACE 0x00000040ULL +#define PROF_MSPROFTX 0x00000080ULL +#define PROF_RUNTIME_API 0x00000100ULL // system profilinig switch #define PROF_CPU 0x00010000ULL @@ -36,17 +29,18 @@ #define PROF_AIVECTORCORE_SAMPLE 0x00400000ULL #define PROF_MODEL_EXECUTE 0x0000001000000ULL -#define PROF_RUNTIME_API 0x0000002000000ULL #define PROF_RUNTIME_TRACE 0x0000004000000ULL #define PROF_SCHEDULE_TIMELINE 0x0000008000000ULL #define PROF_SCHEDULE_TRACE 0x0000010000000ULL #define PROF_AIVECTORCORE_METRICS 0x0000020000000ULL #define PROF_SUBTASK_TIME 0x0000040000000ULL - -#define PROF_TASK_TRACE 0x0000005000062ULL +#define PROF_OP_DETAIL 0x0000080000000ULL #define PROF_MODEL_LOAD 0x8000000000000000ULL +#define PROF_TASK_TRACE (PROF_MODEL_EXECUTE | PROF_RUNTIME_TRACE | PROF_TRAINING_TRACE | \ + PROF_HCCL_TRACE | PROF_TASK_TIME) + // DataTypeConfig MASK #define PROF_ACL_API_MASK 0x00000001ULL #define PROF_TASK_TIME_MASK 0x00000002ULL @@ -55,6 +49,8 @@ #define PROF_L2CACHE_MASK 0x00000010ULL #define PROF_HCCL_TRACE_MASK 0x00000020ULL #define PROF_TRAINING_TRACE_MASK 0x00000040ULL +#define PROF_MSPROFTX_MASK 0x00000080ULL +#define PROF_RUNTIME_API_MASK 0x00000100ULL // system profilinig mask #define PROF_CPU_MASK 0x00010000ULL @@ -66,12 +62,12 @@ #define PROF_AIVECTORCORE_SAMPLE_MASK 0x00400000ULL #define PROF_MODEL_EXECUTE_MASK 0x0000001000000ULL -#define PROF_RUNTIME_API_MASK 0x0000002000000ULL #define PROF_RUNTIME_TRACE_MASK 0x0000004000000ULL #define PROF_SCHEDULE_TIMELINE_MASK 0x0000008000000ULL #define PROF_SCHEDULE_TRACE_MASK 0x0000010000000ULL #define PROF_AIVECTORCORE_METRICS_MASK 0x0000020000000ULL #define PROF_SUBTASK_TIME_MASK 0x0000040000000ULL +#define PROF_OP_DETAIL_MASK 0x0000080000000ULL #define PROF_MODEL_LOAD_MASK 0x8000000000000000ULL @@ -104,7 +100,7 @@ extern "C" { MSVP_PROF_API uint64_t ProfGetOpExecutionTime(const void *data, uint32_t len, uint32_t index); -typedef int32_t Status; +typedef in32_t Status; typedef struct aclprofSubscribeConfig aclprofSubscribeConfig1; /// /// @ingroup AscendCL @@ -135,6 +131,33 @@ MSVP_PROF_API Status aclgrphProfGraphUnSubscribe(const uint32_t graphId); * @retval 0 for failed */ MSVP_PROF_API size_t aclprofGetGraphId(const void *opInfo, size_t opInfoLen, uint32_t index); + +/** +* @ingroup AscendCL +* @brief set stamp pay load +* +* +* @retval void +*/ +MSVP_PROF_API int aclprofSetStampPayload(void *stamp, const int32_t type, void *value); + +/** +* @ingroup AscendCL +* @brief set category and name +* +* +* @retval void +*/ +MSVP_PROF_API int aclprofSetCategoryName(uint32_t category, const char *categoryName); + +/** +* @ingroup AscendCL +* @brief set category to stamp +* +* +* @retval void +*/ +MSVP_PROF_API int aclprofSetStampCategory(void *stamp, uint32_t category); #ifdef __cplusplus } #endif diff --git a/third_party/fwkacllib/inc/toolchain/prof_callback.h b/third_party/fwkacllib/inc/toolchain/prof_callback.h index 5f5a151b..24101aad 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_callback.h +++ b/third_party/fwkacllib/inc/toolchain/prof_callback.h @@ -1,17 +1,8 @@ -/** - * Copyright 2019-2020 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. +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. + * Description: handle perf data + * Author: xp + * Create: 2019-10-13 */ #ifndef MSPROFILER_PROF_CALLBACK_H_ @@ -76,7 +67,8 @@ enum MsprofReporterModuleId { MSPROF_MODULE_HCCL, // HCCL MSPROF_MODULE_ACL, // AclModule MSPROF_MODULE_FRAMEWORK, // Framework - MSPROF_MODULE_RUNTIME // runtime + MSPROF_MODULE_RUNTIME, // runtime + MSPROF_MODULE_MSPROF // msprofTx }; /** @@ -119,7 +111,7 @@ struct MsprofGeOptions { */ enum MsprofCtrlCallbackType { MSPROF_CTRL_INIT_ACL_ENV = 0, // start profiling with acl env - MSPROF_CTRL_INIT_ACL_JSON, // start profiling with acl.json + MSPROF_CTRL_INIT_ACL_JSON, // start pro with acl.json MSPROF_CTRL_INIT_GE_OPTIONS, // start profiling with ge env and options MSPROF_CTRL_FINALIZE, // stop profiling MSPROF_CTRL_INIT_DYNA = 0xFF, // start profiling for dynamic profiling diff --git a/third_party/fwkacllib/inc/toolchain/prof_common.h b/third_party/fwkacllib/inc/toolchain/prof_common.h new file mode 100644 index 00000000..bc56fb7d --- /dev/null +++ b/third_party/fwkacllib/inc/toolchain/prof_common.h @@ -0,0 +1,449 @@ +/* + * Copyright (c) Huawei Technologies Co., Ltd. 2019-2021. All rights reserved. + * Description: handle perf data + * Author: Huawei Technologies Co., Ltd. + * Create: 2019-10-13 + */ +#ifndef MSPROFILER_PROF_COMMON_H_ +#define MSPROFILER_PROF_COMMON_H_ + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +#include + +#define MSPROF_DATA_HEAD_MAGIC_NUM 0x5a5a + +enum MsprofDataTag { + MSPROF_ACL_DATA_TAG = 0, //acl data tag, range: 0~19 + MSPROF_GE_DATA_TAG_MODEL_LOAD = 20, //ge data tag, range: 20~39 + MSPROF_GE_DATA_TAG_FUSION = 21, + MSPROF_GE_DATA_TAG_INFER = 22, + MSPROF_GE_DATA_TAG_TASK = 23, + MSPROF_GE_DATA_TAG_TENSOR = 24, + MSPROF_GE_DATA_TAG_STEP = 25, + MSPROF_GE_DATA_TAG_ID_MAP = 26, + MSPROF_GE_DATA_TAG_HOST_SCH = 27, + MSPROF_RUNTIME_DATA_TAG_API = 40, //runtime data tag, range: 40~59 + MSPROF_RUNTIME_DATA_TAG_TRACK = 41, + MSPROF_AICPU_DATA_TAG = 60, //aicpu data tag, range: 60~79 + MSPROF_HCCL_DATA_TAG = 80, //hccl data tag, range: 80~99 + MSPROF_DP_DATA_TAG = 100, //dp data tag, range: 100~119 + MSPROF_MSPROFTX_DATA_TAG = 120, //hccl data tag, range: 120~139 + MSPROF_DATA_TAG_MAX = 65536, //data tag value type is uint16_t +}; + +/** + * @brief struct of mixed data + */ +#define MSPROF_MIX_DATA_RESERVE_BYTES 7 +#define MSPROF_MIX_DATA_STRING_LEN 120 +enum MsprofMixDataType { + MSPROF_MIX_DATA_HASH_ID = 0, + MSPROF_MIX_DATA_STRING, +}; +struct MsprofMixData { + uint8_t type; // MsprofMixDataType + uint8_t rsv[MSPROF_MIX_DATA_RESERVE_BYTES]; + union { + uint64_t hashId; + char dataStr[MSPROF_MIX_DATA_STRING_LEN]; + } data; +}; + +/** + * @brief profiling command info + */ +#define MSPROF_MAX_DEV_NUM 64 +struct MsprofCommandHandle { + uint64_t profSwitch; + uint64_t profSwitchHi; + uint32_t devNums; + uint32_t devIdList[MSPROF_MAX_DEV_NUM]; + uint32_t modelId; + uint32_t type; +}; + +/** + * @brief struct of data reported by acl + */ +#define MSPROF_ACL_DATA_RESERVE_BYTES 32 +#define MSPROF_ACL_API_NAME_LEN 64 +enum MsprofAclApiType { + MSPROF_ACL_API_TYPE_OP = 1, + MSPROF_ACL_API_TYPE_MODEL, + MSPROF_ACL_API_TYPE_RUNTIME, + MSPROF_ACL_API_TYPE_OTHERS, +}; +struct MsprofAclProfData { + uint16_t magicNumber = MSPROF_DATA_HEAD_MAGIC_NUM; + uint16_t dataTag = MSPROF_ACL_DATA_TAG; + uint32_t apiType; // enum MsprofAclApiType + uint64_t beginTime; + uint64_t endTime; + uint32_t processId; + uint32_t threadId; + char apiName[MSPROF_ACL_API_NAME_LEN]; + uint8_t reserve[MSPROF_ACL_DATA_RESERVE_BYTES]; +}; + +/** + * @brief struct of data reported by GE + */ +#define MSPROF_GE_MODELLOAD_DATA_RESERVE_BYTES 104 +struct MsprofGeProfModelLoadData { + uint16_t magicNumber = MSPROF_DATA_HEAD_MAGIC_NUM; + uint16_t dataTag = MSPROF_GE_DATA_TAG_MODEL_LOAD; + uint32_t modelId; + MsprofMixData modelName; + uint64_t startTime; + uint64_t endTime; + uint8_t reserve[MSPROF_GE_MODELLOAD_DATA_RESERVE_BYTES]; +}; + +#define MSPROF_GE_FUSION_DATA_RESERVE_BYTES 8 +#define MSPROF_GE_FUSION_OP_NUM 8 +struct MsprofGeProfFusionData { + uint16_t magicNumber = MSPROF_DATA_HEAD_MAGIC_NUM; + uint16_t dataTag = MSPROF_GE_DATA_TAG_FUSION; + uint32_t modelId; + MsprofMixData fusionName; + uint64_t inputMemSize; + uint64_t outputMemSize; + uint64_t weightMemSize; + uint64_t workspaceMemSize; + uint64_t totalMemSize; + uint64_t fusionOpNum; + uint64_t fusionOp[MSPROF_GE_FUSION_OP_NUM]; + uint8_t reserve[MSPROF_GE_FUSION_DATA_RESERVE_BYTES]; +}; + +#define MSPROF_GE_INFER_DATA_RESERVE_BYTES 64 +struct MsprofGeProfInferData { + uint16_t magicNumber = MSPROF_DATA_HEAD_MAGIC_NUM; + uint16_t dataTag = MSPROF_GE_DATA_TAG_INFER; + uint32_t modelId; + MsprofMixData modelName; + uint32_t requestId; + uint32_t threadId; + uint64_t inputDataStartTime; + uint64_t inputDataEndTime; + uint64_t inferStartTime; + uint64_t inferEndTime; + uint64_t outputDataStartTime; + uint64_t outputDataEndTime; + uint8_t reserve[MSPROF_GE_INFER_DATA_RESERVE_BYTES]; +}; + +#define MSPROF_GE_TASK_DATA_RESERVE_BYTES 16 +#define MSPROF_GE_OP_TYPE_LEN 56 +enum MsprofGeTaskType { + MSPROF_GE_TASK_TYPE_AI_CORE = 0, + MSPROF_GE_TASK_TYPE_AI_CPU, + MSPROF_GE_TASK_TYPE_AIV, +}; +enum MsprofGeShapeType { + MSPROF_GE_SHAPE_TYPE_STATIC = 0, + MSPROF_GE_SHAPE_TYPE_DYNAMIC, +}; +struct MsprofGeOpType { + uint8_t type; // MsprofMixDataType + uint8_t rsv[MSPROF_MIX_DATA_RESERVE_BYTES]; + union { + uint64_t hashId; + char dataStr[MSPROF_GE_OP_TYPE_LEN]; + } data; +}; +struct MsprofGeProfTaskData { + uint16_t magicNumber = MSPROF_DATA_HEAD_MAGIC_NUM; + uint16_t dataTag = MSPROF_GE_DATA_TAG_TASK; + uint32_t taskType; // MsprofGeTaskType + MsprofMixData opName; + MsprofGeOpType opType; + uint64_t curIterNum; + uint64_t timeStamp; + uint32_t shapeType; // MsprofGeShapeType + uint32_t blockDims; + uint32_t modelId; + uint32_t streamId; + uint32_t taskId; + uint32_t threadId; + uint8_t reserve[MSPROF_GE_TASK_DATA_RESERVE_BYTES]; +}; + +#define MSPROF_GE_TENSOR_DATA_RESERVE_BYTES 8 +#define MSPROF_GE_TENSOR_DATA_SHAPE_LEN 8 +#define MSPROF_GE_TENSOR_DATA_NUM 5 +enum MsprofGeTensorType { + MSPROF_GE_TENSOR_TYPE_INPUT = 0, + MSPROF_GE_TENSOR_TYPE_OUTPUT, +}; +struct MsprofGeTensorData { + uint32_t tensorType; // MsprofGeTensorType + uint32_t format; + uint32_t dataType; + uint32_t shape[MSPROF_GE_TENSOR_DATA_SHAPE_LEN]; +}; + +struct MsprofGeProfTensorData { + uint16_t magicNumber = MSPROF_DATA_HEAD_MAGIC_NUM; + uint16_t dataTag = MSPROF_GE_DATA_TAG_TENSOR; + uint32_t modelId; + uint64_t curIterNum; + uint32_t streamId; + uint32_t taskId; + uint32_t tensorNum; + MsprofGeTensorData tensorData[MSPROF_GE_TENSOR_DATA_NUM]; + uint8_t reserve[MSPROF_GE_TENSOR_DATA_RESERVE_BYTES]; +}; + +#define MSPROF_GE_STEP_DATA_RESERVE_BYTES 27 +enum MsprofGeStepTag { + MSPROF_GE_STEP_TAG_BEGIN = 0, + MSPROF_GE_STEP_TAG_END, +}; +struct MsprofGeProfStepData { + uint16_t magicNumber = MSPROF_DATA_HEAD_MAGIC_NUM; + uint16_t dataTag = MSPROF_GE_DATA_TAG_STEP; + uint32_t modelId; + uint32_t streamId; + uint32_t taskId; + uint64_t timeStamp; + uint64_t curIterNum; + uint32_t threadId; + uint8_t tag; // MsprofGeStepTag + uint8_t reserve[MSPROF_GE_STEP_DATA_RESERVE_BYTES]; +}; + +#define MSPROF_GE_ID_MAP_DATA_RESERVE_BYTES 6 +struct MsprofGeProfIdMapData { + uint16_t magicNumber = MSPROF_DATA_HEAD_MAGIC_NUM; + uint16_t dataTag = MSPROF_GE_DATA_TAG_ID_MAP; + uint32_t graphId; + uint32_t modelId; + uint32_t sessionId; + uint64_t timeStamp; + uint16_t mode; + uint8_t reserve[MSPROF_GE_ID_MAP_DATA_RESERVE_BYTES]; +}; + +#define MSPROF_GE_HOST_SCH_DATA_RESERVE_BYTES 24 +struct MsprofGeProfHostSchData { + uint16_t magicNumber = MSPROF_DATA_HEAD_MAGIC_NUM; + uint16_t dataTag = MSPROF_GE_DATA_TAG_HOST_SCH; + uint32_t threadId; // record in start event + uint64_t element; + uint64_t event; + uint64_t startTime; // record in start event + uint64_t endTime; // record in end event + uint8_t reserve[MSPROF_GE_HOST_SCH_DATA_RESERVE_BYTES]; +}; + +/** + * @brief struct of data reported by RunTime + */ +#define MSPROF_RUNTIME_API_DATA_RESERVE_BYTES 106 +#define MSPROF_RUNTIME_TASK_ID_NUM 10 +#define MSPROF_RUNTIME_API_NAME_LEN 64 +struct MsprofRuntimeProfApiData { + uint16_t magicNumber = MSPROF_DATA_HEAD_MAGIC_NUM; + uint16_t dataTag = MSPROF_RUNTIME_DATA_TAG_API; + uint32_t threadId; + uint64_t entryTime; + uint64_t exitTime; + uint64_t dataSize; + uint8_t apiName[MSPROF_RUNTIME_API_NAME_LEN]; + uint32_t retCode; + uint32_t streamId; + uint32_t taskNum; + uint32_t taskId[MSPROF_RUNTIME_TASK_ID_NUM]; + uint16_t memcpyDirection; + uint8_t reserve[MSPROF_RUNTIME_API_DATA_RESERVE_BYTES]; +}; + +#define MSPROF_RUNTIME_TRACK_DATA_RESERVE_BYTES 10 +#define MSPROF_RUNTIME_TRACK_TASK_TYPE_LEN 32 +struct MsprofRuntimeProfTrackData { + uint16_t magicNumber = MSPROF_DATA_HEAD_MAGIC_NUM; + uint16_t dataTag = MSPROF_RUNTIME_DATA_TAG_TRACK; + uint32_t threadId; + uint64_t timeStamp; + char taskType[MSPROF_RUNTIME_TRACK_TASK_TYPE_LEN]; + uint32_t taskId; + uint16_t streamId; + uint8_t reserve[MSPROF_RUNTIME_TRACK_DATA_RESERVE_BYTES]; +}; + +/** + * @brief struct of data reported by RunTime + */ +#define MSPROF_AICPU_DATA_RESERVE_BYTES 9 +struct MsprofAicpuProfData { + uint16_t magicNumber = MSPROF_DATA_HEAD_MAGIC_NUM; + uint16_t dataTag = MSPROF_AICPU_DATA_TAG; + uint16_t streamId; + uint16_t taskId; + uint64_t runStartTime; + uint64_t runStartTick; + uint64_t computeStartTime; + uint64_t memcpyStartTime; + uint64_t memcpyEndTime; + uint64_t runEndTime; + uint64_t runEndTick; + uint32_t threadId; + uint32_t deviceId; + uint64_t submitTick; + uint64_t scheduleTick; + uint64_t tickBeforeRun; + uint64_t tickAfterRun; + uint32_t kernelType; + uint32_t dispatchTime; + uint32_t totalTime; + uint16_t fftsThreadId; + uint8_t version; + uint8_t reserve[MSPROF_AICPU_DATA_RESERVE_BYTES]; +}; + +/** + * @brief struct of data reported by DP + */ +#define MSPROF_DP_DATA_RESERVE_BYTES 16 +#define MSPROF_DP_DATA_ACTION_LEN 16 +#define MSPROF_DP_DATA_SOURCE_LEN 64 +struct MsprofDpProfData { + uint16_t magicNumber = MSPROF_DATA_HEAD_MAGIC_NUM; + uint16_t dataTag = MSPROF_DP_DATA_TAG; + uint32_t rsv; // Ensure 8-byte alignment + uint64_t timeStamp; + char action[MSPROF_DP_DATA_ACTION_LEN]; + char source[MSPROF_DP_DATA_SOURCE_LEN]; + uint64_t index; + uint64_t size; + uint8_t reserve[MSPROF_DP_DATA_RESERVE_BYTES]; +}; + +/** + * @brief struct of data reported by HCCL + */ +#pragma pack(4) +struct MsprofHcclProfNotify { + uint32_t taskID; + uint64_t notifyID; + uint32_t stage; + uint32_t remoteRank; + uint32_t transportType; + uint32_t role; // role {0: dst, 1:src} + double durationEstimated; +}; + +struct MsprofHcclProfReduce { + uint32_t taskID; + uint64_t src; + uint64_t dst; + uint64_t size; + uint32_t op; // {0: sum, 1: mul, 2: max, 3: min} + uint32_t dataType; // data type {0: INT8, 1: INT16, 2: INT32, 3: FP16, 4:FP32, 5:INT64, 6:UINT64} + uint32_t linkType; // link type {0: 'OnChip', 1: 'HCCS', 2: 'PCIe', 3: 'RoCE'} + uint32_t remoteRank; + uint32_t transportType; // transport type {0: SDMA, 1: RDMA, 2:LOCAL} + uint32_t role; // role {0: dst, 1:src} + double durationEstimated; +}; + +struct MsprofHcclProfRDMA { + uint32_t taskID; + uint64_t src; + uint64_t dst; + uint64_t size; + uint64_t notifyID; + uint32_t linkType; // link type {0: 'OnChip', 1: 'HCCS', 2: 'PCIe', 3: 'RoCE'} + uint32_t remoteRank; + uint32_t transportType; // transport type {0: RDMA, 1:SDMA, 2:LOCAL} + uint32_t role; // role {0: dst, 1:src} + uint32_t type; // RDMA type {0: RDMASendNotify, 1:RDMASendPayload} + double durationEstimated; +}; + +struct MsprofHcclProfMemcpy { + uint32_t taskID; + uint64_t src; + uint64_t dst; + uint64_t size; + uint64_t notifyID; + uint32_t linkType; // link type {0: 'OnChip', 1: 'HCCS', 2: 'PCIe', 3: 'RoCE'} + uint32_t remoteRank; + uint32_t transportType; // transport type {0: RDMA, 1:SDMA, 2:LOCAL} + uint32_t role; // role {0: dst, 1:src} + double durationEstimated; +}; + +struct MsprofHcclProfStageStep { + uint32_t rank; + uint32_t rankSize; +}; + +struct MsprofHcclProfFlag { + uint64_t cclTag; + uint64_t groupName; + uint32_t localRank; + uint32_t workFlowMode; +}; + +/** + * @name MsprofHcclProfData + * @brief struct of data reported by hccl + */ +struct MsprofHcclProfData { + uint16_t magicNumber = MSPROF_DATA_HEAD_MAGIC_NUM; + uint16_t dataTag = MSPROF_HCCL_DATA_TAG; + uint32_t planeID; + uint32_t deviceID; + uint32_t streamID; + double ts; + char name[16]; + union { + MsprofHcclProfNotify notify; + MsprofHcclProfReduce reduce; + MsprofHcclProfStageStep stageStep; + MsprofHcclProfMemcpy forMemcpy; + MsprofHcclProfRDMA RDMA; + MsprofHcclProfFlag flag; + } args; +}; +#pragma pack() + +/** + * @name MsprofStampInfo + * @brief struct of data reported by msproftx + */ +struct MsprofStampInfo { + uint16_t magicNumber; + uint16_t dataTag; + uint32_t processId; + uint32_t threadId; + uint32_t category; //marker category + uint32_t eventType; + int32_t payloadType; + union PayloadValue //payload info for marker + { + uint64_t ullValue; + int64_t llValue; + double dValue; + uint32_t uiValue[2]; + int32_t iValue[2]; + float fValue[2]; + } payload; + uint64_t startTime; + uint64_t endTime; + int32_t messageType; + char message[128]; + uint8_t reserve0[4]; + uint8_t reserve1[72]; +}; + +#ifdef __cplusplus +} +#endif + +#endif // MSPROFILER_PROF_COMMON_H_ diff --git a/third_party/fwkacllib/inc/toolchain/slog.h b/third_party/fwkacllib/inc/toolchain/slog.h index a4680efe..48c753ce 100644 --- a/third_party/fwkacllib/inc/toolchain/slog.h +++ b/third_party/fwkacllib/inc/toolchain/slog.h @@ -111,14 +111,14 @@ extern "C" { #define OPERATION_LOG_MASK (0x10000000) #define RESERVERD_LENGTH 52 -typedef struct tagDCODE { - const char *cName; - int cVal; +typedef struct { + const char *cName; + int cVal; } DCODE; typedef struct tagKV { - char *kname; - char *value; + char *kname; + char *value; } KeyValue; typedef enum { @@ -139,73 +139,74 @@ typedef struct { * module id */ enum { - SLOG, /**< Slog */ - IDEDD, /**< IDE daemon device */ - IDEDH, /**< IDE daemon host */ - HCCL, /**< HCCL */ - FMK, /**< Adapter */ - HIAIENGINE, /**< Matrix */ - DVPP, /**< DVPP */ - RUNTIME, /**< Runtime */ - CCE, /**< CCE */ + SLOG, /**< Slog */ + IDEDD, /**< IDE daemon device */ + IDEDH, /**< IDE daemon host */ + HCCL, /**< HCCL */ + FMK, /**< Adapter */ + HIAIENGINE, /**< Matrix */ + DVPP, /**< DVPP */ + RUNTIME, /**< Runtime */ + CCE, /**< CCE */ #if (OS_TYPE == LINUX) HDC, /**< HDC */ #else HDCL, #endif // OS_TYPE - DRV, /**< Driver */ - MDCFUSION, /**< Mdc fusion */ - MDCLOCATION, /**< Mdc location */ - MDCPERCEPTION, /**< Mdc perception */ - MDCFSM, - MDCCOMMON, - MDCMONITOR, - MDCBSWP, /**< MDC base software platform */ - MDCDEFAULT, /**< MDC undefine */ - MDCSC, /**< MDC spatial cognition */ - MDCPNC, - MLL, /**< abandon */ - DEVMM, /**< Dlog memory managent */ - KERNEL, /**< Kernel */ - LIBMEDIA, /**< Libmedia */ - CCECPU, /**< aicpu shedule */ - ASCENDDK, /**< AscendDK */ - ROS, /**< ROS */ - HCCP, - ROCE, - TEFUSION, - PROFILING, /**< Profiling */ - DP, /**< Data Preprocess */ - APP, /**< User Application */ - TS, /**< TS module */ - TSDUMP, /**< TSDUMP module */ - AICPU, /**< AICPU module */ - LP, /**< LP module */ - TDT, /**< tsdaemon or aicpu shedule */ - FE, - MD, - MB, - ME, - IMU, - IMP, - GE, /**< Fmk */ - MDCFUSA, - CAMERA, - ASCENDCL, - TEEOS, - ISP, - SIS, - HSM, - DSS, - PROCMGR, // Process Manager, Base Platform - BBOX, - AIVECTOR, - TBE, - FV, - MDCMAP, - TUNE, - HSS, /**< helper */ - INVLID_MOUDLE_ID + DRV, /**< Driver */ + MDCFUSION, /**< Mdc fusion */ + MDCLOCATION, /**< Mdc location */ + MDCPERCEPTION, /**< Mdc perception */ + MDCFSM, + MDCCOMMON, + MDCMONITOR, + MDCBSWP, /**< MDC base software platform */ + MDCDEFAULT, /**< MDC undefine */ + MDCSC, /**< MDC spatial cognition */ + MDCPNC, + MLL, /**< abandon */ + DEVMM, /**< Dlog memory managent */ + KERNEL, /**< Kernel */ + LIBMEDIA, /**< Libmedia */ + CCECPU, /**< aicpu shedule */ + ASCENDDK, /**< AscendDK */ + ROS, /**< ROS */ + HCCP, + ROCE, + TEFUSION, + PROFILING, /**< Profiling */ + DP, /**< Data Preprocess */ + APP, /**< User Application */ + TS, /**< TS module */ + TSDUMP, /**< TSDUMP module */ + AICPU, /**< AICPU module */ + LP, /**< LP module */ + TDT, /**< tsdaemon or aicpu shedule */ + FE, + MD, + MB, + ME, + IMU, + IMP, + GE, /**< Fmk */ + MDCFUSA, + CAMERA, + ASCENDCL, + TEEOS, + ISP, + SIS, + HSM, + DSS, + PROCMGR, // Process Manager, Base Platform + BBOX, + AIVECTOR, + TBE, + FV, + MDCMAP, + TUNE, + HSS, /**< helper */ + FFTS, + INVLID_MOUDLE_ID }; /** @@ -262,9 +263,9 @@ DLL_EXPORT int DlogSetAttr(LogAttr logAttr); * @param [in]fmt: log content */ #define dlog_error(moduleId, fmt, ...) \ - do { \ - DlogErrorInner(moduleId, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ - } while (TMP_LOG != 0) + do { \ + DlogErrorInner(moduleId, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ + } while (TMP_LOG != 0) /** * @ingroup slog @@ -275,11 +276,11 @@ DLL_EXPORT int DlogSetAttr(LogAttr logAttr); * @param [in]fmt: log content */ #define dlog_warn(moduleId, fmt, ...) \ - do { \ - if(CheckLogLevel(moduleId, DLOG_WARN) == 1) { \ - DlogWarnInner(moduleId, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ - } \ - } while (TMP_LOG != 0) + do { \ + if (CheckLogLevel(moduleId, DLOG_WARN) == 1) { \ + DlogWarnInner(moduleId, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ + } \ + } while (TMP_LOG != 0) /** * @ingroup slog @@ -290,11 +291,11 @@ DLL_EXPORT int DlogSetAttr(LogAttr logAttr); * @param [in]fmt: log content */ #define dlog_info(moduleId, fmt, ...) \ - do { \ - if(CheckLogLevel(moduleId, DLOG_INFO) == 1) { \ - DlogInfoInner(moduleId, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ - } \ - } while (TMP_LOG != 0) + do { \ + if (CheckLogLevel(moduleId, DLOG_INFO) == 1) { \ + DlogInfoInner(moduleId, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ + } \ + } while (TMP_LOG != 0) /** * @ingroup slog @@ -305,11 +306,11 @@ DLL_EXPORT int DlogSetAttr(LogAttr logAttr); * @param [in]fmt: log content */ #define dlog_debug(moduleId, fmt, ...) \ - do { \ - if(CheckLogLevel(moduleId, DLOG_DEBUG) == 1) { \ - DlogDebugInner(moduleId, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ - } \ - } while (TMP_LOG != 0) + do { \ + if (CheckLogLevel(moduleId, DLOG_DEBUG) == 1) { \ + DlogDebugInner(moduleId, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ + } \ + } while (TMP_LOG != 0) /** * @ingroup slog @@ -319,9 +320,9 @@ DLL_EXPORT int DlogSetAttr(LogAttr logAttr); * @param [in]fmt: log content */ #define dlog_event(moduleId, fmt, ...) \ - do { \ - DlogEventInner(moduleId, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ - } while (TMP_LOG != 0) + do { \ + DlogEventInner(moduleId, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ + } while (TMP_LOG != 0) /** * @ingroup slog @@ -333,11 +334,11 @@ DLL_EXPORT int DlogSetAttr(LogAttr logAttr); * @param [in]fmt: log content */ #define Dlog(moduleId, level, fmt, ...) \ - do { \ - if(CheckLogLevel(moduleId, level) == 1) { \ - DlogInner(moduleId, level, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ - } \ - } while (TMP_LOG != 0) + do { \ + if (CheckLogLevel(moduleId, level) == 1) { \ + DlogInner(moduleId, level, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ + } \ + } while (TMP_LOG != 0) /** * @ingroup slog @@ -350,11 +351,11 @@ DLL_EXPORT int DlogSetAttr(LogAttr logAttr); * @param [in]fmt: log content */ #define DlogSub(moduleId, submodule, level, fmt, ...) \ - do { \ - if(CheckLogLevel(moduleId, level) == 1) { \ - DlogInner(moduleId, level, "[%s:%d][%s]" fmt, __FILE__, __LINE__, submodule, ##__VA_ARGS__); \ - } \ - } while (TMP_LOG != 0) + do { \ + if (CheckLogLevel(moduleId, level) == 1) { \ + DlogInner(moduleId, level, "[%s:%d][%s]" fmt, __FILE__, __LINE__, submodule, ##__VA_ARGS__); \ + } \ + } while (TMP_LOG != 0) /** * @ingroup slog @@ -368,11 +369,11 @@ DLL_EXPORT int DlogSetAttr(LogAttr logAttr); * @param [in]fmt: log content */ #define DlogWithKV(moduleId, level, pstKVArray, kvNum, fmt, ...) \ - do { \ - if(CheckLogLevel(moduleId, level) == 1) { \ - DlogWithKVInner(moduleId, level, pstKVArray, kvNum, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ - } \ - } while (TMP_LOG != 0) + do { \ + if (CheckLogLevel(moduleId, level) == 1) { \ + DlogWithKVInner(moduleId, level, pstKVArray, kvNum, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ + } \ + } while (TMP_LOG != 0) /** * @ingroup slog @@ -452,11 +453,11 @@ DLL_EXPORT int DlogSetAttrForC(LogAttr logAttr); * @param [in]fmt: log content */ #define DlogForC(moduleId, level, fmt, ...) \ - do { \ - if(CheckLogLevelForC(moduleId, level) == 1) { \ - DlogInnerForC(moduleId, level, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ - } \ - } while (TMP_LOG != 0) + do { \ + if (CheckLogLevelForC(moduleId, level) == 1) { \ + DlogInnerForC(moduleId, level, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ + } \ + } while (TMP_LOG != 0) /** * @ingroup slog @@ -469,11 +470,11 @@ DLL_EXPORT int DlogSetAttrForC(LogAttr logAttr); * @param [in]fmt: log content */ #define DlogSubForC(moduleId, submodule, level, fmt, ...) \ - do { \ - if(CheckLogLevelForC(moduleId, level) == 1) { \ - DlogInnerForC(moduleId, level, "[%s:%d][%s]" fmt, __FILE__, __LINE__, submodule, ##__VA_ARGS__); \ - } \ - } while (TMP_LOG != 0) + do { \ + if (CheckLogLevelForC(moduleId, level) == 1) { \ + DlogInnerForC(moduleId, level, "[%s:%d][%s]" fmt, __FILE__, __LINE__, submodule, ##__VA_ARGS__); \ + } \ + } while (TMP_LOG != 0) /** * @ingroup slog @@ -487,11 +488,11 @@ DLL_EXPORT int DlogSetAttrForC(LogAttr logAttr); * @param [in]fmt: log content */ #define DlogWithKVForC(moduleId, level, pstKVArray, kvNum, fmt, ...) \ - do { \ - if(CheckLogLevelForC(moduleId, level) == 1) { \ - DlogWithKVInnerForC(moduleId, level, pstKVArray, kvNum, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ - } \ - } while (TMP_LOG != 0) + do { \ + if (CheckLogLevelForC(moduleId, level) == 1) { \ + DlogWithKVInnerForC(moduleId, level, pstKVArray, kvNum, "[%s:%d]" fmt, __FILE__, __LINE__, ##__VA_ARGS__); \ + } \ + } while (TMP_LOG != 0) /** * @ingroup slog From dc125203a81c9eedd1a2e5bde077df48aecc7808 Mon Sep 17 00:00:00 2001 From: shenwei41 Date: Sat, 12 Feb 2022 15:00:04 +0800 Subject: [PATCH 49/59] upgrade Ascend package 12 Feb 22 --- third_party/fwkacllib/inc/common/type_def.h | 52 +++++++++++++++++++ .../fwkacllib/inc/toolchain/prof_acl_api.h | 2 +- third_party/fwkacllib/inc/tsd/status.h | 29 +++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 third_party/fwkacllib/inc/common/type_def.h create mode 100644 third_party/fwkacllib/inc/tsd/status.h diff --git a/third_party/fwkacllib/inc/common/type_def.h b/third_party/fwkacllib/inc/common/type_def.h new file mode 100644 index 00000000..1bbaf32d --- /dev/null +++ b/third_party/fwkacllib/inc/common/type_def.h @@ -0,0 +1,52 @@ +/** +* Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* +* Description:interface. +* Create: 2021-12-21 +*/ +#ifndef AICPU_TYPE_DEF_H +#define AICPU_TYPE_DEF_H + +#include +#include +#ifndef char_t +typedef char char_t; +#endif + +#ifndef float32_t +typedef float float32_t; +#endif + +#ifndef float64_t +typedef double float64_t; +#endif + +inline uint64_t PtrToValue(const void *ptr) +{ + return static_cast(reinterpret_cast(ptr)); +} + +inline void *ValueToPtr(const uint64_t value) +{ + return reinterpret_cast(static_cast(value)); +} + +template +inline TO *PtrToPtr(TI *ptr) +{ + return reinterpret_cast(ptr); +} + +template +inline T *PtrAdd(T * const ptr, const size_t maxIdx, const size_t idx) +{ + if ((ptr != nullptr) && (idx < maxIdx)) { + return reinterpret_cast(ptr + idx); + } + return nullptr; +} +#endif // AICPU_TYPE_DEF_H diff --git a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h index 15baae46..e592526b 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h +++ b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h @@ -100,7 +100,7 @@ extern "C" { MSVP_PROF_API uint64_t ProfGetOpExecutionTime(const void *data, uint32_t len, uint32_t index); -typedef in32_t Status; +typedef int32_t Status; typedef struct aclprofSubscribeConfig aclprofSubscribeConfig1; /// /// @ingroup AscendCL diff --git a/third_party/fwkacllib/inc/tsd/status.h b/third_party/fwkacllib/inc/tsd/status.h new file mode 100644 index 00000000..e0a9b619 --- /dev/null +++ b/third_party/fwkacllib/inc/tsd/status.h @@ -0,0 +1,29 @@ +/** + * Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2021. All rights reserved. + * + * 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. + */ + +#ifndef INC_TDT_STATUS_H +#define INC_TDT_STATUS_H +#include "common/type_def.h" +namespace tsd { +#ifdef __cplusplus + using TSD_StatusT = uint32_t; +#else + typedef uint32_t TSD_StatusT; +#endif + // success code + constexpr TSD_StatusT TSD_OK = 0U; +} +#endif // INC_TDT_STATUS_H From a2e4cf13f3c34f45a213bc5b078fda62b654bed2 Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Fri, 25 Feb 2022 10:01:24 +0800 Subject: [PATCH 50/59] upgrade Ascend package 24 Feb 22 --- inc/external/acl/OWNERS | 10 ---- inc/external/acl/acl.h | 2 +- inc/external/acl/acl_base.h | 3 +- inc/external/acl/acl_mdl.h | 2 +- inc/external/acl/acl_op.h | 2 +- inc/external/acl/acl_op_compiler.h | 2 +- inc/external/acl/acl_prof.h | 2 +- inc/external/acl/acl_rt.h | 2 +- inc/external/acl/acl_tdt.h | 2 +- inc/external/acl/acl_tdt_queue.h | 2 +- inc/external/acl/error_codes/ge_error_codes.h | 2 +- inc/external/acl/error_codes/rt_error_codes.h | 2 +- inc/external/acl/ops/acl_cblas.h | 2 +- inc/external/acl/ops/acl_dvpp.h | 2 +- inc/external/acl/ops/acl_fv.h | 2 +- inc/external/ge/ge_api.h | 14 +++--- inc/external/ge/ge_api_error_codes.h | 2 +- inc/external/ge/ge_api_types.h | 2 +- inc/external/ge/ge_error_codes.h | 2 +- inc/external/ge/ge_ir_build.h | 2 +- inc/external/hccl/hccl.h | 2 +- inc/external/hccl/hccl_types.h | 2 +- inc/external/runtime/rt_error_codes.h | 2 +- inc/framework/common/file_constant_util.h | 1 - inc/framework/common/helper/model_helper.h | 1 - inc/framework/common/op/attr_value_util.h | 1 - inc/framework/common/op/ge_op_utils.h | 2 - inc/framework/common/profiling_definitions.h | 15 ++++++ inc/framework/common/scope_guard.h | 1 - inc/framework/common/util.h | 2 - inc/framework/executor/ge_executor.h | 4 ++ inc/framework/omg/parser/op_parser.h | 2 - inc/framework/omg/version.h | 1 - metadef | 2 +- .../inc/external/runtime/rt_error_codes.h | 1 + third_party/fwkacllib/inc/ops/array_ops.h | 20 +++++--- third_party/fwkacllib/inc/ops/ctc_ops.h | 38 +++++++-------- third_party/fwkacllib/inc/ops/image_ops.h | 48 +++++++++++++++++++ third_party/fwkacllib/inc/ops/nn_norm_ops.h | 41 +++++++++++++++- third_party/fwkacllib/inc/ops/quantize_ops.h | 23 +++++++++ third_party/fwkacllib/inc/runtime/dev.h | 15 ++++++ third_party/fwkacllib/inc/runtime/kernel.h | 22 +++++++++ third_party/fwkacllib/inc/runtime/rt_model.h | 10 ++++ third_party/fwkacllib/inc/tdt/tsd_client.h | 28 +++++++++++ .../fwkacllib/inc/toolchain/prof_reporter.h | 4 +- 45 files changed, 268 insertions(+), 81 deletions(-) delete mode 100755 inc/external/acl/OWNERS diff --git a/inc/external/acl/OWNERS b/inc/external/acl/OWNERS deleted file mode 100755 index b4b22068..00000000 --- a/inc/external/acl/OWNERS +++ /dev/null @@ -1,10 +0,0 @@ -approvers: -- ji_chen -- wqtshg -- zhangfan_hq -reviewers: -- justin_zhao -- zhangyongfeng88 -- w00267184 -options: - no_parent_owners: true \ No newline at end of file diff --git a/inc/external/acl/acl.h b/inc/external/acl/acl.h index a5194472..99e87e28 100644 --- a/inc/external/acl/acl.h +++ b/inc/external/acl/acl.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/acl/acl_base.h b/inc/external/acl/acl_base.h index c938d4fb..1d9813f3 100644 --- a/inc/external/acl/acl_base.h +++ b/inc/external/acl/acl_base.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. @@ -164,6 +164,7 @@ typedef enum { ACL_FORMAT_NC1HWC0 = 3, ACL_FORMAT_FRACTAL_Z = 4, ACL_FORMAT_NC1HWC0_C04 = 12, + ACL_FORMAT_HWCN = 16, ACL_FORMAT_NDHWC = 27, ACL_FORMAT_FRACTAL_NZ = 29, ACL_FORMAT_NCDHW = 30, diff --git a/inc/external/acl/acl_mdl.h b/inc/external/acl/acl_mdl.h index 778fa519..d0e2d145 100644 --- a/inc/external/acl/acl_mdl.h +++ b/inc/external/acl/acl_mdl.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/acl/acl_op.h b/inc/external/acl/acl_op.h index f340b6bc..c49d56db 100644 --- a/inc/external/acl/acl_op.h +++ b/inc/external/acl/acl_op.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/acl/acl_op_compiler.h b/inc/external/acl/acl_op_compiler.h index 8480b89c..9de0ee85 100644 --- a/inc/external/acl/acl_op_compiler.h +++ b/inc/external/acl/acl_op_compiler.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/acl/acl_prof.h b/inc/external/acl/acl_prof.h index b2e1e1f7..01df5992 100644 --- a/inc/external/acl/acl_prof.h +++ b/inc/external/acl/acl_prof.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/acl/acl_rt.h b/inc/external/acl/acl_rt.h index c5e8272c..578f3bdd 100644 --- a/inc/external/acl/acl_rt.h +++ b/inc/external/acl/acl_rt.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/acl/acl_tdt.h b/inc/external/acl/acl_tdt.h index d928a911..75f07241 100644 --- a/inc/external/acl/acl_tdt.h +++ b/inc/external/acl/acl_tdt.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/acl/acl_tdt_queue.h b/inc/external/acl/acl_tdt_queue.h index 01f0eebf..c8ab02a3 100644 --- a/inc/external/acl/acl_tdt_queue.h +++ b/inc/external/acl/acl_tdt_queue.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/acl/error_codes/ge_error_codes.h b/inc/external/acl/error_codes/ge_error_codes.h index 027c83ea..cc3fbedc 100644 --- a/inc/external/acl/error_codes/ge_error_codes.h +++ b/inc/external/acl/error_codes/ge_error_codes.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/acl/error_codes/rt_error_codes.h b/inc/external/acl/error_codes/rt_error_codes.h index d16af89f..a060dfdb 100644 --- a/inc/external/acl/error_codes/rt_error_codes.h +++ b/inc/external/acl/error_codes/rt_error_codes.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/acl/ops/acl_cblas.h b/inc/external/acl/ops/acl_cblas.h index 3d81eb2b..586d06a8 100644 --- a/inc/external/acl/ops/acl_cblas.h +++ b/inc/external/acl/ops/acl_cblas.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/acl/ops/acl_dvpp.h b/inc/external/acl/ops/acl_dvpp.h index 6ab89c49..a46839f8 100644 --- a/inc/external/acl/ops/acl_dvpp.h +++ b/inc/external/acl/ops/acl_dvpp.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/acl/ops/acl_fv.h b/inc/external/acl/ops/acl_fv.h index 4bd392c9..87480461 100644 --- a/inc/external/acl/ops/acl_fv.h +++ b/inc/external/acl/ops/acl_fv.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/ge/ge_api.h b/inc/external/ge/ge_api.h index 1e80ac4e..73753b72 100644 --- a/inc/external/ge/ge_api.h +++ b/inc/external/ge/ge_api.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. @@ -72,7 +72,7 @@ class GE_FUNC_VISIBILITY Session { /// @return Status result of function /// ATTRIBUTED_DEPRECATED(Status AddGraph(uint32_t, const Graph &, const std::map &)) - Status AddGraph(uint32_t graphId, const Graph &graph, const std::map &options); + Status AddGraph(uint32_t graph_id, const Graph &graph, const std::map &options); /// /// @ingroup client @@ -82,7 +82,7 @@ class GE_FUNC_VISIBILITY Session { /// @param [in] options graph options /// @return Status result of function /// - Status AddGraph(uint32_t graphId, const Graph &graph, const std::map &options); + Status AddGraph(uint32_t graph_id, const Graph &graph, const std::map &options); /// /// @ingroup client @@ -119,7 +119,7 @@ class GE_FUNC_VISIBILITY Session { /// @param [out] outputs output data /// @return Status result of function /// - Status RunGraph(uint32_t graphId, const std::vector &inputs, std::vector &outputs); + Status RunGraph(uint32_t graph_id, const std::vector &inputs, std::vector &outputs); /// /// @ingroup ge_graph @@ -140,9 +140,9 @@ class GE_FUNC_VISIBILITY Session { /// @param [in] inputs: input data /// @return Status result of function /// - Status BuildGraph(uint32_t graphId, const std::vector &inputs); + Status BuildGraph(uint32_t graph_id, const std::vector &inputs); - Status BuildGraph(uint32_t graphId, const std::vector &inputs); /*lint !e148*/ + Status BuildGraph(uint32_t graph_id, const std::vector &inputs); /*lint !e148*/ /// /// @ingroup ge_graph @@ -154,7 +154,7 @@ class GE_FUNC_VISIBILITY Session { /// Please ensure that the implementation of the function is trusted. /// @return Status result of function /// - Status RunGraphAsync(uint32_t graphId, const std::vector &inputs, RunAsyncCallback callback); + Status RunGraphAsync(uint32_t graph_id, const std::vector &inputs, RunAsyncCallback callback); /// /// @ingroup ge_graph diff --git a/inc/external/ge/ge_api_error_codes.h b/inc/external/ge/ge_api_error_codes.h index b5cfb115..7d4cab13 100644 --- a/inc/external/ge/ge_api_error_codes.h +++ b/inc/external/ge/ge_api_error_codes.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/ge/ge_api_types.h b/inc/external/ge/ge_api_types.h index 93ebe284..2ad7dd99 100644 --- a/inc/external/ge/ge_api_types.h +++ b/inc/external/ge/ge_api_types.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/ge/ge_error_codes.h b/inc/external/ge/ge_error_codes.h index 027c83ea..cc3fbedc 100644 --- a/inc/external/ge/ge_error_codes.h +++ b/inc/external/ge/ge_error_codes.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/ge/ge_ir_build.h b/inc/external/ge/ge_ir_build.h index d1d6ade9..5a542fd8 100644 --- a/inc/external/ge/ge_ir_build.h +++ b/inc/external/ge/ge_ir_build.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/hccl/hccl.h b/inc/external/hccl/hccl.h index c24b5374..ea077054 100644 --- a/inc/external/hccl/hccl.h +++ b/inc/external/hccl/hccl.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/hccl/hccl_types.h b/inc/external/hccl/hccl_types.h index ea09fa4d..b018227d 100644 --- a/inc/external/hccl/hccl_types.h +++ b/inc/external/hccl/hccl_types.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/external/runtime/rt_error_codes.h b/inc/external/runtime/rt_error_codes.h index d16af89f..a060dfdb 100644 --- a/inc/external/runtime/rt_error_codes.h +++ b/inc/external/runtime/rt_error_codes.h @@ -1,5 +1,5 @@ /** - * Copyright 2019-2020 Huawei Technologies Co., Ltd + * Copyright 2019-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. diff --git a/inc/framework/common/file_constant_util.h b/inc/framework/common/file_constant_util.h index e0763057..a53c5a24 100644 --- a/inc/framework/common/file_constant_util.h +++ b/inc/framework/common/file_constant_util.h @@ -23,7 +23,6 @@ #include "ge/ge_api_error_codes.h" #include "nlohmann/json.hpp" #include "graph/op_desc.h" -#include "graph/types.h" #include "graph/ge_tensor.h" namespace ge { diff --git a/inc/framework/common/helper/model_helper.h b/inc/framework/common/helper/model_helper.h index 4a098b1f..3dc7c704 100644 --- a/inc/framework/common/helper/model_helper.h +++ b/inc/framework/common/helper/model_helper.h @@ -20,7 +20,6 @@ #include #include -#include "framework/common/fmk_types.h" #include "framework/common/helper/om_file_helper.h" #include "common/model/ge_model.h" #include "common/model/ge_root_model.h" diff --git a/inc/framework/common/op/attr_value_util.h b/inc/framework/common/op/attr_value_util.h index d749ae4f..5a41de05 100644 --- a/inc/framework/common/op/attr_value_util.h +++ b/inc/framework/common/op/attr_value_util.h @@ -34,7 +34,6 @@ #include #include #include -#include "external/graph/types.h" #include "graph/debug/ge_attr_define.h" #include "proto/om.pb.h" diff --git a/inc/framework/common/op/ge_op_utils.h b/inc/framework/common/op/ge_op_utils.h index 53e72074..95f1dca1 100644 --- a/inc/framework/common/op/ge_op_utils.h +++ b/inc/framework/common/op/ge_op_utils.h @@ -21,8 +21,6 @@ #include #include "framework/common/op/attr_value_util.h" -#include "register/register_types.h" -#include "register/register_error_codes.h" #include "framework/common/util.h" #include "graph/attr_value.h" #include "graph/ge_tensor.h" diff --git a/inc/framework/common/profiling_definitions.h b/inc/framework/common/profiling_definitions.h index 90f3823a..6522486b 100644 --- a/inc/framework/common/profiling_definitions.h +++ b/inc/framework/common/profiling_definitions.h @@ -52,6 +52,21 @@ enum { kOpExecute, kAllocMem, kCopyH2D, + kPrepareNode, + kWaitForPrepareDone, + kPropgateOutputs, + kOnNodeDoneCallback, + kValidateInputTensor, + kAfterExecuted, + kRtEventSychronize, + kInferShapeWaitDependShape, + kInferShapeWaitInputTensor, + kInferShapeCallInferFunc, + kInferShapePropgate, + // v2 control node + kSelectBranch, + kExecuteSubGraph, + kInitSubGraphExecutor, // Add new definitions here kProfilingIndexEnd diff --git a/inc/framework/common/scope_guard.h b/inc/framework/common/scope_guard.h index ce9e4c51..bda9ffe2 100644 --- a/inc/framework/common/scope_guard.h +++ b/inc/framework/common/scope_guard.h @@ -18,7 +18,6 @@ #define INC_FRAMEWORK_COMMON_SCOPE_GUARD_H_ #include -#include /// Usage: /// Acquire Resource 1 diff --git a/inc/framework/common/util.h b/inc/framework/common/util.h index ca662242..6a7a1455 100644 --- a/inc/framework/common/util.h +++ b/inc/framework/common/util.h @@ -17,11 +17,9 @@ #ifndef AIR_INC_FRAMEWORK_COMMON_UTIL_H_ #define AIR_INC_FRAMEWORK_COMMON_UTIL_H_ -#include #include #include #include -#include #include #include "external/graph/types.h" diff --git a/inc/framework/executor/ge_executor.h b/inc/framework/executor/ge_executor.h index 2929d26b..66b95180 100644 --- a/inc/framework/executor/ge_executor.h +++ b/inc/framework/executor/ge_executor.h @@ -315,6 +315,10 @@ class GE_FUNC_VISIBILITY GeExecutor { static Status LoadDynamicSingleOpV2(const std::string &model_name, const ModelData &model_data, void *const stream, DynamicSingleOp **const single_op, const uint64_t model_id); + static Status UnloadSingleOp(const uint64_t op_id); + + static Status UnloadDynamicSingleOp(const uint64_t op_id); + static Status ExecuteAsync(DynamicSingleOp *const executor, const std::vector &input_desc, const std::vector &inputs, std::vector &output_desc, std::vector &outputs); diff --git a/inc/framework/omg/parser/op_parser.h b/inc/framework/omg/parser/op_parser.h index b511a8b0..f17b6fee 100644 --- a/inc/framework/omg/parser/op_parser.h +++ b/inc/framework/omg/parser/op_parser.h @@ -21,8 +21,6 @@ #include "framework/omg/parser/parser_types.h" #include "framework/omg/omg_inner_types.h" #include "proto/om.pb.h" -#include "graph/ge_tensor.h" -#include "graph/op_desc.h" #include "graph/utils/op_desc_utils.h" using google::protobuf::Message; diff --git a/inc/framework/omg/version.h b/inc/framework/omg/version.h index 53f155fa..e355d284 100644 --- a/inc/framework/omg/version.h +++ b/inc/framework/omg/version.h @@ -18,7 +18,6 @@ #define INC_FRAMEWORK_OMG_VERSION_H_ #include -#include #include "framework/common/debug/log.h" #include "framework/common/string_util.h" diff --git a/metadef b/metadef index 0a233571..ab3207e9 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit 0a2335712484f85cd44a0f2402eac6932b22b40a +Subproject commit ab3207e99f94aabf036e1c8b068de0df15ff2d01 diff --git a/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h b/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h index 09ce1f65..248303ef 100644 --- a/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h +++ b/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h @@ -62,6 +62,7 @@ static const int32_t ACL_ERROR_RT_OVER_LIMIT = 207012; // over l static const int32_t ACL_ERROR_RT_QUEUE_EMPTY = 207013; // queue is empty static const int32_t ACL_ERROR_RT_QUEUE_FULL = 207014; // queue is full static const int32_t ACL_ERROR_RT_REPEATED_INIT = 207015; // repeated init +static const int32_t ACL_ERROR_RT_AIVEC_OVER_FLOW = 207016; // aivec over flow static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error diff --git a/third_party/fwkacllib/inc/ops/array_ops.h b/third_party/fwkacllib/inc/ops/array_ops.h index 7928db15..ae55234c 100644 --- a/third_party/fwkacllib/inc/ops/array_ops.h +++ b/third_party/fwkacllib/inc/ops/array_ops.h @@ -1496,17 +1496,23 @@ REG_OP(QueueData) /** * @brief Ensures that the tensor's shape matches the expected shape. \n * @par Inputs: -* x: A Tensor. \n +* input: A Tensor. that need to be checked with desired shape +* Must be one of the following types: +* int8, uint8, int16, uint16, int32, int64, float16, float +* double, complex64 complex128 \n * @par Attributes: -* shape: The shape that needs to be checked \n +* shape: required, a desired tensor shape. type: list int \n * @par Outputs: -* y: A tensor. \n +* output: A tensor. has the same type and contents as input +* Must be one of the following types: +* int8, uint8, int16, uint16, int32, int64, float16, float +* double, complex64 complex128 \n */ REG_OP(EnsureShape) - .INPUT(input, TensorType({DT_INT8,DT_UINT8,DT_INT16,DT_UINT16,DT_INT32,DT_INT64,DT_FLOAT16, \ - DT_FLOAT,DT_DOUBLE})) - .OUTPUT(output, TensorType({DT_INT8,DT_UINT8,DT_INT16,DT_UINT16,DT_INT32,DT_INT64,DT_FLOAT16, \ - DT_FLOAT,DT_DOUBLE})) + .INPUT(input, TensorType({DT_INT8,DT_UINT8, DT_INT16, DT_UINT16, DT_INT32, DT_INT64, DT_FLOAT16, \ + DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(output, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, DT_INT32, DT_INT64, DT_FLOAT16, \ + DT_FLOAT,DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .REQUIRED_ATTR(shape, ListInt) .OP_END_FACTORY_REG(EnsureShape) } // namespace ge diff --git a/third_party/fwkacllib/inc/ops/ctc_ops.h b/third_party/fwkacllib/inc/ops/ctc_ops.h index bf50b24d..17e4eabf 100644 --- a/third_party/fwkacllib/inc/ops/ctc_ops.h +++ b/third_party/fwkacllib/inc/ops/ctc_ops.h @@ -156,16 +156,15 @@ REG_OP(CTCBeamSearchDecoder) *@li log_alpha: The probability of possible trace of input to target. *@par Attributes: -*@li blank : Blank label. Default 0. +*@li blank: Blank label. Default 0. *@li reduction: Specifies the reduction to apply to the output. Default: 'mean'. -*@li zero_infinity : Whether to zero infinite losses and the associated gradients. -*@li label_max : The max length of targets. +*@li zero_infinity: Whether to zero infinite losses and the associated gradients. -*@par Third-party framework compatibility +* @par Third-party framework compatibility: * Compatible with Pytorch CTCLoss operator. *@attention Constraints: -*The limit of Label’s length is 1K. +* The limit of Label’s length is 1K. */ REG_OP(CTCLossV2) .INPUT(log_probs, TensorType({DT_FLOAT, DT_DOUBLE})) @@ -177,38 +176,36 @@ REG_OP(CTCLossV2) .ATTR(blank, Int, 0) .ATTR(reduction, String, "mean") .ATTR(zero_infinity, Bool, false) - .ATTR(label_max, Int, 0) .OP_END_FACTORY_REG(CTCLossV2) /** *@brief The Connectionist Temporal Classification loss grad. -*@par Inputs: +* @par Inputs: *@li grad_out: Gradient renewal coefficient. Tensor of size (N), where N = batch size. -*@li log_probs: Tensor of size (T, N, C), where T =input length, N =batch size, +* @li log_probs: Tensor of size (T, N, C), where T =input length, N =batch size, and C = number of classes (including blank). It represent the logarithmized probabilities of the outputs. *@li targets: Tensor of size (N, S) or sum(target_lengths), where S = max target length. It represent the target sequences. -*@li input_lengths: Tuple or tensor of size (N). It represent the lengths of the inputs. +* @li input_lengths: Tuple or tensor of size (N). It represent the lengths of the inputs. *@li target_lengths: Tuple or tensor of size (N). It represent lengths of the targets. -*@li neg_log_likelihood: A loss value which is differentiable with respect to each input node. -*@li log_alpha: The probability of possible trace of input to target. +* @li neg_log_likelihood: A loss value which is differentiable with respect to each input node. +* @li log_alpha: The probability of possible trace of input to target. -*@par Outputs: +* @par Outputs: *@li grad: Tensor of size (T, N, C), The grad of Connectionist Temporal Classification loss. -*@par Attributes: -*@li blank : Blank label. Default 0. -*@li reduction: Specifies the reduction to apply to the output. Default: 'mean'. -*@li zero_infinity : Whether to zero infinite losses and the associated gradients. -*@li label_max : The max length of targets. +* @par Attributes: +*@li blank: Blank label. Default 0. +* @li reduction: Specifies the reduction to apply to the output. Default: 'mean'. +* @li zero_infinity: Whether to zero infinite losses and the associated gradients. -*@par Third-party framework compatibility +* @par Third-party framework compatibility: * Compatible with Pytorch CTCLoss operator. -*@attention Constraints: -*The limit of Label’s length is 1K. +* @attention Constraints: +* The limit of Label’s length is 1K. */ REG_OP(CTCLossV2Grad) .INPUT(grad_out, TensorType({DT_FLOAT, DT_DOUBLE})) @@ -222,7 +219,6 @@ REG_OP(CTCLossV2Grad) .ATTR(blank, Int, 0) .ATTR(reduction, String, "mean") .ATTR(zero_infinity, Bool, false) - .ATTR(label_max, Int, 0) .OP_END_FACTORY_REG(CTCLossV2Grad) } // namespace ge diff --git a/third_party/fwkacllib/inc/ops/image_ops.h b/third_party/fwkacllib/inc/ops/image_ops.h index bf0846c2..ba4433d1 100644 --- a/third_party/fwkacllib/inc/ops/image_ops.h +++ b/third_party/fwkacllib/inc/ops/image_ops.h @@ -349,6 +349,7 @@ REG_OP(ExtractGlimpse) *y:images converted to RGB . \n *@attention Constraints: +*Input images currently supports DT_FLOAT, DT_DOUBLE . *Last dimension of input x must be size 3 . \n *@par Third-party framework compatibility @@ -2307,5 +2308,52 @@ REG_OP(UpsampleNearest1dGrad) .REQUIRED_ATTR(output_size, ListInt) .ATTR(scales, ListFloat, {}) .OP_END_FACTORY_REG(UpsampleNearest1dGrad) + +/** +* @brief JPEG encode input image with provided compression quality. \n + +* @par Inputs: +* @li images: image is a 3-D uint8 tensor of shape [height, width, channels]. +* @li quality: int32 jpeg compression quality value between 0 and 100, 0-D tensor. + +* @par Outputs: JPEG-encoded image +* contents: an output string. \n + +* @par Third-party framework compatibility. +* Compatible with tensorflow EncodeJpegVariableQuality operator. +*/ + +REG_OP(EncodeJpegVariableQuality) + .INPUT(images, TensorType({DT_UINT8})) + .INPUT(quality, TensorType({DT_INT32})) + .OUTPUT(contents, TensorType({DT_STRING})) + .OP_END_FACTORY_REG(EncodeJpegVariableQuality) + +/** +* @brief image to transforms. \n + +* @par Inputs: +* @li images: [batch, height, width, channels], 4-D tensor. +* @li transforms: [batch, 8] or [1, 8] matrix, 2-D tensor. +* @li outout_shape: [new_height, new_width], 1-D tensor. + +* @par Attributes: +* @li interpolation: Interpolation method, "NEAREST" or "BILINEAR", 0-D tensor. +* @li fill_mode: Defaults to "CONSTANT". Fill mode, "REFLECT", "WRAP", or "CONSTANT", 0-D tensor. + +* @par Outputs +* transformed_images: has the same type as iamges, 4-D tensor with shape[batch, new_height, new_width, channels]. \n + +* @par Third-party framework compatibility. +* Compatible with tensorflow ImageProjectiveTransform operator. +*/ +REG_OP(ImageProjectiveTransform) + .INPUT(images, TensorType({DT_UINT8, DT_INT32, DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(transforms, TensorType({DT_FLOAT})) + .INPUT(output_shape, TensorType({DT_INT32})) + .REQUIRED_ATTR(interpolation, String) + .ATTR(fill_mode, String, "CONSTANT") + .OUTPUT(transformed_images, TensorType({DT_UINT8, DT_INT32, DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OP_END_FACTORY_REG(ImageProjectiveTransform) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_IMAGE_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index 38e513db..2d4149e2 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -1700,6 +1700,45 @@ REG_OP(GroupNormRelu) .REQUIRED_ATTR(num_groups, Int) .ATTR(eps, Float, 0.00001) .OP_END_FACTORY_REG(GroupNormRelu) -} // namespace ge +/** +* @brief Function dropout with softmaxgrad and muls + +* @par Inputs: +* Two inputs, including: +* @li y_grad: A mutable Tensor. The type only support float16. +* @li mask: A mutable Tensor. Must met all of the following rules: +* shape of mask should be 1D. +* dtype of mask should be uint8. +* value of shape should met the following algorithm: +* value = (size(x) + 128 - 1) // 128 * 128 +* @li softmax_output: A mutable Tensor. Must met all of the following rules: +* shape of softmax_output should be NZ. +* dtype of softmax_output should be float16. +* it is the output of softmax + +* @par Attributes: +* @li input_keep_prob:A attribute used to judge which units should be keep. +* Has the same type as "x" . \n +* @li alpha: A attribute used to scale tensor. +* Has the same type as "x" . \n +* @li axes: A list of int. The dimension softmax would be performed on. Defaults +* to "[-1]" . \n + +* @par Outputs: +* x_grad: A mutable Tensor. Has the same type as "x". \n + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(DropoutWithMulsAndSoftmaxGrad) + .INPUT(y_grad, TensorType({ DT_FLOAT16 })) + .INPUT(mask, TensorType({ DT_UINT8 })) + .INPUT(softmax_output, TensorType({ DT_FLOAT16 })) + .OUTPUT(x_grad, TensorType({ DT_FLOAT16 })) + .REQUIRED_ATTR(input_keep_prob, Float) + .REQUIRED_ATTR(alpha, Float) + .ATTR(axes, ListInt, { -1 }) + .OP_END_FACTORY_REG(DropoutWithMulsAndSoftmaxGrad) +} // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_NORM_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/quantize_ops.h b/third_party/fwkacllib/inc/ops/quantize_ops.h index fd855734..f6dd9c2d 100644 --- a/third_party/fwkacllib/inc/ops/quantize_ops.h +++ b/third_party/fwkacllib/inc/ops/quantize_ops.h @@ -241,6 +241,29 @@ REG_OP(AscendRequantS16) .ATTR(dual_output, Bool, false) .ATTR(relu_flag, Bool, false) .OP_END_FACTORY_REG(AscendRequantS16) + +/** +* @brief Quantizes the input of int8 . \n + +* @par Inputs: +* @li x: An FRACTAL_Z tensor of type int8, specifying the input. +* @li offset: An FRACTAL_Z tensor of type int8. + +* @par Attributes: +* @li dst_type: A optional int from: DT_INT8, DT_INT4. Defaults to DT_INT8. + +* @par Outputs: +* @li y: output tensor of type int4 or int8 and with format FRACTAL_Z. + +* @par Third-party framework compatibility +* It is a custom operator. It has no corresponding operator in Caffe, Onnx, Tensorflow or Pythorch. +*/ +REG_OP(AscendWeightQuant) + .INPUT(x, TensorType({DT_INT8})) + .INPUT(offset, TensorType({DT_INT8})) + .OUTPUT(y, TensorType({DT_INT8, DT_INT4})) + .ATTR(dst_type, Int, DT_INT8) + .OP_END_FACTORY_REG(AscendWeightQuant) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_QUANTIZE_OPS_H_ diff --git a/third_party/fwkacllib/inc/runtime/dev.h b/third_party/fwkacllib/inc/runtime/dev.h index bce6625b..1c4586e7 100644 --- a/third_party/fwkacllib/inc/runtime/dev.h +++ b/third_party/fwkacllib/inc/runtime/dev.h @@ -82,6 +82,12 @@ typedef enum tagRtDeviceModuleType { RT_MODULE_TYPE_VECTOR_CORE, /**< VECTOR CORE info*/ } rtDeviceModuleType_t; +typedef enum tagRtMemRequestFeature { + MEM_REQUEST_FEATURE_DEFAULT = 0, + MEM_REQUEST_FEATURE_OPP, + MEM_REQUEST_FEATURE_RESERVED +} rtMemRequestFeature_t; + // used for rtGetDevMsg callback function typedef void (*rtGetMsgCallback)(const char_t *msg, uint32_t len); @@ -418,6 +424,15 @@ RTS_API rtError_t rtDeviceResetWithoutTsd(int32_t devId); * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtGetDevMsg(rtGetDevMsgType_t getMsgType, rtGetMsgCallback callback); + +/** + * @ingroup dvrt_dev + * @brief get ts mem type + * @param [in] rtMemRequestFeature_t mem request feature type + * @param [in] mem request size + * @return RT_MEMORY_TS, RT_MEMORY_HBM, RT_MEMORY_TS | RT_MEMORY_POLICY_HUGE_PAGE_ONLY + */ +RTS_API uint32_t rtGetTsMemType(rtMemRequestFeature_t featureType, uint32_t memSize); #if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/runtime/kernel.h b/third_party/fwkacllib/inc/runtime/kernel.h index 1c3f571b..883068a2 100644 --- a/third_party/fwkacllib/inc/runtime/kernel.h +++ b/third_party/fwkacllib/inc/runtime/kernel.h @@ -217,6 +217,13 @@ typedef void (*rtCallback_t)(void *fnData); #define RT_NORMAL_KERNEL_MODE (0x01U) #define RT_ALL_KERNEL_MODE (0x02U) +/** + * @ingroup rt_kernel + * @brief SHAPE kernel type +**/ +#define RT_STATIC_SHAPE_KERNEL (0x00U) +#define RT_DYNAMIC_SHAPE_KERNEL (0x01U) + /** * @ingroup rt_kernel * @brief kernel L1 Fusion Dump bit flags @@ -335,6 +342,21 @@ RTS_API rtError_t rtQueryFunctionRegistered(const char_t *stubName); RTS_API rtError_t rtKernelConfigDump(uint32_t kind, uint32_t dumpSizePerBlock, uint32_t blockDim, void **dumpBaseAddr, rtStream_t stm); +/** +* @ingroup rt_kernel +* @brief get kernel address and prefetchCnt +* @param [in] hdl program for dynamic shape +* @param [in] tilingKey tilingKey for dynamic shape +* @param [in] stubFunc stubFunc for static shape +* @param [in] flag flag for distinguishing between dynamic shape and static shape +* @param [out] addr address of kernel function +* @param [out] prefetchCnt prefetchCnt of kernel function +* @return RT_ERROR_NONE for ok +* @return RT_ERROR_INVALID_VALUE for error input +*/ +RTS_API rtError_t rtKernelGetAddrAndPrefCnt(void *hdl, const uint64_t tilingKey, const void * const stubFunc, + const uint32_t flag, void **addr, uint32_t *prefetchCnt); + /** * @ingroup rt_kernel * @brief launch kernel to device diff --git a/third_party/fwkacllib/inc/runtime/rt_model.h b/third_party/fwkacllib/inc/runtime/rt_model.h index f550887d..883e60a8 100644 --- a/third_party/fwkacllib/inc/runtime/rt_model.h +++ b/third_party/fwkacllib/inc/runtime/rt_model.h @@ -336,6 +336,16 @@ RTS_API rtError_t rtSetTaskGenCallback(rtTaskGenCallback callback); */ RTS_API rtError_t rtModelCreate(rtModel_t *mdl, uint32_t flag); +/** + * @ingroup rt_model + * @brief set ge model id to aicpu + * @param [in] model aicpu model + * @param [in] extid ge model id + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +rtError_t rtModelSetExtId(rtModel_t mdl, uint32_t extId); + /** * @ingroup rt_model * @brief destroy model instance diff --git a/third_party/fwkacllib/inc/tdt/tsd_client.h b/third_party/fwkacllib/inc/tdt/tsd_client.h index 406ab1c3..a6ecffec 100644 --- a/third_party/fwkacllib/inc/tdt/tsd_client.h +++ b/third_party/fwkacllib/inc/tdt/tsd_client.h @@ -34,6 +34,13 @@ extern "C" { #endif // __cplusplus +struct InitFlowGwInfo { + const char_t *groupName; + uint64_t schedPolicy; + uint64_t reschedInterval; + char_t rsv[128]; +}; + /** * @ingroup Open * @brief Used for the Framework process to communicate with the TSDDaemon process, @@ -101,6 +108,27 @@ TDT_LIB_EXPORT uint32_t TsdOpenEx(const uint32_t logicDeviceId, const uint32_t r */ TDT_LIB_EXPORT uint32_t TsdInitQs(const uint32_t logicDeviceId, const char_t * const groupName = nullptr); +/** +* @ingroup InitFlowGw +* @brief Used for the Framework process to communicate with the TSDDaemon process, +* and notify TSD to complete the initialization of FlowGw processes +* +* @par Function +* Used for the Framework process to communicate with the TSDDaemon process, +* and notify TSD to complete the initialization of other processes +* +* @param logicDeviceId [IN] type #unsigned int. Logic device ID +* @param initInfo [IN] type #InitFlowGwInfo pointer. Initialization parameters +* @retval TDT_OK Success +* @retval OtherValues Failure +* +* @par Dependency +* @li libtsdclient.so: Library to which the interface belongs. +* @li tsd_client.h: Header file where the interface declaration is located. +* @li data_common.h: Header file where 'TDT_StatusT' defined +*/ +TDT_LIB_EXPORT uint32_t TsdInitFlowGw(const uint32_t logicDeviceId, const InitFlowGwInfo * const initInfo); + /** * @ingroup Close * @brief notify TSDClient close resource diff --git a/third_party/fwkacllib/inc/toolchain/prof_reporter.h b/third_party/fwkacllib/inc/toolchain/prof_reporter.h index f0747833..afd4863f 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_reporter.h +++ b/third_party/fwkacllib/inc/toolchain/prof_reporter.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef MSPROF_ENGINE_PROF_REPORTER_H_ -#define MSPROF_ENGINE_PROF_REPORTER_H_ +#ifndef MSPROF_ENGINE_PROF_REPORTER_H +#define MSPROF_ENGINE_PROF_REPORTER_H #if (defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)) #define MSVP_PROF_API __declspec(dllexport) From 13887303d0f55122f6842940c96eee84994896b3 Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Wed, 27 Apr 2022 19:45:50 +0800 Subject: [PATCH 51/59] upgrade Ascend package 27 Apr 22 --- .../aicpu/aicpu_schedule/aicpu_op_type_list.h | 35 +- inc/aicpu/common/aicpu_task_struct.h | 104 +++ inc/aicpu/common/type_def.h | 48 ++ .../fwkacllib/inc => inc/aicpu}/tsd/status.h | 10 +- inc/external/acl/acl_base.h | 4 +- inc/external/acl/acl_prof.h | 37 + inc/external/acl/acl_tdt.h | 11 + inc/external/acl/error_codes/ge_error_codes.h | 1 + inc/external/acl/error_codes/rt_error_codes.h | 1 + inc/external/ge/ge_api_types.h | 25 +- inc/external/ge/ge_error_codes.h | 1 + inc/external/hccl/hccl_types.h | 1 - inc/external/runtime/rt_error_codes.h | 1 + inc/framework/common/debug/log.h | 80 -- inc/framework/common/fmk_error_codes.h | 6 +- inc/framework/common/ge_types.h | 18 +- inc/framework/common/helper/model_helper.h | 35 +- inc/framework/common/helper/om_file_helper.h | 26 +- inc/framework/common/profiling_definitions.h | 35 +- inc/framework/common/types.h | 5 +- inc/framework/common/util.h | 19 +- inc/framework/executor/ge_executor.h | 1 - inc/framework/omg/omg.h | 40 +- inc/framework/pne/pne_model.h | 128 +++ inc/framework/pne/process_node_engine.h | 55 ++ metadef | 2 +- .../inc/aicpu/common/aicpu_task_struct.h | 84 -- third_party/fwkacllib/inc/common/type_def.h | 52 -- third_party/fwkacllib/inc/hccl/base.h | 14 + third_party/fwkacllib/inc/ops/array_ops.h | 37 +- .../fwkacllib/inc/ops/avg_pool_1d_ops.h | 2 +- third_party/fwkacllib/inc/ops/data_flow_ops.h | 46 + third_party/fwkacllib/inc/ops/deep_md.h | 111 ++- .../inc/ops/elewise_calculation_ops.h | 188 ++++- third_party/fwkacllib/inc/ops/image_ops.h | 56 +- third_party/fwkacllib/inc/ops/math_ops.h | 8 +- .../inc/ops/matrix_calculation_ops.h | 171 +++- .../fwkacllib/inc/ops/nn_batch_norm_ops.h | 118 +-- third_party/fwkacllib/inc/ops/nn_detect_ops.h | 143 +++- third_party/fwkacllib/inc/ops/nn_norm_ops.h | 85 +- third_party/fwkacllib/inc/ops/nn_ops.h | 220 ++++- .../fwkacllib/inc/ops/nn_pooling_ops.h | 125 +-- .../fwkacllib/inc/ops/nn_training_ops.h | 1 + .../fwkacllib/inc/ops/nonlinear_fuc_ops.h | 83 +- .../fwkacllib/inc/ops/npu_loss_scale_ops.h | 3 +- third_party/fwkacllib/inc/ops/quantize_ops.h | 16 +- third_party/fwkacllib/inc/ops/reduce_ops.h | 194 +++-- third_party/fwkacllib/inc/ops/rnn.h | 793 ++++++++++++------ third_party/fwkacllib/inc/ops/selection_ops.h | 112 ++- .../fwkacllib/inc/ops/split_combination_ops.h | 8 +- .../fwkacllib/inc/ops/stateful_random_ops.h | 24 + .../inc/ops/target_crop_and_resize.h | 2 +- .../fwkacllib/inc/ops/transformation_ops.h | 31 +- third_party/fwkacllib/inc/runtime/base.h | 21 + third_party/fwkacllib/inc/runtime/config.h | 6 +- .../fwkacllib/inc/runtime/dvfsprofile.h | 53 -- third_party/fwkacllib/inc/runtime/kernel.h | 110 ++- third_party/fwkacllib/inc/runtime/mem.h | 21 + third_party/fwkacllib/inc/runtime/rt.h | 1 - .../fwkacllib/inc/runtime/rt_ffts_plus.h | 2 +- third_party/fwkacllib/inc/runtime/rt_model.h | 2 +- third_party/fwkacllib/inc/runtime/stream.h | 11 + .../fwkacllib/inc/toolchain/prof_acl_api.h | 2 + .../fwkacllib/inc/toolchain/prof_callback.h | 88 +- .../fwkacllib/inc/toolchain/prof_common.h | 28 +- third_party/fwkacllib/inc/toolchain/slog.h | 1 + 66 files changed, 2693 insertions(+), 1109 deletions(-) rename {third_party/fwkacllib/inc => inc}/aicpu/aicpu_schedule/aicpu_op_type_list.h (63%) create mode 100644 inc/aicpu/common/aicpu_task_struct.h create mode 100644 inc/aicpu/common/type_def.h rename {third_party/fwkacllib/inc => inc/aicpu}/tsd/status.h (85%) create mode 100644 inc/framework/pne/pne_model.h create mode 100644 inc/framework/pne/process_node_engine.h delete mode 100644 third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h delete mode 100644 third_party/fwkacllib/inc/common/type_def.h delete mode 100644 third_party/fwkacllib/inc/runtime/dvfsprofile.h diff --git a/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h b/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h similarity index 63% rename from third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h rename to inc/aicpu/aicpu_schedule/aicpu_op_type_list.h index 37a2e412..dbf94462 100644 --- a/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h +++ b/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h @@ -18,38 +18,31 @@ #define AICPU_OP_TYPE_LIST_H_ extern "C" { -enum OpKernelType { - TF_KERNEL, - CPU_KERNEL -}; +enum OpKernelType { TF_KERNEL, CPU_KERNEL }; -enum ReturnCode { - OP_TYPE_NOT_SUPPORT, - FORMAT_NOT_SUPPORT, - DTYPE_NOT_SUPPORT -}; +enum ReturnCode { OP_TYPE_NOT_SUPPORT, FORMAT_NOT_SUPPORT, DTYPE_NOT_SUPPORT }; #pragma pack(push, 1) // One byte alignment struct SysOpInfo { - uint64_t opLen; - uint64_t opType; - OpKernelType kernelsType; + uint64_t opLen; + uint64_t opType; + OpKernelType kernelsType; }; struct SysOpCheckInfo { - uint64_t opListNum; - uint64_t offSetLen; - uint64_t sysOpInfoList; - uint64_t opParamInfoList; + uint64_t opListNum; + uint64_t offSetLen; + uint64_t sysOpInfoList; + uint64_t opParamInfoList; }; struct SysOpCheckResp { - uint64_t opListNum; - bool isWithoutJson; - uint64_t returnCodeList; - uint64_t sysOpInfoList; - uint64_t opParamInfoList; + uint64_t opListNum; + bool isWithoutJson; + uint64_t returnCodeList; + uint64_t sysOpInfoList; + uint64_t opParamInfoList; }; #pragma pack(pop) } diff --git a/inc/aicpu/common/aicpu_task_struct.h b/inc/aicpu/common/aicpu_task_struct.h new file mode 100644 index 00000000..6dd83403 --- /dev/null +++ b/inc/aicpu/common/aicpu_task_struct.h @@ -0,0 +1,104 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef AICPU_TASK_STRUCT_H +#define AICPU_TASK_STRUCT_H + +#include + +namespace aicpu { + +using char_t = char; + +#pragma pack(push, 1) +struct AicpuParamHead { + uint32_t length; // Total length: include cunstom message + uint32_t ioAddrNum; // Input and output address number + uint32_t extInfoLength; // extInfo struct Length + uint64_t extInfoAddr; // extInfo address +}; + +enum class AicpuConfigMsgType { + AICPU_CONFIG_MSG_TYPE_BUF_FREE = 0, /* free buf */ + AICPU_CONFIG_MSG_TYPE_BUF_RESET = 1, /* reset buf */ + AICPU_CONFIG_MSG_TYPE_BUF_SET_ADDR = 2, /* set buf addr to aicpu */ +}; + +enum class AicpuErrMsgType { + ERR_MSG_TYPE_NULL = 0, + ERR_MSG_TYPE_AICORE = 1, + ERR_MSG_TYPE_AICPU = 2, +}; + +enum class AicpuExtInfoMsgType { + EXT_MODEL_ID_MSG_TYPE = 0, +}; + +struct AicpuConfigMsg { + uint8_t msgType; + uint8_t reserved1; + uint16_t bufLen; + uint32_t offset; + uint64_t bufAddr; + uint32_t tsId; + uint32_t reserved2; +}; + +struct AicpuModelIdInfo { + uint32_t modelId; + uint32_t extendModelId; + uint32_t extendInfo[13]; +}; + +// 64 bytes +struct AicpuExtendInfo { + uint8_t msgType; + uint8_t version; + uint8_t reserved[2]; + union { + AicpuModelIdInfo modelIdMap; + }; +}; + +struct AicoreErrMsgInfo { + uint8_t errType; + uint8_t version; + uint8_t reserved1[2]; /* reserved1, 4 byte alignment */ + uint32_t errorCode; + uint32_t modelId; + uint32_t taskId; + uint32_t streamId; + uint64_t transactionId; + uint8_t reserved2[228]; /* the total byte is 256, reserved2 len = 256 - other lens */ +}; + +struct AicpuErrMsgInfo { + uint8_t errType; + uint8_t version; + uint8_t reserved1[2]; /* reserved1, 4 byte alignment */ + uint32_t errorCode; + uint32_t modelId; + uint32_t streamId; + uint64_t transactionId; + char_t opName[64]; /* op name str */ + char_t errDesc[128]; /* err msg desc info */ + uint8_t reserved2[40]; /* the total byte is 256, reserved2 len = 256 - other lens */ +}; +#pragma pack(pop) + +} // namespace aicpu + +#endif // AICPU_TASK_STRUCT_H diff --git a/inc/aicpu/common/type_def.h b/inc/aicpu/common/type_def.h new file mode 100644 index 00000000..043b550d --- /dev/null +++ b/inc/aicpu/common/type_def.h @@ -0,0 +1,48 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Description:interface. + * Create: 2021-12-21 + */ +#ifndef AICPU_TYPE_DEF_H +#define AICPU_TYPE_DEF_H + +#include +#include +#ifndef char_t +typedef char char_t; +#endif + +#ifndef float32_t +typedef float float32_t; +#endif + +#ifndef float64_t +typedef double float64_t; +#endif + +inline uint64_t PtrToValue(const void *ptr) { + return static_cast(reinterpret_cast(ptr)); +} + +inline void *ValueToPtr(const uint64_t value) { + return reinterpret_cast(static_cast(value)); +} + +template +inline TO *PtrToPtr(TI *ptr) { + return reinterpret_cast(ptr); +} + +template +inline T *PtrAdd(T *const ptr, const size_t maxIdx, const size_t idx) { + if ((ptr != nullptr) && (idx < maxIdx)) { + return reinterpret_cast(ptr + idx); + } + return nullptr; +} +#endif // AICPU_TYPE_DEF_H diff --git a/third_party/fwkacllib/inc/tsd/status.h b/inc/aicpu/tsd/status.h similarity index 85% rename from third_party/fwkacllib/inc/tsd/status.h rename to inc/aicpu/tsd/status.h index e0a9b619..1010aefb 100644 --- a/third_party/fwkacllib/inc/tsd/status.h +++ b/inc/aicpu/tsd/status.h @@ -19,11 +19,11 @@ #include "common/type_def.h" namespace tsd { #ifdef __cplusplus - using TSD_StatusT = uint32_t; +using TSD_StatusT = uint32_t; #else - typedef uint32_t TSD_StatusT; +typedef uint32_t TSD_StatusT; #endif - // success code - constexpr TSD_StatusT TSD_OK = 0U; -} +// success code +constexpr TSD_StatusT TSD_OK = 0U; +} // namespace tsd #endif // INC_TDT_STATUS_H diff --git a/inc/external/acl/acl_base.h b/inc/external/acl/acl_base.h index 1d9813f3..b23629b6 100644 --- a/inc/external/acl/acl_base.h +++ b/inc/external/acl/acl_base.h @@ -114,6 +114,7 @@ static const int ACL_ERROR_INVALID_MAX_OPQUEUE_NUM_CONFIG = 148048; static const int ACL_ERROR_INVALID_OPP_PATH = 148049; static const int ACL_ERROR_OP_UNSUPPORTED_DYNAMIC = 148050; static const int ACL_ERROR_RELATIVE_RESOURCE_NOT_CLEARED = 148051; +static const int ACL_ERROR_UNSUPPORTED_JPEG = 148052; static const int ACL_ERROR_BAD_ALLOC = 200000; static const int ACL_ERROR_API_NOT_SUPPORT = 200001; @@ -153,7 +154,8 @@ typedef enum { ACL_BOOL = 12, ACL_STRING = 13, ACL_COMPLEX64 = 16, - ACL_COMPLEX128 = 17 + ACL_COMPLEX128 = 17, + ACL_BF16 = 27 } aclDataType; typedef enum { diff --git a/inc/external/acl/acl_prof.h b/inc/external/acl/acl_prof.h index 01df5992..4a9a5be9 100644 --- a/inc/external/acl/acl_prof.h +++ b/inc/external/acl/acl_prof.h @@ -60,6 +60,15 @@ typedef enum { ACL_STEP_END = 1 // step end } aclprofStepTag; +typedef enum { + ACL_SUBSCRIBE_OP = 0, + ACL_SUBSCRIBE_SUBGRAPH = 1, + ACL_SUBSCRIBE_OP_THREAD = 2, + ACL_SUBSCRIBE_NONE +} aclprofSubscribeOpFlag; + +typedef enum { ACL_SUBSCRIBE_ATTRI_THREADID = 0, ACL_SUBSCRIBE_ATTRI_NONE } aclprofSubscribeOpAttri; + typedef struct aclprofConfig aclprofConfig; typedef struct aclprofStopConfig aclprofStopConfig; typedef struct aclprofAicoreEvents aclprofAicoreEvents; @@ -338,6 +347,34 @@ MSVP_PROF_API uint64_t aclprofGetOpDuration(const void *opInfo, size_t opInfoLen */ MSVP_PROF_API size_t aclprofGetModelId(const void *opInfo, size_t opInfoLen, uint32_t index); +/** + * @ingroup AscendCL + * @brief get op flag from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * @param index [IN] index of op array in opInfo + * + * @retval op flag + * @retval ACL_SUBSCRIBE_NONE for failed + */ +MSVP_PROF_API aclprofSubscribeOpFlag aclprofGetOpFlag(const void *opInfo, size_t opInfoLen, uint32_t index); + +/** + * @ingroup AscendCL + * @brief get op flag from subscription data + * + * @param opInfo [IN] pointer to subscription data + * @param opInfoLen [IN] memory size of subscription data + * @param index [IN] index of op array in opInfo + * @param attri [IN] attribute of op + * + * @retval op flag + * @retval NULL for failed + */ +MSVP_PROF_API const char *aclprofGetOpAttriValue(const void *opInfo, size_t opInfoLen, uint32_t index, + aclprofSubscribeOpAttri attri); + /** * @ingroup AscendCL * @brief diff --git a/inc/external/acl/acl_tdt.h b/inc/external/acl/acl_tdt.h index 75f07241..4cea7500 100644 --- a/inc/external/acl/acl_tdt.h +++ b/inc/external/acl/acl_tdt.h @@ -197,6 +197,17 @@ ACL_FUNC_VISIBILITY aclError acltdtAddDataItem(acltdtDataset *dataset, acltdtDat */ ACL_FUNC_VISIBILITY size_t acltdtGetDatasetSize(const acltdtDataset *dataset); +/** + * @ingroup AscendCL + * @brief Get the name of dataset + * + * @param dataset [IN] pointer to the dataset + * + * @retval null for failed + * @retval OtherValues success + */ +ACL_FUNC_VISIBILITY const char *acltdtGetDatasetName(const acltdtDataset *dataset); + /** * @ingroup AscendCL * @brief Stop the channel diff --git a/inc/external/acl/error_codes/ge_error_codes.h b/inc/external/acl/error_codes/ge_error_codes.h index cc3fbedc..550471cf 100644 --- a/inc/external/acl/error_codes/ge_error_codes.h +++ b/inc/external/acl/error_codes/ge_error_codes.h @@ -59,6 +59,7 @@ static const uint32_t ACL_ERROR_GE_SHAPE_INVALID = 145021U; static const uint32_t ACL_ERROR_GE_DATATYPE_INVALID = 145022U; static const uint32_t ACL_ERROR_GE_MEMORY_ALLOCATION = 245000U; static const uint32_t ACL_ERROR_GE_MEMORY_OPERATE_FAILED = 245001U; +static const uint32_t ACL_ERROR_GE_DEVICE_MEMORY_OPERATE_FAILED = 245002U; static const uint32_t ACL_ERROR_GE_INTERNAL_ERROR = 545000U; static const uint32_t ACL_ERROR_GE_LOAD_MODEL = 545001U; static const uint32_t ACL_ERROR_GE_EXEC_LOAD_MODEL_PARTITION_FAILED = 545002U; diff --git a/inc/external/acl/error_codes/rt_error_codes.h b/inc/external/acl/error_codes/rt_error_codes.h index a060dfdb..daeca17c 100644 --- a/inc/external/acl/error_codes/rt_error_codes.h +++ b/inc/external/acl/error_codes/rt_error_codes.h @@ -45,6 +45,7 @@ static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type static const int32_t ACL_ERROR_RT_WAIT_TIMEOUT = 107019; // wait timeout +static const int32_t ACL_ERROR_RT_TASK_TIMEOUT = 107020; // task timeout static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error diff --git a/inc/external/ge/ge_api_types.h b/inc/external/ge/ge_api_types.h index 2ad7dd99..f513cd51 100644 --- a/inc/external/ge/ge_api_types.h +++ b/inc/external/ge/ge_api_types.h @@ -120,6 +120,8 @@ const char_t *const PERFORMANCE_MODE = "ge.performance_mode"; const char_t *const SHAPE_GENERALIZED_BUILD_MODE = "ge.shape_generalized_build_mode"; const char_t *const MODIFY_MIXLIST = "ge.exec.modify_mixlist"; const char_t *const OP_PRECISION_MODE = "ge.exec.op_precision_mode"; +const char_t *const CUSTOMIZE_DTYPES = "ge.customizeDtypes"; +const char_t *const COMPRESSION_OPTIMIZE_CONF = "ge.compressionOptimizeConf"; } // namespace configure_option // Configure stream num by Session constructor options param, // its value should be int32_t type, default value is "1" @@ -268,9 +270,18 @@ const std::string ENABLE_SMALL_CHANNEL = "ge.enableSmallChannel"; // Configure Compress Weight flag const std::string ENABLE_COMPRESS_WEIGHT = "ge.enableCompressWeight"; +// Configure Sparse Matrix Weight flag +const std::string ENABLE_SPARSE_MATRIX_WEIGHT = "ge.enableSparseMatrixWeight"; + // Configure fusion switch file path const std::string FUSION_SWITCH_FILE = "ge.fusionSwitchFile"; +// Configure compression optimize file path +const std::string COMPRESSION_OPTIMIZE_CONF = "ge.compressionOptimizeConf"; + +// Configure customize dtypes path +const std::string CUSTOMIZE_DTYPES = "ge.customizeDtypes"; + // Save original model const std::string SAVE_ORIGINAL_MODEL = "ge.saveOriginalModel"; @@ -289,6 +300,10 @@ const char_t *const ENABLE_PRINT_OP_PASS = "ge.enablePrintOpPass"; // Its value should be file path, default value is "./" const char_t *const DEBUG_DIR = "ge.debugDir"; +// Configure switch for op status check such as overflow +// Its value should be true of flase +const char_t *const STATUS_CHECK = "ge.status_check"; + // Configure operator compiler cache path // Its value should be file path, default value is "./" const char_t *const OP_COMPILER_CACHE_DIR = "ge.op_compiler_cache_dir"; @@ -411,6 +426,7 @@ static const char_t *const OP_SELECT_IMPL_MODE = ge::OP_SELECT_IMPL_MODE.c_str() static const char_t *const OUTPUT_TYPE = ge::OUTPUT_DATATYPE.c_str(); static const char_t *const BUFFER_OPTIMIZE = ge::BUFFER_OPTIMIZE.c_str(); static const char_t *const ENABLE_COMPRESS_WEIGHT = ge::ENABLE_COMPRESS_WEIGHT.c_str(); +static const char_t *const SPARSITY = ge::ENABLE_SPARSE_MATRIX_WEIGHT.c_str(); static const char_t *const COMPRESS_WEIGHT_CONF = "compress_weight_conf"; static const char_t *const OUT_NODES = ge::OUTPUT_NODE_NAME.c_str(); static const char_t *const INPUT_FP16_NODES = ge::INPUT_FP16_NODES.c_str(); @@ -427,6 +443,8 @@ static const char_t *const PERFORMANCE_MODE = ge::PERFORMANCE_MODE.c_str(); static const char_t *const SHAPE_GENERALIZED_BUILD_MODE = ge::SHAPE_GENERALIZED_BUILD_MODE.c_str(); static const char_t *const MODIFY_MIXLIST = ge::MODIFY_MIXLIST.c_str(); static const char_t *const OP_PRECISION_MODE = ge::OP_PRECISION_MODE.c_str(); +static const char_t *const CUSTOMIZE_DTYPES = "ge.customizeDtypes"; +static const char_t *const COMPRESSION_OPTIMIZE_CONF = "ge.compressionOptimizeConf"; // for interface: aclgrphBuildModel #ifdef __GNUC__ @@ -456,7 +474,8 @@ const std::set ir_builder_suppported_options = {INPUT_FORMAT, OP_BANK_UPDATE, PERFORMANCE_MODE, SHAPE_GENERALIZED_BUILD_MODE, - MODIFY_MIXLIST}; + MODIFY_MIXLIST, + CUSTOMIZE_DTYPES}; // for interface: aclgrphParse const std::set ir_parser_suppported_options = { @@ -469,6 +488,7 @@ const std::set global_options = {CORE_TYPE, BUFFER_OPTIMIZE, ENABLE_COMPRESS_WEIGHT, COMPRESS_WEIGHT_CONF, + SPARSITY, PRECISION_MODE, TUNE_DEVICE_IDS, EXEC_DISABLE_REUSED_MEMORY, @@ -483,7 +503,8 @@ const std::set global_options = {CORE_TYPE, DEBUG_DIR, OP_COMPILER_CACHE_DIR, OP_COMPILER_CACHE_MODE, - MODIFY_MIXLIST}; + MODIFY_MIXLIST, + COMPRESSION_OPTIMIZE_CONF}; #endif } // namespace ir_option } // namespace ge diff --git a/inc/external/ge/ge_error_codes.h b/inc/external/ge/ge_error_codes.h index cc3fbedc..550471cf 100644 --- a/inc/external/ge/ge_error_codes.h +++ b/inc/external/ge/ge_error_codes.h @@ -59,6 +59,7 @@ static const uint32_t ACL_ERROR_GE_SHAPE_INVALID = 145021U; static const uint32_t ACL_ERROR_GE_DATATYPE_INVALID = 145022U; static const uint32_t ACL_ERROR_GE_MEMORY_ALLOCATION = 245000U; static const uint32_t ACL_ERROR_GE_MEMORY_OPERATE_FAILED = 245001U; +static const uint32_t ACL_ERROR_GE_DEVICE_MEMORY_OPERATE_FAILED = 245002U; static const uint32_t ACL_ERROR_GE_INTERNAL_ERROR = 545000U; static const uint32_t ACL_ERROR_GE_LOAD_MODEL = 545001U; static const uint32_t ACL_ERROR_GE_EXEC_LOAD_MODEL_PARTITION_FAILED = 545002U; diff --git a/inc/external/hccl/hccl_types.h b/inc/external/hccl/hccl_types.h index b018227d..2fe98fde 100644 --- a/inc/external/hccl/hccl_types.h +++ b/inc/external/hccl/hccl_types.h @@ -88,7 +88,6 @@ typedef enum { } HcclDataType; const uint32_t HCCL_ROOT_INFO_BYTES = 4108; // 4108: root info length - /** * @brief HCCL root info */ diff --git a/inc/external/runtime/rt_error_codes.h b/inc/external/runtime/rt_error_codes.h index a060dfdb..daeca17c 100644 --- a/inc/external/runtime/rt_error_codes.h +++ b/inc/external/runtime/rt_error_codes.h @@ -45,6 +45,7 @@ static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type static const int32_t ACL_ERROR_RT_WAIT_TIMEOUT = 107019; // wait timeout +static const int32_t ACL_ERROR_RT_TASK_TIMEOUT = 107020; // task timeout static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error diff --git a/inc/framework/common/debug/log.h b/inc/framework/common/debug/log.h index 07affc3f..a796670c 100644 --- a/inc/framework/common/debug/log.h +++ b/inc/framework/common/debug/log.h @@ -129,86 +129,6 @@ } \ } -// If expr is not true, print the log and execute a custom statement -#define GE_CHK_BOOL_EXEC_WARN(expr, exec_expr, ...) \ - { \ - const bool b = (expr); \ - if (!b) { \ - GELOGW(__VA_ARGS__); \ - exec_expr; \ - } \ - } -// If expr is not true, print the log and execute a custom statement -#define GE_CHK_BOOL_EXEC_INFO(expr, exec_expr, ...) \ - { \ - const bool b = (expr); \ - if (!b) { \ - GELOGI(__VA_ARGS__); \ - exec_expr; \ - } \ - } - -// If expr is not true, print the log and execute a custom statement -#define GE_CHK_BOOL_TRUE_EXEC_INFO(expr, exec_expr, ...) \ - { \ - const bool b = (expr); \ - if (b) { \ - GELOGI(__VA_ARGS__); \ - exec_expr; \ - } \ - } - -// If expr is true, print logs and execute custom statements -#define GE_CHK_BOOL_TRUE_EXEC_WITH_LOG(expr, exec_expr, ...) \ - { \ - const bool b = (expr); \ - if (b) { \ - GELOGE(ge::FAILED, __VA_ARGS__); \ - exec_expr; \ - } \ - } -// If expr is true, print the Information log and execute a custom statement -#define GE_CHK_TRUE_EXEC_INFO(expr, exec_expr, ...) \ - { \ - const bool b = (expr); \ - if (b) { \ - GELOGI(__VA_ARGS__); \ - exec_expr; \ - } \ - } - -// If expr is not SUCCESS, print the log and execute the expression + return -#define GE_CHK_BOOL_TRUE_RET_VOID(expr, exec_expr, ...) \ - { \ - const bool b = (expr); \ - if (b) { \ - GELOGE(ge::FAILED, __VA_ARGS__); \ - exec_expr; \ - return; \ - } \ - } - -// If expr is not SUCCESS, print the log and execute the expression + return _status -#define GE_CHK_BOOL_TRUE_EXEC_RET_STATUS(expr, _status, exec_expr, ...) \ - { \ - const bool b = (expr); \ - if (b) { \ - REPORT_INNER_ERROR("E19999", __VA_ARGS__); \ - GELOGE(ge::FAILED, __VA_ARGS__); \ - exec_expr; \ - return (_status); \ - } \ - } - -// If expr is not true, execute a custom statement -#define GE_CHK_BOOL_EXEC_NOLOG(expr, exec_expr) \ - { \ - const bool b = (expr); \ - if (!b) { \ - exec_expr; \ - } \ - } - // -----------------runtime related macro definitions------------------------------- // If expr is not RT_ERROR_NONE, print the log #define GE_CHK_RT(expr) \ diff --git a/inc/framework/common/fmk_error_codes.h b/inc/framework/common/fmk_error_codes.h index 1ecd96cb..00610af5 100644 --- a/inc/framework/common/fmk_error_codes.h +++ b/inc/framework/common/fmk_error_codes.h @@ -42,9 +42,9 @@ #include "register/register_error_codes.h" // Each module uses the following four macros to define error codes: -#define DECLARE_ERRORNO_OMG(name, value) DECLARE_ERRORNO(SYSID_FWK, MODID_OMG, (name), (value)) -#define DECLARE_ERRORNO_OME(name, value) DECLARE_ERRORNO(SYSID_FWK, MODID_OME, (name), (value)) -#define DECLARE_ERRORNO_CALIBRATION(name, value) DECLARE_ERRORNO(SYSID_FWK, MODID_CALIBRATION, (name), (value)) +#define DECLARE_ERRORNO_OMG(name, value) DECLARE_ERRORNO(SYSID_FWK, MODID_OMG, name, value) +#define DECLARE_ERRORNO_OME(name, value) DECLARE_ERRORNO(SYSID_FWK, MODID_OME, name, value) +#define DECLARE_ERRORNO_CALIBRATION(name, value) DECLARE_ERRORNO(SYSID_FWK, MODID_CALIBRATION, name, value) #define DEF_ERRORNO(name, desc) const ErrorNoRegisterar g_##name##_errorno((name), (desc)); diff --git a/inc/framework/common/ge_types.h b/inc/framework/common/ge_types.h index f1f6e54a..74a386a7 100644 --- a/inc/framework/common/ge_types.h +++ b/inc/framework/common/ge_types.h @@ -88,11 +88,12 @@ constexpr uint64_t kInferSessionId = 0U; constexpr uint64_t kReleaseFlag = 1U; constexpr uint32_t kInvalidModelId = 0xFFFFFFFFU; constexpr size_t kNumTaskWithAtomicAddrCleanTask = 2U; +constexpr uint32_t INVALID_MODEL_ID = 0xFFFFFFFFUL; // dynamic execute mode const char_t *const kLazyRecompile = "lazy_recompile"; -constexpr size_t kMaxHostMemInputLen = 64U; +constexpr size_t kMaxHostMemInputLen = 128U; // 64 aligned // Data cache, including data address and length struct DataBuffer { @@ -239,6 +240,19 @@ struct ModelData { std::string om_name; // om file name, used for data dump }; +struct ModelParam { + ModelParam() : priority(0), mem_base(0U), mem_size(0U), weight_base(0U), weight_size(0U) {} + ModelParam(const int32_t pri, const uintptr_t m_base, const size_t m_len, const uintptr_t w_base, const size_t w_len) + : priority(pri), mem_base(m_base), mem_size(m_len), weight_base(w_base), weight_size(w_len) {} + ~ModelParam() = default; + + int32_t priority; + uintptr_t mem_base; + size_t mem_size; + uintptr_t weight_base; + size_t weight_size; +}; + // The definition of Model information struct ModelInfo { uint32_t version = 0U; @@ -314,7 +328,7 @@ struct TaskDescInfo { std::vector output_format; std::vector> output_shape; std::vector output_data_type; - uint32_t context_id; + uint32_t context_id = 0xFFFFFFFFUL; }; struct OpDescInfo { diff --git a/inc/framework/common/helper/model_helper.h b/inc/framework/common/helper/model_helper.h index 3dc7c704..fda86b19 100644 --- a/inc/framework/common/helper/model_helper.h +++ b/inc/framework/common/helper/model_helper.h @@ -35,11 +35,11 @@ class GE_FUNC_VISIBILITY ModelHelper { Status SaveToOmModel(const GeModelPtr &ge_model, const SaveParam &save_param, const std::string &output_file, ge::ModelBufferData &model) const; Status SaveToOmRootModel(const GeRootModelPtr &ge_root_model, const SaveParam &save_param, - const std::string &output_file, ModelBufferData &model, const bool is_unknown_shape); - Status SaveOriginalGraphToOmModel(const ge::Graph &graph, const std::string &output_file); + const std::string &output_file, ModelBufferData &model, const bool is_unknown_shape) const; + Status SaveOriginalGraphToOmModel(const ge::Graph &graph, const std::string &output_file) const; Status LoadModel(const ge::ModelData &model_data); Status LoadRootModel(const ge::ModelData &model_data); - static void SetModelToGeModel(GeModelPtr &ge_model, Model &model); + static void SetModelToGeModel(const GeModelPtr &ge_model, Model &model); GeModelPtr GetGeModel(); GeRootModelPtr GetGeRootModel(); @@ -52,7 +52,7 @@ class GE_FUNC_VISIBILITY ModelHelper { } Status GetBaseNameFromFileName(const std::string &file_name, std::string &base_name) const; - Status GetModelNameFromMergedGraphName(const std::string &graph_name, std::string &model_name) const; + Status GetModelNameFromMergedGraphName(const ComputeGraphPtr &compute_graph, std::string &model_name) const; private: bool is_assign_model_ = false; @@ -64,18 +64,21 @@ class GE_FUNC_VISIBILITY ModelHelper { ModelHelper(const ModelHelper &) = default; ModelHelper &operator=(const ModelHelper &) = default; - Status GenerateGeModel(OmFileLoadHelper &om_load_helper); - Status GenerateGeRootModel(OmFileLoadHelper &om_load_helper); - Status LoadModelData(OmFileLoadHelper &om_load_helper); - Status LoadModelData(OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model, const size_t mode_index) const; - Status LoadWeights(OmFileLoadHelper &om_load_helper); - Status LoadWeights(OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model, const size_t mode_index) const; - Status LoadTask(OmFileLoadHelper &om_load_helper); - Status LoadTask(OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model, const size_t mode_index) const; - Status LoadTBEKernelStore(OmFileLoadHelper &om_load_helper); - Status LoadTBEKernelStore(OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model, const size_t mode_index) const; - Status LoadCustAICPUKernelStore(OmFileLoadHelper &om_load_helper); - Status LoadCustAICPUKernelStore(OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model, + + bool IsPartitionedGraph(const GeModelPtr &cur_model) const; + + Status GenerateGeModel(const OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model, const size_t mode_index, + const bool is_dyn_root); + Status GenerateGeRootModel(const OmFileLoadHelper &om_load_helper); + + Status LoadModelData(const OmFileLoadHelper &om_load_helper, const GeModelPtr &cur_model, + const size_t mode_index) const; + Status LoadWeights(const OmFileLoadHelper &om_load_helper, const GeModelPtr &cur_model, + const size_t mode_index) const; + Status LoadTask(const OmFileLoadHelper &om_load_helper, const GeModelPtr &cur_model, const size_t mode_index) const; + Status LoadTBEKernelStore(const OmFileLoadHelper &om_load_helper, const GeModelPtr &cur_model, + const size_t mode_index) const; + Status LoadCustAICPUKernelStore(const OmFileLoadHelper &om_load_helper, const GeModelPtr &cur_model, const size_t mode_index) const; Status SaveModelPartition(std::shared_ptr &om_file_save_helper, const ModelPartitionType type, diff --git a/inc/framework/common/helper/om_file_helper.h b/inc/framework/common/helper/om_file_helper.h index 2d715486..4ec5fa75 100644 --- a/inc/framework/common/helper/om_file_helper.h +++ b/inc/framework/common/helper/om_file_helper.h @@ -48,7 +48,7 @@ struct SaveParam { class GE_FUNC_VISIBILITY OmFileLoadHelper { public: - Status Init(const ge::ModelData &model); + Status Init(const ModelData &model); Status Init(uint8_t *const model_data, const uint32_t model_data_size); @@ -56,16 +56,15 @@ class GE_FUNC_VISIBILITY OmFileLoadHelper { Status GetModelPartition(const ModelPartitionType type, ModelPartition &partition); - Status GetModelPartition(const ModelPartitionType type, ModelPartition &partition, const size_t model_index); + Status GetModelPartition(const ModelPartitionType type, ModelPartition &partition, const size_t model_index) const; OmFileContext context_; std::vector model_contexts_; private: - Status CheckModelValid(const ge::ModelData &model) const; - - Status LoadModelPartitionTable(uint8_t *const model_data, const uint32_t model_data_size); + Status LoadModelPartitionTable(uint8_t *const model_data, const uint32_t model_data_size, const size_t model_index, + size_t &mem_offset); Status LoadModelPartitionTable(uint8_t *const model_data, const uint32_t model_data_size, const uint32_t model_num); @@ -78,9 +77,7 @@ class GE_FUNC_VISIBILITY OmFileSaveHelper { return model_header_; } - uint32_t GetModelDataSize() const { - return context_.model_data_len_; - } + uint32_t GetModelDataSize() const; ModelPartitionTable *GetPartitionTable(); @@ -88,20 +85,19 @@ class GE_FUNC_VISIBILITY OmFileSaveHelper { Status AddPartition(const ModelPartition &partition, const size_t cur_index); - Status SaveModel(const SaveParam &save_param, const char_t *const output_file, ge::ModelBufferData &model, + Status SaveModel(const SaveParam &save_param, const char_t *const output_file, ModelBufferData &model, const bool is_offline = true); - Status SaveModelToFile(const char_t *const output_file, ge::ModelBufferData &model, const bool is_offline = true); - - std::vector model_contexts_; - - ModelFileHeader model_header_; - OmFileContext context_; + Status SaveModelToFile(const char_t *const output_file, ModelBufferData &model, const bool is_offline = true); ModelPartitionTable *GetPartitionTable(const size_t cur_ctx_index); Status SaveRootModel(const SaveParam &save_param, const char_t *const output_file, ModelBufferData &model, const bool is_offline); + + private: + ModelFileHeader model_header_; + std::vector model_contexts_; }; } // namespace ge #endif // INC_FRAMEWORK_COMMON_HELPER_OM_FILE_HELPER_H_ diff --git a/inc/framework/common/profiling_definitions.h b/inc/framework/common/profiling_definitions.h index 6522486b..5506fa5d 100644 --- a/inc/framework/common/profiling_definitions.h +++ b/inc/framework/common/profiling_definitions.h @@ -49,7 +49,12 @@ enum { kAtomic, kKernelLaunchPrepare, kRtKernelLaunch, + kRtEventCreateRecord, + kRtEventSync, + kRtEventDestroy, + kRtStreamSync, kOpExecute, + kModelExecute, kAllocMem, kCopyH2D, kPrepareNode, @@ -67,6 +72,33 @@ enum { kSelectBranch, kExecuteSubGraph, kInitSubGraphExecutor, + // fuzz compile + kSelectBin, + kFindCompileCache, + kAddCompileCache, + kFuzzCompileOp, + kCalcRuningParam, + kGenTask, + kRegisterBin, + + // FFTS Plus + kFftsPlusPreThread, + kFftsPlusNodeThread, + kFftsPlusInferShape, + kOpFftsCalculateV2, + kInitThreadRunInfo, + kFftsPlusGraphSchedule, + kKnownGetAddrAndPrefCnt, + kKernelGetAddrAndPrefCnt, + kUpdateAddrAndPrefCnt, + kInitOpRunInfo, + kGetAutoThreadParam, + kAllocateOutputs, + kAllocateWorkspaces, + kInitTaskAddrs, + kInitThreadRunParam, + kUpdateTaskAndCache, + kFftsPlusTaskLaunch, // Add new definitions here kProfilingIndexEnd @@ -88,7 +120,7 @@ class ProfilingContext { * 因此编译时注册字符串的动作并没有生效。在执行时,动态的打开了profiling,这种场景下,执行时无法拿到注册后字符串 */ bool IsEnabled() const noexcept { - return enabled_ && profiler_ != nullptr; + return enabled_ && (profiler_ != nullptr); } void SetEnable() noexcept { enabled_ = true; @@ -184,5 +216,6 @@ class ScopeProfiler { ge::profiling::ProfilingContext::GetInstance().RecordCurrentThread((element), (event), \ ge::profiling::EventType::kEventEnd) #define PROFILING_SCOPE(element, event) ge::profiling::ScopeProfiler profiler((element), (event)) +#define PROFILING_SCOPE_CONST(element, event) const ge::profiling::ScopeProfiler profiler((element), (event)) #define PROFILING_SCOPE_ELEMENT(element) profiler.SetElement((element)) #endif // AIR_CXX_PROFILING_DEFINITIONS_H diff --git a/inc/framework/common/types.h b/inc/framework/common/types.h index 475def7f..a4df4e2f 100644 --- a/inc/framework/common/types.h +++ b/inc/framework/common/types.h @@ -17,13 +17,10 @@ #ifndef INC_FRAMEWORK_COMMON_TYPES_H_ #define INC_FRAMEWORK_COMMON_TYPES_H_ -#include #include #include #include #include -#include -#include #include "framework/common/fmk_error_codes.h" #include "framework/common/fmk_types.h" @@ -47,6 +44,8 @@ FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string PROFIL FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string MODEL_ATTR_TASKS; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string MODEL_ATTR_TASK_GEN_BASE_ADDR; +FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string MODEL_ATTR_TASK_GEN_HOST_BASE_ADDR; +FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string MODEL_ATTR_HOST_MEMORY_SIZE; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string MODEL_ATTR_TASK_GEN_WEIGHT_ADDR; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const std::string MODEL_ATTR_FUSION_MODEL_DEF; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const uint64_t ALLOC_MEMORY_MAX_SIZE; // Max size of 8 GB. diff --git a/inc/framework/common/util.h b/inc/framework/common/util.h index 6a7a1455..666f5ccd 100644 --- a/inc/framework/common/util.h +++ b/inc/framework/common/util.h @@ -231,17 +231,20 @@ constexpr int32_t OM_PROTO_VERSION = 2; /// @return string /// template -GE_FUNC_VISIBILITY std::string ToString(std::vector &v) { +GE_FUNC_VISIBILITY std::string ToString(const std::vector &v) { + bool first = true; std::stringstream ss; ss << "["; - for (const T x : v) { - ss << x; - ss << ", "; + for (const T &x : v) { + if (first) { + first = false; + ss << x; + } else { + ss << ", " << x; + } } - // Delete the two extra characters at the end of the line. - std::string str = ss.str().substr(0U, ss.str().length() - 2U); - str += "]"; - return str; + ss << "]"; + return ss.str(); } /// diff --git a/inc/framework/executor/ge_executor.h b/inc/framework/executor/ge_executor.h index 66b95180..a3f7cea1 100644 --- a/inc/framework/executor/ge_executor.h +++ b/inc/framework/executor/ge_executor.h @@ -27,7 +27,6 @@ #include "framework/common/types.h" #include "graph/tensor.h" #include "graph/ge_tensor.h" -#include "runtime/base.h" namespace ge { class SingleOp; diff --git a/inc/framework/omg/omg.h b/inc/framework/omg/omg.h index cab51e0d..0d8b59d1 100644 --- a/inc/framework/omg/omg.h +++ b/inc/framework/omg/omg.h @@ -17,10 +17,12 @@ #ifndef INC_FRAMEWORK_OMG_OMG_H_ #define INC_FRAMEWORK_OMG_OMG_H_ -#include #include #include #include + +#include +#include "external/ge/ge_api_types.h" #include "framework/omg/omg_inner_types.h" #include "framework/omg/parser/parser_inner_ctx.h" #include "proto/ge_ir.pb.h" @@ -31,20 +33,14 @@ #include "graph/model.h" #include "runtime/kernel.h" -using domi::Status; -using std::pair; -using std::string; -using std::unordered_map; -using std::vector; - namespace ge { /** * @ingroup domi_omg * @brief init omg context * @return void */ -GE_FUNC_VISIBILITY Status InitDomiOmgContext(const std::string &input_shape, const std::string &input_format, - const std::string &net_format, bool is_dynamic_input); +GE_FUNC_VISIBILITY domi::Status InitDomiOmgContext(const std::string &input_shape, const std::string &input_format, + const std::string &net_format, bool is_dynamic_input); /** * @ingroup domi_omg @@ -61,10 +57,10 @@ GE_FUNC_VISIBILITY Status InitDomiOmgContext(const std::string &input_shape, con * @param [in] atc_params multiply atc params * @return Status result code */ -GE_FUNC_VISIBILITY Status ParseGraph(ge::Graph &graph, const std::map &atc_params, - const char *model_file, const char *weights_file, domi::FrameworkType type, - const char *op_conf = nullptr, const char *target = nullptr, - RunMode run_mode = RunMode::GEN_OM_MODEL, bool is_dynamic_input = false); +GE_FUNC_VISIBILITY domi::Status ParseGraph(ge::Graph &graph, const std::map &atc_params, + const char *model_file, const char *weights_file, domi::FrameworkType type, + const char *op_conf = nullptr, const char *target = nullptr, + RunMode run_mode = RunMode::GEN_OM_MODEL, bool is_dynamic_input = false); /** * @ingroup domi_omg @@ -74,9 +70,9 @@ GE_FUNC_VISIBILITY Status ParseGraph(ge::Graph &graph, const std::map &file_list, std::string &caffe_parser_path); -GE_FUNC_VISIBILITY Status DumpInfershapeJson(const ge::Graph &graph, const char *json_file); +GE_FUNC_VISIBILITY domi::Status DumpInfershapeJson(const ge::Graph &graph, const char *json_file); -GE_FUNC_VISIBILITY Status SetOutputNodeInfo(ge::Graph &graph, const std::string &output_type, - const std::string &output); +GE_FUNC_VISIBILITY domi::Status SetOutputNodeInfo(ge::Graph &graph, const std::string &output_type, + const std::string &output); -GE_FUNC_VISIBILITY Status GetOutputLeaf(ge::NodePtr node, - std::vector> &output_nodes_info); +GE_FUNC_VISIBILITY domi::Status GetOutputLeaf(ge::NodePtr node, + std::vector> &output_nodes_info); GE_FUNC_VISIBILITY void CreateOutputNodesInfo(std::vector> &output_nodes_info, std::vector &output_nodes_name); diff --git a/inc/framework/pne/pne_model.h b/inc/framework/pne/pne_model.h new file mode 100644 index 00000000..1721d09c --- /dev/null +++ b/inc/framework/pne/pne_model.h @@ -0,0 +1,128 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. + * + * 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. + */ + +#ifndef INC_FRAMEWORK_PNE_MODEL_H_ +#define INC_FRAMEWORK_PNE_MODEL_H_ + +#include +#include +#include + +#include "graph/compute_graph.h" +#include "framework/common/debug/log.h" +#include "framework/common/ge_inner_error_codes.h" +#include "framework/common/ge_types.h" +#include "framework/engine/dnnengine.h" +#include "external/ge/ge_ir_build.h" + +namespace ge { +const std::string PNE_ID_NPU = "NPU"; +const std::string PNE_ID_CPU = "HOST_CPU"; + +struct ModelRelation; +class PneModel { + public: + PneModel() = default; + explicit PneModel(const ComputeGraphPtr &root_graph) : root_graph_(root_graph){}; + virtual ~PneModel() = default; + PneModel(const PneModel &other) = delete; + PneModel &operator=(const PneModel &other) = delete; + + public: + inline Status AddSubModel(const shared_ptr &submodel, std::string type = "") { + if (submodel == nullptr) { + GELOGE(INTERNAL_ERROR, "submodel is nullptr, type = %s", type.c_str()); + return INTERNAL_ERROR; + } + submodel->SetModelType(type); + if (!submodels_.emplace(submodel->GetModelName(), submodel).second) { + GELOGE(INTERNAL_ERROR, "submodel already exist, name = %s, type = %s", submodel->GetModelName().c_str(), + type.c_str()); + return INTERNAL_ERROR; + } + return SUCCESS; + } + + inline const std::shared_ptr GetSubmodel(const std::string &name) const { + const auto &it = submodels_.find(name); + if (it == submodels_.end()) { + return nullptr; + } + return it->second; + } + + inline const std::map> &GetSubmodels() const { + return submodels_; + } + + inline void SetModelType(const std::string &type) { + model_type_ = type; + } + + inline const std::string &GetModelType() const { + return model_type_; + } + + inline void SetModelName(const std::string &model_name) { + model_name_ = model_name; + } + + inline const std::string &GetModelName() const { + return model_name_; + } + + inline void SetRootGraph(const ComputeGraphPtr graph) { + root_graph_ = graph; + } + + inline const ComputeGraphPtr &GetRootGraph() const { + return root_graph_; + } + + inline void SetModelRelation(std::shared_ptr model_relation) { + model_relation_ = std::move(model_relation); + } + + inline const std::shared_ptr GetModelRelation() const { + return model_relation_; + } + + public: + virtual Status SerializeModel(ModelBufferData &model_buff) = 0; + + virtual Status UnSerializeModel(const ModelBufferData &model_buff) = 0; + + virtual void SetModelId(const uint32_t model_id) { + model_id_ = model_id; + } + + virtual uint32_t GetModelId() const { + return model_id_; + } + + private: + std::map> submodels_; + std::shared_ptr model_relation_; + ComputeGraphPtr root_graph_ = nullptr; + std::string model_name_; + std::string model_type_; + uint32_t model_id_ = INVALID_MODEL_ID; +}; + +using PneModelPtr = std::shared_ptr; +} // namespace ge + +#endif // INC_FRAMEWORK_PNE_MODEL_H_ diff --git a/inc/framework/pne/process_node_engine.h b/inc/framework/pne/process_node_engine.h new file mode 100644 index 00000000..55ceac8b --- /dev/null +++ b/inc/framework/pne/process_node_engine.h @@ -0,0 +1,55 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. + * + * 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. + */ + +#ifndef INC_FRAMEWORK_PROCESS_NODE_ENGINE_H_ +#define INC_FRAMEWORK_PROCESS_NODE_ENGINE_H_ + +#include +#include +#include + +#include "framework/common/ge_inner_error_codes.h" +#include "framework/common/ge_types.h" +#include "graph/manager/graph_manager_utils.h" +#include "framework/pne/pne_model.h" + +namespace ge { +class ProcessNodeEngine { + public: + ProcessNodeEngine() = default; + virtual ~ProcessNodeEngine() = default; + ProcessNodeEngine(const ProcessNodeEngine &other) = delete; + ProcessNodeEngine &operator=(const ProcessNodeEngine &other) = delete; + + public: + virtual Status Initialize(const std::map &options) = 0; + + virtual Status Finalize() = 0; + + virtual Status OptimizeGraph(const std::vector &inputs, ComputeGraphPtr &compute_graph) = 0; + + virtual Status BuildGraph(ComputeGraphPtr &compute_graph, PneModelPtr &model) = 0; + + virtual const std::string &GetEngineName(const ge::NodePtr &node_ptr = nullptr) const = 0; + + protected: + std::string engine_id_; +}; + +using ProcessNodeEnginePtr = std::shared_ptr; +} // namespace ge + +#endif // INC_FRAMEWORK_PROCESS_NODE_ENGINE_H_ diff --git a/metadef b/metadef index ab3207e9..f3e9df35 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit ab3207e99f94aabf036e1c8b068de0df15ff2d01 +Subproject commit f3e9df35da67ff00a22a09ec5b369bbc4bac9e74 diff --git a/third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h b/third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h deleted file mode 100644 index ceae0f0f..00000000 --- a/third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h +++ /dev/null @@ -1,84 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef AICPU_TASK_STRUCT_H_ -#define AICPU_TASK_STRUCT_H_ - -#include - -namespace aicpu { - -#pragma pack(push, 1) -struct AicpuParamHead -{ - uint32_t length; // Total length: include cunstom message - uint32_t ioAddrNum; // Input and output address number - uint32_t extInfoLength; // extInfo struct Length - uint64_t extInfoAddr; // extInfo address -}; - -enum class AicpuConfigMsgType { - AICPU_CONFIG_MSG_TYPE_BUF_FREE = 0, /* free buf */ - AICPU_CONFIG_MSG_TYPE_BUF_RESET = 1, /* reset buf */ - AICPU_CONFIG_MSG_TYPE_BUF_SET_ADDR = 2, /* set buf addr to aicpu */ -}; - -enum class AicpuErrMsgType { - ERR_MSG_TYPE_NULL = 0, - ERR_MSG_TYPE_AICORE = 1, - ERR_MSG_TYPE_AICPU = 2, -}; - -typedef struct tagAicpuConfigMsg { - uint8_t msgType; - uint8_t reserved1; - uint16_t bufLen; - uint32_t offset; - uint64_t bufAddr; - uint32_t tsId; - uint32_t reserved2; -} AicpuConfigMsg; - -typedef struct tagAicoreErrMsgInfo { - uint8_t errType; - uint8_t version; - uint8_t reserved1[2]; /* reserved1, 4 byte alignment */ - uint32_t errorCode; - uint32_t modelId; - uint32_t taskId; - uint32_t streamId; - uint64_t transactionId; - uint8_t reserved2[228]; /* the total byte is 256, reserved2 len = 256 - other lens */ -} AicoreErrMsgInfo; - -typedef struct tagAicpuErrMsgInfo { - uint8_t errType; - uint8_t version; - uint8_t reserved1[2]; /* reserved1, 4 byte alignment */ - uint32_t errorCode; - uint32_t modelId; - uint32_t streamId; - uint64_t transactionId; - char opName[64]; /* op name str */ - char errDesc[128]; /* err msg desc info */ - uint8_t reserved2[40]; /* the total byte is 256, reserved2 len = 256 - other lens */ -} AicpuErrMsgInfo; -#pragma pack(pop) - -} // namespace aicpu - -#endif // AICPU_TASK_STRUCT_H_ - diff --git a/third_party/fwkacllib/inc/common/type_def.h b/third_party/fwkacllib/inc/common/type_def.h deleted file mode 100644 index 1bbaf32d..00000000 --- a/third_party/fwkacllib/inc/common/type_def.h +++ /dev/null @@ -1,52 +0,0 @@ -/** -* Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -* -* Description:interface. -* Create: 2021-12-21 -*/ -#ifndef AICPU_TYPE_DEF_H -#define AICPU_TYPE_DEF_H - -#include -#include -#ifndef char_t -typedef char char_t; -#endif - -#ifndef float32_t -typedef float float32_t; -#endif - -#ifndef float64_t -typedef double float64_t; -#endif - -inline uint64_t PtrToValue(const void *ptr) -{ - return static_cast(reinterpret_cast(ptr)); -} - -inline void *ValueToPtr(const uint64_t value) -{ - return reinterpret_cast(static_cast(value)); -} - -template -inline TO *PtrToPtr(TI *ptr) -{ - return reinterpret_cast(ptr); -} - -template -inline T *PtrAdd(T * const ptr, const size_t maxIdx, const size_t idx) -{ - if ((ptr != nullptr) && (idx < maxIdx)) { - return reinterpret_cast(ptr + idx); - } - return nullptr; -} -#endif // AICPU_TYPE_DEF_H diff --git a/third_party/fwkacllib/inc/hccl/base.h b/third_party/fwkacllib/inc/hccl/base.h index 4dd9e023..8ca4015c 100644 --- a/third_party/fwkacllib/inc/hccl/base.h +++ b/third_party/fwkacllib/inc/hccl/base.h @@ -197,6 +197,20 @@ typedef struct tagCommAttr { WorkMode mode; // ͨڵprobeģʽ uint32_t deviceId = 0; } CommAttr; + +typedef void* HcclMessage; +typedef void* HcclRequest; + +typedef struct { + int srcRank; // /̽⵽msg/ŷķͶrank_idMPI׼壬߿Է + int tag; // /̽⵽msg/ŷtagMPI׼壬߿Է + int error; // /̽Ĵ0no errorothers̳MPI׼壬߿Է + int cancelled; // ָʵ֣߷ + int count; // /̽⵽payloadСָʵ֣߷ +} HcclStatus; + +#define HCCL_REQUEST_NULL NULL + #ifdef __cplusplus } #endif // __cplusplus diff --git a/third_party/fwkacllib/inc/ops/array_ops.h b/third_party/fwkacllib/inc/ops/array_ops.h index ae55234c..37b0f9f5 100644 --- a/third_party/fwkacllib/inc/ops/array_ops.h +++ b/third_party/fwkacllib/inc/ops/array_ops.h @@ -501,6 +501,7 @@ REG_OP(Constant) *@brief Creates a file constant tensor, The operator is used to process the very large weight which is store in file. \n *@par Attributes: +*file_path: A string, used to record file path. \n *file_id: A string, used to record file id. \n *shape: data shape. \n *dtype: data type. \n @@ -511,7 +512,8 @@ REG_OP(Constant) REG_OP(FileConstant) .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT16, DT_UINT16, \ DT_UINT8, DT_INT32, DT_INT64, DT_UINT32, DT_UINT64, DT_BOOL, DT_DOUBLE})) - .REQUIRED_ATTR(file_id, String) + .ATTR(file_path, String, "") + .ATTR(file_id, String, "") .REQUIRED_ATTR(shape, ListInt) .REQUIRED_ATTR(dtype, Type) .OP_END_FACTORY_REG(FileConstant) @@ -1205,6 +1207,39 @@ REG_OP(Copy) .REQUIRED_ATTR(N, Int) .OP_END_FACTORY_REG(Copy); +/** +*@brief copy the src tensor to the dst tensor according the special parameter . \n + +*@par Inputs: +*Eight inputs, including: +*dst: A tensor. Must be one of the following types: +* double, float32, float16, int8, uint8, int16, uint16, int32, uint32, int64, uint64, bool +*dst_size: A tensor with type int32 +*dst_stride: A tensor with type int32 +*dst_storage_offset: A tensor with type int32 +*src: A tensor. Must be one of the following types: +* double, float32, float16, int8, uint8, int16, uint16, int32, uint32, int64, uint64, bool +*src_size: A tensor with type int32 +*src_stride: A tensor with type int32 +*src_storage_offset: the storage_offset of src tensor . \n + +*@par Outputs: +*dst: An ref tensor.Must be one of the following types: +* double, float32, float16, int8, uint8, int16, uint16, int32, uint32, int64, uint64, bool . \n +*/ + +REG_OP(ViewCopy) + .INPUT(dst, TensorType::BasicType()) + .INPUT(dst_size, TensorType::IndexNumberType()) + .INPUT(dst_stride, TensorType::IndexNumberType()) + .INPUT(dst_storage_offset, TensorType::IndexNumberType()) + .INPUT(src, TensorType::BasicType()) + .INPUT(src_size, TensorType::IndexNumberType()) + .INPUT(src_stride, TensorType::IndexNumberType()) + .INPUT(src_storage_offset, TensorType::IndexNumberType()) + .OUTPUT(dst, TensorType::BasicType()) + .OP_END_FACTORY_REG(ViewCopy) + /** *@brief Generates fingerprint values. \n diff --git a/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h b/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h index d0800a08..70eb3272 100644 --- a/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h +++ b/third_party/fwkacllib/inc/ops/avg_pool_1d_ops.h @@ -28,7 +28,7 @@ namespace ge { *@par Inputs: * @li x: A tensor. Must be one of the following types:uint8, int8,int16, int32, - int64, float16, float, double.The format must be NHWC NCHW NC1HWC0. + int64, float16, float, double.The format must be NHWC/NCHW. *@par Attributes: *@li ksize: Kernel size. Input type is int. diff --git a/third_party/fwkacllib/inc/ops/data_flow_ops.h b/third_party/fwkacllib/inc/ops/data_flow_ops.h index 91a59327..3ff6f871 100644 --- a/third_party/fwkacllib/inc/ops/data_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/data_flow_ops.h @@ -2261,6 +2261,33 @@ REG_OP(OutfeedEnqueueOp) .ATTR(channel_name, String, "") .OP_END_FACTORY_REG(OutfeedEnqueueOp) +/** +*@brief Enqueue a Tensor on the computation outfeed. \n + +*@par Inputs: +*Inputs include: +*x: A Tensor. Must be one of the following types: float16, float32, +float64, int8, int16, uint16, uint8, int32, int64, uint32, uint64, +bool, double, string. It's a dynamic input. \n +*tensor_name: A Tensor. Must be string types. \n + +*@par Attributes: +*channel_name: name of operator channel, default "". \n + +*@attention Constraints: +*The implementation for OutfeedEnqueueOpV2 on Ascend uses AICPU, with bad performance. + +*@par Third-party framework compatibility +*@li compatible with tensorflow OutfeedEnqueueOpV2 operator. +*/ +REG_OP(OutfeedEnqueueOpV2) + .DYNAMIC_INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, + DT_INT16, DT_UINT16, DT_UINT8, DT_INT32, DT_INT64, DT_UINT32, + DT_UINT64, DT_BOOL, DT_DOUBLE, DT_STRING})) + .INPUT(tensor_name, TensorType({DT_STRING})) + .ATTR(channel_name, String, "") + .OP_END_FACTORY_REG(OutfeedEnqueueOpV2) + /** *@brief LruCache, create cache resource. *@par Inputs: @@ -2478,5 +2505,24 @@ REG_OP(GetNextFromQueue) .ATTR(output_types, ListType, {}) .ATTR(output_shapes, ListListInt, {{}, {}}) .OP_END_FACTORY_REG(GetNextFromQueue) + +/** +* @brief OptionalGetValue +* @par Inputs: +* optional: A tensor of type variant +* @par Outputs: +* components: A list of Tensor objects of output_types +* @par Attributes: +* output_types: types of all outputs +* output_shapes: shapes of all outputs +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(OptionalGetValue) + .INPUT(optional, TensorType({DT_VARIANT})) + .DYNAMIC_OUTPUT(components, TensorType::BasicType()) + .REQUIRED_ATTR(output_types, ListType) + .REQUIRED_ATTR(output_shapes, ListListInt) + .OP_END_FACTORY_REG(OptionalGetValue) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_DATA_FLOW_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/deep_md.h b/third_party/fwkacllib/inc/ops/deep_md.h index ef335f33..0f5e07c1 100644 --- a/third_party/fwkacllib/inc/ops/deep_md.h +++ b/third_party/fwkacllib/inc/ops/deep_md.h @@ -54,8 +54,6 @@ REG_OP(TabulateFusion) .INPUT(em, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) .OUTPUT(descriptor, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) .REQUIRED_ATTR(last_layer_size, Int) - .ATTR(split_count, Int, 1) - .ATTR(split_index, Int, 0) .OP_END_FACTORY_REG(TabulateFusion) /** @@ -102,9 +100,105 @@ REG_OP(ProdEnvMatA) .ATTR(rcut_r_smth, Float, 1.0) .ATTR(sel_a, ListInt, {}) .ATTR(sel_r, ListInt, {}) - .ATTR(split_count, Int, 1) - .ATTR(split_index, Int, 0) .OP_END_FACTORY_REG(ProdEnvMatA) + +/** +* @brief Calculate ProdEnvMatACalRij. +* Use type, natoms, sel_a, and rcut_r as constraints, find the central element in +* the corresponding coord through mesh, output the index of the central element +* and the distance between the central element and each neighbor. \n +* +* @par Inputs: +* @li coord: A Tensor. Must be one of the following types: float32, float64. +* @li type: A Tensor. Must be one of the following types: int32. +* @li natoms: A Tensor. Must be one of the following types: int32. +* @li box: A Tensor. Must be one of the following types: float32, float64. +* @li mesh: A Tensor. Must be one of the following types: int32. +* +* @par Outputs: +* rij: A Tensor. Must be one of the following types: float32, float64. +* nlist: A Tensor. Must be one of the following types: int32. +* distance: A Tensor. Must be one of the following types: float32, float64. +* rij_x: A Tensor. Must be one of the following types: float32, float64. +* rij_y: A Tensor. Must be one of the following types: float32, float64. +* rij_z: A Tensor. Must be one of the following types: float32, float64. \n +* +* @par Attributes: +* @li rcut_a: A Float. +* @li rcut_r: A Float. +* @li rcut_r_smth: A Float. +* @li sel_a: A ListInt. +* @li sel_r: A ListInt. \n +* +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(ProdEnvMatACalcRij) + .INPUT(coord, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(type, TensorType({DT_INT32})) + .INPUT(natoms, TensorType({DT_INT32})) + .INPUT(box, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(mesh, TensorType({DT_INT32})) + .OUTPUT(rij, TensorType({DT_FLOAT, DT_DOUBLE})) + .OUTPUT(nlist, TensorType({DT_INT32})) + .OUTPUT(distance, TensorType({DT_FLOAT, DT_DOUBLE})) + .OUTPUT(rij_x, TensorType({DT_FLOAT, DT_DOUBLE})) + .OUTPUT(rij_y, TensorType({DT_FLOAT, DT_DOUBLE})) + .OUTPUT(rij_z, TensorType({DT_FLOAT, DT_DOUBLE})) + .ATTR(rcut_a, Float, 1.0) + .ATTR(rcut_r, Float, 1.0) + .ATTR(rcut_r_smth, Float, 1.0) + .ATTR(sel_a, ListInt, {}) + .ATTR(sel_r, ListInt, {}) + .OP_END_FACTORY_REG(ProdEnvMatACalcRij) + +/** +* @brief Calculate ProdEnvMatACalcDescrpt. \n +* +* @par Inputs: +* @li distance: A Tensor. Must be one of the following types: float32, float64. +* @li rij_x: A Tensor. Must be one of the following types: float32, float64. +* @li rij_y: A Tensor. Must be one of the following types: float32, float64. +* @li rij_z: A Tensor. Must be one of the following types: float32, float64. +* @li type: A Tensor. Must be one of the following types: int32. +* @li natoms: A Tensor. Must be one of the following types: int32. +* @li mesh: A Tensor. Must be one of the following types: int32. +* @li davg: A Tensor. Must be one of the following types: float32, float64. +* @li dstd: A Tensor. Must be one of the following types: float32, float64. \n +* +* @par Outputs: +* @li descrpt: A Tensor. Must be one of the following types: float32, float64. +* @li descrpt_deriv: A Tensor. Must be one of the following types: float32, float64. \n +* +* @par Attributes: +* @li rcut_a: A Float. +* @li rcut_r: A Float. +* @li rcut_r_smth: A Float. +* @li sel_a: A ListInt. +* @li sel_r: A ListInt. \n +* +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(ProdEnvMatACalcDescrpt) + .INPUT(distance, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(rij_x, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(rij_y, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(rij_z, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(type, TensorType({DT_INT32})) + .INPUT(natoms, TensorType({DT_INT32})) + .INPUT(mesh, TensorType({DT_INT32})) + .INPUT(davg, TensorType({DT_FLOAT, DT_DOUBLE})) + .INPUT(dstd, TensorType({DT_FLOAT, DT_DOUBLE})) + .OUTPUT(descrpt, TensorType({DT_FLOAT, DT_DOUBLE})) + .OUTPUT(descrpt_deriv, TensorType({DT_FLOAT, DT_DOUBLE})) + .ATTR(rcut_a, Float, 1.0) + .ATTR(rcut_r, Float, 1.0) + .ATTR(rcut_r_smth, Float, 1.0) + .ATTR(sel_a, ListInt, {}) + .ATTR(sel_r, ListInt, {}) + .OP_END_FACTORY_REG(ProdEnvMatACalcDescrpt) + /** * @brief Calculate ProdForceSeA. \n * @@ -134,8 +228,6 @@ REG_OP(ProdForceSeA) .OUTPUT(atom_force, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) .REQUIRED_ATTR(n_a_sel, Int) .REQUIRED_ATTR(n_r_sel, Int) - .ATTR(split_count, Int, 1) - .ATTR(split_index, Int, 0) .OP_END_FACTORY_REG(ProdForceSeA) /** @@ -171,8 +263,6 @@ REG_OP(ProdVirialSeA) .OUTPUT(atom_virial, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) .REQUIRED_ATTR(n_a_sel, Int) .REQUIRED_ATTR(n_r_sel, Int) - .ATTR(split_count, Int, 1) - .ATTR(split_index, Int, 0) .OP_END_FACTORY_REG(ProdVirialSeA) /** @@ -195,6 +285,9 @@ REG_OP(ProdVirialSeA) * Two attributes, including: * @li split_count: A Scalar. * @li split_index: A Scalar. \n +* +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(TabulateFusionGrad) .INPUT(table, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) @@ -205,8 +298,6 @@ REG_OP(TabulateFusionGrad) .INPUT(descriptor, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) .OUTPUT(dy_dem_x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) .OUTPUT(dy_dem, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) - .ATTR(split_count, Int, 1) - .ATTR(split_index, Int, 0) .OP_END_FACTORY_REG(TabulateFusionGrad) } // namespace ge diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index 1cd89c69..c4b38d06 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -286,7 +286,7 @@ REG_OP(Minimum) *@par Inputs: *One inputs, include: *x:A Tensor of type float16, float32, int32, int64, double, -* complex64, complex128.the format can be [NCHW,NC1HWC0,NHWC,ND,NCHW,NC1HWC0,NHWC,ND] +* complex64, complex128.the format can be [NCHW,NHWC,ND] *@par Outputs: *y:A Tensor with same type as "x". \n @@ -418,7 +418,7 @@ REG_OP(SquaredDifference) *@par Inputs: *x: A Tensor of type float16, float32, double, complex64, complex128. -* the format can be [NCHW,NC1HWC0,NHWC,ND] +* the format can be [NCHW,NHWC,ND] *@par Outputs: *y: A Tensor of the same type as "x". \n @@ -439,7 +439,7 @@ REG_OP(Cos) * Two inputs, including: *@li x1: A Tensor. Must be one of the following types: * float16, float32, int32, int8, uint8, float64, int64, uint16, int16, -* complex64, complex128, the format can be [NCHW,NC1HWC0,NHWC,ND]. +* complex64, complex128, the format can be [NCHW,NHWC,ND]. *@li x2: A Tensor. Has the same type and format as input "x1". \n *@par Outputs: @@ -468,7 +468,7 @@ REG_OP(Div) *@li x1: A Tensor. Must be one of the following types: * float16, float32, int32, int8, uint8, double, int16, int64, complex64, * complex128, quint8, qint8, qint32, string, bool. the format can be -* [NCHW, NC1HWC0, NHWC, ND] +* [NCHW, NHWC, ND] *@li x2: A Tensor of the same type and format as "x1". \n *@par Outputs: @@ -533,6 +533,24 @@ REG_OP(Expm1) .OUTPUT(y, TensorType::UnaryDataType()) .OP_END_FACTORY_REG(Expm1) +/** +* @brief Computes the expint(x). \n + +* @par Inputs: +* One input: +* x: A Tensor. Must be one of the following types: bfloat16, half, float32, double. \n + +* @par Outputs: +* y: A Tensor of the same type as "x". \n + +* @par Third-party framework compatibility +* Compatible with TensorFlow operator Expint. +*/ +REG_OP(Expint) + .INPUT(x, TensorType({DT_BF16, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_BF16, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OP_END_FACTORY_REG(Expint) + /** *@brief: Computes the reciprocal of "x". \n @@ -665,6 +683,24 @@ REG_OP(NotEqual) .OUTPUT(y, TensorType({DT_BOOL})) .OP_END_FACTORY_REG(NotEqual) +/** +* @brief Computes ndtri element-wise (y = sqrt(2) * erfinv(2 * x - 1)) + +* @par Inputs: +* One input: +* x: A Tensor. Must be one of the following types: bfloat16, float16, float32, double \n + +* @par Outputs: +* y: A Tensor. Has the same type and format as input "x". \n + +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator Ndtri. +*/ +REG_OP(Ndtri) + .INPUT(x, TensorType({DT_BF16, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_BF16, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OP_END_FACTORY_REG(Ndtri) + /** *@brief Computes numerical negative value element-wise (y = -x) @@ -740,6 +776,31 @@ REG_OP(Xdivy) DT_COMPLEX128})) .OP_END_FACTORY_REG(Xdivy) +/** +* @brief Computes "x" multiplied by the logarithm of y element-wise, +* if "x" == 0, return "0". \n + +* @par Inputs: +* Two inputs, including: +* @li x: A Tensor. Must be one of the following types: float16, float32, +* double, complex64, complex128. +* @li y: A Tensor. Has the same type as "x". \n + +* @par Outputs: +* z: A Tensor. Has the same type as "x". \n + +* @par Third-party framework compatibility +* Compatible with TensorFlow operator Xlog1py. +*/ +REG_OP(Xlog1py) + .INPUT(x, TensorType({DT_HALF, DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, + DT_COMPLEX128})) + .INPUT(y, TensorType({DT_HALF, DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, + DT_COMPLEX128})) + .OUTPUT(z, TensorType({DT_HALF, DT_FLOAT, DT_DOUBLE, DT_COMPLEX64, + DT_COMPLEX128})) + .OP_END_FACTORY_REG(Xlog1py) + /** *@brief Computes "x" multiplied by the logarithm of y element-wise, * if "x" == 0, return "0". \n @@ -970,6 +1031,25 @@ REG_OP(LogicalOr) .OUTPUT(y, TensorType({DT_BOOL})) .OP_END_FACTORY_REG(LogicalOr) +/** +* @brief Computes spence of x element-wise. \n + +* +* @par Inputs: +* x: A tensor. Must be one of the following types: bfloat16, float16, float32, double. +* +* @par Outputs: +* y: A tensor. Has the same type as "x". +* +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator Spence. +* +*/ +REG_OP(Spence) + .INPUT(x, TensorType({DT_BF16, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_BF16, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OP_END_FACTORY_REG(Spence) + /** *@brief Returns the truth value of x1 AND x2 element-wise. \n @@ -1176,6 +1256,31 @@ REG_OP(FusedMulAdd) .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) .OP_END_FACTORY_REG(FusedMulAdd) +/** +*@brief Confuse mul+add+add with broadcast. \n + +*@par Inputs: +*Four inputs, including: +* @li x1: A Tensor. Must be one of the following types:int32, float16, float32. +* @li x2: A Tensor of the same type as "x1". +* @li x3: A Tensor of the same type as "x1". +* @li x4: A Tensor of the same type as "x1". \n + +*@par Outputs: +* y: A Tensor. Has the same type as "x1". \n + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ + +REG_OP(FusedMulAddAdd) + .INPUT(x1, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .INPUT(x2, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .INPUT(x3, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .INPUT(x4, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) + .OP_END_FACTORY_REG(FusedMulAddAdd) + /** *@brief Returns x1 + x2 element-wise. \n @@ -1299,7 +1404,7 @@ REG_OP(AssignSub) *@par Inputs: * Two inputs, including: -*@li y: An NCHW, NC1HWC0, NHWC, ND Tensor. Must be one of the following types: \ +*@li y: An NCHW, NHWC, ND Tensor. Must be one of the following types: \ * float, int32, int8, double, complex64, complex128, half. *@li dy: A Tensor of the same type and format as "y". \n @@ -1321,11 +1426,11 @@ REG_OP(RsqrtGrad) *@brief Computes hyperbolic sine of "x" element-wise. \n *@par Inputs: -*x: An NCHW, NC1HWC0, NHWC,or ND Tensor of type float, double, complex64, +*x: An NCHW, NHWC,or ND Tensor of type float, double, complex64, * complex128, half. \n *@par Outputs: -*y: A NCHW, NC1HWC0, NHWC,or ND Tensor of type float, double, complex64, +*y: A NCHW, NHWC,or ND Tensor of type float, double, complex64, * complex128, half. \n *@par Third-party framework compatibility @@ -1365,7 +1470,7 @@ REG_OP(ClipByValue) *@par Inputs: *x: A Tensor of type float16, float32, double, complex64, complex128. -* the format can be [NCHW,NC1HWC0,NHWC,ND]. \n +* the format can be [NCHW,NHWC,ND]. \n *@par Outputs: *y: A Tensor. Has the same type as "x". \n @@ -1385,7 +1490,7 @@ REG_OP(Cosh) *@par Inputs: * Two inputs, including: *@li x1: A Tensor. Must be one of the following types:float16, float32, int32, -* int8, uint8, double, the format can be [NCHW,NC1HWC0,NHWC,ND]. +* int8, uint8, double, the format can be [NCHW,NHWC,ND]. *@li x2: A Tensor of the same type as "x1". \n *@par Outputs: @@ -1410,7 +1515,7 @@ REG_OP(DivNoNan) * One input: \n *x: A Tensor, Must be one of the following types: * int32, uint8, int16, int8, int64, int64, uint16, uint32, uint64, -* and format can be [NCHW,NC1HWC0,NHWC,ND] +* and format can be [NCHW,NHWC,ND] *@par Outputs: *y: A Tensor. Has the same type and format as "x" @@ -1662,6 +1767,44 @@ REG_OP(Atan2) .OUTPUT(y, TensorType::FloatingDataType()) .OP_END_FACTORY_REG(Atan2) +/** +* @brief Computes fresnel_cos of x element-wise. \n + +* +* @par Inputs: +* x: A tensor. Must be one of the following types: bfloat16, float16, float32, double. +* +* @par Outputs: +* y: A tensor. Has the same type as "x". +* +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator FresnelCos. +* +*/ +REG_OP(FresnelCos) + .INPUT(x, TensorType({DT_BF16, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_BF16, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OP_END_FACTORY_REG(FresnelCos) + +/** +* @brief Computes fresnel_sin of x element-wise. \n + +* +* @par Inputs: +* x: A tensor. Must be one of the following types: bfloat16, float16, float32, double. +* +* @par Outputs: +* y: A tensor. Has the same type as "x". +* +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator FresnelSin. +* +*/ +REG_OP(FresnelSin) + .INPUT(x, TensorType({DT_BF16, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_BF16, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OP_END_FACTORY_REG(FresnelSin) + /** *@brief Returns the truth value of abs(x1-x2) < tolerance element-wise. \n @@ -1978,7 +2121,7 @@ REG_OP(BitwiseOr) *@par Inputs: *Two inputs, including: *@li x1: A Tensor. Must be one of the following types: int8, int16, int32, int64, uint8, uint16, uint32, uint64. -* The format is NC1HWC0 or ND. Broadcasting is supported. +* The format is ND. Broadcasting is supported. *@li x2: A Tensor. Has the same type and format as "x1". \n *@par Outputs: @@ -3463,12 +3606,12 @@ REG_OP(Addcmul) REG_OP(AxpyV2) .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) .INPUT(x2, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) - .INPUT(alpha, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(alpha, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) .OP_END_FACTORY_REG(AxpyV2) /** -* @brief Add the partial values of two tensors in format NC1HWC0. +* @brief Add the partial values of two tensors. * @par Inputs: * @li x1: A Tensor in 5HD, and must be one of the following types: float16, @@ -3852,6 +3995,25 @@ REG_OP(ApplyAdamV2) .OUTPUT(v, TensorType({ DT_FLOAT, DT_FLOAT16 })) .ATTR(adam_mode, String, "adam") .OP_END_FACTORY_REG(ApplyAdamV2) + +/** +* @brief Computes Dawsn operation. \n + +* +* @par Inputs: +* x: A tensor. Must be one of the following types: bfloat16, float16, float32, float64. +* +* @par Outputs: +* y: A tensor. Has the same type as "x". +* +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator Dawsn. +* +*/ +REG_OP(Dawsn) + .INPUT(x, TensorType({DT_BF16, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_BF16, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OP_END_FACTORY_REG(Dawsn) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_ELEWISE_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/image_ops.h b/third_party/fwkacllib/inc/ops/image_ops.h index ba4433d1..d38f0b60 100644 --- a/third_party/fwkacllib/inc/ops/image_ops.h +++ b/third_party/fwkacllib/inc/ops/image_ops.h @@ -671,6 +671,7 @@ size for the images . \n output tensors are aligned, preserving the values at the corner pixels. Defaults to false . * @li half_pixel_centers: An optional bool. Defaults to False . \n +* @li dtype: An Type attr, support type list [DT_FP32, DT_U8]. Defaults to DT_FP32 . \n *@par Outputs: *y: 4-D with shape [batch, new_height, new_width, channels] . \n @@ -682,12 +683,13 @@ Defaults to false . */ REG_OP(ResizeBilinearV2) - .INPUT(x, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, - DT_INT32, DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(x, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, DT_INT32, + DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) .INPUT(size, TensorType({DT_INT32})) - .OUTPUT(y, TensorType({DT_FLOAT})) + .OUTPUT(y, TensorType({DT_UINT8, DT_FLOAT})) .ATTR(align_corners, Bool, false) .ATTR(half_pixel_centers, Bool, false) + .ATTR(dtype, Type, DT_FLOAT) .OP_END_FACTORY_REG(ResizeBilinearV2) /** @@ -1267,7 +1269,7 @@ REG_OP(DecodeAndCropJpeg) *@par Inputs: * One input: -*x: An NC1HWC0 Tensor. +*x: A Tensor. * Must be one of the following types: float16, float32 . \n *@par Attributes: @@ -1304,7 +1306,7 @@ REG_OP(ResizeBilinearV2D) *@par Inputs: * One input: -*images: An NC1HWC0 Tensor. +*images: A Tensor. * Must be one of the following types: float16, float32 . \n *@par Attributes: @@ -1338,7 +1340,7 @@ REG_OP(KeepRatioResizeBilinear) *@par Inputs: * One input: -*x: An NC1HWC0 Tensor. +*x: A Tensor. * Must be one of the following types: float16, float32, int32, int8, uint8 *@par Attributes: @@ -1737,17 +1739,17 @@ round_prefer_ceil, floor, ceil. Only used by nearest interpolation. */ REG_OP(Resize) - .INPUT(x, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, DT_INT32, - DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) - .INPUT(roi, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) - .INPUT(scales, TensorType({DT_FLOAT})) - .OPTIONAL_INPUT(sizes, TensorType({DT_INT64})) - .OUTPUT(y, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, DT_INT32, - DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(x, TensorType({DT_INT8,DT_UINT8,DT_INT16,DT_UINT16,DT_INT32, + DT_INT64,DT_FLOAT16,DT_FLOAT,DT_DOUBLE})) + .OPTIONAL_INPUT(roi, TensorType({DT_FLOAT16,DT_FLOAT,DT_DOUBLE})) + .OPTIONAL_INPUT(scales, TensorType({DT_FLOAT})) + .OPTIONAL_INPUT(sizes, TensorType({DT_INT64,DT_INT32})) + .OUTPUT(y, TensorType({DT_INT8,DT_UINT8,DT_INT16,DT_UINT16,DT_INT32, + DT_INT64,DT_FLOAT16,DT_FLOAT,DT_DOUBLE})) .ATTR(coordinate_transformation_mode, String, "half_pixel") .ATTR(cubic_coeff_a, Float, -0.75) .ATTR(exclude_outside, Int, 0) - .ATTR(extrapolation_value, Float, 0) + .ATTR(extrapolation_value, Float, 0.0) .ATTR(mode, String, "nearest") .ATTR(nearest_mode, String, "round_prefer_floor") .OP_END_FACTORY_REG(Resize) @@ -2309,6 +2311,32 @@ REG_OP(UpsampleNearest1dGrad) .ATTR(scales, ListFloat, {}) .OP_END_FACTORY_REG(UpsampleNearest1dGrad) +/** +* @brief Function parse image from string to int. \n + +* @par Inputs: +* contents: A Tensor of type string. 0-D. The JPEG, GIF, PNG, BMP-encoded image. \n + +* @par Attributes: +* @li channels: An optional int. Defaults to 0. Number of color channels for the decoded image. +* @li dtype: type of image +* @li expand_animations: Controls the shape of the returned op's output. If 'true', the returned op will + produce a 4-D tensor for GIF files. If 'false', the returned op will produce a 3-D tensor for GIF files. + +* @par Outputs: +* image: A Tensor dtype of uint8, uint16 or float. + +* @par Restrictions: +* Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(DecodeImage) + .INPUT(contents, TensorType({DT_STRING})) + .OUTPUT(image, TensorType({DT_UINT8, DT_UINT16, DT_FLOAT})) + .ATTR(channels, Int, 0) + .ATTR(dtype, Type, DT_UINT8) + .ATTR(expand_animations, Bool, true) + .OP_END_FACTORY_REG(DecodeImage) + /** * @brief JPEG encode input image with provided compression quality. \n diff --git a/third_party/fwkacllib/inc/ops/math_ops.h b/third_party/fwkacllib/inc/ops/math_ops.h index f6e2df88..75ef276a 100644 --- a/third_party/fwkacllib/inc/ops/math_ops.h +++ b/third_party/fwkacllib/inc/ops/math_ops.h @@ -425,7 +425,7 @@ REG_OP(EndOfSequence) *@par Inputs: *x: A Tensor of type float16, float32 or double. the format can be -* [NCHW,NC1HWC0,NHWC,ND] +* [NCHW,NHWC,ND] *@par Outputs: *y: A Tensor. Has the same type and format as "x" . \n @@ -462,15 +462,15 @@ REG_OP(Erfc) *@par Inputs: *Three inputs, including: -*@li x: A Tensor of type float32, float16, int32, int64. -*@li range: A Tensor of type float32,float16,int32, int64. +*@li x: A Tensor of type float32, int32, int64. float16 is currently not supported. +*@li range: A Tensor of type float32, int32, int64. float16 is currently not supported. *@li nbins: A Tensor of type int32 . \n *@par Attributes: * dtype: An optional attribute. Defaults to "int32" . \n *@par Outputs: -*y: A Tensor. A Tensor of type int32 or int64 . \n +*y: A Tensor. A Tensor of type int32. \n *@par Third-party framework compatibility * Compatible with TensorFlow operator HistogramFixedWidth. diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index e8931120..a7465af0 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -24,6 +24,57 @@ #include "graph/operator_reg.h" namespace ge { +/** +* @brief + / (MatMul -> ConfusionTransposeD). + LayerNorm - (MatMul -> ConfusionTransposeD). + \ (MatMul -> ConfusionTransposeD). \n +* @par Inputs: +* Nine inputs, including: +* @li x: A Tensor. Must be one of the following types: float16. +* @li kernel_query: A Tensor. Must be one of the following types: float16. +* @li kernel_key: A Tensor. Must be one of the following types: float16. +* @li kernel_value: A Tensor. Must be one of the following types: float16. +* @li gamma: A Tensor. Must be one of the following types: float16. +* @li beta: A Tensor. Must be one of the following types: float16. +* @li bias_query: A Tensor. Must be one of the following types: float16. +* @li bias_key: A Tensor. Must be one of the following types: float16. +* @li bias_value: A Tensor. Must be one of the following types: float16. \n + +* @par Attributes: +* @li epsilon: A optional attribute, the type is float32. Defaults to 1e-7. +* @li trans_a: A optional attribute, the type is bool. Defaults to False. +* @li trans_b: A optional attribute, the type is bool. Defaults to False. \n + +* @par Outputs: +* Six outputs, including: +* @li norm: A Tensor. Must be one of the following types: float16. +* @li query_output: A Tensor. Must be one of the following types: float16. +* @li key_output: A Tensor. Must be one of the following types: float16. +* @li value_output: A Tensor. Must be one of the following types: float16. +* @li mean: A Tensor. Must be one of the following types: float16. +* @li variance: A Tensor. Must be one of the following types: float16. \n +*/ +REG_OP(AttentionLnQKV) + .INPUT(x, TensorType({DT_FLOAT16})) + .INPUT(kernel_query, TensorType({DT_FLOAT16})) + .INPUT(kernel_key, TensorType({DT_FLOAT16})) + .INPUT(kernel_value, TensorType({DT_FLOAT16})) + .INPUT(gamma, TensorType({DT_FLOAT16})) + .INPUT(beta, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(bias_query, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(bias_key, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(bias_value, TensorType({DT_FLOAT16})) + .OUTPUT(norm, TensorType({DT_FLOAT16})) + .OUTPUT(query_output, TensorType({DT_FLOAT16})) + .OUTPUT(key_output, TensorType({DT_FLOAT16})) + .OUTPUT(value_output, TensorType({DT_FLOAT16})) + .OUTPUT(mean, TensorType({DT_FLOAT16})) + .OUTPUT(variance, TensorType({DT_FLOAT16})) + .ATTR(epsilon, Float, 0.0000001) + .ATTR(trans_a, Bool, false) + .ATTR(trans_b, Bool, false) + .OP_END_FACTORY_REG(AttentionLnQKV) /** *@brief Multiplies matrix "a" by matrix "b", producing "a * b" . \n @@ -31,9 +82,9 @@ namespace ge { *@par Inputs: *Three inputs, including: * @li x1: A matrix Tensor. 2D. Must be one of the following types: float16, -* float32, int32. Has format [ND, NHWC, FRACTAL_NZ]. +* float32, int32. Has format [ND, NHWC]. * @li x2: A matrix Tensor. 2D. Must be one of the following types: float16, -* float32, int32. Has format [ND, NHWC, FRACTAL_NZ]. +* float32, int32. Has format [ND, NHWC]. * @li bias: A optional 1D Tensor. Must be one of the following types: float16, * float32, int32. Has format [ND, NHWC] . \n @@ -43,7 +94,7 @@ namespace ge { *@par Outputs: *y: The result matrix Tensor. 2D. Must be one of the following types: float16, -* float32, int32. Has format [ND, NHWC, FRACTAL_NZ] . \n +* float32, int32. Has format [ND, NHWC] . \n *@par Third-party framework compatibility * Compatible with the TensorFlow operator BatchMatmul. @@ -63,9 +114,9 @@ REG_OP(MatMul) *@par Inputs: *Four inputs, including: * @li x1: A matrix Tensor. 2D. Must be one of the following types: float32, - float16, int32, int8. Has format [ND, NHWC, FRACTAL_NZ]. + float16, int32, int8. Has format [ND, NHWC]. * @li x2: A matrix Tensor. 2D. Must be one of the following types: float32, - float16, int32, int8. Has format [ND, NHWC, FRACTAL_NZ]. + float16, int32, int8. Has format [ND, NHWC]. * @li bias: A 1D Tensor. Must be one of the following types: float32, float16, int32. Has format [ND, NHWC]. * @li offset_w: A Optional 1D Tensor for quantized inference. Type is int8. @@ -82,7 +133,11 @@ REG_OP(MatMul) *@par Outputs: *y: The result matrix Tensor. 2D. Must be one of the following types: float32, - float16, int32. Has format [ND, NHWC, FRACTAL_NZ]. \n + float16, int32. Has format [ND, NHWC]. \n + +*@attention Constraints: +* if performances better in format NZ, please close + "MatmulTransdataFusionPass" in fusion configuration. \n *@par Third-party framework compatibility * Compatible with the TensorFlow operator BatchMatmul. @@ -124,6 +179,10 @@ REG_OP(MatMulV2) *y: The result matrix Tensor. 2D. Must be one of the following types: int32, * float16. \n +*@attention Constraints: +* if performances better in format NZ, please close + "MatmulTransdataFusionPass" in fusion configuration. + */ REG_OP(MatMulV2Compress) .INPUT(x1, TensorType({DT_INT8})) @@ -138,7 +197,7 @@ REG_OP(MatMulV2Compress) .OP_END_FACTORY_REG(MatMulV2Compress) /** -*@brief Performs Matrix-to-matrix Multiply, producing c=alpha[0]*a*b+beta[0]*c . \n +*@brief Performs Matrix-to-matrix Multiply, producing y=alpha[0]*a*b+beta[0]*c . \n *@attention Constraints: * For better performance, The k-axis must be aligned to 16 (input type @@ -147,24 +206,24 @@ REG_OP(MatMulV2Compress) *@par Inputs: *Five inputs, including: *@li a: A matrix Tensor. Must be one of the following types: float16, int8. -* Has format [ND, FRACTAL_NZ]. 2D(ND) or 4D(FRACTAL_NZ). +* Has format [ND]. *@li b: A matrix Tensor. Must be one of the following types: float16, int8. -* Has format [ND, FRACTAL_NZ, FRACTAL_Z]. 2D(ND) or 4D(FRACTAL_NZ, FRACTAL_Z). +* Has format ND. *@li c: A matrix Tensor. Must be one of the following types: float16, int32, -* float32. has format [ND, FRACTAL_NZ]. 2D(ND) or 4D(FRACTAL_NZ). +* float32. has format ND. *@li alpha: A 1D Tensor. The shape of alpha is [1].Must be one of the following * types: float16, int32, float32. Has format [ND]. *@li beta: A 1D Tensor. The shape of beta is [1]. Must be one of the following * types: float16, int32, float32. Has format [ND]. * The format of a, b, c has restriction:\n * When type of a is int8 and type of c is int32, the format of a, b, c should -* all be ND, or a is FRACTAL_NZ and b is FRACTAL_Z and c is ND.\n +* all be ND.\n * When type of a is int8 and type of c is float32, the format of a, b, c should -* all be ND or a is FRACTAL_NZ and b is FRACTAL_Z and c is FRACTAL_NZ.\n +* all be ND.\n * When type of a is float16 and type of c is float16, the format of a, b, c -* should all be ND or FRACTAL_NZ.\n +* should all be ND.\n * When type of a is float16 and type of c is float32, the format of a, b, c -* should all be ND or FRACTAL_NZ . \n +* should all be ND. \n *@par Attributes: *Two attributes, including: @@ -175,8 +234,7 @@ REG_OP(MatMulV2Compress) *@par Outputs: *y: The result matrix Tensor. Must be one of the following types: float16, -* float32, int32. Has format [ND, FRACTAL_NZ], the format should be equal to a. -* 2D(ND) or 4D(FRACTAL_NZ). +* float32, int32. Has format [ND], the format should be equal to a. */ REG_OP(GEMM) @@ -196,9 +254,9 @@ REG_OP(GEMM) *@par Inputs: *Two inputs, including: * @li x1: A matrix Tensor. Must be one of the following types: float16, -* float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ]. +* float32, int32. 2D or higher. Has format [ND, NHWC]. * @li x2: A matrix Tensor. Must be one of the following types: float16, -* float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ] . \n +* float32, int32. 2D or higher. Has format [ND, NHWC] . \n *@par Attributes: *@li adj_x1: A bool. If True, changes the shape of "x1" from [B, M, K] to [B, K, M]. @@ -206,7 +264,7 @@ REG_OP(GEMM) *@par Outputs: *y: The result matrix Tensor. 2D or higher. Must be one of the following types: float16, -* float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ]. Has the same shape length as "x1" and "x2" . \n +* float32, int32. 2D or higher. Has format [ND, NHWC]. Has the same shape length as "x1" and "x2" . \n *@par Third-party framework compatibility * Compatible with the TensorFlow operator BatchMatmul. @@ -227,11 +285,11 @@ REG_OP(BatchMatMul) * @par Inputs: * Three inputs, including: * @li x1: A matrix Tensor. Must be one of the following types: float16, -* float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ]. +* float32, int32. 2D or higher. Has format [ND, NHWC]. * @li x2: A matrix Tensor. Must be one of the following types: float16, -* float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ] . \n +* float32, int32. 2D or higher. Has format [ND, NHWC] . \n * @li bias: A matrix Tensor. Must be one of the following types: float16, -* float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ] . \n +* float32, int32. 2D or higher. Has format [ND, NHWC] . \n * @par Attributes: * @li adj_x1: A bool. If True, changes the shape of "x1" from [B, M, K] to [B, K, M]. @@ -239,7 +297,11 @@ REG_OP(BatchMatMul) * @par Outputs: * y: The result matrix Tensor. 2D or higher. Must be one of the following types: float16, -* float32, int32. 2D or higher. Has format [ND, NHWC, FRACTAL_NZ]. Has the same shape length as "x1" and "x2" . \n +* float32, int32. 2D or higher. Has format [ND, NHWC]. Has the same shape length as "x1" and "x2" . \n + +*@attention Constraints: +* if performances better in format NZ, please close + "MatmulTransdataFusionPass" in fusion configuration. \n * @par Third-party framework compatibility * Compatible with the TensorFlow operator BatchMatmul. @@ -265,7 +327,12 @@ REG_OP(BatchMatMulV2) * TensorType::FloatingDataType() . \n *@par Outputs: -*y: A Tensor. Has the same type as "x". +*y: A Tensor. Has the same type as "x". \n + +*@attention Constraints: +* if performances better in format NZ, please close + "MatmulTransdataFusionPass" in fusion configuration. \n + *@par Third-party framework compatibility *Compatible with the TensorFlow operator L2Loss. */ @@ -405,6 +472,56 @@ REG_OP(MatrixSetDiagD) .OUTPUT(y, TensorType::BasicType()) .OP_END_FACTORY_REG(MatrixSetDiagD) +/** +* @brief Function AttentionScore. \n + +* @par Inputs: +* six inputs, including: +* @li query: A matrix Tensor. The type only support float16. +* @li key: A matrix Tensor. The type only support float16. +* @li value: A matrix Tensor. The type only support float16. +* @li padding_mask: A matrix Tensor. The type only support float16. +* @li scale: A scalar. The type only support float16. +* @li drop_mask: A matrix Tensor. The type only support uint8. \n + +* @par Attributes: +* @li keep_prob: A mutable Tensor. Must met all of the following rules: + shape of "keep_prob" should be (1,) or [1,]. +* @li query_transpose: A bool. If True, changes the shape of "query" from [K, M] to + [M, K]. +* @li key_transpose: A bool. If True, changes the shape of "key" from [N, K] to + [K, N]. +* @li bmm_score_transpose_a: A bool. If True, changes the shape of "mid_data" from [K, M] to + [M, K]. +* @li bmm_score_transpose_b: A bool. If True, changes the shape of "value" from [N, K] to + [K, N]. +* @li axes: A list of int. The dimension softmax would be performed on. Defaults + to "[-1]" . \n + +* @par Outputs: +* attention_score: The result matrix Tensor. The type only support float16. +* softmax_output: The result matrix Tensor. The type only support float16. + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(AttentionScore) + .INPUT(query, TensorType({DT_FLOAT16})) + .INPUT(key, TensorType({DT_FLOAT16})) + .INPUT(value, TensorType({DT_FLOAT16})) + .INPUT(padding_mask, TensorType({DT_FLOAT16})) + .INPUT(scale, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(drop_mask, TensorType({DT_INT8})) + .OUTPUT(attention_score, TensorType({DT_FLOAT16})) + .OUTPUT(softmax_output, TensorType({DT_FLOAT16})) + .ATTR(keep_prob, Float, 1.0) + .ATTR(query_transpose, Bool, false) + .ATTR(key_transpose, Bool, false) + .ATTR(bmm_score_transpose_a, Bool, false) + .ATTR(bmm_score_transpose_b, Bool, false) + .ATTR(softmax_axes, ListInt, {-1}) + .OP_END_FACTORY_REG(AttentionScore) + /** *@brief Applies sparse "updates" to individual values or slices in a Variable . \n @@ -1211,7 +1328,7 @@ REG_OP(IndexAdd) *qint8, quint8, qint32, uint16, complex128, uint32, uint64. \n * @li x2: A Tensor of the same type as "x1". -* @li indices: A Tensor of the indices, +* @li indices: A Tensor of the indices, * @par Attributes: * @li accumulate: Does it support self accumulation.Defaults to 0. @@ -1394,8 +1511,8 @@ REG_OP(Trace) */ REG_OP(Pinverse) - .INPUT(x, TensorType({ DT_FLOAT, DT_DOUBLE })) - .OUTPUT(y, TensorType({ DT_FLOAT, DT_DOUBLE })) + .INPUT(x, TensorType({ DT_FLOAT, DT_DOUBLE })) + .OUTPUT(y, TensorType({ DT_FLOAT, DT_DOUBLE })) .ATTR(rcond, Float, 1e-15) .OP_END_FACTORY_REG(Pinverse) diff --git a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h index 7a28a738..c6aad6dc 100644 --- a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h @@ -86,35 +86,37 @@ REG_OP(L2NormalizeGrad) *@brief Performs batch normalization . \n *@par Inputs: -* Five inputs, including: (NHWC, NCHW, or NC1HWC0 supported) -*@li x: A 4D or 5D Tensor of type float16 or float32, with format NHWC or NCHW for 4D or NC1HWC0 for 5D. -*@li scale: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D -if input "x" is with format NC1HWC0. Specifies the scaling factor. -*@li offset: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D -if input "x" is with format NC1HWC0. Specifies the offset. -*@li mean: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D -if input "x" is with format NC1HWC0. Specifies the mean used for inference. Must be "None" if the +* Five inputs, including: (NHWC, NCHW) +*@li x: A 4D or 5D Tensor of type float16 or float32, with format NHWC or NCHW. +*@li scale: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. +Specifies the scaling factor. +*@li offset: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Specifies the offset. +*@li mean: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. +Specifies the mean used for inference. Must be "None" if the operation is used for training. -*@li variance: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be -5D if input "x" is with format NC1HWC0. Specifies the variance used for inference. Must be "None" +*@li variance: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. +Specifies the variance used for inference. Must be "None" if the operation is used for training . \n *@par Attributes: -*@li epsilon: An optional float32, specifying the small value added to variance to avoid dividing by zero. Defaults to "0.0001". +*@li epsilon: An optional float32, specifying the small value added to variance to avoid dividing by zero. +Defaults to "0.0001". *@li data_format: An optional string, specifying the format of "x". Defaults to "NHWC". -*@li is_training: An optional bool, specifying if the operation is used for training or inference. Defaults to "True" . \n +*@li is_training: An optional bool, specifying if the operation is used for training or inference. +Defaults to "True" . \n *@par Outputs: -* Five outputs, including: (NHWC, NCHW, or NC1HWC0 supported) -*@li y: A 4D or 5D Tensor of type float16 or float32 for the normalized "x", with format NHWC or NCHW for 4D or NC1HWC0 for 5D. -*@li batch_mean: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D -if input "x" is with format NC1HWC0. Specifies the mean of "x". +* Five outputs, including: (NHWC, NCHW) +*@li y: A 4D or 5D Tensor of type float16 or float32 for the normalized "x", with format NHWC or NCHW. +*@li batch_mean: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. +Specifies the mean of "x". *@li batch_variance: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. -Must be 5D if input "x" is with format NC1HWC0. Specifies the variance of "x". +Specifies the variance of "x". *@li reserve_space_1: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. -Must be 5D if input "x" is with format NC1HWC0. Specifies the mean of "x" for gradient computation. Pass "None" to skip this output. +Specifies the mean of "x" for gradient computation. Pass "None" to skip this output. *@li reserve_space_2: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. -*@li reserve_space_3: An optional Tensor of type float32. For compatibility with tensorflow, only has one useless emement. \n +*@li reserve_space_3: An optional Tensor of type float32. For compatibility with tensorflow, +only has one useless emement. \n *@attention Constraints: *@li If the operation is used for inference and outputs "reserve_space_1" and "reserve_space_2" are available, @@ -264,17 +266,17 @@ REG_OP(SyncBatchNormBackwardElemt) *@brief Performs batch normalization . \n *@par Inputs: -* Five inputs, including: (NHWC, NCHW, or NC1HWC0 supported) -*@li x: A 3D or 6D Tensor of type float16 or float32, with format NDHWC or NCDHW for 4D or NDC1HWC0 for 6D. -*@li scale: A Tensor of type float32. Must be 1D if input "x" is with format NDHWC or NCDHW. Must be 6D -if input "x" is with format NDC1HWC0. Specifies the scaling factor. -*@li offset: A Tensor of type float32. Must be 3D if input "x" is with format NDHWC or NCDHW. Must be 6D -if input "x" is with format NC1HWC0. Specifies the offset. -*@li mean: A Tensor of type float32. Must be 3D if input "x" is with format NDHWC or NCDHW. Must be 6D -if input "x" is with format NC1HWC0. Specifies the mean used for inference. Must be "None" if the +* Five inputs, including: (NHWC, NCHW) +*@li x: A 3D or 6D Tensor of type float16 or float32, with format NDHWC or NCDHW. +*@li scale: A Tensor of type float32. Must be 1D if input "x" is with format NDHWC or NCDHW. +Specifies the scaling factor. +*@li offset: A Tensor of type float32. Must be 3D if input "x" is with format NDHWC or NCDHW. +Specifies the offset. +*@li mean: A Tensor of type float32. Must be 3D if input "x" is with format NDHWC or NCDHW. +Specifies the mean used for inference. Must be "None" if the operation is used for training. -*@li variance: A Tensor of type float32. Must be 3D if input "x" is with format NHWC or NCHW. Must be -5D if input "x" is with format NC1HWC0. Specifies the variance used for inference. Must be "None" +*@li variance: A Tensor of type float32. Must be 3D if input "x" is with format NHWC or NCHW. +Specifies the variance used for inference. Must be "None" if the operation is used for training . \n *@par Attributes: @@ -283,16 +285,16 @@ if the operation is used for training . \n *@li is_training: An optional bool, specifying if the operation is used for training or inference. Defaults to "True" . \n *@par Outputs: -* Five outputs, including: (NHWC, NCHW, or NC1HWC0 supported) -*@li y: A 3D or 6D Tensor of type float16 or float32 for the normalized "x", with format NDHWC or NCDHW for 4D or NDC1HWC0 for 6D. -*@li batch_mean: A Tensor of type float32. Must be 3D if input "x" is with format NDHWC or NCDHW. Must be 6D -if input "x" is with format NDC1HWC0. Specifies the mean of "x". +* Five outputs, including: (NHWC, NCHW) +*@li y: A 3D or 6D Tensor of type float16 or float32 for the normalized "x", with format NDHWC or NCDHW. +*@li batch_mean: A Tensor of type float32. Must be 3D if input "x" is with format NDHWC or NCDHW. +Specifies the mean of "x". *@li batch_variance: A Tensor of type float32. Must be 1D if input "x" is with format NDHWC or NCDHW. -Must be 6D if input "x" is with format NDC1HWC0. Specifies the variance of "x". +Specifies the variance of "x". *@li reserve_space_1: An optional Tensor of type float32. Must be 1D if input "x" is with format NDHWC or NCDHW. -Must be 6D if input "x" is with format NDC1HWC0. Specifies the mean of "x" for gradient computation. Pass "None" to skip this output. +Specifies the mean of "x" for gradient computation. Pass "None" to skip this output. *@li reserve_space_2: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. -Must be 6D if input "x" is with format NDC1HWC0. Specifies the variance of "x" for gradient computation. Pass "None" to skip this output . \n +Specifies the variance of "x" for gradient computation. Pass "None" to skip this output . \n *@attention Constraints: *@li If the operation is used for inference and outputs "reserve_space_1" and "reserve_space_2" are available, @@ -375,11 +377,11 @@ REG_OP(BatchNormExt2) *@par Inputs: * Five inputs, including: -*@li y_backprop: A 4D or 5D Tensor of type float16 or float32, with format NHWC, NCHW, or NC1HWC0, for the gradient. -*@li x: A 4D or 5D Tensor of type float16 or float32, with format NHWC, NCHW, or NC1HWC0. -*@li scale: A 4D or 5D Tensor of type float32, with format NHWC, NCHW, or NC1HWC0. -*@li reserve_space_1: A 4D or 5D Tensor of type float32, with format NHWC, NCHW, or NC1HWC0. It is an output of BatchNorm. -*@li reserve_space_2: A 4D or 5D Tensor of type float32, with format NHWC, NCHW, or NC1HWC0. It is an output of BatchNorm . +*@li y_backprop: A 4D or 5D Tensor of type float16 or float32, with format NHWC, NCHW, for the gradient. +*@li x: A 4D or 5D Tensor of type float16 or float32, with format NHWC, NCHW. +*@li scale: A 4D or 5D Tensor of type float32, with format NHWC, NCHW. +*@li reserve_space_1: A 4D or 5D Tensor of type float32, with format NHWC, NCHW. It is an output of BatchNorm. +*@li reserve_space_2: A 4D or 5D Tensor of type float32, with format NHWC, NCHW. It is an output of BatchNorm . *@li reserve_space_3: A 1D optional Tensor of type float32. It is an output of BatchNorm . \n *@par Attributes: @@ -388,11 +390,11 @@ REG_OP(BatchNormExt2) *@li is_training: An optional bool. Defaults to "true". Specifies the operation is for training (default) or inference . \n *@par Outputs: -*@li x_backprop: A Tensor of type float16 or float32, with format NHWC, NCHW, or NC1HWC0, for the offset of "x". -*@li scale_backprop: A Tensor of type float32, with format NHWC, NCHW, or NC1HWC0, for the offset of "scale". -*@li *offset_backprop: A Tensor of type float32, with format NHWC, NCHW, or NC1HWC0, for the offset of "offset". -*@li *reserve_space_4: A Tensor of type float32, with shape NHWC, NCHW, or NC1HWC0. Pass "None" to skip this output. -*@li *reserve_space_5: A Tensor of type float32, with shape NHWC, NCHW, or NC1HWC0. Pass "None" to skip this output . \n +*@li x_backprop: A Tensor of type float16 or float32, with format NHWC, NCHW, for the offset of "x". +*@li scale_backprop: A Tensor of type float32, with format NHWC, NCHW, for the offset of "scale". +*@li *offset_backprop: A Tensor of type float32, with format NHWC, NCHW, for the offset of "offset". +*@li *reserve_space_4: A Tensor of type float32, with shape NHWC, NCHW. Pass "None" to skip this output. +*@li *reserve_space_5: A Tensor of type float32, with shape NHWC, NCHW. Pass "None" to skip this output . \n *@attention Constraints: * The preceding layer of this operator must be operator BatchNorm . \n @@ -423,11 +425,11 @@ REG_OP(BatchNormGrad) *@par Inputs: * Five inputs, including: -*@li y_backprop: A 3D or 6D Tensor of type float16 or float32, with format NDHWC, NCDHW, or NDC1HWC0, for the gradient. -*@li x: A 3D or 6D Tensor of type float16 or float32, with format NDHWC, NCDHW, or NDC1HWC0. -*@li scale: A 3D or 6D Tensor of type float32, with format NDHWC, NCDHW, or NDC1HWC0. -*@li reserve_space_1: A 3D or 6D Tensor of type float32, with format NDHWC, NCDHW, or NC1HWC0. It is an output of BatchNorm. -*@li reserve_space_2: A 3D or 6D Tensor of type float32, with format NDHWC, NCDHW, or NC1HWC0. It is an output of BatchNorm . \n +*@li y_backprop: A 3D or 6D Tensor of type float16 or float32, with format NDHWC, NCDHW, for the gradient. +*@li x: A 3D or 6D Tensor of type float16 or float32, with format NDHWC, NCDHW. +*@li scale: A 3D or 6D Tensor of type float32, with format NDHWC, NCDHW. +*@li reserve_space_1: A 3D or 6D Tensor of type float32, with format NDHWC, NCDHW. It is an output of BatchNorm. +*@li reserve_space_2: A 3D or 6D Tensor of type float32, with format NDHWC, NCDHW. It is an output of BatchNorm . \n *@par Attributes: *@li epsilon: An optional float32. Defaults to "0.0001". A small float number added to the variance of "x". @@ -435,11 +437,11 @@ REG_OP(BatchNormGrad) *@li is_training: An optional bool. Defaults to "true". Specifies the operation is for training (default) or inference . \n *@par Outputs: -*@li x_backprop: A Tensor of type float16 or float32, with format NHWC, NCHW, or NC1HWC0, for the offset of "x". -*@li scale_backprop: A Tensor of type float32, with format NDHWC, NCDHW, or NDC1HWC0, for the offset of "scale". -*@li *offset_backprop: A Tensor of type float32, with format NDHWC, NCDHW, or NDC1HWC0, for the offset of "offset". -*@li *reserve_space_4: A Tensor of type float32, with shape NDHWC, NCDHW, or NDC1HWC0. Pass "None" to skip this output. -*@li *reserve_space_5: A Tensor of type float32, with shape NDHWC, NCDHW, or NDC1HWC0. Pass "None" to skip this output . \n +*@li x_backprop: A Tensor of type float16 or float32, with format NHWC, NCHW, for the offset of "x". +*@li scale_backprop: A Tensor of type float32, with format NDHWC, NCDHW, for the offset of "scale". +*@li *offset_backprop: A Tensor of type float32, with format NDHWC, NCDHW, for the offset of "offset". +*@li *reserve_space_4: A Tensor of type float32, with shape NDHWC, NCDHW. Pass "None" to skip this output. +*@li *reserve_space_5: A Tensor of type float32, with shape NDHWC, NCDHW. Pass "None" to skip this output . \n *@attention Constraints: * The preceding layer of this operator must be operator BatchNorm . \n @@ -515,7 +517,7 @@ REG_OP(BatchNormGradExt2) *@brief Performs batch normalization . \n *@par Inputs: -*@li x: A 4D or 5D Tensor of type float16 or float32, with format NHWC or NCHW for 4D or NC1HWC0 for 5D. +*@li x: A 4D or 5D Tensor of type float16 or float32, with format NHWC or NCHW. *@li mean: A Tensor of type float32 or float16. Must be 1D if input "x" Specifies the mean used for inference. *@li variance: A Tensor of type float32 or float16 . Must be 1D if input "x" Specifies the variance used for inference. *@li momentum: A Tensor,represents the mean and the variance's scale factor @@ -545,7 +547,7 @@ REG_OP(BNInference) *@brief Performs batch normalization . \n *@par Inputs: -*@li x: A 4D or 5D Tensor of type float16 or float32, with format NHWC or NCHW for 4D or NC1HWC0 for 5D. +*@li x: A 4D or 5D Tensor of type float16 or float32, with format NHWC or NCHW. *@li mean: A Tensor of type float32 or float16. Must be 1D if input "x" Specifies the mean used for inference. *@li variance: A Tensor of type float32 or float16 . Must be 1D if input "x" Specifies the variance used for inference. *@li scale: An optional tensor of type float16 or float32, no use diff --git a/third_party/fwkacllib/inc/ops/nn_detect_ops.h b/third_party/fwkacllib/inc/ops/nn_detect_ops.h index 2ccb184f..f35f67c5 100644 --- a/third_party/fwkacllib/inc/ops/nn_detect_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_detect_ops.h @@ -268,7 +268,7 @@ REG_OP(ROIAlign) *@par Inputs: * Two inputs, including: -*@li x: An NC1HWC0 or NCHW feature map of type is float32 or float16. +*@li x: An NCHW feature map of type is float32 or float16. *@li img: source image. Has the same type and format as "x" . \n *@par Attributes: @@ -316,12 +316,12 @@ REG_OP(PriorBox) *@par Inputs: * Six inputs, including: -*@li x: An NC1HWC0 or NCHW feature map of type is float32 or float16. +*@li x: An NCHW feature map of type is float32 or float16. *@li img: source image. Has the same type and format as "x". -*@li data_h: An NC1HWC0 or NCHW tensor of type float32 or float16, specifying the matrix for indexing the feature map height. -*@li data_w: An NC1HWC0 or NCHW tensor of type float32 or float16, specifying the matrix for indexing the feature map width. -*@li box_height: An NC1HWC0 or NCHW tensor of type float32 or float16, specifying the height of each prior box. -*@li box_width: An NC1HWC0 or NCHW tensor of type float32 or float16, specifying the width of each prior box . \n +*@li data_h: An NCHW tensor of type float32 or float16, specifying the matrix for indexing the feature map height. +*@li data_w: An NCHW tensor of type float32 or float16, specifying the matrix for indexing the feature map width. +*@li box_height: An NCHW tensor of type float32 or float16, specifying the height of each prior box. +*@li box_width: An NCHW tensor of type float32 or float16, specifying the width of each prior box . \n *@par Attributes: *@li min_size: A required float32, specifying the minimum edge length of a square prior box. @@ -371,7 +371,7 @@ REG_OP(PriorBoxD) *@par Inputs: * Six inputs, including: -*@li x: An NC1HWC0 or NCHW feature map of type is float32 or float16. +*@li x: An NCHW feature map of type is float32 or float16. *@li img: source image. Has the same type and format as "x". *@li boxes: An ND tensor of type float32 or float16, specifying the prior box information. Same as output y @@ -420,7 +420,7 @@ REG_OP(PriorBoxDV2) *@par Inputs: * Two inputs, including: -*@li x: An NC1HWC0 tensor of type float16 or float32, describing the feature +*@li x: A tensor of type float16 or float32, describing the feature * map, dimension C1 must be equal to * (int(output_dim+15)/C0))*group_size*group_size. *@li rois: A tensor of type float16 or float32, with shape @@ -438,7 +438,7 @@ REG_OP(PriorBoxDV2) * coordinates to the ROI coordinates . \n *@par Outputs: -*y: An NC1HWC0 tensor of type float16 or float32, describing the result +*y: A tensor of type float16 or float32, describing the result * feature map . \n *@attention Constraints: @@ -1171,7 +1171,7 @@ REG_OP(SPP) *@par Inputs: * Three inputs, including: -*@li x: An NC1HWC0 tensor of type float16 or float32, describing the feature +*@li x: A tensor of type float16 or float32, describing the feature * map. The data of x must be greater than or equal to "0.0". *@li rois: A tensor of type float16 or float32, with 3D shape * [batch, 5, roi_max_num], describing the RIOs. Each ROI consists of five @@ -1195,7 +1195,7 @@ REG_OP(SPP) * coordinates of width to the ROI coordinates . \n *@par Outputs: -*y: An NC1HWC0 tensor of type float16 or float32, describing the result +*y: A tensor of type float16 or float32, describing the result * feature map . \n *@attention Constraints: @@ -1844,6 +1844,7 @@ REG_OP(NonMaxSuppressionV7) REG_OP(RoiExtractor) .DYNAMIC_INPUT(features, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(rois, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(index, TensorType({DT_INT32})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(finest_scale, Int, 56) .ATTR(roi_scale_factor, Float, 0) @@ -1860,7 +1861,7 @@ REG_OP(RoiExtractor) *@par Inputs: * Two inputs, including: -*@li x: An NC1HWC0 tensor of type float16 or float32, describing the feature +*@li x: A tensor of type float16 or float32, describing the feature * map, dimension C1 must be equal to * (int(output_dim+15)/C0))*group_size*group_size. *@li rois: A tensor of type float16 or float32, with shape @@ -1878,7 +1879,7 @@ REG_OP(RoiExtractor) * coordinates to the ROI coordinates . \n *@par Outputs: -*y: An NC1HWC0 tensor of type float16 or float32, describing the result +*y: A tensor of type float16 or float32, describing the result * feature map . \n *@attention Constraints: @@ -1898,7 +1899,7 @@ REG_OP(PSROIPoolingV2) *@par Inputs: * Two inputs, including: -*@li x: An NC1HWC0 tensor of type float16 or float32, describing the result +*@li x: A tensor of type float16 or float32, describing the result * feature map . \n *@li rois: A tensor of type float16 or float32, with shape * [batch, 5, rois_num], describing the ROIs, each ROI consists of five @@ -1916,7 +1917,7 @@ REG_OP(PSROIPoolingV2) *@li input_size: A required listInt, mapping the gradinput size: (H, W) *@par Outputs: -*y: An NC1HWC0 tensor of type float16 or float32, describing the feature +*y: A tensor of type float16 or float32, describing the feature * map, dimension C1 must be equal to * (int(output_dim+15)/C0))*group_size*group_size. @@ -2030,7 +2031,7 @@ REG_OP(GridAssignPositive) .OP_END_FACTORY_REG(GridAssignPositive) /** -*@brief GIoUGrad . \n +* @brief Calculate the inverse gradient of GIoU. \n *@par Inputs: *@li dy : data of grad increment, a 1D Tensor of type float16 or float32 with @@ -2064,17 +2065,88 @@ REG_OP(GIoUGrad) .OP_END_FACTORY_REG(GIoUGrad) /** -*@brief RotatedOverlaps . \n +* @brief Calculate the inverse gradient of DIoU. \n + +* @par Inputs: +* @li dy : data of grad increment, a 1D Tensor of type float16 or float32 with +* shape (N,). +* @li bboxes: Bounding boxes, a 2D Tensor of type float16 or float32 with +* shape (4, N). "N" indicates the number of bounding boxes, and the value +* "4" refers to [x1, y1, x2, y2] or [x, y, w, h]. +* @li gtboxes: Ground-truth boxes, a 2D Tensor of type float16 or float32 +* with shape (4, M). "M" indicates the number of ground truth boxes, and +* the value "4" refers to [x1, y1, x2, y2] or [x, y, w, h] . \n + +* @par Attributes: +* @li trans: An optional attr, true for 'xywh', false for 'xyxy', only support true now. +* @li is_cross: An optional attr, if false M equals N, only support false now. +* @li mode: An optional attr, a character string with the value range of ['iou', 'iof'], +* only support 'iou' now. \n + +* @par Outputs: +* @li dbboxes: A 2D Tensor of type float16 or float32 with shape [4, N]. +* @li dgtboxes: A 2D Tensor of type float16 or float32 with shape [4, M]. +*/ +REG_OP(DIoUGrad) + .INPUT(dy, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(bboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(gtboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dbboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dgtboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(trans, Bool, false) + .ATTR(is_cross, Bool, true) + .ATTR(mode, String, "iou") + .OP_END_FACTORY_REG(DIoUGrad) + +/** +* @brief Calculate the inverse gradient of CIoU. \n + +* @par Inputs: +* @li dy : data of grad increment, a 1D Tensor of type float16 or float32 with +* shape (N,). +* @li bboxes: Bounding boxes, a 2D Tensor of type float16 or float32 with +* shape (4, N). "N" indicates the number of bounding boxes, and the value +* "4" refers to [x1, y1, x2, y2] or [x, y, w, h]. +* @li gtboxes: Ground-truth boxes, a 2D Tensor of type float16 or float32 +* with shape (4, M). "M" indicates the number of ground truth boxes, and +* the value "4" refers to [x1, y1, x2, y2] or [x, y, w, h] . +* @li atan_sub: Intermediate result of forward calculation, +* a 1D Tensor of type float16 or float32 with shape (N,). \n + +* @par Attributes: +* @li trans: An optional attr, true for 'xywh', false for 'xyxy', only support true now. +* @li is_cross: An optional attr, if false M equals N, only support false now. +* @li mode: An optional attr, a character string with the value range of ['iou', 'iof'], +* only support 'iou' now. \n + +* @par Outputs: +* @li dbboxes: A 2D Tensor of type float16 or float32 with shape [4, N]. +* @li dgtboxes: A 2D Tensor of type float16 or float32 with shape [4, M]. +*/ +REG_OP(CIoUGrad) + .INPUT(dy, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(bboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(gtboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(atan_sub, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dbboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dgtboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(trans, Bool, false) + .ATTR(is_cross, Bool, true) + .ATTR(mode, String, "iou") + .OP_END_FACTORY_REG(CIoUGrad) + +/** +* @brief RotatedOverlaps . \n *@par Inputs: *@li boxes : data of grad increment, a 3D Tensor of type float32 with * shape (B, 5, N). "N" indicates the number of boxes, and the value * "5" refers to [x1, y1, x2, y2, theta] or [x, y, w, h, theta]. -*@li query_boxes: Bounding boxes, a 3D Tensor of type float32 with +* @li query_boxes: Bounding boxes, a 3D Tensor of type float32 with * shape (B, 5, K). "K" indicates the number of boxes, and the value * "5" refers to [x1, y1, x2, y2, theta] or [x, y, w, h, theta]. -*@par Attributes: +* @par Attributes: * trans: An optional attr, true for 'xyxyt', false for 'xywht'. *@par Outputs: @@ -2093,21 +2165,21 @@ REG_OP(RotatedOverlaps) /** *@brief RotatedIou . \n -*@par Inputs: +* @par Inputs: *@li boxes : data of grad increment, a 3D Tensor of type float32 with * shape (B, 5, N). "N" indicates the number of boxes, and the value * "5" refers to [x1, y1, x2, y2, theta] or [x, y, w, h, theta]. -*@li query_boxes: Bounding boxes, a 3D Tensor of type float32 with +* @li query_boxes: Bounding boxes, a 3D Tensor of type float32 with * shape (B, 5, K). "K" indicates the number of boxes, and the value * "5" refers to [x1, y1, x2, y2, theta] or [x, y, w, h, theta]. -*@par Attributes: +* @par Attributes: *@li trans: An optional attr, true for 'xyxyt', false for 'xywht'. -*@li mode: An optional attr, a character string with the value range of ['iou', 'iof'], +* @li mode: An optional attr, a character string with the value range of ['iou', 'iof'], * only support 'iou' now. *@li is_cross: Cross calculation when it is True, and one-to-one calculation when it is False. *@li v_threshold: An optional attr, provide condition relaxation for intersection calculation. -*@li e_threshold: An optional attr, provide condition relaxation for intersection calculation. +* @li e_threshold: An optional attr, provide condition relaxation for intersection calculation. *@par Outputs: * iou: A 3D Tensor of float32 with shape [B, N, K]. @@ -2140,7 +2212,7 @@ REG_OP(RotatedIou) * "N" indicates the number of bounding boxes, and the value "5" refers to * "x0", "x1", "y0", "y1" and "angle". \n -*@par Attributes: +* @par Attributes: *@li weight: A float list for "x0", "x1", "y0", "y1" and "angle", * defaults to [1.0, 1.0, 1.0, 1.0, 1.0]. @@ -2183,6 +2255,27 @@ REG_OP(RotatedBoxDecode) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .ATTR(weight, ListFloat, {1.0, 1.0, 1.0, 1.0, 1.0}) .OP_END_FACTORY_REG(RotatedBoxDecode) + +/** +* @brief sort rois to balance on each core. \n + +* @par Inputs: +* one inputs, including: +* @li rois: ROI position. A 2D Tensor of float32 or float16 with shape (N, 5). "N" indicates the number of ROIs, +* the value "5" indicates the indexes of images where the ROIs are located, "batch", "x0", "y0", "x1", and "y1". + +* @par Outputs: +* @li balance_rois: A 2D Tensor of float32 or float16 with shape (N, 5), Outputs of the rois which balance. +* @li index: 1D Tensor 0f int32 with shape (N,), that is the index of origin rois. + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(BalanceRois) + .INPUT(rois, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(balance_rois, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(index, TensorType({DT_INT32})) + .OP_END_FACTORY_REG(BalanceRois) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_DETECT_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index 2d4149e2..1e71c99c 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -104,9 +104,8 @@ REG_OP(SoftmaxCrossEntropyWithLogits) *@par Inputs: * Two inputs, including: * @li softmax: Output of the softmax operator. Must be one of the following -* types: float16, float31, int32, int8, uint8. The format is NC1HWC0 or DN. -* @li grad_softmax: A Tensor. Has the same shape and type as "softmax". -* The format is NC1HWC0 or DN . \n +* types: float16, float31, int32, int8, uint8. +* @li grad_softmax: A Tensor. Has the same shape and type as "softmax".\n *@par Attributes: * axes: An optional list of ints. Defaults to "{-1}" . \n @@ -1101,8 +1100,8 @@ REG_OP(GroupNorm) *@brief Performs instance normalization . \n *@par Inputs: -* Five inputs, including: (NC1HWC0, supported) -*@li x: A 5D Tensor of type float16 or float32, NC1HWC0. +* Five inputs, including: +*@li x: A 5D Tensor of type float16 or float32. *@li gamma: A Tensor of type float32. A 5D Tensor for scaling factor, to scale the normalized x. *@li beta: A Tensor of type float32. @@ -1121,7 +1120,7 @@ the value used for the running_mean and running_var computation. Default: "0.1". variance to avoid dividing by zero. Defaults to "0.00001" . \n *@par Outputs: -* Three outputs, including: (NHWC, NCHW NC1HWC0 supported) +* Three outputs, including: (NHWC, NCHW supported) *@li y: A 5D tensor of type float16 or float32 for the normalized "x", *@li batch_mean: A Tensor of type float32. Specifies the mean of "x". @@ -1154,7 +1153,7 @@ REG_OP(InstanceNormV2) *@brief Performs instance normalization for inference. *@par Inputs:\n -* Five inputs, including: (NC1HWC0 supported) +* Five inputs, including: *@li x: A Tensor of type float16 or float32. *@li gamma: A [N, C1, 1, 1, C0] Tensor of type float32, for the scaling gamma. *@li beta: A [N, C1, 1, 1, C0] Tensor of type float32, for the scaling beta. @@ -1740,5 +1739,77 @@ REG_OP(DropoutWithMulsAndSoftmaxGrad) .REQUIRED_ATTR(alpha, Float) .ATTR(axes, ListInt, { -1 }) .OP_END_FACTORY_REG(DropoutWithMulsAndSoftmaxGrad) + +/** +* @brief Loss function that measures the softmax cross entropy. \n + +* @par Inputs: +* Three inputs, including: +* @li scores: A Tensor. Must be one of the following types: half, float32, double. +* A "batch_size * num_classes" matrix. +* @li labels: A Tensor. Must be one of the following types: "int32", "int64". +* @li weights: A manual rescaling weight given to each class. +* If given, it has to be a 1D Tensor assigning weight to each of the classes. +* Otherwise, it is treated as if having all ones. \n + +* @par Attributes: +* ignore_index:Specifies a target value that is ignored and does not contribute to the input gradient. +* It's an optional value. +* reduction: A character string from "none", "mean", and "sum", specifying the gradient output mode. Defaults to "mean" . \n + +* @par Outputs: +* @li loss: A Tensor for per example loss (a "batch_size" vector). Has the same type as "scores". +* @li log_prop: A Tensor. Has the same type as "scores" . \n + +* @par Third-party framework compatibility +* Compatible with the ONNX operator SoftmaxCrossEntropyLoss. +*/ +REG_OP(SoftmaxCrossEntropyLoss) + .INPUT(scores, TensorType({DT_DOUBLE,DT_FLOAT16,DT_FLOAT,DT_BFLOAT16})) + .INPUT(labels, TensorType({DT_INT32, DT_INT64})) + .OPTIONAL_INPUT(weights, TensorType({DT_DOUBLE,DT_FLOAT16,DT_FLOAT,DT_BFLOAT16})) + .ATTR(ignore_index, Int, 0) + .ATTR(reduction, String, "mean") + .OUTPUT(loss, TensorType({DT_DOUBLE,DT_FLOAT16,DT_FLOAT,DT_BFLOAT16})) + .OUTPUT(log_prop, TensorType({DT_DOUBLE,DT_FLOAT16,DT_FLOAT,DT_BFLOAT16})) + .OP_END_FACTORY_REG(SoftmaxCrossEntropyLoss) + +/** +* @brief Function axpy with softmax and dropoutdomask . \n + +* @par Inputs: +* Three inputs, including: +* @li x1: A mutable Tensor. The type only support float16. +* @li x2: A mutable Tensor. The type only support float16. +* @li mask: A mutable Tensor. Must meet all of the following rules: +* shape of mask should be 1D. +* dtype of mask should be uint8. +* value of shape should meet the following algorithm: +* value = (size(x) + 128 - 1) // 128 * 128 . \n + +* @par Attributes: +* @li alpha: A attribute used to scale tensor. The type is float . \n +* @li input_keep_prob: A attribute used to judge which units should be keep. +* The type is float . \n +* @li axis: A list of int. The dimension softmax would be performed on. Defaults +* to "[-1]" . \n + +* @par Outputs: +* y1: A mutable Tensor. Has the same type as "x1". \n +* y2: A mutable Tensor. Has the same type as "x1". \n + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(AxpyWithSoftmaxAndDropOutDoMask) + .INPUT(x1, TensorType({DT_FLOAT16})) + .INPUT(x2, TensorType({DT_FLOAT16})) + .INPUT(mask, TensorType({DT_UINT8})) + .OUTPUT(y1, TensorType({DT_FLOAT16})) + .OUTPUT(y2, TensorType({DT_FLOAT16})) + .REQUIRED_ATTR(alpha, Float) + .REQUIRED_ATTR(input_keep_prob, Float) + .ATTR(axis, ListInt, {-1}) + .OP_END_FACTORY_REG(AxpyWithSoftmaxAndDropOutDoMask) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_NORM_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_ops.h b/third_party/fwkacllib/inc/ops/nn_ops.h index 5b1a4dd0..83aa30d2 100644 --- a/third_party/fwkacllib/inc/ops/nn_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_ops.h @@ -54,17 +54,17 @@ REG_OP(InTopKV2) *@brief Performs batch normalization . \n *@par Inputs: -* Five inputs, including: (NHWC, NCHW, or NC1HWC0 supported) -*@li x: A 4D or 5D Tensor of type float16 or float32, with format NHWC or NCHW for 4D or NC1HWC0 for 5D. -*@li scale: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D -if input "x" is with format NC1HWC0. Specifies the scaling factor. -*@li offset: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D -if input "x" is with format NC1HWC0. Specifies the offset. -*@li mean: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D -if input "x" is with format NC1HWC0. Specifies the mean used for inference. Must be "None" if the +* Five inputs, including: (NHWC, NCHW supported) +*@li x: A 4D or 5D Tensor of type float16 or float32, with format NHWC or NCHW for 4D. +*@li scale: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. +Specifies the scaling factor. +*@li offset: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. +Specifies the offset. +*@li mean: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. +Specifies the mean used for inference. Must be "None" if the operation is used for training. -*@li variance: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be -5D if input "x" is with format NC1HWC0. Specifies the variance used for inference. Must be "None" +*@li variance: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. +Specifies the variance used for inference. Must be "None" if the operation is used for training . \n *@par Attributes: @@ -73,16 +73,16 @@ if the operation is used for training . \n *@li is_training: An optional bool, specifying if the operation is used for training or inference. Defaults to "True" . \n *@par Outputs: -* Five outputs, including: (NHWC, NCHW, or NC1HWC0 supported) -*@li y: A 4D or 5D Tensor of type float16 or float32 for the normalized "x", with format NHWC or NCHW for 4D or NC1HWC0 for 5D. -*@li batch_mean: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. Must be 5D -if input "x" is with format NC1HWC0. Specifies the mean of "x". +* Five outputs, including: (NHWC, NCHWsupported) +*@li y: A 4D or 5D Tensor of type float16 or float32 for the normalized "x", with format NHWC or NCHW for 4D. +*@li batch_mean: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. +Specifies the mean of "x". *@li batch_variance: A Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. -Must be 5D if input "x" is with format NC1HWC0. Specifies the variance of "x". +pecifies the variance of "x". *@li reserve_space_1: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. -Must be 5D if input "x" is with format NC1HWC0. Specifies the mean of "x" for gradient computation. Pass "None" to skip this output. +Specifies the mean of "x" for gradient computation. Pass "None" to skip this output. *@li reserve_space_2: An optional Tensor of type float32. Must be 1D if input "x" is with format NHWC or NCHW. -Must be 5D if input "x" is with format NC1HWC0. Specifies the variance of "x" for gradient computation. Pass "None" to skip this output . \n +Specifies the variance of "x" for gradient computation. Pass "None" to skip this output . \n *@attention Constraints: *@li If the operation is used for inference and outputs "reserve_space_1" and "reserve_space_2" are available, @@ -109,18 +109,20 @@ REG_OP(FusedBatchNormV2) * @brief Large amount of data sort.First operator of TopK. * @par Inputs: * two input, including: - * @li input_data: A Tensor. Data to be sorted. Support float16 - * @li input_index: A Tensor. Range(0, 2048). Datatype and format is same as input_data. + * @li input_data: A Tensor. Data to be sorted. Support float16 or float32. + * @li input_index: A Tensor. Range(0, 2048). Support float16 or int32. * @par Attributes: * k_num: Int.Number to be sorted. * @par Outputs: * One output, including: * output_proposal: A Tensor. Datatype and format is same as input_data. Proposal sorted for each channel. + * @par Restrictions: + * Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(SegmentSort) - .INPUT(input_data, TensorType({DT_FLOAT16})) - .INPUT(input_index, TensorType({DT_FLOAT16})) - .OUTPUT(output_proposal, TensorType({DT_FLOAT16})) + .INPUT(input_data, TensorType({DT_FLOAT16,DT_FLOAT})) + .INPUT(input_index, TensorType({DT_FLOAT16,DT_INT32})) + .OUTPUT(output_proposal, TensorType({DT_FLOAT16,DT_FLOAT})) .REQUIRED_ATTR(k_num, Int) .OP_END_FACTORY_REG(SegmentSort) @@ -128,17 +130,23 @@ REG_OP(SegmentSort) * @brief: Large amount of data sort.Second operator of TopK. * @par Inputs: * One input, including: - * input_proposal: A Tensor. Proposal sorted for each channel. Support float16 + * input_proposal: A Tensor. Proposal sorted for each channel. Support float16 or float32 * @par Attributes: * k_num: Int.Number to be sorted. + * include_index: Bool.include_index is false,output proposal. include_index is true, output data and index. * @par Outputs: - * One output, including: + * Two output, including: * output_proposal: A Tensor. Datatype and format is same as input_data. Proposal sorted for each channel. + * output_index: A Tensor.If include_index is true, output index. + * @par Restrictions: + * Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(MultiMerge) - .INPUT(input_proposal, TensorType({DT_FLOAT16})) - .OUTPUT(output_proposal, TensorType({DT_FLOAT16})) + .INPUT(input_proposal, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(output_proposal, TensorType({DT_FLOAT16,DT_FLOAT})) + .OUTPUT(output_index, TensorType({DT_INT32})) .REQUIRED_ATTR(k_num, Int) + .ATTR(include_index, Bool, false) .OP_END_FACTORY_REG(MultiMerge) /** @@ -152,12 +160,166 @@ REG_OP(MultiMerge) * Two output, including: * @li output_data: A Tensor. Datatype and format is same as input_data. Data sorted. * @li output_index: A Tensor. int32. Data index. + * @par Restrictions: + * Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(SingleMerge) - .INPUT(input_proposal, TensorType({DT_FLOAT16})) - .OUTPUT(output_data, TensorType({DT_FLOAT16})) - .OUTPUT(output_index, TensorType({DT_INT32})) + .INPUT(input_proposal, TensorType({ DT_FLOAT16 })) + .OUTPUT(output_data, TensorType({ DT_FLOAT16 })) + .OUTPUT(output_index, TensorType({ DT_INT32 })) .REQUIRED_ATTR(k_num, Int) .OP_END_FACTORY_REG(SingleMerge) + +/** + * @brief MultiHeadAttention. + * @par Inputs: + * thirteen input, including: + * @li query: A Tensor. Query of Attention. Support float16 + * @li key: A Tensor. Key of Attention. Support float16 + * @li value: A Tensor. Value of Attention. Support float16 + * @li query_weight: A Tensor. QueryWeight of Attention. Support float16 + * @li key_weight: A Tensor. KeyWeight of Attention. Support float16 + * @li value_weight: A Tensor. ValueWeight of Attention. Support float16 + * @li attn_mask: A Tensor. AttentionMask of Attention. Support float16 + * @li out_proj_weight: A Tensor. OutProjWeight of Attention. Support float16 + * @li query_bias: Optional Tensor. QueryBias of Attention. Support float16 + * @li key_bias: Optional Tensor. KeyBias of Attention. Support float16 + * @li value_bias: Optional Tensor. ValueBias of Attention. Support float16 + * @li out_proj_bias: Optional Tensor. OutProjBias of Attention. Support float16 + * @li dropout_mask_input: Optional Tensor. DropOutMask of Attention. Support uint8 \n + + * @par Attributes: + * @li attn_head_num: Attention Head numbers, Support int + * @li attn_dim_per_head: Attention dim of a Head, Support int + * @li src_len: source length, Support int + * @li tgt_len: target length, Support int + * @li keep_prob: dropout keep probability, Support float + * @li softmax_use_float: SoftMax Use Float32 to keep precision, Support bool \n + + * @par Outputs: + * Eight output, including: + * @li y: A Tensor. Result of Attention. Support float16 + * @li dropout_mask: DropOutMask of Attention. Support uint8 + * @li query_res: Query Result of Attention. Support float16 + * @li key_res: Key Result of Attention. Support float16 + * @li value_res: Value Result of Attention. Support float16 + * @li attn_scores: Attention Scores of SoftMax. Support float16, float + * @li attn_res: Attention Result of SoftMax. Support float16 + * @li context: Context of Attention. Support float16 + + * @par Restrictions: + * Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. + */ +REG_OP(MultiHeadAttention) + .INPUT(query, TensorType({DT_FLOAT16})) + .INPUT(key, TensorType({DT_FLOAT16})) + .INPUT(value, TensorType({DT_FLOAT16})) + .INPUT(query_weight, TensorType({DT_FLOAT16})) + .INPUT(key_weight, TensorType({DT_FLOAT16})) + .INPUT(value_weight, TensorType({DT_FLOAT16})) + .INPUT(attn_mask, TensorType({DT_FLOAT16})) + .INPUT(out_proj_weight, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(query_bias, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(key_bias, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(value_bias, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(out_proj_bias, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(dropout_mask_input, TensorType({DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT16})) + .OUTPUT(dropout_mask, TensorType({DT_UINT8})) + .OUTPUT(query_res, TensorType({DT_FLOAT16})) + .OUTPUT(key_res, TensorType({DT_FLOAT16})) + .OUTPUT(value_res, TensorType({DT_FLOAT16})) + .OUTPUT(attn_scores, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(attn_res, TensorType({DT_FLOAT16})) + .OUTPUT(context, TensorType({DT_FLOAT16})) + .REQUIRED_ATTR(attn_head_num, Int) + .REQUIRED_ATTR(attn_dim_per_head, Int) + .REQUIRED_ATTR(src_len, Int) + .REQUIRED_ATTR(tgt_len, Int) + .REQUIRED_ATTR(keep_prob, Float) + .REQUIRED_ATTR(softmax_use_float, Bool) + .OP_END_FACTORY_REG(MultiHeadAttention) + +/** + * @brief MultiHeadAttentionGrad. + * @par Inputs: + * thirteen input, including: + * @li query: A Tensor. Query of Attention. Support float16 + * @li key: A Tensor. Key of Attention. Support float16 + * @li value: A Tensor. Value of Attention. Support float16 + * @li query_weight: A Tensor. QueryWeight of Attention. Support float16 + * @li key_weight: A Tensor. KeyWeight of Attention. Support float16 + * @li value_weight: A Tensor. ValueWeight of Attention. Support float16 + * @li out_proj_weight: A Tensor. OutProjWeight of Attention. Support float16 + * @li query_res: A Tensor. Query Result of Attention. Support float16 + * @li key_res: A Tensor. Key Result of Attention. Support float16 + * @li value_res: A Tensor. Value Result of Attention. Support float16 + * @li attn_scores: A Tensor. Attention Scores of Attention. Support float16, float + * @li attn_res: A Tensor. Attention Result of Attention. Support float16 + * @li context: A Tensor. Context of Attention. Support float16 + * @li y_grad: A Tensor. Grad of Attention. Support float16 + * @li dropout_mask: : A Tensor. Query Result of Attention. Support uint8 \n + + * @par Attributes: + * @li attn_head_num: Attention Head numbers, Support int + * @li attn_dim_per_head: Attention dim of a Head, Support int + * @li src_len: source length, Support int + * @li tgt_len: target length, Support int + * @li keep_prob: dropout keep probability, Support float + * @li softmax_use_float: SoftMax Use Float32 to keep precision, Support bool + * @li bias_grad_mask: mask for attention has bias grad, Support list bool \n + + * @par Outputs: + * Eight output, including: + * @li query_weight_grad: QueryWeight Grad of Attention. Support float16 + * @li key_weight_grad: KeyWeight Grad of Attention. Support float16 + * @li value_weight_grad: ValueWeight Grad of Attention. Support float16 + * @li out_proj_weight_grad: OutProjWeight Grad of Attention. Support float16 + * @li query_grad: Query Grad of Attention. Support float16 + * @li key_grad: Key Grad of Attention. Support float16 + * @li value_grad: Value Grad of Attention. Support float16 + * @li query_bias_grad: QueryBias Grad of Attention. Support float16 + * @li key_bias_grad: KeyBias Grad of Attention. Support float16 + * @li value_bias_grad: ValueBias Grad of Attention. Support float16 + * @li out_proj_bias_grad: OutProjBias Grad of Attention. Support float16 + + * @par Restrictions: + * Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. + */ +REG_OP(MultiHeadAttentionGrad) + .INPUT(query, TensorType({DT_FLOAT16})) + .INPUT(key, TensorType({DT_FLOAT16})) + .INPUT(value, TensorType({DT_FLOAT16})) + .INPUT(query_weight, TensorType({DT_FLOAT16})) + .INPUT(key_weight, TensorType({DT_FLOAT16})) + .INPUT(value_weight, TensorType({DT_FLOAT16})) + .INPUT(out_proj_weight, TensorType({DT_FLOAT16})) + .INPUT(query_res, TensorType({DT_FLOAT16})) + .INPUT(key_res, TensorType({DT_FLOAT16})) + .INPUT(value_res, TensorType({DT_FLOAT16})) + .INPUT(attn_scores, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(attn_res, TensorType({DT_FLOAT16})) + .INPUT(context, TensorType({DT_FLOAT16})) + .INPUT(y_grad, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(dropout_mask, TensorType({DT_UINT8})) + .OUTPUT(query_weight_grad, TensorType({DT_FLOAT16})) + .OUTPUT(key_weight_grad, TensorType({DT_UINT8})) + .OUTPUT(value_weight_grad, TensorType({DT_FLOAT16})) + .OUTPUT(out_proj_weight_grad, TensorType({DT_FLOAT16})) + .OUTPUT(query_grad, TensorType({DT_FLOAT16})) + .OUTPUT(key_grad, TensorType({DT_FLOAT16})) + .OUTPUT(value_grad, TensorType({DT_FLOAT16})) + .OUTPUT(query_bias_grad, TensorType({DT_FLOAT16})) + .OUTPUT(key_bias_grad, TensorType({DT_FLOAT16})) + .OUTPUT(value_bias_grad, TensorType({DT_FLOAT16})) + .OUTPUT(out_proj_bias_grad, TensorType({DT_FLOAT16})) + .REQUIRED_ATTR(attn_head_num, Int) + .REQUIRED_ATTR(attn_dim_per_head, Int) + .REQUIRED_ATTR(src_len, Int) + .REQUIRED_ATTR(tgt_len, Int) + .REQUIRED_ATTR(keep_prob, Float) + .REQUIRED_ATTR(softmax_use_float, Bool) + .REQUIRED_ATTR(bias_grad_mask, ListBool) + .OP_END_FACTORY_REG(MultiHeadAttentionGrad) }// namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h index 1c689ee9..e81b84c4 100644 --- a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h @@ -81,10 +81,16 @@ REG_OP(Pooling) *x: A tensor of type float16, float32, double . \n *@par Attributes: -*@li ksize: A required list of 4 ints, specifying the size (N, C, H, and W) of the sliding window, where N = C = 1, and H and W are positive integers within the range [1, 255]. -*@li strides: A required list of 4 ints, specifying the stride of the sliding window. The strides of the N and C dimensions are 1. The strides of the H and W dimensions are positive integers within the range [1, 63]. -*@li padding: A required string, specifying the padding algorithm, either "VALID" or "SAME". With "SAME" means that the outputs will have the same spatial dimensions as its inputs. With "VALID" means no padding. -*@li data_format: An optional string, specifying the data format of "ksize" and "strides", either "NCHW", "NC1HWC0", or "NHWC" (default) . \n +*@li ksize: A required list of 4 ints, specifying the size (N, C, H, and W) of the sliding window, + * where N = C = 1, and H and W are positive integers within the range [1, 255]. +*@li strides: A required list of 4 ints, specifying the stride of the sliding window. + * The strides of the N and C dimensions are 1. + * The strides of the H and W dimensions are positive integers within the range [1, 63]. +*@li padding: A required string, specifying the padding algorithm, + * either "VALID" or "SAME". With "SAME" means that the outputs will have the same spatial dimensions as its inputs. + * With "VALID" means no padding. +*@li data_format: An optional string, specifying the data format of "ksize" and "strides", + * either "NCHW", or "NHWC" (default) . \n *@par Outputs: *y: The average pooled output tensor. Has the same type and format as input "x" . \n @@ -94,7 +100,8 @@ REG_OP(Pooling) *@li Only single input and single output are supported. *@li Global pooling is supported. *@li "ksize_H" and "ksize_W" are positive integers within the range [1, 255]. ksize_H * ksize_W < 256 -*@li Due to instruction restrictions, the values of "strides_h" and "strides_w" are positive integers within the range [1, 63]. +*@li Due to instruction restrictions, + * the values of "strides_h" and "strides_w" are positive integers within the range [1, 63]. *@par Third-party framework compatibility * Compatible with the TensorFlow operator AvgPool. */ @@ -114,11 +121,18 @@ REG_OP(AvgPool) *x: A tensor of type float16, float32, double. *@par Attributes: -*@li ksize: A required list of 4 ints, specifying the size (N, C, H, and W) of the sliding window, where N = C = 1, and H and W are positive integers within the range [1, 255]. -*@li strides: A required list of 4 ints, specifying the stride of the sliding window. The strides of the N and C dimensions are 1. The strides of the H and W dimensions are positive integers within the range [1, 63]. -*@li padding_mode: A required string, specifying the padding algorithm, either "VALID", "SAME" and "CALCULATED". With "SAME" means that the outputs will have the same spatial dimensions as its inputs. With "VALID" means no padding. +*@li ksize: A required list of 4 ints, specifying the size (N, C, H, and W) of the sliding window, + * where N = C = 1, and H and W are positive integers within the range [1, 255]. +*@li strides: A required list of 4 ints, specifying the stride of the sliding window. + * The strides of the N and C dimensions are 1. + * The strides of the H and W dimensions are positive integers within the range [1, 63]. +*@li padding_mode: A required string, specifying the padding algorithm, + * either "VALID", "SAME" and "CALCULATED". + * With "SAME" means that the outputs will have the same spatial dimensions as its inputs. + * With "VALID" means no padding. *@li pads: Pad value when padding_mode is "CALCULATED". -*@li data_format: An optional string, specifying the data format of "ksize" and "strides", either "NCHW", "NC1HWC0", or "NHWC" (default). +*@li data_format: An optional string, specifying the data format of "ksize" and "strides", + * either "NCHW", or "NHWC" (default). *@li global_pooling: Global or not. If true, pads will change to {0,0,0,0} and ksize will change to [input_h, input_w] *@li ceil_mode: Use ceil or floor to calculate the output size when padding_mode is "CALCULATED". *@li exclusive: Ignore padding area or not when calculating average. @@ -130,7 +144,8 @@ REG_OP(AvgPool) *@li Only single input and single output are supported. *@li Global pooling is supported. *@li "ksize_H" and "ksize_W" are positive integers within the range [1, 255]. ksize_H * ksize_W < 256 -*@li Due to instruction restrictions, the values of "strides_h" and "strides_w" are positive integers within the range [1, 63]. +*@li Due to instruction restrictions, + * the values of "strides_h" and "strides_w" are positive integers within the range [1, 63]. *@par Third-party framework compatibility * Compatible with the TensorFlow operator AvgPoolV2. */ @@ -310,21 +325,24 @@ REG_OP(AvgPool3DGradD) *@par Inputs: * One input: -*x: An NC1HWC0 Tensor of type float16. +*x: A Tensor of type float16. *@par Attributes: -*@li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for each dimension of the input tensor. No default value. -*@li strides: A required list of int8, int16, int32, or int64 values, specifying the stride of the sliding window for each dimension of the input tensor. No default value. +*@li ksize: A required list of int8, int16, int32, or int64 values, + * specifying the size of the window for each dimension of the input tensor. No default value. +*@li strides: A required list of int8, int16, int32, or int64 values, + * specifying the stride of the sliding window for each dimension of the input tensor. No default value. *@li padding: A required string. No default value. -*@li data_format: An optional string. Defaults to "NC1HWC0" . \n +*@li data_format: An optional string . \n *@par Outputs: *y: A Tensor. Has the same type and format as input "x" . \n *@attention Constraints: *@li "ksize" is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, ksize[1] * ksize[2] <= 255. -*@li "stride is a list that has length 4: strides[0] = 1 or strides[3] = 1, strides[1] <= 63, strides[0] >= 1, strides[2] <= 63, strides[2] >= 1. +*@li "stride is a list that has length 4: strides[0] = 1 or strides[3] = 1, + * strides[1] <= 63, strides[0] >= 1, strides[2] <= 63, strides[2] >= 1. *@li "padding" is either "SAME" or "VALID" . \n *@par Third-party framework compatibility @@ -348,7 +366,7 @@ REG_OP(MaxPoolExt2) *@par Inputs: * One input: -*x: An NC1HWC0 Tensor. Supported type:float16, float32, double, int8, int16, +*x: A Tensor. Supported type:float16, float32, double, int8, int16, * int32, int64, uint8, uint16, qint8 *@par Attributes: @@ -391,7 +409,7 @@ REG_OP(MaxPool) *@brief Performs max 3d pooling on the input . \n *@par Inputs: -*x: An NC1HWC0 Tensor. Supported type float16, float32, double . \n +*x: A Tensor. Supported type float16, float32, double . \n *@par Attributes: *@li ksize: A required list of int8, int16, int32, or int64 values, @@ -457,7 +475,6 @@ REG_OP(MaxPool3D) * y: An 6D tensor. the maxpool3d output(max value), format as NDoC1HoWoC0. * @par Outputs: * argmax: A 5D uint16 tensor. the indice output. -* format as NC1HWC0, actually it represent N, Do, C1*ksize, Ho*Wo//16, 16. */ REG_OP(MaxPool3DWithArgmax) .INPUT(x, TensorType::RealNumberType()) @@ -546,9 +563,9 @@ REG_OP(MaxPool3DGradGrad) * @brief Computes gradients of the maxpooling function . \n * @par Inputs: -* @li x1: A mutable NC1HWC0 tensor of type RealNumberType. -* @li x2: A mutable NC1HWC0 tensor of type RealNumberTypex. -* @li grad: A mutable NC1HWC0 tensor of type RealNumberType . \n +* @li x1: A mutable tensor of type RealNumberType. +* @li x2: A mutable tensor of type RealNumberTypex. +* @li grad: A mutable tensor of type RealNumberType . \n * @par Attributes: * @li ksize: A required tuple or list, specifying the size of the window for @@ -630,21 +647,24 @@ REG_OP(MaxPoolGradGrad) *@par Inputs: * Three inputs: -*@li x: An NC1HWC0 Tensor of type float16. -*@li strides: A required type of int32 values, specifying the stride of the sliding window for each dimension of the input tensor. No default value. -*@li ksize: A required type of int32 values, specifying the size of the window for each dimension of the input tensor. No default value. +*@li x: A Tensor of type float16. +*@li strides: A required type of int32 values, + * specifying the stride of the sliding window for each dimension of the input tensor. No default value. +*@li ksize: A required type of int32 values, + * specifying the size of the window for each dimension of the input tensor. No default value. *@par Attributes: *@li padding: A required string. No default value. -*@li data_format: An optional string. Defaults to "NC1HWC0" . \n +*@li data_format: An optional string. \n *@par Outputs: *y: A Tensor. Has the same type and format as input "x" . \n *@attention Constraints: *@li "ksize" is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, ksize[1] * ksize[2] <= 255. -*@li "stride is a list that has length 4: strides[0] = 1 or strides[3] = 1, strides[1] <= 63, strides[0] >= 1, strides[2] <= 63, strides[2] >= 1. +*@li "stride is a list that has length 4: strides[0] = 1 or strides[3] = 1, strides[1] <= 63, strides[0] >= 1, + * strides[2] <= 63, strides[2] >= 1. *@li "padding" is either "SAME" or "VALID" . \n *@par Third-party framework compatibility @@ -713,7 +733,7 @@ REG_OP(MaxPoolWithArgmax) *@li grad: An 4d tensor. Supported type: float, double, int32, * uint8, int16, int8, int64, uint16, half, uint32, uint64. * Must set the format, supported format list ["NCHW, NHWC"] -*@li argmx: An NC1HWC0 tensor of type int32 or int64 . \n +*@li argmx: A tensor of type int32 or int64 . \n *@par Attributes: *@li ksize: A required list of int8, int16, int32, or int64 values, @@ -753,8 +773,8 @@ REG_OP(MaxPoolGradWithArgmax) *@par Inputs: * Two inputs: -*@li x: An NC1HWC0 Tensor of type float16. -*@li mask: An NC1HWC0 Tensor of type uint16 . \n +*@li x: A Tensor of type float16. +*@li mask: A Tensor of type uint16 . \n *@par Attributes: *@li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for each dimension of the input tensor. No default value. @@ -763,7 +783,7 @@ REG_OP(MaxPoolGradWithArgmax) *@li originshape:A required list of int8, int16, int32, or int64 values, No default value. \n *@par Outputs: -*argmax: An NC1HWC0 Tensor of type int32 . \n +*argmax: A Tensor of type int32 . \n *@attention Constraints: *@li "ksize" is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, ksize[1] * ksize[2] <= 255. @@ -1314,7 +1334,7 @@ REG_OP(AvgPool1DD) *@par Outputs: *y: A Tensor. Has the same type and format as input "x". -*argmax: A Tensor. type:uint16, format:NC1HWC0. +*argmax: A Tensor. type:uint16. *@attention Constraints: *@li "ksize" is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, ksize[1] * ksize[2] <= 255. *@li "strides is a list that has length 4: strides[0] = 1 or strides[3] = 1, strides[1] <= 63, strides[0] >= 1, @@ -1388,7 +1408,7 @@ REG_OP(MaxPoolGradWithArgmaxV2) * @par Inputs: * One input: -* x: An NC1HWC0 Tensor. Supported type:float16, float32, double, int32, int64, +* x: A Tensor. Supported type:float16, float32, double, int32, int64, * uint8, int16, int8, uint16, qint8 * @par Attributes: @@ -1400,9 +1420,8 @@ REG_OP(MaxPoolGradWithArgmaxV2) * the input tensor. No default value. * @li padding_mode: A required string. Defaults to "CALCULATED". * @li pads:A required list of int8, int16, int32, or int64 values, -* a data to caculate when padding_mode is "CALCULATED". +* a data to calculate when padding_mode is "CALCULATED". * @li data_format: An optional string. Defaults to "NHWC" . -* If data_format = "NC1HWC0", ori_format must be "NCHW". * @li global_pooling bool, Whether to use the global pooling. * If global_pooling = true, kernel size and paddings will be ignored. * Default False @@ -1418,7 +1437,7 @@ REG_OP(MaxPoolGradWithArgmaxV2) * ksize[1] * ksize[2] <= 255. * @li "stride is a list that has length 4: strides[0] = 1 or strides[3] = 1, * strides[1] <= 63, strides[0] >= 1, strides[2] <= 63, strides[2] >= 1. -* @li "padding" is "SAME" "VALID" or "CACULATE" . +* @li "padding" is "SAME" "VALID" or "CALCULATE" . * @par Third-party framework compatibility @@ -1440,9 +1459,9 @@ REG_OP(MaxPoolV3) * @brief Computes gradients of the maxpooling function . \n * @par Inputs: -* @li orig_input: A mutable NC1HWC0 tensor of type RealNumberType. -* @li orig_output: A mutable NC1HWC0 tensor of type RealNumberTypex. -* @li grad: A mutable NC1HWC0 tensor of type RealNumberType . \n +* @li orig_input: A mutable tensor of type RealNumberType. +* @li orig_output: A mutable tensor of type RealNumberTypex. +* @li grad: A mutable tensor of type RealNumberType . \n * @par Attributes: * @li ksize: A required list of int8, int16, int32, or int64 values, @@ -1650,9 +1669,9 @@ REG_OP(AdaptiveAvgPool2dGrad) * @par Inputs: * Three inputs, including: -* @li x: An NC1HWC0 tensor of type float16. -* @li grad: An NC1HWC0 tensor of type float16. -* @li argmax: An NC1HWC0 tensor of type uint16 or int64. \n +* @li x: A tensor of type float16. +* @li grad: A tensor of type float16. +* @li argmax: A tensor of type uint16 or int64. \n * @par Attributes: * @li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for @@ -1665,11 +1684,11 @@ REG_OP(AdaptiveAvgPool2dGrad) * y: A Tensor. Has the same type and format as input "x". \n * @attention Constraints: -* @li "ksize" is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, ksize[1] * ksize[2] <= 255. -* @li "strides" is a list that has length 4: strides[0] = 1 or strides[3] = 1 -* @li "pads" is listint. -* @li "ceil_mode" defaults to False. -* @li "data_format" defaults to "NC1HWC0". \n +* @li ksize: is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, ksize[1] * ksize[2] <= 255. +* @li strides: is a list that has length 4: strides[0] = 1 or strides[3] = 1 +* @li pads: listint. +* @li ceil_mode: defaults to False. +* @li data_format: A optional string. \n * @par Third-party framework compatibility * Compatible with the TensorFlow operator MaxPoolGradWithArgmaxV1. @@ -1693,7 +1712,7 @@ REG_OP(MaxPoolGradWithArgmaxV1) * @par Inputs: * One input: -* x: An NC1HWC0 Tensor of type float16. \n +* x: A Tensor of type float16. \n * @par Attributes: * @li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for @@ -1704,15 +1723,15 @@ REG_OP(MaxPoolGradWithArgmaxV1) * @par Outputs: * y: A Tensor. Has the same type and format as input "x". -* argmax: A Tensor. type:uint16, format:NC1HWC0. \n +* argmax: A Tensor. type:uint16. \n * @attention Constraints: -* @li "ksize" is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, ksize[1] * ksize[2] <= 255. -* @li "stride is a list that has length 4: strides[0] = 1 or strides[3] = 1, strides[1] <= 63, strides[0] >= 1, +* @li ksize: a list that has length 4: ksize[0] = 1 or ksize[3] = 1, ksize[1] * ksize[2] <= 255. +* @li stride: a list that has length 4: strides[0] = 1 or strides[3] = 1, strides[1] <= 63, strides[0] >= 1, * strides[2] <= 63, strides[2] >= 1. -* @li "pads" is listint. -* @li "ceil_mode" defaults to False. -* @li "data_format" defaults to "NC1HWC0". \n +* @li pads: listint. +* @li ceil_mode: defaults to False. +* @li data_format: A optional string. \n * @par Third-party framework compatibility * Compatible with the TensorFlow operator MaxPoolWithArgmaxV1. diff --git a/third_party/fwkacllib/inc/ops/nn_training_ops.h b/third_party/fwkacllib/inc/ops/nn_training_ops.h index bc75cfb7..21ee90ab 100644 --- a/third_party/fwkacllib/inc/ops/nn_training_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_training_ops.h @@ -159,6 +159,7 @@ REG_OP(SparseApplyAdagrad) .INPUT(grad, TensorType({DT_FLOAT})) .INPUT(indices, TensorType({DT_INT32})) .OUTPUT(var, TensorType({DT_FLOAT})) + .OUTPUT(accum, TensorType({DT_FLOAT})) .ATTR(use_locking, Bool, false) .ATTR(update_slots, Bool, true) .OP_END_FACTORY_REG(SparseApplyAdagrad) diff --git a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h index fc61815e..7930ae07 100644 --- a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h +++ b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h @@ -423,8 +423,8 @@ REG_OP(Softplus) *@par Inputs: *Two inputs: -* @li gradients: An NC1HWC0 or ND Tensor of type float16 or float32. -* @li features: An NC1HWC0 or ND Tensor of type float16 or float32. +* @li gradients: A ND Tensor of type float16 or float32. +* @li features: A ND Tensor of type float16 or float32. *@par Outputs: @@ -457,16 +457,35 @@ REG_OP(Softsign) .OUTPUT(y, TensorType::FloatingDataType()) .OP_END_FACTORY_REG(Softsign) +/** + * @brief Computes softsignGrad: y_grad / (1 + abs(x)) ** 2 . + * + * @par Inputs: + * Two inputs, including: + * @li y_grad: A Tensor.Must be one of the following types:float16, float32, + * @li x: A Tensor of the same type and shape as "gradients". + + * @par x_grad: + * output:A Tensor. Has the same type as "y_grad". + * @par Third-party framework compatibility + * Compatible with the TensorFlow operator SoftsignGrad. + */ +REG_OP(SoftsignGrad) + .INPUT(y_grad, TensorType::FloatingDataType()) + .INPUT(x, TensorType::FloatingDataType()) + .OUTPUT(x_grad, TensorType::FloatingDataType()) + .OP_END_FACTORY_REG(SoftsignGrad) + /** *@brief Computes scaled exponential linear: scale * alpha * (exp(x) - 1) . \n *@par Inputs: * One input: *x: A Tensor. Must be one of the following types: float16, float, double - * int32, int8. format:ND, NC1HWC0 . \n + * int32, int8. format:ND. \n *@par Outputs: -*y: A Tensor. Has the same type and format as input "x". format:ND, NC1HWC0 . \n +*y: A Tensor. Has the same type and format as input "x". format:ND. \n *@see Region() @@ -480,6 +499,26 @@ REG_OP(Selu) DT_INT8,DT_INT32})) .OP_END_FACTORY_REG(Selu) +/** +* @brief Computes SeluGrad backprops: y_grad * (y + scale * alpha) +* if y < 0, scale * y_grad otherwise . + +* @par Inputs: +* Two inputs, including: +* @li y_grad: A Tensor of type RealNumberType . +* @li y: A Tensor of type RealNumberType . +* @par Outputs: +* x_grad: A Tensor. Must have the same type as "y_grad" . + +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator SeluGrad. +*/ +REG_OP(SeluGrad) + .INPUT(y_grad, TensorType::RealNumberType()) + .INPUT(y, TensorType::RealNumberType()) + .OUTPUT(x_grad, TensorType::RealNumberType()) + .OP_END_FACTORY_REG(SeluGrad) + /** *@brief Computes rectified linear gradients for a ReLU operation . \n @@ -640,7 +679,9 @@ REG_OP(Elu) *x: A float16, float32, for the input data type . \n *@par Attributes: -*li alpha: A float32. Defines at which negative value the ELU saturates. Defaults to "1.0" . +*@li alpha1: A float32. Defines at which negative value the ELU saturates. Defaults to "1.0" . +*@li alpha2: A float32. Defines at which negative value the ELU saturates. Defaults to "1.0" . +*@li alpha3: A float32. Defines at which positive value the ELU saturates. Defaults to "1.0" . \n *@par Outputs: *y: A float16, float32, for the normalized result . \n @@ -656,9 +697,39 @@ REG_OP(Elu) REG_OP(Celu) .INPUT(x, TensorType({DT_FLOAT,DT_FLOAT16})) .OUTPUT(y, TensorType({DT_FLOAT,DT_FLOAT16})) - .ATTR(alpha, Float, 1.0) + .ATTR(alpha1, Float, 1.0) + .ATTR(alpha2, Float, 1.0) + .ATTR(alpha3, Float, 1.0) .OP_END_FACTORY_REG(Celu) +/** +*@brief Continuously Differentiable Exponential Linear Uints: +* Perform the linear uint element-wise on the input tensor X using formula: +* max(0, x) + min(0, alpha * (exp(x/alpha) - 1)). \n + +*@par Inputs: +*x: A float16, float32, for the input data type . \n + +*@par Attributes: +*li alpha: A float32. Defines at which negative value the CELU saturates. Defaults to "1.0" . + +*@par Outputs: +*y: A float16, float32, for the normalized result . \n + +*@attention Constraints: +*@li The input is of type float16 or float32 . \n + +*@par Multiple batches supported or not +*Supported +*@par Third-party framework compatibility +*@li Compatible with ONNX's Celu operator +*/ +REG_OP(CeluV2) + .INPUT(x, TensorType({DT_FLOAT,DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_FLOAT,DT_FLOAT16})) + .ATTR(alpha, Float, 1.0) + .OP_END_FACTORY_REG(CeluV2) + /** *@brief Computes gradients for the exponential linear (Elu) operation. * diff --git a/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h b/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h index 1bdfb2c7..b69abea5 100644 --- a/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h +++ b/third_party/fwkacllib/inc/ops/npu_loss_scale_ops.h @@ -141,8 +141,7 @@ REG_OP(NPUClearFloatStatusV2) *Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(NPUGetFloatStatusV2) - .DYNAMIC_INPUT(addr, TensorType{DT_FLOAT}) - .OUTPUT(data, TensorType({DT_FLOAT})) + .OUTPUT(data, TensorType({DT_INT32})) .OP_END_FACTORY_REG(NPUGetFloatStatusV2) } // namespace ge diff --git a/third_party/fwkacllib/inc/ops/quantize_ops.h b/third_party/fwkacllib/inc/ops/quantize_ops.h index f6dd9c2d..1f30db61 100644 --- a/third_party/fwkacllib/inc/ops/quantize_ops.h +++ b/third_party/fwkacllib/inc/ops/quantize_ops.h @@ -115,13 +115,13 @@ REG_OP(AscendQuant) *@brief Dequantizes the input . \n *@par Inputs: -*@li x: An tensor of type int32, specifying the input. -*@li deq_scale: An tensor of type float16 or uint64, specifying the scaling ratio . \n +* @li x: An tensor of type int32, specifying the input. +* @li deq_scale: An tensor of type uint64, specifying the scaling ratio . \n *@par Attributes: -*@li sqrt_mode: A optional bool, specifying whether to perform square root on "scale", either "True" or "False". Defaults to "False". -*@li relu_flag: A optional bool, specifying whether to perform ReLU, either "True" or "False". Defaults to "False". -*@li dtype: A optional int32, specifying the output data type. Defaults to "DT_FLOAT" . \n +* @li sqrt_mode: A optional bool, specifying whether to perform square root on "scale", either "True" or "False". Defaults to "False". +* @li relu_flag: A optional bool, specifying whether to perform ReLU, either "True" or "False". Defaults to "False". +* @li dtype: A optional int32, specifying the output data type. Defaults to "DT_FLOAT" . \n *@par Outputs: *y: The dequantized output tensor of type float16 or float32. \n @@ -246,14 +246,14 @@ REG_OP(AscendRequantS16) * @brief Quantizes the input of int8 . \n * @par Inputs: -* @li x: An FRACTAL_Z tensor of type int8, specifying the input. -* @li offset: An FRACTAL_Z tensor of type int8. +* @li x: A tensor of type int8, specifying the input. +* @li offset: A tensor of type int8. * @par Attributes: * @li dst_type: A optional int from: DT_INT8, DT_INT4. Defaults to DT_INT8. * @par Outputs: -* @li y: output tensor of type int4 or int8 and with format FRACTAL_Z. +* @li y: output tensor of type int4 or int8. * @par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe, Onnx, Tensorflow or Pythorch. diff --git a/third_party/fwkacllib/inc/ops/reduce_ops.h b/third_party/fwkacllib/inc/ops/reduce_ops.h index 6fa95abc..2c4b3059 100644 --- a/third_party/fwkacllib/inc/ops/reduce_ops.h +++ b/third_party/fwkacllib/inc/ops/reduce_ops.h @@ -28,7 +28,7 @@ namespace ge { *@brief Performs reduced batch normalization . \n *@par Inputs: -*x: A 5D Tensor of type float16 or float32, with format NC1HWC0 . \n +*x: A tensor of type float16 or float32. \n *@par Outputs: *@li sum: A 1D Tensor of type float32 for SUM reduced "x". @@ -49,11 +49,11 @@ REG_OP(BNTrainingReduce) *@brief Performs reduced batch normalization . \n *@par Inputs: -*x: A 6D Tensor of type float16 or float32, with format NDC1HWC0 . \n +*x: A tensor of type float16 or float32. \n *@par Outputs: -*@li sum: A 3D Tensor of type float32 for SUM reduced "x". -*@li square_sum: A 3D Tensor of type float32 for SUMSQ reduced "x" . \n +*@li sum: A tensor of type float32 for SUM reduced "x". +*@li square_sum: A tensor of type float32 for SUMSQ reduced "x" . \n *@attention Constraints: * This operator is a BatchNorm fusion operator for updating the moving @@ -71,17 +71,17 @@ REG_OP(BN3DTrainingReduce) *@par Inputs: * Seven inputs, including: -*@li grads: A 5D Tensor of type float16 or float32, with format NC1HWC0, for +*@li grads: A tensor of type float16 or float32, for * the gradient. -*@li x: A 5D Tensor of type float16 or float32, with format NC1HWC0. -*@li diff_scale: A 5D Tensor of type float32, with format NC1HWC0, +*@li x: A tensor of type float16 or float32. +*@li diff_scale: A tensor of type float32, * for the mean of "x". -*@li diff_offset: A 5D Tensor of type float32, with format NC1HWC0, +*@li diff_offset: A tensor of type float32, * for the variance of "x". -*@li scale: A 5D Tensor of type float32, with format NC1HWC0. -*@li batch_mean: A 5D Tensor of type float32, with format NC1HWC0, +*@li scale: A tensor of type float32. +*@li batch_mean: A tensor of type float32, * for the mean of "x". -*@li batch_variance: A 5D Tensor of type float32, with format NC1HWC0, +*@li batch_variance: A tensor of type float32, * for the variance of "x" . \n *@par Attributes: @@ -89,7 +89,7 @@ REG_OP(BN3DTrainingReduce) * added to the variance of "x" . \n *@par Outputs: -*y: A Tensor of type float16 or float32, with format NC1HWC0, for the offset +*y: A Tensor of type float16 or float32, for the offset * of "x" . \n *@attention Constraints: @@ -114,17 +114,17 @@ REG_OP(BNTrainingReduceGrad) *@par Inputs: * Seven inputs, including: -*@li grads: A 6D Tensor of type float16 or float32, with format NDC1HWC0, for +*@li grads: A tensor of type float16 or float32, for * the gradient. -*@li x: A 6D Tensor of type float16 or float32, with format NDC1HWC0. -*@li diff_scale: A 6D Tensor of type float32, with format NDC1HWC0, +*@li x: A tensor of type float16 or float32. +*@li diff_scale: A tensor of type float32, * for the mean of "x". -*@li diff_offset: A 6D Tensor of type float32, with format NDC1HWC0, +*@li diff_offset: A tensor of type float32, * for the variance of "x". -*@li scale: A 6D Tensor of type float32, with format NDC1HWC0. -*@li batch_mean: A 6D Tensor of type float32, with format NDC1HWC0, +*@li scale: A tensor of type float32. +*@li batch_mean: A tensor of type float32, * for the mean of "x". -*@li batch_variance: A 6D Tensor of type float32, with format NDC1HWC0, +*@li batch_variance: A tensor of type float32, * for the variance of "x" . \n *@par Attributes: @@ -132,7 +132,7 @@ REG_OP(BNTrainingReduceGrad) * added to the variance of "x" . \n *@par Outputs: -*y: A Tensor of type float16 or float32, with format NDC1HWC0, for the offset +*y: A Tensor of type float16 or float32, for the offset * of "x" . \n *@attention Constraints: @@ -156,8 +156,8 @@ REG_OP(BN3DTrainingReduceGrad) *@brief Performs reduced batch normalization . \n *@par Inputs: -* Seven inputs, including: (NC1HWC0 supported) -*@li x: A 5D Tensor of type float16 or float32. +* Seven inputs, including: +*@li x: A tensor of type float16 or float32. *@li sum: A 1D Tensor of type float32 for the output of operator * BNTrainingReduce. *@li square_sum: A 1D Tensor of type float32 for the output of operator @@ -174,10 +174,10 @@ REG_OP(BN3DTrainingReduceGrad) * and variance . \n *@par Outputs: -* Five outputs, including: (NC1HWC0 supported) -*@li y: A 5D Tensor of type float16 or float32, for normalized "x". -*@li mean: A 5D Tensor of type float32, for the updated mean. -*@li variance: A 5D Tensor of type float32, for the updated variance. +* Five outputs, including: +*@li y: A tensor of type float16 or float32, for normalized "x". +*@li mean: A tensor of type float32, for the updated mean. +*@li variance: A tensor of type float32, for the updated variance. *@li batch_mean: A 1D Tensor of type float32, for the mean of "x". *@li batch_variance: A 1D Tensor of type float32, for the variance of "x" . \n @@ -209,16 +209,16 @@ REG_OP(BNTrainingUpdate) *@brief Performs reduced batch normalization . \n *@par Inputs: -* Seven inputs, including: (NDC1HWC0 supported) -*@li x: A 6D Tensor of type float16 or float32. -*@li sum: A 6D Tensor of type float32 for the output of operator +* Seven inputs, including: +*@li x: A tensor of type float16 or float32. +*@li sum: A tensor of type float32 for the output of operator * BN3DTrainingUpdate. -*@li square_sum: A 6D Tensor of type float32 for the output of operator +*@li square_sum: A tensor of type float32 for the output of operator * BN3DTrainingUpdate. -*@li scale: A 6D Tensor of type float32, for the scaling factor. -*@li offset: A 6D Tensor of type float32, for the scaling offset. -*@li mean: A 6D Tensor of type float32, for the updated mean. -*@li variance: A 6D Tensor of type float32, for the updated variance . \n +*@li scale: A tensor of type float32, for the scaling factor. +*@li offset: A tensor of type float32, for the scaling offset. +*@li mean: A tensor of type float32, for the updated mean. +*@li variance: A tensor of type float32, for the updated variance . \n *@par Attributes: *@li epsilon: A required float32, specifying the small value added to variance @@ -227,12 +227,12 @@ REG_OP(BNTrainingUpdate) * and variance . \n *@par Outputs: -* Five outputs, including: (NDC1HWC0 supported) -*@li y: A 6D Tensor of type float16 or float32, for normalized "x". -*@li mean: A 6D Tensor of type float32, for the updated mean. -*@li variance: A 6D Tensor of type float32, for the updated variance. -*@li batch_mean: A 6D Tensor of type float32, for the mean of "x". -*@li batch_variance: A 6D Tensor of type float32, for the variance of "x" . \n +* Five outputs, including: +*@li y: A tensor of type float16 or float32, for normalized "x". +*@li mean: A tensor of type float32, for the updated mean. +*@li variance: A tensor of type float32, for the updated variance. +*@li batch_mean: A tensor of type float32, for the mean of "x". +*@li batch_variance: A tensor of type float32, for the variance of "x" . \n *@attention Constraints: *@li This operator is a BatchNorm fusion operator for updating the moving @@ -262,19 +262,19 @@ REG_OP(BN3DTrainingUpdate) *@brief Performs batch normalization for inference . \n *@par Inputs: -* Five inputs, including: (NC1HWC0 supported) -*@li x: A 5D Tensor of type float16 or float32. -*@li scale: A 5D Tensor of type float32, for the scaling factor. -*@li offset: A 5D Tensor of type float32, for the scaling offset. -*@li mean: A 5D Tensor of type float32, for the mean. -*@li variance: A 5D Tensor of type float32, for the variance . \n +* Five inputs, including: +*@li x: A tensor of type float16 or float32. +*@li scale: A tensor of type float32, for the scaling factor. +*@li offset: A tensor of type float32, for the scaling offset. +*@li mean: A tensor of type float32, for the mean. +*@li variance: A tensor of type float32, for the variance . \n *@par Attributes: *epsilon: An optional float32, specifying the small value added to variance to * avoid dividing by zero. Defaults to "0.0001" . \n *@par Outputs: -*y: A 5D Tensor of type float16 or float32 for the normalized "x" . \n +*y: A tensor of type float16 or float32 for the normalized "x" . \n *@attention Constraints: *For Ascend 310, the result accuracy fails to reach 1/1000 due to the square root @@ -295,21 +295,21 @@ REG_OP(BNInfer) assignmoving average . \n *@par Inputs: -*Five inputs, including: (NC1HWC0 supported) -*@li x: A 5D Tensor of type float16 or float32. -*@li sum: A 5D Tensor of type float32 for the output of operator BNTrainingReduce. -*@li square_sum: A 5D Tensor of type float32 for the output of operator BNTrainingReduce. -*@li scale: A 5D Tensor of type float32, for the scaling factor. -*@li offset: A 5D Tensor of type float32, for the scaling offset . \n +*Five inputs, including: +*@li x: A tensor of type float16 or float32. +*@li sum: A tensor of type float32 for the output of operator BNTrainingReduce. +*@li square_sum: A tensor of type float32 for the output of operator BNTrainingReduce. +*@li scale: A tensor of type float32, for the scaling factor. +*@li offset: A tensor of type float32, for the scaling offset . \n *@par Attributes: *epsilon: A required float32, specifying the small value added to variance to avoid dividing by zero . \n *@par Outputs: -*Three outputs, including: (NC1HWC0 supported) -*@li y: A 5D Tensor of type float16 or float32, for normalized "x". -*@li batch_mean: A 5D Tensor of type float32, for the mean of "x". -*@li batch_variance: A 5D Tensor of type float32, for the variance of "x" . \n +*Three outputs, including: +*@li y: A tensor of type float16 or float32, for normalized "x". +*@li batch_mean: A tensor of type float32, for the mean of "x". +*@li batch_variance: A tensor of type float32, for the variance of "x" . \n *@attention Constraints: *This operator is used in conjunction with BNTrainingReduce. @@ -332,22 +332,22 @@ REG_OP(BNTrainingUpdateV2) assign moving average . \n *@par Inputs: -* Five inputs, including: (NC1HWC0 supported) -*@li x: A 5D Tensor of type float16 or float32. -*@li sum: A 5D Tensor of type float32 for the output of operator BNTrainingReduce. -*@li square_sum: A 5D Tensor of type float32 for the output of operator BNTrainingReduce. -*@li scale: A 5D Tensor of type float32, for the scaling factor. -*@li offset: A 5D Tensor of type float32, for the scaling offset . \n +* Five inputs, including: +*@li x: A tensor of type float16 or float32. +*@li sum: A tensor of type float32 for the output of operator BNTrainingReduce. +*@li square_sum: A tensor of type float32 for the output of operator BNTrainingReduce. +*@li scale: A tensor of type float32, for the scaling factor. +*@li offset: A tensor of type float32, for the scaling offset . \n *@par Attributes: *epsilon: A required float32, specifying the small value added to variance to avoid dividing by zero . \n *@par Outputs: -*@li y: A 5D Tensor of type float16 or float32, for normalized "x". -*@li batch_mean: A 5D Tensor of type float32, for the mean of "x". -*@li batch_variance: A 5D Tensor of type float32, for the variance of "x". -*@li reserve_1: A 5D Tensor of type float32, for the mean of batch "x". Has the same type as batch_mean. -*@li reserve_2: A 5D Tensor of type float32, for the variance of batch "x". Has the same type as batch_mean . \n +*@li y: A tensor of type float16 or float32, for normalized "x". +*@li batch_mean: A tensor of type float32, for the mean of "x". +*@li batch_variance: A tensor of type float32, for the variance of "x". +*@li reserve_1: A tensor of type float32, for the mean of batch "x". Has the same type as batch_mean. +*@li reserve_2: A tensor of type float32, for the variance of batch "x". Has the same type as batch_mean . \n *@attention Constraints: *@li This operator is used in conjunction with BNTrainingReduce. @@ -372,12 +372,12 @@ REG_OP(BNTrainingUpdateV3) *@par Inputs: * Four inputs, including: -*@li grads: A 5D Tensor of type float16 or float32, with format NC1HWC0, +*@li grads: A tensor of type float16 or float32, * for the gradient. -*@li x: A 5D Tensor of type float16 or float32, with format NC1HWC0. -*@li batch_mean: A 5D Tensor of type float32, with format NC1HWC0, +*@li x: A tensor of type float16 or float32. +*@li batch_mean: A tensor of type float32, * for the mean of "x". -*@li batch_variance: A 5D Tensor of type float32, with format NC1HWC0, +*@li batch_variance: A tensor of type float32, * for the variance of "x" . \n *@par Attributes: @@ -385,9 +385,9 @@ REG_OP(BNTrainingUpdateV3) * added to the variance of "x" . \n *@par Outputs: -*@li diff_scale: A Tensor of type float32, with format NC1HWC0, +*@li diff_scale: A Tensor of type float32, * for the offset of "scale". -*@li diff_offset: A Tensor of type float32, with format NC1HWC0, +*@li diff_offset: A Tensor of type float32, * for the offset of "offset" . \n */ @@ -406,12 +406,12 @@ REG_OP(BNTrainingUpdateGrad) *@par Inputs: * Four inputs, including: -*@li grads: A 6D Tensor of type float16 or float32, with format NDC1HWC0, +*@li grads: A tensor of type float16 or float32, * for the gradient. -*@li x: A 6D Tensor of type float16 or float32, with format NDC1HWC0. -*@li batch_mean: A 6D Tensor of type float32, with format NDC1HWC0, +*@li x: A tensor of type float16 or float32. +*@li batch_mean: A tensor of type float32, * for the mean of "x". -*@li batch_variance: A 6D Tensor of type float32, with format NDC1HWC0, +*@li batch_variance: A tensor of type float32, * for the variance of "x" . \n *@par Attributes: @@ -419,9 +419,9 @@ REG_OP(BNTrainingUpdateGrad) * added to the variance of "x" . \n *@par Outputs: -*@li diff_scale: A Tensor of type float32, with format NDC1HWC0, +*@li diff_scale: A Tensor of type float32, * for the offset of "scale". -*@li diff_offset: A Tensor of type float32, with format NDC1HWC0, +*@li diff_offset: A Tensor of type float32, * for the offset of "offset" . \n */ @@ -440,15 +440,15 @@ REG_OP(BN3DTrainingUpdateGrad) *@par Inputs: * Three inputs, including: -*@li grads: A 5D Tensor of type loat16 or float32, with format NC1HWC0, for the gradient. -*@li scale: A 5D Tensor of type float32, with format NC1HWC0. -*@li batch_variance: A 5D Tensor of type float32, with format NC1HWC0. It is an output of BatchNorm . \n +*@li grads: A tensor of type loat16 or float32, for the gradient. +*@li scale: A tensor of type float32. +*@li batch_variance: A tensor of type float32. It is an output of BatchNorm . \n *@par Attributes: *epsilon: An optional float32. Defaults to "0.0001". A small float number added to the variance of "x" . \n *@par Outputs: -*x_backprop: A Tensor of type float16 or float32, with format NC1HWC0, for the offset of "x" . \n +*x_backprop: A Tensor of type float16 or float32, for the offset of "x" . \n *@attention Constraints: * The preceding layer of this operator must be operator BatchNorm. @@ -663,6 +663,9 @@ REG_OP(ReduceProdD) *keep_dims: A bool or NoneType. * - If true, retains reduced dimensions with length 1. * - If false, the rank of the tensor is reduced by 1 for each entry in axis. +*noop_with_empty_axes: A bool. +* - If true, when axes = [], not reduce. +* - If false, when axes = [], reduce all. *@par Outputs: *y: A Tensor. Has the same type as "x" . \n @@ -674,6 +677,7 @@ REG_OP(ReduceMean) .INPUT(axes, TensorType::IndexNumberType()) .OUTPUT(y, TensorType::NumberType()) .ATTR(keep_dims, Bool, false) + .ATTR(noop_with_empty_axes, Bool, true) .OP_END_FACTORY_REG(ReduceMean) /** @@ -690,6 +694,9 @@ REG_OP(ReduceMean) *@li keep_dims: A bool or NoneType. * - If true, retains reduced dimensions with length 1. * - If false, the rank of the tensor is reduced by 1 for each entry in axis. +*@li noop_with_empty_axes: A bool default False. +* - If true, same as tf. +* - If false, when x's shape is [], reduce all dims, for onnx. *@par Outputs: *y: A Tensor. Has the same type as "x" . \n @@ -704,6 +711,7 @@ REG_OP(ReduceMeanD) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) .REQUIRED_ATTR(axes, ListInt) .ATTR(keep_dims, Bool, false) + .ATTR(noop_with_empty_axes, Bool, false) .OP_END_FACTORY_REG(ReduceMeanD) /** @@ -983,7 +991,7 @@ REG_OP(EuclideanNormD) *@brief Performs instance normalization for inference . \n *@par Inputs: -* Five inputs, including: (NC1HWC0 supported) +* Five inputs, including: *@li x: A Tensor of type float16 or float32. *@li gamma: A [N, C1, 1, 1, C0] Tensor of type float32, for the scaling gamma. *@li beta: A [N, C1, 1, 1, C0] Tensor of type float32, for the scaling beta. @@ -1184,22 +1192,22 @@ REG_OP(GNTrainingReduce) *@par Inputs: * Seven inputs, including: (NCHW NHWC supported) *@li x: A Tensor of type float16 or float32. -*@li sum: A 5D Tensor of type float32, +*@li sum: A tensor of type float32, shape is [N, G, 1, 1, 1] for NCHW, [N, 1, 1, G, 1] for NHWC for the output of operator GNTrainingReduce. -*@li square_sum: A 5D Tensor of type float32, +*@li square_sum: A tensor of type float32, shape is [N, G, 1, 1, 1] for NCHW, [N, 1, 1, G, 1] for NHWC for the output of operator GNTrainingReduce. -*@li scale: A 5D Tensor of type float32, +*@li scale: A tensor of type float32, shape is [1, G, 1, 1, 1] for NCHW, [1, 1, 1, G, 1] for NHWC is for the scaling gamma. -*@li offset: A 5D Tensor of type float32, +*@li offset: A tensor of type float32, shape is [1, G, 1, 1, 1] for NCHW, [1, 1, 1, G, 1] for NHWC for the scaling beta. -*@li mean: A 5D Tensor of type float32, +*@li mean: A tensor of type float32, shape is [N, G, 1, 1, 1] for NCHW, [N, 1, 1, G, 1] for NHWC for the updated mean. -*@li variance: A 5D Tensor of type float32, +*@li variance: A tensor of type float32, shape is [N, G, 1, 1, 1] for NCHW, [N, 1, 1, G, 1] for NHWC for the updated variance. @@ -1209,7 +1217,7 @@ for the updated variance. *@li num_groups: Int, specifying the num of groups. required, same to GNTrainingReduce *@par Outputs: -* Three outputs, including: (NC1HWC0 supported) +* Three outputs, including: *@li y: A Tensor of type float16 or float32, for normalized "x". *@li batch_mean: A Tensor of type float32, for the updated mean. *@li batch_variance: A Tensor of type float32, for the updated variance . \n @@ -1338,7 +1346,7 @@ REG_OP(ReduceStdWithMean) *@brief Performs reduced batch normalization . \n *@par Inputs: -*x: A 5D Tensor of type float16 or float32, with format NC1HWC0 . \n +*x: A tensor of type float16 or float32 . \n *@par Outputs: *@li mean: A Tensor of type float32 for SUM reduced "x". diff --git a/third_party/fwkacllib/inc/ops/rnn.h b/third_party/fwkacllib/inc/ops/rnn.h index 43951402..51784547 100644 --- a/third_party/fwkacllib/inc/ops/rnn.h +++ b/third_party/fwkacllib/inc/ops/rnn.h @@ -28,10 +28,10 @@ namespace ge { *@brief: Basic LSTM Cell forward calculation. *@par Inputs: *five inputs: -*@li x:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_NZ. -*@li h:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_NZ. -*@li c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li w:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_Z. +*@li x:A 4D Tensor. Must be one of the following types: float16. +*@li h:A 4D Tensor. Must be one of the following types: float16. +*@li c:A 4D Tensor. Must be one of the following types: float16, float32. +*@li w:A 4D Tensor. Must be one of the following types: float16. *@li b:A 1D Tensor. Must be one of the following types: float16. The format must be ND . \n *@li mask:A 1D Tensor. Must be one of the following types: uint8. @@ -75,12 +75,12 @@ REG_OP(BasicLSTMCell) *@brief: Dynamic LSTM forward calculation . \n *@par Inputs: -*@li x:A 4D Tensor. Must be the type float32. The format must be FRACTAL_NZ. -*@li w:A 4D Tensor. Must be the type float32. The format must be FRACTAL_Z. +*@li x:A 4D Tensor. Must be the type float32. +*@li w:A 4D Tensor. Must be the type float32. *@li b:A 1D Tensor. Must be the type float32. The format must be ND . \n *@par Outputs: -*output_h:A Tensor of output. Must be the type float32. The format must be FRACTAL_Z. +*output_h:A Tensor of output. Must be the type float32. *@par Restrictions: *Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. @@ -96,27 +96,27 @@ REG_OP(DynamicLSTM) *@brief: DynamicRNNGrad calculation. *@par Inputs: *ten inputs: \n -*@li x:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li w:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li b:A 1D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li y:A 1D Tensor. Must be one of the following types: int32. The format must be FRACTAL_NZ. -*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li init_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dc:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li i:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li j:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li f:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li o:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li x:A 4D Tensor. Must be one of the following types: float16, float32. +*@li w:A 4D Tensor. Must be one of the following types: float16, float32. +*@li b:A 1D Tensor. Must be one of the following types: float16, float32. +*@li y:A 1D Tensor. Must be one of the following types: int32. +*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. +*@li init_c:A 4D Tensor. Must be one of the following types: float16, float32. +*@li h:A 4D Tensor. Must be one of the following types: float16, float32. +*@li c:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dc:A 4D Tensor. Must be one of the following types: float16, float32. +*@li i:A 4D Tensor. Must be one of the following types: float16, float32. +*@li j:A 4D Tensor. Must be one of the following types: float16, float32. +*@li f:A 4D Tensor. Must be one of the following types: float16, float32. +*@li o:A 4D Tensor. Must be one of the following types: float16, float32. +*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. *@li seq_length:A 1D Tensor. Must be one of the following types: int32. *@li mask:A 1D Tensor. Must be one of the following types: int8. -*@li wci:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li wcf:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li wco:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li wci:A 4D Tensor. Must be one of the following types: float16, float32. +*@li wcf:A 4D Tensor. Must be one of the following types: float16, float32. +*@li wco:A 4D Tensor. Must be one of the following types: float16, float32. *@par Attributes: *@li cell_type:An string identifying the cell type in the op. Default to "LSTM". Only LSTM is currently supported. @@ -131,14 +131,14 @@ REG_OP(DynamicLSTM) *@par Outputs: *eight outputs: \n -*@li dw:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li db:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dx:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dc_prev:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dwci:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dwcf:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dwco:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dw:A 4D Tensor. Must be one of the following types: float16, float32. +*@li db:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dx:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dc_prev:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dwci:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dwcf:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dwco:A 4D Tensor. Must be one of the following types: float16, float32. */ REG_OP(DynamicRNNGrad) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -185,15 +185,15 @@ REG_OP(DynamicRNNGrad) *@brief: DynamicRNN calculation. *@par Inputs: *ten inputs: -*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li w:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. +*@li w:A required 4D Tensor. Must be one of the following types: float16, float32. *@li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. -*@li seq_length:A optional Tensor. Only Support float16 in FRACTAL_NZ and int32 in ND. -*@li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. -*@li wcf:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. -*@li wco:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li seq_length:A optional Tensor. Only Support int32 in ND. +*@li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. +*@li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. +*@li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. +*@li wcf:A 4D optional Tensor. Must be one of the following types: float16, float32. +*@li wco:A 4D optional Tensor. Must be one of the following types: float16, float32. *@li mask:A 1D optional Tensor. Must be one of the following types: uint8. The format must be ND . \n *@par Attributes: @@ -212,14 +212,14 @@ REG_OP(DynamicRNNGrad) *@par Outputs: *eight outputs: -*@li y:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li output_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li output_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li i:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li j:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li f:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li o:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li y:A 4D Tensor. Must be one of the following types: float16, float32. +*@li output_h:A 4D Tensor. Must be one of the following types: float16, float32. +*@li output_c:A 4D Tensor. Must be one of the following types: float16, float32. +*@li i:A 4D Tensor. Must be one of the following types: float16, float32. +*@li j:A 4D Tensor. Must be one of the following types: float16, float32. +*@li f:A 4D Tensor. Must be one of the following types: float16, float32. +*@li o:A 4D Tensor. Must be one of the following types: float16, float32. +*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. *@par Third-party framework compatibility: * Compatible with the TF operator LSTM. */ @@ -260,18 +260,16 @@ REG_OP(DynamicRNN) *@brief: DynamicRNNV2 calculation. *@par Inputs: *ten inputs: -*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. *@li weight_input:A required 4D Tensor. Must be one of the following types: float16, float32. -*The format must be FRACTAL_Z. *@li weight_hidden:A required 4D Tensor. Must be one of the following types: float16, float32. -*The format must be FRACTAL_Z. *@li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. -*@li seq_length:A optional 1D Tensor. Must be one of the following types: int32. The format must be ND. -*@li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. -*@li wcf:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. -*@li wco:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li seq_length:A optional 1D Tensor. Must be one of the following types: float16, int32. +*@li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. +*@li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. +*@li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. +*@li wcf:A 4D optional Tensor. Must be one of the following types: float16, float32. +*@li wco:A 4D optional Tensor. Must be one of the following types: float16, float32. *@li mask:A 1D optional Tensor. Must be one of the following types: uint8. The format must be ND . \n *@par Attributes: @@ -298,16 +296,16 @@ REG_OP(DynamicRNN) *@par Outputs: *eight outputs: -*@li y:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li output_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li y:A 4D Tensor. Must be one of the following types: float16, float32. +*@li output_h:A 4D Tensor. Must be one of the following types: float16, float32. *Return the last output_h. -*@li output_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li output_c:A 4D Tensor. Must be one of the following types: float16, float32. *Return the last output_c. -*@li i:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li j:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li f:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li o:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li i:A 4D Tensor. Must be one of the following types: float16, float32. +*@li j:A 4D Tensor. Must be one of the following types: float16, float32. +*@li f:A 4D Tensor. Must be one of the following types: float16, float32. +*@li o:A 4D Tensor. Must be one of the following types: float16, float32. +*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. *@par Third-party framework compatibility: * Compatible with the TF operator LSTM or TF keras operator LSTM. */ @@ -317,7 +315,7 @@ REG_OP(DynamicRNNV2) .INPUT(weight_input, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(weight_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) .OPTIONAL_INPUT(b, TensorType({DT_FLOAT16, DT_FLOAT})) - .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32})) + .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32, DT_FLOAT16})) .OPTIONAL_INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) .OPTIONAL_INPUT(init_c, TensorType({DT_FLOAT16, DT_FLOAT})) .OPTIONAL_INPUT(wci, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -349,22 +347,133 @@ REG_OP(DynamicRNNV2) .ATTR(is_training, Bool, true) .OP_END_FACTORY_REG(DynamicRNNV2) +/** +* @brief: DynamicRNNV2Grad calculation. +* @par Inputs: +* twenty-one inputs: +* @li x:A required 4D Tensor. Must be one of the following types: float16, float32. +* @li w_x:A required 4D Tensor. Must be one of the following types: float16, float32. +* @li w_h:A required 4D Tensor. Must be one of the following types: float16, float32. +* @li y:A 4D Tensor. Must be one of the following types: float16, float32. +* @li init_h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li init_c:A 4D Tensor. Must be one of the following types: float16, float32. +* @li h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li c:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dy:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dh:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dc:A 4D Tensor. Must be one of the following types: float16, float32. +* @li i:A 4D Tensor. Must be one of the following types: float16, float32. +* @li j:A 4D Tensor. Must be one of the following types: float16, float32. +* @li f:A 4D Tensor. Must be one of the following types: float16, float32. +* @li o:A 4D Tensor. Must be one of the following types: float16, float32. +* @li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. +* @li seq_length:A 1D Tensor. Must be one of the following types: int32. +* @li wci:A 4D Tensor. Must be one of the following types: float16, float32. +* @li wcf:A 4D Tensor. Must be one of the following types: float16, float32. +* @li wco:A 4D Tensor. Must be one of the following types: float16, float32. +* @li mask:A 1D Tensor. Must be one of the following types: int8. \n + +* @par Attributes: +* @li cell_type:An string identifying the cell type in the op. Default to "LSTM". Only LSTM is currently supported. +* @li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". +* Only UNIDIRECTIONAL is currently supported. +* @li cell_depth:An integer identifying the cell depth in the op. Default to 1. Only 1 is currently supported. +* @li use_peephole:An bool identifying if use peephole in the op. Default to false. +* Only false is currently supported. +* @li keep_prob:An float identifying the keep prob in the op. Default to 1. Only 1 is currently supported. +* @li cell_clip:An float identifying the cell clip in the op. Default to -1. Only -1 is currently supported. +* @li num_proj:An integer identifying the num projection in the op. Default to 0. Only 0 is currently supported. +* @li time_major:An bool identifying the time major in the op. Default to true. Only true is currently supported. +* @li activation:An string identifying the type of activation function in the op. Default to "tanh". +* Only "tanh" is currently supported. +* @li recurrent_activation:An string identifying the type of activation function in the op. Default to "sigmoid". +* Only "sigmoid" is currently supported. +* @li gate_order:An string identifying the type of gate order in the op. Support "ijfo" and "ifco". Default to "ijfo". +* Set "ijfo" for TF operator LSTM, Set "ifco" for TF Keras/Pytorch LSTM . +* @li stateful: An bool identifying the type of stateful in the op. Default to fasle.Only false is currently supported. +* @li merge_mode: An string identifying the type of merge_modein the op. Default to "concat". +* Only "concat" is currently supported. \n + +* @par Outputs: +* nine outputs: +* @li dw_x:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dw_h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li db:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dx:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dc_prev:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dwci:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dwcf:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dwco:A 4D Tensor. Must be one of the following types: float16, float32. + +* @par Third-party framework compatibility: +* Compatible with the TF operator LSTM or TF keras operator LSTM. + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(DynamicRNNV2Grad) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(w_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(w_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(init_c, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(h, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(c, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(dy, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(dh, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(dc, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(i, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(j, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(f, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(o, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(tanhct, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32})) + .OPTIONAL_INPUT(wci, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wcf, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(wco, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(mask, TensorType({DT_UINT8})) + .OUTPUT(dw_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dw_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(db, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dx, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dh_prev, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dc_prev, TensorType({DT_FLOAT16, DT_FLOAT})) + .DYNAMIC_OUTPUT(dwci, TensorType({DT_FLOAT16, DT_FLOAT})) + .DYNAMIC_OUTPUT(dwcf, TensorType({DT_FLOAT16, DT_FLOAT})) + .DYNAMIC_OUTPUT(dwco, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(cell_type, String, "LSTM") + .ATTR(direction, String, "UNIDIRECTIONAL") + .ATTR(cell_depth, Int, 1) + .ATTR(use_peephole, Bool, false) + .ATTR(keep_prob, Float, 1.0) + .ATTR(cell_clip, Float, -1.0) + .ATTR(num_proj, Int, 0) + .ATTR(time_major, Bool, true) + .ATTR(activation, String, "tanh") + .ATTR(recurrent_activation, String, "sigmoid") + .ATTR(gate_order, String, "ijfo") + .ATTR(stateful, Bool, false) + .ATTR(merge_mode, String, "concat") + .OP_END_FACTORY_REG(DynamicRNNV2Grad) + /** *@brief: DynamicRNNV3 calculation. *@par Inputs: *ten inputs: -*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li w:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. +*@li w:A required 4D Tensor. Must be one of the following types: float16, float32. *@li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. *@li seq_length:A optional 1D Tensor. Must be one of the following types: int32. The format must be ND. -*@li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li wcf:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li wco:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. +*@li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. +*@li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. +*@li wcf:A 4D optional Tensor. Must be one of the following types: float16, float32. +*@li wco:A 4D optional Tensor. Must be one of the following types: float16, float32. *@li mask:A 1D optional Tensor. Must be one of the following types: uint8. The format must be ND . \n -*@li real_mask:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li project:A 4D optional Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li real_mask:A 4D optional Tensor. Must be one of the following types: float16, float32. +*@li project:A 4D optional Tensor. Must be one of the following types: float16, float32. *@par Attributes: *@li cell_type:An string identifying the cell type in the op. Default to "LSTM". Only LSTM is currently supported. @@ -381,14 +490,14 @@ REG_OP(DynamicRNNV2) *@par Outputs: *eight outputs: -*@li y:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li output_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li output_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li i:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li j:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li f:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li o:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li y:A 4D Tensor. Must be one of the following types: float16, float32. +*@li output_h:A 4D Tensor. Must be one of the following types: float16, float32. +*@li output_c:A 4D Tensor. Must be one of the following types: float16, float32. +*@li i:A 4D Tensor. Must be one of the following types: float16, float32. +*@li j:A 4D Tensor. Must be one of the following types: float16, float32. +*@li f:A 4D Tensor. Must be one of the following types: float16, float32. +*@li o:A 4D Tensor. Must be one of the following types: float16, float32. +*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. *@par Third-party framework compatibility: * Compatible with the TF operator LSTM. */ @@ -430,16 +539,16 @@ REG_OP(DynamicRNNV3) *@brief: DynamicLSTMV2 calculation. *@par Inputs: *ten inputs: -*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li w:A required 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. +*@li w:A required 4D Tensor. Must be one of the following types: float16, float32. *@li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. *@li cont:A required 2D Tensor. Must be one of the following types: float16, float32. The format must be ND. *@li w_xc_x_static:A optional 2D Tensor. Must be one of the following types: float16, float32. The format must be ND. -*@li h0:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li c0:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li wci:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. -*@li wcf:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. -*@li wco:A optional 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li h0:A optional 4D Tensor. Must be one of the following types: float16, float32. +*@li c0:A optional 4D Tensor. Must be one of the following types: float16, float32. +*@li wci:A optional 4D Tensor. Must be one of the following types: float16, float32. +*@li wcf:A optional 4D Tensor. Must be one of the following types: float16, float32. +*@li wco:A optional 4D Tensor. Must be one of the following types: float16, float32. *@li mask:A optional 1D Tensor. Must be one of the following types: uint8. The format must be ND . *@par Attributes: @@ -450,11 +559,11 @@ REG_OP(DynamicRNNV3) *@par Outputs: *eight outputs: -*@li y:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li output_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li output_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li last_output_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li last_output_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li y:A 4D Tensor. Must be one of the following types: float16, float32. +*@li output_h:A 4D Tensor. Must be one of the following types: float16, float32. +*@li output_c:A 4D Tensor. Must be one of the following types: float16, float32. +*@li last_output_h:A 4D Tensor. Must be one of the following types: float16, float32. +*@li last_output_c:A 4D Tensor. Must be one of the following types: float16, float32. *@par Third-party framework compatibility: * Compatible with the Caffe operator LSTM. *@par Restrictions: @@ -487,25 +596,25 @@ REG_OP(DynamicLSTMV2) *@brief: LSTMInputGrad calculation. *@par Inputs: *ten inputs: \n -*@li w:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li init_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dc:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li i:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li j:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li f:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li o:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li w:A 4D Tensor. Must be one of the following types: float16, float32. +*@li init_c:A 4D Tensor. Must be one of the following types: float16, float32. +*@li c:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dc:A 4D Tensor. Must be one of the following types: float16, float32. +*@li i:A 4D Tensor. Must be one of the following types: float16, float32. +*@li j:A 4D Tensor. Must be one of the following types: float16, float32. +*@li f:A 4D Tensor. Must be one of the following types: float16, float32. +*@li o:A 4D Tensor. Must be one of the following types: float16, float32. +*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. *@par Outputs: *four outputs: \n -*@li dx:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dc_prev:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dgate:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_NZ. +*@li dx:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dc_prev:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dgate:A 4D Tensor. Must be one of the following types: float16. */ REG_OP(LSTMInputGrad) .INPUT(w, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -531,18 +640,18 @@ REG_OP(LSTMInputGrad) *@brief: Dynamic LSTM Cell grad calculation.Calculate the gradient of gates and cell state. *@par Inputs: *twelve inputs: -*@li init_c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dc:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li i:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li j:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li f:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li o:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li mask:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li t_state:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ . \n +*@li init_c:A 4D Tensor. Must be one of the following types: float16, float32. +*@li c:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dc:A 4D Tensor. Must be one of the following types: float16, float32. +*@li i:A 4D Tensor. Must be one of the following types: float16, float32. +*@li j:A 4D Tensor. Must be one of the following types: float16, float32. +*@li f:A 4D Tensor. Must be one of the following types: float16, float32. +*@li o:A 4D Tensor. Must be one of the following types: float16, float32. +*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. +*@li mask:A 4D Tensor. Must be one of the following types: float16, float32. +*@li t_state:A 4D Tensor. Must be one of the following types: float16, float32. . \n *@par Attributes: *@li forget_bias:An integer identifying the forget bias in the op. Default to 1. @@ -584,8 +693,8 @@ REG_OP(DynamicLSTMGradCell) *@brief: Basic LSTM Cell backward calculation.Calculate the gradient of input and hidden state. *@par Inputs: *three inputs: -*@li dgate:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_NZ. -*@li w:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_Z. +*@li dgate:A 4D Tensor. Must be one of the following types: float16. +*@li w:A 4D Tensor. Must be one of the following types: float16. *@li dropout_mask:A 1D Tensor. Must be one of the following types: uint8. The format must be ND . \n *@par Attributes: @@ -612,9 +721,9 @@ REG_OP(BasicLSTMCellInputGrad) *@brief: Basic LSTM Cell backward calculation.Calculate the gradient of weight and bias. *@par Inputs: *three inputs: -*@li x:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_NZ. -*@li h:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_NZ. -*@li dgate:A 4D Tensor. Must be one of the following types: uint8. The format must be FRACTAL_NZ . \n +*@li x:A 4D Tensor. Must be one of the following types: float16. +*@li h:A 4D Tensor. Must be one of the following types: float16. +*@li dgate:A 4D Tensor. Must be one of the following types: uint8. \n *@par Outputs: *two outputs: @@ -636,14 +745,14 @@ REG_OP(BasicLSTMCellWeightGrad) *@brief: Basic LSTM Cell backward calculation.Calculate the gradient of gates and cell state. *@par Inputs: *eight inputs: -*@li c:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dht:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dct:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li it:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li jt:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li ft:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li ot:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ . \n +*@li c:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dht:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dct:A 4D Tensor. Must be one of the following types: float16, float32. +*@li it:A 4D Tensor. Must be one of the following types: float16, float32. +*@li jt:A 4D Tensor. Must be one of the following types: float16, float32. +*@li ft:A 4D Tensor. Must be one of the following types: float16, float32. +*@li ot:A 4D Tensor. Must be one of the following types: float16, float32. +*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. \n *@par Attributes: *@li forget_bias:An integer identifying the forget bias in the op. Default to 1. @@ -676,14 +785,14 @@ REG_OP(BasicLSTMCellCStateGrad) *@brief: RNN operator. *@par Inputs: *eight inputs: -*@li x:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_NZ. +*@li x:A 4D Tensor. Must be one of the following types: float16. *@li cont:A 1D Tensor. Must be one of the following types: float16. The format must be ND. -*@li x_static:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_NZ. -*@li h_0:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li w_xh:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_Z. -*@li w_sh:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_Z. -*@li w_hh:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_Z. -*@li w_ho:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_Z. +*@li x_static:A 4D Tensor. Must be one of the following types: float16. +*@li h_0:A 4D Tensor. Must be one of the following types: float16, float32. +*@li w_xh:A 4D Tensor. Must be one of the following types: float16. +*@li w_sh:A 4D Tensor. Must be one of the following types: float16. +*@li w_hh:A 4D Tensor. Must be one of the following types: float16. +*@li w_ho:A 4D Tensor. Must be one of the following types: float16. *@li bias_h:A 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. *@li bias_o:A 1D Tensor. Must be one of the following types: float16, float32. The format must be ND . \n @@ -693,8 +802,8 @@ REG_OP(BasicLSTMCellCStateGrad) *@par Outputs: *two outputs: -*@li o:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li h_t:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li o:A 4D Tensor. Must be one of the following types: float16, float32. +*@li h_t:A 4D Tensor. Must be one of the following types: float16, float32. *@par Restrictions: *Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ @@ -719,13 +828,13 @@ REG_OP(RNN) *@brief: BasicRNNCell operator. *@par Inputs: *eight inputs: -*@li x:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_NZ. +*@li x:A 4D Tensor. Must be one of the following types: float16. *@li cont:A 1D Tensor. Must be one of the following types: float16. The format must be ND. -*@li w_xh_x_static:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_NZ. -*@li h_0:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li w_xh:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_Z. -*@li w_hh:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_Z. -*@li w_ho:A 4D Tensor. Must be one of the following types: float16. The format must be FRACTAL_Z. +*@li w_xh_x_static:A 4D Tensor. Must be one of the following types: float16. +*@li h_0:A 4D Tensor. Must be one of the following types: float16, float32. +*@li w_xh:A 4D Tensor. Must be one of the following types: float16. +*@li w_hh:A 4D Tensor. Must be one of the following types: float16. +*@li w_ho:A 4D Tensor. Must be one of the following types: float16. *@li bias_h:A 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. *@li bias_o:A 1D Tensor. Must be one of the following types: float16, float32. The format must be ND . \n @@ -735,8 +844,8 @@ REG_OP(RNN) *@par Outputs: *two outputs: -*@li o_t:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li h_t:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li o_t:A 4D Tensor. Must be one of the following types: float16, float32. +*@li h_t:A 4D Tensor. Must be one of the following types: float16, float32. *@par Restrictions: *Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. @@ -761,13 +870,13 @@ REG_OP(BasicRNNCell) *@brief DynamicGRU calculation. *@par Inputs: *seven inputs: -*@li x:Must be one of the following types: float16. The format must be FRACTAL_NZ. -*@li w:Must be one of the following types: float16. The format must be FRACTAL_Z. +*@li x:Must be one of the following types: float16. +*@li w:Must be one of the following types: float16. *@li b:Must be one of the following types: float16, float32. The format must be ND. -*@li cw:Must be one of the following types: float16. The format must be FRACTAL_Z. +*@li cw:Must be one of the following types: float16. *@li cb:Must be one of the following types: float16, float32. The format must be ND. *@li seq_length:Must be one of the following types: int32. The format must be ND. -*@li init_h:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li init_h:Must be one of the following types: float16, float32. *@par Attributes: *@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. @@ -781,11 +890,11 @@ REG_OP(BasicRNNCell) *@par Outputs: *five outputs: -*@li y:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li output_h:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li r:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li i:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li n:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li y:Must be one of the following types: float16, float32. +*@li output_h:Must be one of the following types: float16, float32. +*@li r:Must be one of the following types: float16, float32. +*@li i:Must be one of the following types: float16, float32. +*@li n:Must be one of the following types: float16, float32. *@par Restrictions: *Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. @@ -817,16 +926,16 @@ REG_OP(DynamicGRU) *@brief DynamicGRUV2 calculation. *@par Inputs: *seven inputs: -*@li x:Must be one of the following types: float16. The format must be FRACTAL_NZ. -*@li weight_input:Must be one of the following types: float16. The format must be FRACTAL_Z. -*@li weight_hidden:Must be one of the following types: float16. The format must be FRACTAL_Z. +*@li x:Must be one of the following types: float16. +*@li weight_input:Must be one of the following types: float16. +*@li weight_hidden:Must be one of the following types: float16. *@li bias_input:Must be one of the following types: float16, float32. The format must be ND. *@li bias_hidden:Must be one of the following types: float16, float32. The format must be ND. -*@li seq_length:Must be one of the following types: float16 in FRACTAL_NZ and int32 in ND. -*@li init_h:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li seq_length:Must be one of the following types: int32 in ND. +*@li init_h:Must be one of the following types: float16, float32. *@par Attributes: -*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. +*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Support "UNIDIRECTIONAL" and "REDIRECTIONAL". *@li cell_depth:An integer identifying the cell depth in the op. Default to 1. *@li keep_prob:An float identifying the keep prob in the op. Default to 1. *@li cell_clip:An float identifying the cell clip in the op. Default to -1. @@ -839,12 +948,12 @@ REG_OP(DynamicGRU) *@par Outputs: *six outputs: -*@li y:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li output_h:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li update:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li reset:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li new:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li hidden_new:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li y:Must be one of the following types: float16, float32. +*@li output_h:Must be one of the following types: float16, float32. +*@li update:Must be one of the following types: float16, float32. +*@li reset:Must be one of the following types: float16, float32. +*@li new:Must be one of the following types: float16, float32. +*@li hidden_new:Must be one of the following types: float16, float32. */ REG_OP(DynamicGRUV2) .INPUT(x, TensorType({DT_FLOAT16})) @@ -877,15 +986,14 @@ REG_OP(DynamicGRUV2) *@brief DynamicGRUV2Hidden calculation. *@par Inputs: *five inputs: -*@li x_weight_input:Must be one of the following types: float32. The format must be FRACTAL_NZ. -*@li weight_hidden:Must be one of the following types: float16. The format must be FRACTAL_Z. +*@li x_weight_input:Must be one of the following types: float32. +*@li weight_hidden:Must be one of the following types: float16. *@li bias_hidden:Must be one of the following types: float16, float32. The format must be ND. -*@li seq_length:Must be one of the following types: float16 in FRACTAL_NZ and int32 in ND. -*@li init_h:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li seq_length:Must be one of the following types: int32 in ND. +*@li init_h:Must be one of the following types: float16, float32. *@par Attributes: -*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". -Only UNIDIRECTIONAL is currently supported. +*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Support "UNIDIRECTIONAL" and "REDIRECTIONAL". *@li cell_depth:An integer identifying the cell depth in the op. Default to 1. *@li keep_prob:An float identifying the keep prob in the op. Default to 1. *@li cell_clip:An float identifying the cell clip in the op. Default to -1. @@ -899,12 +1007,12 @@ Only tanh is currently supported. *@par Outputs: *six outputs: -*@li y:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li output_h:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li update:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li reset:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li new:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li hidden_new:Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li y:Must be one of the following types: float16, float32. +*@li output_h:Must be one of the following types: float16, float32. +*@li update:Must be one of the following types: float16, float32. +*@li reset:Must be one of the following types: float16, float32. +*@li new:Must be one of the following types: float16, float32. +*@li hidden_new:Must be one of the following types: float16, float32. *@par Restrictions: *Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. @@ -933,25 +1041,214 @@ REG_OP(DynamicGRUV2Hidden) .ATTR(is_training, Bool, true) .OP_END_FACTORY_REG(DynamicGRUV2Hidden) +/** +*@brief DynamicAUGRU calculation. +*@par Inputs: +*eight inputs: +*@li x:Must be one of the following types: float16. +*@li weight_input:Must be one of the following types: float16. +*@li weight_hidden:Must be one of the following types: float16. +*@li weight_attr:Must be one of the following types: float16. +*@li bias_input:Must be one of the following types: float16, float32. The format must be ND. +*@li bias_hidden:Must be one of the following types: float16, float32. The format must be ND. +*@li seq_length:Must be one of the following types: int32 in ND. +*@li init_h:Must be one of the following types: float16, float32. + +*@par Attributes: +*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. +*@li cell_depth:An integer identifying the cell depth in the op. Default to 1. +*@li keep_prob:An float identifying the keep prob in the op. Default to 1. +*@li cell_clip:An float identifying the cell clip in the op. Default to -1. +*@li num_proj:An integer identifying the num projection in the op. Default to 0. +*@li time_major:An bool identifying the time major in the op. Default to true. +*@li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported. +*@li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. +*@li reset_after:An bool identifying whether to apply reset gate after matrix multiplication. Default to true. +*@li is_training:An bool identifying is training in the op. Default to true. + +*@par Outputs: +*seven outputs: +*@li y:Must be one of the following types: float16, float32. +*@li output_h:Must be one of the following types: float16, float32. +*@li update:Must be one of the following types: float16, float32. +*@li update_att:Must be one of the following types: float16, float32. +*@li reset:Must be one of the following types: float16, float32. +*@li new:Must be one of the following types: float16, float32. +*@li hidden_new:Must be one of the following types: float16, float32. +*/ +REG_OP(DynamicAUGRU) +.INPUT(x, TensorType({DT_FLOAT16})) +.INPUT(weight_input, TensorType({DT_FLOAT16})) +.INPUT(weight_hidden, TensorType({DT_FLOAT16})) +.INPUT(weight_att, TensorType({DT_FLOAT16})) +.OPTIONAL_INPUT(bias_input, TensorType({DT_FLOAT16, DT_FLOAT})) +.OPTIONAL_INPUT(bias_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) +.OPTIONAL_INPUT(seq_length, TensorType({DT_INT32, DT_FLOAT16})) +.OPTIONAL_INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) +.OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) +.OUTPUT(output_h, TensorType({DT_FLOAT16, DT_FLOAT})) +.OUTPUT(update, TensorType({DT_FLOAT16, DT_FLOAT})) +.OUTPUT(update_att, TensorType({DT_FLOAT16, DT_FLOAT})) +.OUTPUT(reset, TensorType({DT_FLOAT16, DT_FLOAT})) +.OUTPUT(new, TensorType({DT_FLOAT16, DT_FLOAT})) +.OUTPUT(hidden_new, TensorType({DT_FLOAT16, DT_FLOAT})) +.ATTR(direction, String, "UNIDIRECTIONAL") +.ATTR(cell_depth, Int, 1) +.ATTR(keep_prob, Float, 1.0) +.ATTR(cell_clip, Float, -1.0) +.ATTR(num_proj, Int, 0) +.ATTR(time_major, Bool, true) +.ATTR(activation, String, "tanh") +.ATTR(gate_order, String, "zrh") +.ATTR(reset_after, Bool, true) +.ATTR(is_training, Bool, true) +.OP_END_FACTORY_REG(DynamicAUGRU) + +/** +*@brief: DynamicAUGRUGrad calculation. +*@par Inputs: +*sixteen inputs: \n +*@li x:A 4D Tensor. Must be one of the following types: float16, float32. +*@li weight_input:A 4D Tensor. Must be one of the following types: float16, float32. +*@li weight_hidden:A 4D Tensor. Must be one of the following types: float16, float32. +*@li weight_att:A 4D Tensor. Must be one of the following types: float16, float32. +*@li y:A 4D Tensor. Must be one of the following types: float16, float32. +*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. +*@li h:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. +*@li update:A 4D Tensor. Must be one of the following types: float16, float32. +*@li update_att:A 4D Tensor. Must be one of the following types: float16, float32. +*@li reset:A 4D Tensor. Must be one of the following types: float16, float32. +*@li new:A 4D Tensor. Must be one of the following types: float16, float32. +*@li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. +*@li seq_length:A 4D Tensor. Must be one of the following types: float16, float32. +*@li mask:A 4D Tensor. Must be one of the following types: float16, float32. + +*@par Attributes: +*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. +*@li cell_depth:An integer identifying the cell depth in the op. Default to 1. +*@li keep_prob:An float identifying the keep prob in the op. Default to 1. +*@li cell_clip:An float identifying the cell clip in the op. Default to -1. +*@li num_proj:An integer identifying the num projection in the op. Default to 0. +*@li time_major:An bool identifying the time major in the op. Default to true. +*@li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. +*@li reset_after:An bool identifying whether to apply reset gate after matrix multiplication. Default to true. + +*@par Outputs: +*seven outputs: \n +*@li dw_input:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dw_hidden:A 4D Tensor. Must be one of the following types: float16, float32. +*@li db_input:A 4D Tensor. Must be one of the following types: float16, float32. +*@li db_hidden:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dx:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dw_att:A 4D Tensor. Must be one of the following types: float16, float32. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(DynamicAUGRUGrad) +.INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(weight_input, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(weight_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(weight_att, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(h, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(dy, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(dh, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(update, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(update_att, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(reset, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(new, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(hidden_new, TensorType({DT_FLOAT16, DT_FLOAT})) +.OPTIONAL_INPUT(seq_length, TensorType({DT_INT32})) +.OPTIONAL_INPUT(mask, TensorType({DT_UINT8})) +.OUTPUT(dw_input, TensorType({DT_FLOAT16, DT_FLOAT})) +.OUTPUT(dw_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) +.OUTPUT(db_input, TensorType({DT_FLOAT16, DT_FLOAT})) +.OUTPUT(db_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) +.OUTPUT(dx, TensorType({DT_FLOAT16, DT_FLOAT})) +.OUTPUT(dh_prev, TensorType({DT_FLOAT16, DT_FLOAT})) +.OUTPUT(dw_att, TensorType({DT_FLOAT16, DT_FLOAT})) +.ATTR(direction, String, "UNIDIRECTIONAL") +.ATTR(cell_depth, Int, 1) +.ATTR(keep_prob, Float, -1.0) +.ATTR(cell_clip, Float, -1.0) +.ATTR(num_proj, Int, 0) +.ATTR(time_major, Bool, true) +.ATTR(gate_order, String, "zrh") +.ATTR(reset_after, Bool, true) +.OP_END_FACTORY_REG(DynamicAUGRUGrad) + +/** +*@brief: AUGRUHiddenGrad calculation. +*@par Inputs: +*eleven inputs: \n +*@li weight_att:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dh_pre_t:A 4D Tensor. Must be one of the following types: float16, float32. +*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. +*@li h:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. +*@li update:A 4D Tensor. Must be one of the following types: float16, float32. +*@li update_att:A 4D Tensor. Must be one of the following types: float16, float32. +*@li reset:A 4D Tensor. Must be one of the following types: float16, float32. +*@li new:A 4D Tensor. Must be one of the following types: float16, float32. +*@li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. + +*@par Attributes: +*@li t_state:An Int identifying the current t state. Default to [0, 4]. +*@li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. + +*@par Outputs: +*four outputs: \n +*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dgate_h:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dnt_x:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dw_att_t:A 4D Tensor. Must be one of the following types: float16, float32. + +*@par Restrictions: +*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(AUGRUHiddenGradCell) +.INPUT(weight_att, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(dh_pre_t, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(h, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(dy, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(dh, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(update, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(update_att, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(reset, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(new, TensorType({DT_FLOAT16, DT_FLOAT})) +.INPUT(hidden_new, TensorType({DT_FLOAT16, DT_FLOAT})) +.OUTPUT(dh_prev, TensorType({DT_FLOAT16, DT_FLOAT})) +.OUTPUT(dgate_h, TensorType({DT_FLOAT16, DT_FLOAT})) +.OUTPUT(dnt_x, TensorType({DT_FLOAT16, DT_FLOAT})) +.OUTPUT(dw_att_t, TensorType({DT_FLOAT16, DT_FLOAT})) +.ATTR(t_state, Int, 0) +.ATTR(gate_order, String, "zrh") +.OP_END_FACTORY_REG(AUGRUHiddenGradCell) /** *@brief: DynamicGRUV2Grad calculation. *@par Inputs: *fourteen inputs: \n -*@li x:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li weight_input:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li weight_hidden:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li y:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li update:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li reset:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li new:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li seq_length:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li mask:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li x:A 4D Tensor. Must be one of the following types: float16, float32. +*@li weight_input:A 4D Tensor. Must be one of the following types: float16, float32. +*@li weight_hidden:A 4D Tensor. Must be one of the following types: float16, float32. +*@li y:A 4D Tensor. Must be one of the following types: float16, float32. +*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. +*@li h:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. +*@li update:A 4D Tensor. Must be one of the following types: float16, float32. +*@li reset:A 4D Tensor. Must be one of the following types: float16, float32. +*@li new:A 4D Tensor. Must be one of the following types: float16, float32. +*@li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. +*@li seq_length:A 4D Tensor. Must be one of the following types: float16, float32. +*@li mask:A 4D Tensor. Must be one of the following types: float16, float32. *@par Attributes: *@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. @@ -965,12 +1262,12 @@ REG_OP(DynamicGRUV2Hidden) *@par Outputs: *six outputs: \n -*@li dw_input:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dw_hidden:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li db_input:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li db_hidden:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dx:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dw_input:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dw_hidden:A 4D Tensor. Must be one of the following types: float16, float32. +*@li db_input:A 4D Tensor. Must be one of the following types: float16, float32. +*@li db_hidden:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dx:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. *@par Restrictions: *Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. @@ -1010,15 +1307,15 @@ REG_OP(DynamicGRUV2Grad) *@brief: GRUV2HiddenGrad calculation. *@par Inputs: *nine inputs: \n -*@li dh_pre_t:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li update:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li reset:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li new:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dh_pre_t:A 4D Tensor. Must be one of the following types: float16, float32. +*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. +*@li h:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. +*@li update:A 4D Tensor. Must be one of the following types: float16, float32. +*@li reset:A 4D Tensor. Must be one of the following types: float16, float32. +*@li new:A 4D Tensor. Must be one of the following types: float16, float32. +*@li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. *@par Attributes: *@li t_state:An Int identifying the current t state. Default to [0, 4]. @@ -1026,9 +1323,9 @@ REG_OP(DynamicGRUV2Grad) *@par Outputs: *three outputs: \n -*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dgate_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dnt_x:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dgate_h:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dnt_x:A 4D Tensor. Must be one of the following types: float16, float32. *@par Restrictions: *Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. @@ -1053,15 +1350,15 @@ REG_OP(GRUV2HiddenGradCell) *@brief: DynamicGRUCellGrad calculation. *@par Inputs: *ten inputs: \n -*@li dh_pre_t:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li update:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li reset:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li new:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ.+ -*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dh_pre_t:A 4D Tensor. Must be one of the following types: float16, float32. +*@li h:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. +*@li update:A 4D Tensor. Must be one of the following types: float16, float32. +*@li reset:A 4D Tensor. Must be one of the following types: float16, float32. +*@li new:A 4D Tensor. Must be one of the following types: float16, float32. +*@li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32.+ +*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. *@li t_state:A 1D Tensor. Must be one of the following types: int32. The format must be ND. *@par Attributes: @@ -1069,9 +1366,9 @@ REG_OP(GRUV2HiddenGradCell) *@par Outputs: *three outputs: \n -*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dgate_h:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li dnt_x:A 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dgate_h:A 4D Tensor. Must be one of the following types: float16, float32. +*@li dnt_x:A 4D Tensor. Must be one of the following types: float16, float32. *@par Restrictions: *Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. @@ -1130,13 +1427,13 @@ REG_OP(EmbeddingDenseGrad) *@brief CommonLSTM calculation. *@par Inputs: *eight inputs: \n -*@li x:Each time step is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li w:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. -*@li r:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_ZN_LSTM. +*@li x:Each time step is a 4D Tensor. Must be one of the following types: float16, float32. +*@li w:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. +*@li r:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. *@li b:An optional input. Each direction is a 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. *@li sequence_lens:An optional input. A 1D Tensor.Must be one of the following types: int32. The format must be ND. -*@li initial_h:An optional input. Each direction is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li initial_c:An optional input. Each direction is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li initial_h:An optional input. Each direction is a 4D Tensor. Must be one of the following types: float16, float32. +*@li initial_c:An optional input. Each direction is a 4D Tensor. Must be one of the following types: float16, float32. *@li p:An optional input. Each direction is a 1D Tensor.Must be one of the following types: float16, float32. The format must be ND. *@par Attributes: @@ -1150,9 +1447,9 @@ REG_OP(EmbeddingDenseGrad) *@par Outputs: *three outputs: \n -*@li y:First dimension is time step, second dimension is direction, others is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li y_h:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. -*@li y_c:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. The format must be FRACTAL_NZ. +*@li y:First dimension is time step, second dimension is direction, others is a 4D Tensor. Must be one of the following types: float16, float32. +*@li y_h:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. +*@li y_c:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. */ REG_OP(CommonLSTM) @@ -1202,12 +1499,12 @@ REG_OP(RnnGenMaskV2) * @par Inputs: * Eight inputs, including: -* @li x: The input sequences packed (and pontentially padded) into on 3D Tesnor(float16). The format must be FRACTAL_NZ -* @li w: The weight tensor for the gates is 3D Tensor(float16). The format must be FRACTAL_Z -* @li r: The recurrence weight tesnor is 3D Tensor(float16). The format must be FRACTAL_Z +* @li x: The input sequences packed (and pontentially padded) into on 3D Tesnor(float16). +* @li w: The weight tensor for the gates is 3D Tensor(float16). +* @li r: The recurrence weight tesnor is 3D Tensor(float16). * @li b: The bias tensor for the gates. The format must be ND * @li sequence_lens: Optional tensor specifying lengths of sequences(int32). The format must be ND -* @li init_h: Optional initial value of the hidden(float16,float32). The format must be FRACTAL_NZ +* @li init_h: Optional initial value of the hidden(float16,float32). * @par Attributes: * @li activation_alpha: Optional scaling values used by some activation functions. \n @@ -1219,8 +1516,8 @@ REG_OP(RnnGenMaskV2) * @li linear_before_reset: When computing the output of the hidden gate, apply the linear transformation before multiplying by the output of the reset gate. \n * @par Outputs: -* @li y: A Tensor that concats all the intermediate output values of the hidden(float16,float32). The format must be FRACTAL_NZ -* @li y_h: The last output value of the hidden(float16,float32). The format must be FRACTAL_NZ +* @li y: A Tensor that concats all the intermediate output values of the hidden(float16,float32). +* @li y_h: The last output value of the hidden(float16,float32). */ REG_OP(CommonGRU) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -1251,17 +1548,17 @@ REG_OP(CommonGRU) * @li per_sample_weights: to indicate all weights should be taken to be 1. * If specified, per_sample_weights must have exactly the same shape as input * and is treated as having the same offsets, if those are not None. -* Only supported for mode='sum'..\n +* Only supported for mode='sum'.\n * @par Attributes: -* @li mode: An string attr which use "sum"``, ``"mean"`` or ``"max"``. Specifies the way to reduce the bag.. \n +* @li mode: An string attr which use "sum"``, ``"mean"`` or ``"max"``. Specifies the way to reduce the bag. \n * @li scale_grad_by_freq: An optional bool. Defaults to "False". * If "True", "grad_weight" will be scale by word_frequency. * If "False", "grad_weight" will not be scale by word_frequency. \n * @li sparse: if True, gradient w.r.t.attr weight matrix will be a sparse tensor. \n * @li include_last_offset: if True, attr offsets has one additional element, where the last element -* is equivalent to the size of indices. This matches the CSR format.. \n +* is equivalent to the size of indices. This matches the CSR format. \n * @par Outputs: * y: A mutable output Tensor of new word grad has the same type as "grads". \n diff --git a/third_party/fwkacllib/inc/ops/selection_ops.h b/third_party/fwkacllib/inc/ops/selection_ops.h index 2cc8fd1d..d29f3d63 100644 --- a/third_party/fwkacllib/inc/ops/selection_ops.h +++ b/third_party/fwkacllib/inc/ops/selection_ops.h @@ -940,11 +940,13 @@ REG_OP(SliceDV2) * @par Attributes: * @li k: A required int that is at least 0, specifying the number of top elements * to look for along the last dimension (along each row for matrices). -* @li sorted: An optional bool. Defaults to true. -* If true, the resulting "k" elements will be sorted by the values in descending -* order. +* @li sorted: An optional bool. Defaults to "True". +* If "True", the returned "k" elements are themselves sorted. +* If "False", the returned "k" elements are not sorted. * @li dim: An optional int. Defaults to -1. For reserved use. -* @li largest: An optional bool. Defaults to true. For reserved use. \n +* @li largest: An optional bool, controls whether to return largest or smallest elements. Defaults to true. +* If "True", the "k" largest elements are returned in descending order. +* If "False", the "k" smallest elements are returned in ascending order. \n * @par Outputs: * @li values: A Tensor, specifying the sorted data. Has the same type as "input". @@ -989,11 +991,14 @@ REG_OP(TopKD) * int32 to float16. \n * @par Attributes: -* @li sorted: An optional bool. Defaults to true. -* If true, the resulting "k" elements will be sorted by the values in descending -* order. +* @li sorted: An optional bool. Defaults to "True". +* If "True", the returned "k" elements are themselves sorted. +* If "False", the returned "k" elements are not sorted. * @li dim: An optional int. Defaults to -1. For reserved use. -* @li largest: An optional bool. Defaults to true. For reserved use. \n +* @li largest: An optional bool, controls whether to return largest or smallest elements. Defaults to true. +* If "True", the "k" largest elements are returned in descending order. +* If "False", the "k" smallest elements are returned in ascending order. \n + * @par Outputs: * @li values: A Tensor, specifying the sorted data. Has the same type as @@ -1028,11 +1033,13 @@ REG_OP(TopKV2D) * for matrices) . \n * @par Attributes: -* @li sorted: An optional bool. Defaults to true. -* If true, the resulting "k" elements will be sorted by the values in descending -* order. +* @li sorted: An optional bool. Defaults to "True". +* If "True", the returned "k" elements are themselves sorted. +* If "False", the returned "k" elements are not sorted. * @li dim: An optional int. Defaults to -1. For reserved use. -* @li largest: An optional bool. Defaults to true. For reserved use. \n +* @li largest: An optional bool, controls whether to return largest or smallest elements. Defaults to true. +* If "True", the "k" largest elements are returned in descending order. +* If "False", the "k" smallest elements are returned in ascending order. \n * @par Outputs: * @li values: A Tensor, specifying the sorted data. Has the same type as @@ -1066,10 +1073,12 @@ REG_OP(TopKV2) * for matrices) . \n * @par Attributes: -* @li sorted: Defaults to true. -* If true, the resulting "k" elements will be sorted by the values in descending -* order. -* @li largest:If true the resulting `k` elements will be sorted by the values in descending order. +* @li sorted: An optional bool. Defaults to "True". +* If "True", the returned "k" elements are themselves sorted. +* If "False", the returned "k" elements are not sorted. +* @li largest: An optional bool, controls whether to return largest or smallest elements. Defaults to true. +* If "True", the "k" largest elements are returned in descending order. +* If "False", the "k" smallest elements are returned in ascending order. * @li dim:0-D. Number of top elements to look for along the last dimension (along each row for matrices). \n * @par Outputs: @@ -2534,32 +2543,75 @@ REG_OP(StridedSliceV3) .OP_END_FACTORY_REG(StridedSliceV3) /** -*@brief MovingSumWithSigmoid. +* @brief Sum the alpha according to the offset and ksize, + and quadrature it with the sigmoid value of energy. \n -*@par Inputs: -*Four inputs, including: +* @par Inputs: +* Three inputs, including: * @li alpha: A Tensor. Must be one of the following types: float32, float16. * @li energy: A Tensor. Must be one of the following types: float32, float16. -* @li beam_size: A Tensor of type int32. -* @li frame_size: A Tensor of type int32. \n +* @li offset: A Tensor of type int32. \n *@par Outputs: -* y: A Tensor. Has the same type as "alpha". \n +* y: A Tensor with same type as "alpha". \n * * @par Attributes: -* window_size: A int. +* ksize: A int. * * @par Restrictions: -* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(MovingSumWithSigmoid) - .INPUT(alpha, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(energy, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(beam_size, TensorType({DT_INT32})) - .INPUT(frame_size, TensorType({DT_INT32})) - .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) - .REQUIRED_ATTR(window_size, Int) + .INPUT(alpha, TensorType::BasicType()) + .INPUT(energy, TensorType::BasicType()) + .INPUT(offset, TensorType({DT_INT32})) + .OUTPUT(y, TensorType::BasicType()) + .REQUIRED_ATTR(ksize, Int) .OP_END_FACTORY_REG(MovingSumWithSigmoid) + +/** +* @brief Choose the value of X with value according to mask. + +* @par Inputs: +* two inputs, including: +* @li x: A Tensor of dtype is BasicType. +* @li mask: A Tensor of dtype is bool. \n + +* @par Outputs: +* y: A tensor with the same type as x. \n + +* @par Third-party framework compatibility +* Compatible with the Numpy operator select.\n +*/ +REG_OP(MaskedSelect) + .INPUT(x, TensorType::BasicType()) + .INPUT(mask, TensorType({DT_BOOL})) + .OUTPUT(y, TensorType::BasicType()) + .OP_END_FACTORY_REG(MaskedSelect) + +/** +* @brief Sum X1 and X2 according to the offset recorded in seq_len1 and seq_len2. \n + +* @par Inputs: +* Four inputs, including: +* @li x1: A Tensor. Support BasicType. +* @li x2: A Tensor. Support BasicType. +* @li seq_len1: A Tensor. Support int32. +* @li seq_len2: A Tensor. Support int32. \n + +* @par Outputs: +* y: A Tensor with same type as "x1". \n + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(DynSeqOuter) + .INPUT(x1, TensorType::BasicType()) + .INPUT(x2, TensorType::BasicType()) + .INPUT(seq_len1, TensorType({DT_INT32})) + .INPUT(seq_len2, TensorType({DT_INT32})) + .OUTPUT(y, TensorType::BasicType()) + .OP_END_FACTORY_REG(DynSeqOuter) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_SELECTION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/split_combination_ops.h b/third_party/fwkacllib/inc/ops/split_combination_ops.h index 7d181545..2915590d 100644 --- a/third_party/fwkacllib/inc/ops/split_combination_ops.h +++ b/third_party/fwkacllib/inc/ops/split_combination_ops.h @@ -188,7 +188,7 @@ REG_OP(ParallelConcat) *@par Inputs: * One input: -*x: Dynamic input.An NC1HWC0 or ND Tensor. +*x: Dynamic input.A ND Tensor. *Must be one of the following types: float16, float32, int32, int8, int16, int64, uint8, uint16, uint32, uint64 *@par Attributes: @@ -219,7 +219,7 @@ REG_OP(ConcatV2D) *@par Inputs: * Two inputs, including: -*@li Dynamic input "x" is An NC1HWC0 or ND Tensor. +*@li Dynamic input "x" is A ND Tensor. *Must be one of the following types: float16, float32, int32, int8, int16, int64, uint8, uint16, uint32, uint64 *@li concat_dim: An int32, or int64. Specifies the dimension along which to concatenate . \n @@ -247,7 +247,7 @@ REG_OP(ConcatV2) *@par Inputs: * One input: -*x:Dynamic input. An NC1HWC0 or ND Tensor. +*x:Dynamic input. A ND Tensor. *Must be one of the following types: float16, float32, int32, int8, int16, int64, uint8, uint16, uint32, uint64 *@par Attributes: @@ -278,7 +278,7 @@ REG_OP(ConcatD) *@par Inputs: * Two inputs, including: -*@li x: Dynamic input.An NC1HWC0 or ND Tensor. +*@li x: Dynamic input.A ND Tensor. *Must be one of the following types: float16, float32, double, int32, * uint8, int16, int8, complex64, int64, qint8, quint8, qint32, uint16, * complex128, uint32, uint64, qint16, quint16. diff --git a/third_party/fwkacllib/inc/ops/stateful_random_ops.h b/third_party/fwkacllib/inc/ops/stateful_random_ops.h index f4eb763c..e776c416 100644 --- a/third_party/fwkacllib/inc/ops/stateful_random_ops.h +++ b/third_party/fwkacllib/inc/ops/stateful_random_ops.h @@ -236,6 +236,30 @@ REG_OP(StatefulUniformInt) .OUTPUT(y, TensorType({DT_INT64})) .OP_END_FACTORY_REG(StatefulUniformInt) +/** +* @brief Advance the counter of a counter-based RNG. The state of the RNG after +* `rng_skip(n)` will be the same as that after `stateful_uniform([n])` +* (or any other distribution). The actual increment added to the +* counter is an unspecified implementation detail . \n + +* @par Inputs: +* @li value: Stores the state of the RNG. +* @li algorithm: The RNG algorithm. +* @li delta: The amount of advancement . \n + +* @par Outputs: +* value:A Returns Random values with specified shape . \n + +* @par Third-party framework compatibility +* Compatible with tensorflow RngReadAndSkipV2 operator. +*/ + +REG_OP(RngReadAndSkipV2) + .INPUT(value, TensorType({DT_INT64})) + .INPUT(algorithm, TensorType({DT_INT32})) + .INPUT(delta, TensorType({DT_UINT64})) + .OUTPUT(value, TensorType({DT_INT64})) + .OP_END_FACTORY_REG(RngReadAndSkipV2) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_STATEFUL_RANDOM_OPS_H_ \ No newline at end of file diff --git a/third_party/fwkacllib/inc/ops/target_crop_and_resize.h b/third_party/fwkacllib/inc/ops/target_crop_and_resize.h index 9bef1d7b..d9dea358 100644 --- a/third_party/fwkacllib/inc/ops/target_crop_and_resize.h +++ b/third_party/fwkacllib/inc/ops/target_crop_and_resize.h @@ -39,7 +39,7 @@ namespace ge { *input_format: A required string, specifying the input format. \n *@par Outputs: -*y: The output tensor of type uint8, format only support NC1HWC0_C04. +*y: The output tensor of type uint8. *@par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. * diff --git a/third_party/fwkacllib/inc/ops/transformation_ops.h b/third_party/fwkacllib/inc/ops/transformation_ops.h index 2bbab7a2..eef76cd5 100644 --- a/third_party/fwkacllib/inc/ops/transformation_ops.h +++ b/third_party/fwkacllib/inc/ops/transformation_ops.h @@ -138,9 +138,11 @@ REG_OP(Transpose) * For branches without padding also can be types: int16, int64, uint8, uint16, uint32, uint64 . \n *@par Attributes: -*@li src_format: A string source data format, can be "NHWC", "NCHW", "FRACTAL_Z" etc. -*@li dst_format: A string target data format, can be "NC1HWC0", "NCHW", "FRACTAL_Z" etc. -*@li group: A optional int32, default value is 1. \n +*@li src_format: A string source data format, can be "NHWC", "NCHW" etc. +*@li dst_format: A string target data format, can be "NCHW" etc. +*@li src_subformat: A optional int32 for source sub-format, default value is 0. +*@li dst_subformat: A optional int32 for target sub-format, default value is 0. +*@li groups: A optional int32, default value is 1. \n *@par Outputs: *dst: A Tensor. Has the same type as "src". @@ -150,6 +152,8 @@ REG_OP(TransData) .OUTPUT(dst, TensorType::BasicType()) .REQUIRED_ATTR(src_format, String) .REQUIRED_ATTR(dst_format, String) + .ATTR(src_subformat, Int, 0) + .ATTR(dst_subformat, Int, 0) .ATTR(groups, Int, 1) .OP_END_FACTORY_REG(TransData) @@ -236,13 +240,13 @@ REG_OP(Flatten) *@par Inputs: * Three inputs, including: -*@li x: A 5D Tensor of type float16 or int8 or uint8, with format NC1HWC0. +*@li x: A 5D Tensor of type float16 or int8 or uint8. *@li block_shape: A 1D list or tuple of int32 or int64. *@li crops: A 2D list or tuple of int32 or int64. Specifies the amount to *crop from start and end dimensions after permutation . \n *@par Outputs: -*y: A Tensor with format NC1HWC0. Has the same type as input "x" . \n +*y: A Tensor has the same type as input "x" . \n *@par Third-party framework compatibility * Compatible with the TensorFlow operator BatchToSpaceND. @@ -259,7 +263,7 @@ REG_OP(BatchToSpaceND) *@par Inputs: * One input: -*x: A 5D Tensor of type float16 or int8 or uint8, with format NC1HWC0 . \n +*x: A 5D Tensor of type float16 or int8 or uint8. \n *@par Attributes: *@li block_shape: A required 1D list or tuple of int32 or int64. @@ -267,7 +271,7 @@ REG_OP(BatchToSpaceND) * from the start and end dimensions after permutation . \n *@par Outputs: -*y: A Tensor with format NC1HWC0. Has the same type as input "x". +*y: A Tensor has the same type as input "x". *@par Third-party framework compatibility @@ -288,12 +292,12 @@ REG_OP(BatchToSpaceNDD) *@par Inputs: * Three inputs, including: -*@li x: A 5D Tensor of type float16 or float32, with format NC1HWC0. +*@li x: A 5D Tensor of type float16 or float32. *@li block_shape: A 1D list or tuple of int32 or int64. *@li paddings: A 2D list or tuple of int32 or int64. Specifies the padding for the start and end dimensions after permutation . \n *@par Outputs: -*y: A Tensor with format NC1HWC0. Has the same type as input "x" . \n +*y: A Tensor has the same type as input "x" . \n *@par Third-party framework compatibility * Compatible with the TensorFlow operator SpaceToBatchND. @@ -310,14 +314,14 @@ REG_OP(SpaceToBatchND) *@par Inputs: * One input: -*x: A 5D Tensor of type float16 or float32, with format NC1HWC0 . \n +*x: A 5D Tensor of type float16 or float32. \n *@par Attributes: *@li block_shape: A required 1D list or tuple of int32 or int64. *@li paddings: A required 2D list or tuple of int32 or int64. Specifies the padding for the start and end dimensions after permutation . \n *@par Outputs: -*y: A Tensor with format NC1HWC0. Has the same type as input "x" . \n +*y: A Tensor has the same type as input "x" . \n *@par Third-party framework compatibility * Compatible with the TensorFlow operator SpaceToBatchND. @@ -516,7 +520,7 @@ REG_OP(SpaceToBatchD) * tensors . \n * @par Inputs: -* x: A rank-R tensor (R > 0) of type BasicType, with format ND or NC1HWC0 . \n +* x: A rank-R tensor (R > 0) of type BasicType. \n * @par Attributes: * @li num: A required int, specifying the number of tensors to be unpacked to. @@ -529,8 +533,7 @@ REG_OP(SpaceToBatchD) * @attention Constraints: * @li If "num" is not specified, it is inferred from the shape of "x". -* @li For the ND format, "axis" is in the range [-R, R); For the NC1HWC0 format, -* "axis" must not be 2, 3, -2, or -3 . \n +* @li For the ND format, "axis" is in the range [-R, R). \n * @par Third-party framework compatibility * Compatible with the TensorFlow operator Unpack. diff --git a/third_party/fwkacllib/inc/runtime/base.h b/third_party/fwkacllib/inc/runtime/base.h index c9779326..85740add 100644 --- a/third_party/fwkacllib/inc/runtime/base.h +++ b/third_party/fwkacllib/inc/runtime/base.h @@ -140,6 +140,16 @@ typedef void *rtModel_t; #define RT_PROF_MAX_DEV_NUM 64 +#define PATH_LEN_MAX 1023 +#define PARAM_LEN_MAX 4095 +typedef struct rtCommandHandleParams { + uint32_t pathLen; + uint32_t storageLimit; // MB + uint32_t profDataLen; + char_t path[PATH_LEN_MAX + 1]; + char_t profData[PARAM_LEN_MAX + 1]; +} rtCommandHandleParams_t; + /** * @ingroup profiling_base * @brief profiling command info @@ -151,6 +161,7 @@ typedef struct rtProfCommandHandle { uint32_t devIdList[RT_PROF_MAX_DEV_NUM]; uint32_t modelId; uint32_t type; + rtCommandHandleParams_t commandHandleParams; } rtProfCommandHandle_t; /** @@ -251,6 +262,16 @@ RTS_API rtError_t rtProfSetProSwitch(void *data, uint32_t len); */ RTS_API rtError_t rtProfRegisterCtrlCallback(uint32_t moduleId, rtProfCtrlHandle callback); +/** + * @ingroup profiling_base + * @brief set profling switch, called by profiling + * @param [in] data rtProfilingCommandHandle + * @param [in] len length of data + * @return RT_ERROR_NONE for ok + * @return ACL_ERROR_RT_PARAM_INVALID for error input + */ +RTS_API rtError_t rtProfilingCommandHandle(uint32_t type, void *data, uint32_t len); + /** * @ingroup dvrt_base * @brief register callback for error code diff --git a/third_party/fwkacllib/inc/runtime/config.h b/third_party/fwkacllib/inc/runtime/config.h index 3881ac5c..0030fea4 100644 --- a/third_party/fwkacllib/inc/runtime/config.h +++ b/third_party/fwkacllib/inc/runtime/config.h @@ -36,7 +36,8 @@ typedef enum tagRtChipType { CHIP_CLOUD_V2 = 5, CHIP_NO_DEVICE = 6, CHIP_MINI_V3 = 7, - CHIP_END = 8, + CHIP_5612 = 8, /* 1911T */ + CHIP_END = 9, } rtChipType_t; typedef enum tagRtAicpuScheType { @@ -77,7 +78,8 @@ typedef enum tagRtPlatformType { PLATFORM_CLOUD_V2 = 6, PLATFORM_LHISI_SD3403 = 7, PLATFORM_MINI_V3 = 8, - PLATFORM_END = 9, + PLATFORM_MINI_5612 = 9, + PLATFORM_END = 10, } rtPlatformType_t; typedef enum tagRtCubeFracMKNFp16 { diff --git a/third_party/fwkacllib/inc/runtime/dvfsprofile.h b/third_party/fwkacllib/inc/runtime/dvfsprofile.h deleted file mode 100644 index 2813d73b..00000000 --- a/third_party/fwkacllib/inc/runtime/dvfsprofile.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) Huawei Technologies Co., Ltd. 2020-2021. All rights reserved. - * Description: dvfsprofile.h - * Create: 2020-01-01 - */ - -#ifndef CCE_RUNTIME_DVFSPROFILE_H -#define CCE_RUNTIME_DVFSPROFILE_H - -#include "base.h" - -#if defined(__cplusplus) -extern "C" { -#endif - -typedef enum dvfsProfileMode { - DVFS_PROFILE_PERFORMANCE_PRIORITY, - DVFS_PROFILE_BALANCE_PRIORITY, - DVFS_PROFILE_POWER_PRIORITY, - DVFS_PROFILE_PRIORITY_MAX -} DvfsProfileMode; - -/** - * @ingroup dvrt_dvfsprofile - * @brief Set the performance mode of the device - * @param [in] profMode dvfsProfileMode - * @return RT_ERROR_NONE for ok - * @return RT_ERROR_INVALID_VALUE for error input - */ -RTS_API rtError_t rtSetDvfsProfile(DvfsProfileMode profMode); - -/** - * @ingroup dvrt_dvfsprofile - * @brief Set the performance mode of the device - * @return RT_ERROR_NONE for ok - * @return RT_ERROR_INVALID_VALUE for invalid value - */ -RTS_API rtError_t rtUnsetDvfsProfile(); - -/** - * @ingroup dvrt_dvfsprofile - * @brief Get the current performance mode of the device - * @param [in|out] pmode dvfsProfileMode type pointer - * @return RT_ERROR_NONE for ok - * @return RT_ERROR_INVALID_VALUE for error input - */ -RTS_API rtError_t rtGetDvfsProfile(DvfsProfileMode *pmode); - -#if defined(__cplusplus) -} -#endif - -#endif // CCE_RUNTIME_DVFSPROFILE_H diff --git a/third_party/fwkacllib/inc/runtime/kernel.h b/third_party/fwkacllib/inc/runtime/kernel.h index 883068a2..83dc7a91 100644 --- a/third_party/fwkacllib/inc/runtime/kernel.h +++ b/third_party/fwkacllib/inc/runtime/kernel.h @@ -130,6 +130,32 @@ typedef struct tagRtArgsWithTiling { uint8_t reserved[6]; } rtArgsWithTiling_t; +/** + * @ingroup rt_kernel + * @brief host memory input struct + */ +typedef struct rtHostInputInfo { + uint16_t addrOffset; + uint16_t dataOffset; +} rtHostInputInfo_t; + +/** + * @ingroup rt_kernel + * @brief args struct + */ +typedef struct tagRtArgsEx { + void *args; // args host mem addr + rtHostInputInfo_t *hostInputInfoPtr; // nullptr means no host mem input + uint32_t argsSize; // input + output + tiling addr size + tiling data size + host mem + uint16_t tilingAddrOffset; // tiling addr offset + uint16_t tilingDataOffset; // tiling data offset + uint16_t hostInputInfoNum; // hostInputInfo num + uint8_t hasTiling; // if has tiling: 0 means no tiling + uint8_t isNoNeedH2DCopy; // is no need host to device copy: 0 means need H2D copy, + // others means doesn't need H2D copy. + uint8_t reserved[4]; +} rtArgsEx_t; + /** * @ingroup rt_KernelConfigDump * @brief device dump type @@ -208,6 +234,7 @@ typedef void (*rtCallback_t)(void *fnData); #define RT_KERNEL_DEVICE_FIRST (0x10U) #define RT_KERNEL_HOST_ONLY (0x20U) #define RT_KERNEL_HOST_FIRST (0x40U) +#define RT_KERNEL_BIUPERF_FLAG (0x80U) /** * @ingroup rt_kernel @@ -375,36 +402,33 @@ RTS_API rtError_t rtKernelLaunch(const void *stubFunc, uint32_t blockDim, void * /** * @ingroup rt_kernel * @brief launch kernel with handle to device - * @param [in] hdl program - * @param [in] kernelInfoExt kernel Info extension. device function description or tiling key, - * depending static shape or dynmaic shape. - * @param [in] blockDim block dimentions - * @param [in] args argments address for kernel function - * @param [in] argsSize argements size - * @param [in] smDesc shared memory description - * @param [in] stm associated stream - * @param [in] kernelInfo kernel info + * @param [in] hdl program + * @param [in] tilingKey tilingKey + * @param [in] blockDim block dimentions + * @param [in] argsInfo argments address for kernel function + * @param [in] smDesc shared memory description + * @param [in] stm associated stream + * @param [in] kernelInfo kernel info * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtKernelLaunchWithHandle(void *hdl, const void *kernelInfoExt, uint32_t blockDim, - void *args, uint32_t argsSize, rtSmDesc_t *smDesc, rtStream_t stream_, +RTS_API rtError_t rtKernelLaunchWithHandle(void *hdl, const uint64_t tilingKey, uint32_t blockDim, + rtArgsEx_t *argsInfo, rtSmDesc_t *smDesc, rtStream_t stm, const void *kernelInfo); /** - * @ingroup rt_kernel + * @ingroup rtKernelLaunchWithFlag * @brief launch kernel to device * @param [in] stubFunc stub function * @param [in] blockDim block dimentions - * @param [in] args argments address for kernel function - * @param [in] argsSize argements size - * @param [in] smDesc shared memory description - * @param [in] stm associated stream - * @param [in] flag dump flag + * @param [in] argsInfo argments address for kernel function + * @param [in] smDesc shared memory description + * @param [in] stm associated stream + * @param [in] flags dump flag * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ -RTS_API rtError_t rtKernelLaunchWithFlag(const void *stubFunc, uint32_t blockDim, void *args, uint32_t argsSize, +RTS_API rtError_t rtKernelLaunchWithFlag(const void *stubFunc, uint32_t blockDim, rtArgsEx_t *argsInfo, rtSmDesc_t *smDesc, rtStream_t stm, uint32_t flags); /** @@ -465,38 +489,37 @@ RTS_API rtError_t rtAicpuKernelLaunch(const rtKernelLaunchNames_t *launchNames, uint32_t blockDim, const void *args, uint32_t argsSize, rtSmDesc_t *smDesc, rtStream_t stm); /** - * @ingroup rt_kernel(abandoned) + * @ingroup rtCpuKernelLaunchWithFlag(abandoned) * @brief launch cpu kernel to device with dump identifier * @param [in] soName so name * @param [in] kernelName kernel name * @param [in] blockDim block dimentions - * @param [in] args argments address for kernel function - * @param [in] argsSize argments size + * @param [in] argsInfo argments address for kernel function * @param [in] smDesc shared memory description - * @param [in] stm associated stream + * @param [in] stm associated stream * @param [in] flag dump flag or others function flag * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtCpuKernelLaunchWithFlag(const void *soName, const void *kernelName, uint32_t blockDim, - const void *args, uint32_t argsSize, rtSmDesc_t *smDesc, rtStream_t stm, + const rtArgsEx_t *argsInfo, rtSmDesc_t *smDesc, rtStream_t stm, uint32_t flags); /** - * @ingroup rt_kernel(in use) + * @ingroup rtAicpuKernelLaunchWithFlag(in use) * @brief launch cpu kernel to device with dump identifier * @param [in] launchNames names for kernel launch * @param [in] blockDim block dimentions * @param [in] args argments address for kernel function - * @param [in] argsSize argments size * @param [in] smDesc shared memory description - * @param [in] stm associated stream - * @param [in] flag dump flag or others function flag + * @param [in] stm associated stream + * @param [in] flags dump flag or others function flag * @return RT_ERROR_NONE for ok * @return RT_ERROR_INVALID_VALUE for error input */ RTS_API rtError_t rtAicpuKernelLaunchWithFlag(const rtKernelLaunchNames_t *launchNames, uint32_t blockDim, - const void *args, uint32_t argsSize, rtSmDesc_t *smDesc, rtStream_t stm, uint32_t flags); + const rtArgsEx_t *argsInfo, rtSmDesc_t *smDesc, rtStream_t stm, + uint32_t flags); /** * @ingroup rt_kernel @@ -702,37 +725,6 @@ RTS_API rtError_t rtStartMDCProfiler(void **addr, uint32_t length); */ RTS_API rtError_t rtStopMDCProfiler(void *addr); -/** - * @ingroup rt_kernel - * @brief launch kernel with tiling data to device - * @param [in] stubFunc stub function - * @param [in] blockDim block dimentions - * @param [in] argsInfo argments info address for kernel function - * @param [in] smDesc shared memory description - * @param [in] stm associated stream - * @return RT_ERROR_NONE for ok - * @return RT_ERROR_INVALID_VALUE for error input - */ -RTS_API rtError_t rtKernelLaunchWithTiling(const void *stubFunc, uint32_t blockDim, - rtArgsWithTiling_t *argsInfo, rtSmDesc_t *smDesc, rtStream_t stm); - -/** - * @ingroup rt_kernel - * @brief launch kernel with handle and tiling data to device - * @param [in] hdl program - * @param [in] kernelInfoExt kernel Info extension. device function description or tiling key, - * depending static shape or dynmaic shape. - * @param [in] blockDim block dimentions - * @param [in] argsInfo argments info address for kernel function - * @param [in] smDesc shared memory description - * @param [in] stm associated stream - * @param [in] kernelInfo kernel info - * @return RT_ERROR_NONE for ok - * @return RT_ERROR_INVALID_VALUE for error input - */ -RTS_API rtError_t rtKernelLaunchWithHandleAndTiling(void *hdl, const void *kernelInfoExt, uint32_t blockDim, - rtArgsWithTiling_t *argsInfo, rtSmDesc_t *smDesc, rtStream_t stm, const void* kernelInfo); - #if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/runtime/mem.h b/third_party/fwkacllib/inc/runtime/mem.h index 7f3a4bc7..3d2b0170 100644 --- a/third_party/fwkacllib/inc/runtime/mem.h +++ b/third_party/fwkacllib/inc/runtime/mem.h @@ -30,6 +30,7 @@ extern "C" { #define RT_MEMORY_DDR_NC (0x20U) // DDR memory of non-cache #define RT_MEMORY_TS (0x40U) // Used for Ts memory #define RT_MEMORY_TS_4G (0x40U) // Used for Ts memory(only 1951) +#define RT_MEMORY_HOST (0x81U) // Memory on host #define RT_MEMORY_RESERVED (0x100U) #define RT_MEMORY_L1 (0x1U << 16U) @@ -57,6 +58,14 @@ extern "C" { #define RT_MEMORY_POLICY_HUGE_PAGE_ONLY_P2P (0x4000U) // Malloc mem only use huge page, use for p2p, 0x1U << 14U #define RT_MEMORY_POLICY_DEFAULT_PAGE_ONLY_P2P (0x8000U) // Malloc mem only use default page, use for p2p, 0x1U << 15U +/** + * @ingroup dvrt_mem + * @brief memory attribute + */ +#define RT_MEMORY_ATTRIBUTE_DEFAULT (0x0U) +// memory read only attribute, now only dvpp memory support. +#define RT_MEMORY_ATTRIBUTE_READONLY (0x100000U) // Malloc readonly, 1<<20. + #define MEM_ALLOC_TYPE_BIT (0x3FFU) // mem type bit in <0, 9> /** @@ -230,6 +239,18 @@ RTS_API rtError_t rtFree(void *devPtr); */ RTS_API rtError_t rtDvppMalloc(void **devPtr, uint64_t size); +/** + * @ingroup dvrt_mem + * @brief alloc device memory for dvpp, support set flag + * @param [in|out] devPtr memory pointer + * @param [in] size memory size + * @param [in] flag mem flag, can use mem attribute set read only. + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + * @return others is error + */ +RTS_API rtError_t rtDvppMallocWithFlag(void **devPtr, uint64_t size, uint32_t flag); + /** * @ingroup dvrt_mem * @brief free device memory for dvpp diff --git a/third_party/fwkacllib/inc/runtime/rt.h b/third_party/fwkacllib/inc/runtime/rt.h index 10b763b2..de1b768b 100644 --- a/third_party/fwkacllib/inc/runtime/rt.h +++ b/third_party/fwkacllib/inc/runtime/rt.h @@ -11,7 +11,6 @@ #include "config.h" #include "context.h" #include "dev.h" -#include "dvfsprofile.h" #include "event.h" #include "kernel.h" #include "mem.h" diff --git a/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h b/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h index 4978d5fa..4b3447df 100644 --- a/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h +++ b/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h @@ -36,4 +36,4 @@ RTS_API rtError_t rtFftsPlusTaskLaunchWithFlag(rtFftsPlusTaskInfo_t *fftsPlusTas #if defined(__cplusplus) && !defined(COMPILE_OMG_PACKAGE) } #endif -#endif // CCE_RUNTIME_RT_FFTS_PLUS_H \ No newline at end of file +#endif // CCE_RUNTIME_RT_FFTS_PLUS_H diff --git a/third_party/fwkacllib/inc/runtime/rt_model.h b/third_party/fwkacllib/inc/runtime/rt_model.h index 883e60a8..b4919a93 100644 --- a/third_party/fwkacllib/inc/runtime/rt_model.h +++ b/third_party/fwkacllib/inc/runtime/rt_model.h @@ -131,7 +131,7 @@ typedef struct tagAllKernelTaskInfo { uint16_t argsCount; uint16_t argsSize; uint16_t reserved; - const void *kernelInfoExt; + uint64_t tilingKey; void *handle; uint8_t *smDesc; const uint8_t *args; diff --git a/third_party/fwkacllib/inc/runtime/stream.h b/third_party/fwkacllib/inc/runtime/stream.h index 026b0155..f1fe528b 100644 --- a/third_party/fwkacllib/inc/runtime/stream.h +++ b/third_party/fwkacllib/inc/runtime/stream.h @@ -80,6 +80,17 @@ RTS_API rtError_t rtStreamDestroy(rtStream_t stm); */ RTS_API rtError_t rtStreamWaitEvent(rtStream_t stm, rtEvent_t evt); +/** + * @ingroup dvrt_stream + * @brief wait an recorded event for stream, used for 1951 pg1 + * @param [in] stm the wait stream + * @param [in] event the event to wait + * @param [in] timeout timeout value for 1951 pg1 + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtStreamWaitEventWithTimeout(rtStream_t stm, rtEvent_t evt, uint32_t timeout); + /** * @ingroup dvrt_stream * @brief wait stream to be complete diff --git a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h index e592526b..718fc69d 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_acl_api.h +++ b/third_party/fwkacllib/inc/toolchain/prof_acl_api.h @@ -36,6 +36,7 @@ #define PROF_SUBTASK_TIME 0x0000040000000ULL #define PROF_OP_DETAIL 0x0000080000000ULL +#define PROF_AICPU_MODEL 0x4000000000000000ULL #define PROF_MODEL_LOAD 0x8000000000000000ULL #define PROF_TASK_TRACE (PROF_MODEL_EXECUTE | PROF_RUNTIME_TRACE | PROF_TRAINING_TRACE | \ @@ -69,6 +70,7 @@ #define PROF_SUBTASK_TIME_MASK 0x0000040000000ULL #define PROF_OP_DETAIL_MASK 0x0000080000000ULL +#define PROF_AICPU_MODEL_MASK 0x4000000000000000ULL #define PROF_MODEL_LOAD_MASK 0x8000000000000000ULL #if (defined(_WIN32) || defined(_WIN64) || defined(_MSC_VER)) diff --git a/third_party/fwkacllib/inc/toolchain/prof_callback.h b/third_party/fwkacllib/inc/toolchain/prof_callback.h index 24101aad..7b7551fd 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_callback.h +++ b/third_party/fwkacllib/inc/toolchain/prof_callback.h @@ -83,17 +83,6 @@ enum MsprofReporterCallbackType { MSPROF_REPORTER_HASH // hash data to id }; -/** - * @name MsprofReporterCallback - * @brief callback to start reporter/stop reporter/report date - * @param moduleId [IN] enum MsprofReporterModuleId - * @param type [IN] enum MsprofReporterCallbackType - * @param data [IN] callback data (nullptr on INTI/UNINIT) - * @param len [IN] callback data size (0 on INIT/UNINIT) - * @return enum MsprofErrorCode - */ -typedef int32_t (*MsprofReporterCallback)(uint32_t moduleId, uint32_t type, void *data, uint32_t len); - #define MSPROF_OPTIONS_DEF_LEN_MAX (2048) /** @@ -114,6 +103,7 @@ enum MsprofCtrlCallbackType { MSPROF_CTRL_INIT_ACL_JSON, // start pro with acl.json MSPROF_CTRL_INIT_GE_OPTIONS, // start profiling with ge env and options MSPROF_CTRL_FINALIZE, // stop profiling + MSPROF_CTRL_INIT_HELPER, // start profiling in helper device MSPROF_CTRL_INIT_DYNA = 0xFF, // start profiling for dynamic profiling }; @@ -127,40 +117,88 @@ enum MsprofCommandHandleType { }; /** - * @name MsprofCtrlCallback - * @brief callback to start/stop profiling - * @param type [IN] enum MsprofCtrlCallbackType - * @param data [IN] callback data - * @param len [IN] callback data size - * @return enum MsprofErrorCode + * @brief profiling command type */ +enum ProfCtrlType { + PROF_CTRL_INVALID = 0, + PROF_CTRL_SWITCH, + PROF_CTRL_REPORTER, + PROF_CTRL_STEPINFO, + PROF_CTRL_BUTT +}; + +/** + * @brief Prof Chip ID + */ +enum Prof_Chip_ID { + PROF_CHIP_ID0 = 0 +}; + typedef int32_t (*MsprofCtrlCallback)(uint32_t type, void *data, uint32_t len); +typedef int32_t (*MsprofReporterCallback)(uint32_t moduleId, uint32_t type, void *data, uint32_t len); /** - * @name MsprofSetDeviceCallback - * @brief callback to notify set/reset device - * @param devId [IN] device id - * @param isOpenDevice [IN] true: set device, false: reset device + * @brief the struct of profiling set setp info */ -typedef void (*MsprofSetDeviceCallback)(uint32_t devId, bool isOpenDevice); +typedef struct ProfStepInfoCmd { + uint64_t index_id; + uint16_t tag_id; + void *stream; +} ProfStepInfoCmd_t; +/** + * @name ProfCommandHandle + * @brief callback to start/stop profiling + * @param type [IN] enum call back type + * @param data [IN] callback data + * @param len [IN] callback data size + * @return enum MsprofErrorCode + */ +typedef int32_t (*ProfCommandHandle)(uint32_t type, void *data, uint32_t len); /* - * @name MsprofInit + * @name profInit * @brief Profiling module init * @param [in] dataType: profiling type: ACL Env/ACL Json/GE Option * @param [in] data: profiling switch data * @param [in] dataLen: Length of data * @return 0:SUCCESS, >0:FAILED */ -MSVP_PROF_API int32_t MsprofInit(uint32_t dataType, void *data, uint32_t dataLen); +MSVP_PROF_API int32_t MsprofInit(uint32_t moduleId, void *data, uint32_t dataLen); +/** + * @name profRegisterCallback + * @brief register callback to profiling + * @param moduleId [IN] module Id + * @param handle [IN] the pointer of callback + */ +MSVP_PROF_API int32_t MsprofRegisterCallback(uint32_t moduleId, ProfCommandHandle handle); +/* + * @name profReportData + * @brief start reporter/stop reporter/report date + * @param moduleId [IN] enum profReporterModuleId + * @param type [IN] enum profReporterCallbackType + * @param data [IN] data (nullptr on INTI/UNINIT) + * @param len [IN] data size (0 on INIT/UNINIT) + * @return enum MsprofErrorCod + */ +MSVP_PROF_API int32_t MsprofReportData(uint32_t moduleId, uint32_t type, void* data, uint32_t len); +MSVP_PROF_API int32_t MsprofSetDeviceIdByGeModelIdx(const uint32_t geModelIdx, const uint32_t deviceId); +MSVP_PROF_API int32_t MsprofUnsetDeviceIdByGeModelIdx(const uint32_t geModelIdx, const uint32_t deviceId); /* - * @name AscendCL + * @name profFinalize * @brief Finishing Profiling * @param NULL * @return 0:SUCCESS, >0:FAILED */ MSVP_PROF_API int32_t MsprofFinalize(); +/** + * @name profNotifySetDevice + * @brief notify set/reset device + * @param devId [IN] device id + * @param isOpenDevice [IN] true: set device, false: reset device + */ +MSVP_PROF_API int32_t MsprofNotifySetDevice(uint32_t chipId, uint32_t deviceId, bool isOpen); + #ifdef __cplusplus } #endif diff --git a/third_party/fwkacllib/inc/toolchain/prof_common.h b/third_party/fwkacllib/inc/toolchain/prof_common.h index bc56fb7d..e2eb5b69 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_common.h +++ b/third_party/fwkacllib/inc/toolchain/prof_common.h @@ -28,6 +28,7 @@ enum MsprofDataTag { MSPROF_RUNTIME_DATA_TAG_API = 40, //runtime data tag, range: 40~59 MSPROF_RUNTIME_DATA_TAG_TRACK = 41, MSPROF_AICPU_DATA_TAG = 60, //aicpu data tag, range: 60~79 + MSPROF_AICPU_MODEL_TAG = 61, MSPROF_HCCL_DATA_TAG = 80, //hccl data tag, range: 80~99 MSPROF_DP_DATA_TAG = 100, //dp data tag, range: 100~119 MSPROF_MSPROFTX_DATA_TAG = 120, //hccl data tag, range: 120~139 @@ -52,6 +53,16 @@ struct MsprofMixData { } data; }; +#define PATH_LEN_MAX 1023 +#define PARAM_LEN_MAX 4095 +struct MsprofCommandHandleParams { + uint32_t pathLen; + uint32_t storageLimit; // MB + uint32_t profDataLen; + char path[PATH_LEN_MAX + 1]; + char profData[PARAM_LEN_MAX + 1]; +}; + /** * @brief profiling command info */ @@ -63,6 +74,7 @@ struct MsprofCommandHandle { uint32_t devIdList[MSPROF_MAX_DEV_NUM]; uint32_t modelId; uint32_t type; + struct MsprofCommandHandleParams params; }; /** @@ -136,7 +148,7 @@ struct MsprofGeProfInferData { uint8_t reserve[MSPROF_GE_INFER_DATA_RESERVE_BYTES]; }; -#define MSPROF_GE_TASK_DATA_RESERVE_BYTES 16 +#define MSPROF_GE_TASK_DATA_RESERVE_BYTES 12 #define MSPROF_GE_OP_TYPE_LEN 56 enum MsprofGeTaskType { MSPROF_GE_TASK_TYPE_AI_CORE = 0, @@ -169,6 +181,7 @@ struct MsprofGeProfTaskData { uint32_t streamId; uint32_t taskId; uint32_t threadId; + uint32_t contextId; uint8_t reserve[MSPROF_GE_TASK_DATA_RESERVE_BYTES]; }; @@ -305,6 +318,19 @@ struct MsprofAicpuProfData { uint8_t reserve[MSPROF_AICPU_DATA_RESERVE_BYTES]; }; +struct MsprofAicpuModelProfData { + uint16_t magicNumber = MSPROF_DATA_HEAD_MAGIC_NUM; + uint16_t dataTag = MSPROF_AICPU_MODEL_TAG; + uint32_t rsv; // Ensure 8-byte alignment + uint64_t timeStamp; + uint64_t indexId; + uint32_t modelId; + uint16_t tagId; + uint16_t rsv1; + uint64_t eventId; + uint8_t reserve[24]; +}; + /** * @brief struct of data reported by DP */ diff --git a/third_party/fwkacllib/inc/toolchain/slog.h b/third_party/fwkacllib/inc/toolchain/slog.h index 48c753ce..f42ea167 100644 --- a/third_party/fwkacllib/inc/toolchain/slog.h +++ b/third_party/fwkacllib/inc/toolchain/slog.h @@ -206,6 +206,7 @@ enum { TUNE, HSS, /**< helper */ FFTS, + OP, INVLID_MOUDLE_ID }; From 6836213e68393abc74219c39423791d79c8a86dd Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Fri, 29 Apr 2022 10:31:18 +0800 Subject: [PATCH 52/59] fix headers --- .../aicpu/aicpu_schedule/aicpu_op_type_list.h | 50 +++++++++ .../inc/aicpu/common/aicpu_task_struct.h | 104 ++++++++++++++++++ third_party/fwkacllib/inc/common/type_def.h | 48 ++++++++ third_party/fwkacllib/inc/tsd/status.h | 29 +++++ 4 files changed, 231 insertions(+) create mode 100644 third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h create mode 100644 third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h create mode 100644 third_party/fwkacllib/inc/common/type_def.h create mode 100644 third_party/fwkacllib/inc/tsd/status.h diff --git a/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h b/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h new file mode 100644 index 00000000..dbf94462 --- /dev/null +++ b/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h @@ -0,0 +1,50 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2019-2020. All rights reserved. + * + * 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. + */ + +#ifndef AICPU_OP_TYPE_LIST_H_ +#define AICPU_OP_TYPE_LIST_H_ + +extern "C" { +enum OpKernelType { TF_KERNEL, CPU_KERNEL }; + +enum ReturnCode { OP_TYPE_NOT_SUPPORT, FORMAT_NOT_SUPPORT, DTYPE_NOT_SUPPORT }; + +#pragma pack(push, 1) +// One byte alignment +struct SysOpInfo { + uint64_t opLen; + uint64_t opType; + OpKernelType kernelsType; +}; + +struct SysOpCheckInfo { + uint64_t opListNum; + uint64_t offSetLen; + uint64_t sysOpInfoList; + uint64_t opParamInfoList; +}; + +struct SysOpCheckResp { + uint64_t opListNum; + bool isWithoutJson; + uint64_t returnCodeList; + uint64_t sysOpInfoList; + uint64_t opParamInfoList; +}; +#pragma pack(pop) +} + +#endif // AICPU_OP_TYPE_LIST_H_ diff --git a/third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h b/third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h new file mode 100644 index 00000000..6dd83403 --- /dev/null +++ b/third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h @@ -0,0 +1,104 @@ +/** + * Copyright 2019-2020 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. + */ + +#ifndef AICPU_TASK_STRUCT_H +#define AICPU_TASK_STRUCT_H + +#include + +namespace aicpu { + +using char_t = char; + +#pragma pack(push, 1) +struct AicpuParamHead { + uint32_t length; // Total length: include cunstom message + uint32_t ioAddrNum; // Input and output address number + uint32_t extInfoLength; // extInfo struct Length + uint64_t extInfoAddr; // extInfo address +}; + +enum class AicpuConfigMsgType { + AICPU_CONFIG_MSG_TYPE_BUF_FREE = 0, /* free buf */ + AICPU_CONFIG_MSG_TYPE_BUF_RESET = 1, /* reset buf */ + AICPU_CONFIG_MSG_TYPE_BUF_SET_ADDR = 2, /* set buf addr to aicpu */ +}; + +enum class AicpuErrMsgType { + ERR_MSG_TYPE_NULL = 0, + ERR_MSG_TYPE_AICORE = 1, + ERR_MSG_TYPE_AICPU = 2, +}; + +enum class AicpuExtInfoMsgType { + EXT_MODEL_ID_MSG_TYPE = 0, +}; + +struct AicpuConfigMsg { + uint8_t msgType; + uint8_t reserved1; + uint16_t bufLen; + uint32_t offset; + uint64_t bufAddr; + uint32_t tsId; + uint32_t reserved2; +}; + +struct AicpuModelIdInfo { + uint32_t modelId; + uint32_t extendModelId; + uint32_t extendInfo[13]; +}; + +// 64 bytes +struct AicpuExtendInfo { + uint8_t msgType; + uint8_t version; + uint8_t reserved[2]; + union { + AicpuModelIdInfo modelIdMap; + }; +}; + +struct AicoreErrMsgInfo { + uint8_t errType; + uint8_t version; + uint8_t reserved1[2]; /* reserved1, 4 byte alignment */ + uint32_t errorCode; + uint32_t modelId; + uint32_t taskId; + uint32_t streamId; + uint64_t transactionId; + uint8_t reserved2[228]; /* the total byte is 256, reserved2 len = 256 - other lens */ +}; + +struct AicpuErrMsgInfo { + uint8_t errType; + uint8_t version; + uint8_t reserved1[2]; /* reserved1, 4 byte alignment */ + uint32_t errorCode; + uint32_t modelId; + uint32_t streamId; + uint64_t transactionId; + char_t opName[64]; /* op name str */ + char_t errDesc[128]; /* err msg desc info */ + uint8_t reserved2[40]; /* the total byte is 256, reserved2 len = 256 - other lens */ +}; +#pragma pack(pop) + +} // namespace aicpu + +#endif // AICPU_TASK_STRUCT_H diff --git a/third_party/fwkacllib/inc/common/type_def.h b/third_party/fwkacllib/inc/common/type_def.h new file mode 100644 index 00000000..043b550d --- /dev/null +++ b/third_party/fwkacllib/inc/common/type_def.h @@ -0,0 +1,48 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Description:interface. + * Create: 2021-12-21 + */ +#ifndef AICPU_TYPE_DEF_H +#define AICPU_TYPE_DEF_H + +#include +#include +#ifndef char_t +typedef char char_t; +#endif + +#ifndef float32_t +typedef float float32_t; +#endif + +#ifndef float64_t +typedef double float64_t; +#endif + +inline uint64_t PtrToValue(const void *ptr) { + return static_cast(reinterpret_cast(ptr)); +} + +inline void *ValueToPtr(const uint64_t value) { + return reinterpret_cast(static_cast(value)); +} + +template +inline TO *PtrToPtr(TI *ptr) { + return reinterpret_cast(ptr); +} + +template +inline T *PtrAdd(T *const ptr, const size_t maxIdx, const size_t idx) { + if ((ptr != nullptr) && (idx < maxIdx)) { + return reinterpret_cast(ptr + idx); + } + return nullptr; +} +#endif // AICPU_TYPE_DEF_H diff --git a/third_party/fwkacllib/inc/tsd/status.h b/third_party/fwkacllib/inc/tsd/status.h new file mode 100644 index 00000000..1010aefb --- /dev/null +++ b/third_party/fwkacllib/inc/tsd/status.h @@ -0,0 +1,29 @@ +/** + * Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2021. All rights reserved. + * + * 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. + */ + +#ifndef INC_TDT_STATUS_H +#define INC_TDT_STATUS_H +#include "common/type_def.h" +namespace tsd { +#ifdef __cplusplus +using TSD_StatusT = uint32_t; +#else +typedef uint32_t TSD_StatusT; +#endif +// success code +constexpr TSD_StatusT TSD_OK = 0U; +} // namespace tsd +#endif // INC_TDT_STATUS_H From f8ff91f6420d8cd96c1338e29f074b091a0f0ae4 Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Thu, 5 May 2022 11:18:57 +0800 Subject: [PATCH 53/59] fix ge_model.h --- ge/common/model/ge_model.h | 22 ++-- inc/aicpu/aicpu_schedule/aicpu_op_type_list.h | 50 --------- inc/aicpu/common/aicpu_task_struct.h | 104 ------------------ inc/aicpu/common/type_def.h | 48 -------- inc/aicpu/tsd/status.h | 29 ----- 5 files changed, 11 insertions(+), 242 deletions(-) delete mode 100644 inc/aicpu/aicpu_schedule/aicpu_op_type_list.h delete mode 100644 inc/aicpu/common/aicpu_task_struct.h delete mode 100644 inc/aicpu/common/type_def.h delete mode 100644 inc/aicpu/tsd/status.h diff --git a/ge/common/model/ge_model.h b/ge/common/model/ge_model.h index 256c6db0..08d7c4da 100755 --- a/ge/common/model/ge_model.h +++ b/ge/common/model/ge_model.h @@ -27,16 +27,16 @@ #include "common/cust_aicpu_kernel_store.h" #include "framework/common/debug/log.h" #include "framework/common/fmk_error_codes.h" +#include "framework/common/ge_types.h" #include "graph/buffer.h" #include "external/graph/graph.h" #include "proto/task.pb.h" namespace ge { -const uint32_t INVALID_MODEL_ID = 0xFFFFFFFFUL; class GeModel : public AttrHolder { public: GeModel(); - ~GeModel() = default; + ~GeModel() override = default; GeModel(const GeModel &other) = delete; GeModel &operator=(const GeModel &other) = delete; @@ -57,10 +57,13 @@ class GeModel : public AttrHolder { void SetCustAICPUKernelStore(const CustAICPUKernelStore &cust_aicpu_kernal_store); void SetWeight(const Buffer &weights_buffer); + bool LoadTBEKernelStore(const uint8_t *const data, const size_t len); + bool loadAICPUKernelStore(const uint8_t *const data, const size_t len); + void SetName(const std::string &name); - void SetVersion(uint32_t version); + void SetVersion(const uint32_t version); void SetPlatformVersion(const std::string &platform_version); - void SetPlatformType(uint8_t platform_type); + void SetPlatformType(const uint8_t platform_type); void SetAttr(const ProtoAttrMap &attrs); @@ -70,13 +73,10 @@ class GeModel : public AttrHolder { using AttrHolder::GetAllAttrs; using AttrHolder::GetAllAttrNames; - void SetModelId(uint32_t model_id) { model_id_ = model_id; } + void SetModelId(const uint32_t model_id) { model_id_ = model_id; } uint32_t GetModelId() const { return model_id_; } - Status GetSessionId(uint32_t model_id, uint64_t &session_id) const; - void InsertSessionMap(uint32_t model_id, uint64_t session_id) { - model_id_to_session_id_map_.insert({model_id, session_id}); - } + Status GetSessionId(const uint32_t model_id, uint64_t &session_id) const; protected: ConstProtoAttrMap &GetAttrMap() const override; @@ -93,9 +93,9 @@ class GeModel : public AttrHolder { Buffer weights_buffer_; /*lint !e148*/ std::string name_; - uint32_t version_ = {0}; + uint32_t version_ = {0U}; std::string platform_version_; - uint8_t platform_type_ = {0}; + uint8_t platform_type_ = {0U}; uint32_t model_id_ = INVALID_MODEL_ID; std::map model_id_to_session_id_map_; }; diff --git a/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h b/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h deleted file mode 100644 index dbf94462..00000000 --- a/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright (c) Huawei Technologies Co., Ltd. 2019-2020. All rights reserved. - * - * 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. - */ - -#ifndef AICPU_OP_TYPE_LIST_H_ -#define AICPU_OP_TYPE_LIST_H_ - -extern "C" { -enum OpKernelType { TF_KERNEL, CPU_KERNEL }; - -enum ReturnCode { OP_TYPE_NOT_SUPPORT, FORMAT_NOT_SUPPORT, DTYPE_NOT_SUPPORT }; - -#pragma pack(push, 1) -// One byte alignment -struct SysOpInfo { - uint64_t opLen; - uint64_t opType; - OpKernelType kernelsType; -}; - -struct SysOpCheckInfo { - uint64_t opListNum; - uint64_t offSetLen; - uint64_t sysOpInfoList; - uint64_t opParamInfoList; -}; - -struct SysOpCheckResp { - uint64_t opListNum; - bool isWithoutJson; - uint64_t returnCodeList; - uint64_t sysOpInfoList; - uint64_t opParamInfoList; -}; -#pragma pack(pop) -} - -#endif // AICPU_OP_TYPE_LIST_H_ diff --git a/inc/aicpu/common/aicpu_task_struct.h b/inc/aicpu/common/aicpu_task_struct.h deleted file mode 100644 index 6dd83403..00000000 --- a/inc/aicpu/common/aicpu_task_struct.h +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef AICPU_TASK_STRUCT_H -#define AICPU_TASK_STRUCT_H - -#include - -namespace aicpu { - -using char_t = char; - -#pragma pack(push, 1) -struct AicpuParamHead { - uint32_t length; // Total length: include cunstom message - uint32_t ioAddrNum; // Input and output address number - uint32_t extInfoLength; // extInfo struct Length - uint64_t extInfoAddr; // extInfo address -}; - -enum class AicpuConfigMsgType { - AICPU_CONFIG_MSG_TYPE_BUF_FREE = 0, /* free buf */ - AICPU_CONFIG_MSG_TYPE_BUF_RESET = 1, /* reset buf */ - AICPU_CONFIG_MSG_TYPE_BUF_SET_ADDR = 2, /* set buf addr to aicpu */ -}; - -enum class AicpuErrMsgType { - ERR_MSG_TYPE_NULL = 0, - ERR_MSG_TYPE_AICORE = 1, - ERR_MSG_TYPE_AICPU = 2, -}; - -enum class AicpuExtInfoMsgType { - EXT_MODEL_ID_MSG_TYPE = 0, -}; - -struct AicpuConfigMsg { - uint8_t msgType; - uint8_t reserved1; - uint16_t bufLen; - uint32_t offset; - uint64_t bufAddr; - uint32_t tsId; - uint32_t reserved2; -}; - -struct AicpuModelIdInfo { - uint32_t modelId; - uint32_t extendModelId; - uint32_t extendInfo[13]; -}; - -// 64 bytes -struct AicpuExtendInfo { - uint8_t msgType; - uint8_t version; - uint8_t reserved[2]; - union { - AicpuModelIdInfo modelIdMap; - }; -}; - -struct AicoreErrMsgInfo { - uint8_t errType; - uint8_t version; - uint8_t reserved1[2]; /* reserved1, 4 byte alignment */ - uint32_t errorCode; - uint32_t modelId; - uint32_t taskId; - uint32_t streamId; - uint64_t transactionId; - uint8_t reserved2[228]; /* the total byte is 256, reserved2 len = 256 - other lens */ -}; - -struct AicpuErrMsgInfo { - uint8_t errType; - uint8_t version; - uint8_t reserved1[2]; /* reserved1, 4 byte alignment */ - uint32_t errorCode; - uint32_t modelId; - uint32_t streamId; - uint64_t transactionId; - char_t opName[64]; /* op name str */ - char_t errDesc[128]; /* err msg desc info */ - uint8_t reserved2[40]; /* the total byte is 256, reserved2 len = 256 - other lens */ -}; -#pragma pack(pop) - -} // namespace aicpu - -#endif // AICPU_TASK_STRUCT_H diff --git a/inc/aicpu/common/type_def.h b/inc/aicpu/common/type_def.h deleted file mode 100644 index 043b550d..00000000 --- a/inc/aicpu/common/type_def.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Description:interface. - * Create: 2021-12-21 - */ -#ifndef AICPU_TYPE_DEF_H -#define AICPU_TYPE_DEF_H - -#include -#include -#ifndef char_t -typedef char char_t; -#endif - -#ifndef float32_t -typedef float float32_t; -#endif - -#ifndef float64_t -typedef double float64_t; -#endif - -inline uint64_t PtrToValue(const void *ptr) { - return static_cast(reinterpret_cast(ptr)); -} - -inline void *ValueToPtr(const uint64_t value) { - return reinterpret_cast(static_cast(value)); -} - -template -inline TO *PtrToPtr(TI *ptr) { - return reinterpret_cast(ptr); -} - -template -inline T *PtrAdd(T *const ptr, const size_t maxIdx, const size_t idx) { - if ((ptr != nullptr) && (idx < maxIdx)) { - return reinterpret_cast(ptr + idx); - } - return nullptr; -} -#endif // AICPU_TYPE_DEF_H diff --git a/inc/aicpu/tsd/status.h b/inc/aicpu/tsd/status.h deleted file mode 100644 index 1010aefb..00000000 --- a/inc/aicpu/tsd/status.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * Copyright (c) Hisilicon Technologies Co., Ltd. 2019-2021. All rights reserved. - * - * 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. - */ - -#ifndef INC_TDT_STATUS_H -#define INC_TDT_STATUS_H -#include "common/type_def.h" -namespace tsd { -#ifdef __cplusplus -using TSD_StatusT = uint32_t; -#else -typedef uint32_t TSD_StatusT; -#endif -// success code -constexpr TSD_StatusT TSD_OK = 0U; -} // namespace tsd -#endif // INC_TDT_STATUS_H From 4c708fd78ee5e4d5a3b4852f3eafc8b3b4142a39 Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Wed, 18 May 2022 20:30:04 +0800 Subject: [PATCH 54/59] upgrade Ascend package 18 May 22 --- inc/external/ge/ge_api_types.h | 2 + inc/external/hccl/hccl.h | 28 +++- inc/framework/common/debug/log.h | 2 +- inc/framework/common/ge_types.h | 1 + inc/framework/common/op_types.h | 10 +- inc/framework/common/profiling_definitions.h | 5 +- inc/framework/common/runtime_tensor_desc.h | 38 +++++ inc/framework/common/types.h | 1 + inc/framework/common/util.h | 14 +- inc/framework/omg/parser/model_parser.h | 35 ++-- inc/framework/omg/parser/parser_factory.h | 9 +- inc/framework/omg/parser/weights_parser.h | 11 ++ inc/framework/pne/process_node_engine.h | 12 ++ inc/framework/runtime/gert_api.h | 27 ++++ inc/framework/runtime/model_desc.h | 94 +++++++++++ inc/framework/runtime/model_v2_executor.h | 142 ++++++++++++++++ metadef | 2 +- third_party/fwkacllib/inc/hccl/base.h | 2 + third_party/fwkacllib/inc/ops/all_ops.h | 2 + third_party/fwkacllib/inc/ops/array_ops.h | 33 ++++ .../fwkacllib/inc/ops/case_condition_ops.h | 53 ------ .../inc/ops/coordinates_1d_to_2d_ops.h | 48 ------ .../inc/ops/elewise_calculation_ops.h | 4 +- third_party/fwkacllib/inc/ops/encoding_ops.h | 49 ++++++ .../fwkacllib/inc/ops/functional_ops.h | 24 +++ .../fwkacllib/inc/ops/index_to_addr_ops.h | 63 -------- third_party/fwkacllib/inc/ops/map_ops.h | 152 ++++++++++++++++++ .../inc/ops/matrix_calculation_ops.h | 79 +++++++++ third_party/fwkacllib/inc/ops/nn_detect_ops.h | 40 +++++ .../fwkacllib/inc/ops/nonlinear_fuc_ops.h | 32 ++-- third_party/fwkacllib/inc/ops/selection_ops.h | 28 ++++ .../fwkacllib/inc/ops/slice_write_ops.h | 50 ------ third_party/fwkacllib/inc/ops/sparse_ops.h | 6 +- third_party/fwkacllib/inc/ops/vector_search.h | 92 +++++++++++ third_party/fwkacllib/inc/runtime/rt_model.h | 14 ++ 35 files changed, 933 insertions(+), 271 deletions(-) create mode 100644 inc/framework/common/runtime_tensor_desc.h create mode 100644 inc/framework/runtime/gert_api.h create mode 100644 inc/framework/runtime/model_desc.h create mode 100644 inc/framework/runtime/model_v2_executor.h delete mode 100644 third_party/fwkacllib/inc/ops/case_condition_ops.h delete mode 100644 third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h create mode 100644 third_party/fwkacllib/inc/ops/encoding_ops.h delete mode 100644 third_party/fwkacllib/inc/ops/index_to_addr_ops.h create mode 100644 third_party/fwkacllib/inc/ops/map_ops.h delete mode 100644 third_party/fwkacllib/inc/ops/slice_write_ops.h diff --git a/inc/external/ge/ge_api_types.h b/inc/external/ge/ge_api_types.h index f513cd51..8ed1174c 100644 --- a/inc/external/ge/ge_api_types.h +++ b/inc/external/ge/ge_api_types.h @@ -70,6 +70,8 @@ const char_t *const OPTION_EXEC_DYNAMIC_INPUT = "ge.exec.dynamicInput"; const char_t *const OPTION_EXEC_DYNAMIC_EXECUTE_MODE = "ge.exec.dynamicGraphExecuteMode"; const char_t *const OPTION_EXEC_DATA_INPUTS_SHAPE_RANGE = "ge.exec.dataInputsShapeRange"; const char_t *const OPTION_EXEC_ENABLE_COPY_OUTPUT_ADDR = "ge.exec.enableCopyOutputAddr"; +const char_t *const OPTION_EXEC_GRAPH_EXEC_TIMEOUT = "ge.exec.graphExecTimeout"; +const char_t *const OPTION_EXEC_MODEL_EXEC_TIMEOUT = "ge.exec.modelExecTimeout"; // Option key: memory init const char_t *const GRAPH_MEMORY_MAX_SIZE = "ge.graphMemoryMaxSize"; diff --git a/inc/external/hccl/hccl.h b/inc/external/hccl/hccl.h index ea077054..170c7862 100644 --- a/inc/external/hccl/hccl.h +++ b/inc/external/hccl/hccl.h @@ -145,7 +145,7 @@ extern HcclResult HcclGetRankId(HcclComm comm, uint32_t *rank); extern HcclResult HcclBarrier(HcclComm comm, aclrtStream stream); /** - * @brief AllGather operator. + * @brief Send operator. * * @param sendBuff A pointer identifying the input data address of the operator. * @param count An integer(u64) identifying the number of the send data. @@ -158,7 +158,7 @@ extern HcclResult HcclBarrier(HcclComm comm, aclrtStream stream); extern HcclResult HcclSend(void *sendBuf, uint64_t count, HcclDataType dataType, uint32_t destRank, HcclComm comm, aclrtStream stream); /** - * @brief AllGather operator. + * @brief Recv operator. * * @param recvBuff A pointer identifying the output data address of the operator. * @param count An integer(u64) identifying the number of the receive data. @@ -171,6 +171,30 @@ extern HcclResult HcclSend(void *sendBuf, uint64_t count, HcclDataType dataType, extern HcclResult HcclRecv(void *recvBuf, uint64_t count, HcclDataType dataType, uint32_t srcRank, HcclComm comm, aclrtStream stream); +/** + * @brief AlltoAllV operator. + * + * @param sendBuff A pointer identifying the input data address of the operator. + * @param sendCounts Integer array, where entry i specifies the number of elements to send to rank i. + * @param sdispls Integer array, where entry i specifies the displacement (offset from sendbuf, in units of sendtype) + * from which to send data to rank i. + * @param sendType Datatype of send buffer elements, must be one of the following types: int8, int32, int64, uint64, + * float16, float32. + * @param recvBuf A pointer identifying the output data address of the operator. + * @param recvCounts Integer array, where entry j specifies the number of elements to receive from rank j. + * @param rdispls Integer array, where entry j specifies the displacement (offset from recvbuf, in units of recvtype) to + * which data from rank j should be written. + * @param recvType Datatype of receive buffer elements, must be one of the following types: int8, int32, int64, uint64, + * float16, float32. + * @param comm A pointer identifying the communication resource based on. + * @param stream A pointer identifying the stream information. + * @return HcclResult + */ + +extern HcclResult HcclAlltoAllV(const void *sendBuf, const void *sendCounts, const void *sdispls, HcclDataType sendType, + const void *recvBuf, const void *recvCounts, const void *rdispls, HcclDataType recvType, + HcclComm comm, aclrtStream stream); + /** * @brief Destroy HCCL comm * diff --git a/inc/framework/common/debug/log.h b/inc/framework/common/debug/log.h index a796670c..1f755faa 100644 --- a/inc/framework/common/debug/log.h +++ b/inc/framework/common/debug/log.h @@ -88,7 +88,7 @@ if ((expr) != ge::GRAPH_SUCCESS) { \ REPORT_CALL_ERROR("E19999", "Operator graph failed"); \ GELOGE(ge::FAILED, __VA_ARGS__); \ - return (FAILED); \ + return (ge::FAILED); \ } \ } while (false) diff --git a/inc/framework/common/ge_types.h b/inc/framework/common/ge_types.h index 74a386a7..bbbbf4b2 100644 --- a/inc/framework/common/ge_types.h +++ b/inc/framework/common/ge_types.h @@ -309,6 +309,7 @@ struct Options { int32_t physical_device_id; std::string profiling_mode; std::string profiling_options; + int32_t graphExecTimeout; }; // Profiling info of task diff --git a/inc/framework/common/op_types.h b/inc/framework/common/op_types.h index 2b7009e8..12123925 100644 --- a/inc/framework/common/op_types.h +++ b/inc/framework/common/op_types.h @@ -45,14 +45,6 @@ class GE_FUNC_VISIBILITY OpTypeContainer { private: std::set op_type_list_; }; - -class GE_FUNC_VISIBILITY OpTypeRegistrar { - public: - explicit OpTypeRegistrar(const std::string &op_type) noexcept { - OpTypeContainer::Instance()->Register(op_type); - } - ~OpTypeRegistrar() {} -}; } // namespace ge #define REGISTER_OPTYPE_DECLARE(var_name, str_name) \ @@ -60,7 +52,7 @@ class GE_FUNC_VISIBILITY OpTypeRegistrar { #define REGISTER_OPTYPE_DEFINE(var_name, str_name) \ const char_t *var_name = str_name; \ - const ge::OpTypeRegistrar g_##var_name##_reg(str_name); + const bool g_##var_name##_reg = (static_cast(OpTypeContainer::Instance()->Register(str_name)), true); #define IS_OPTYPE_EXISTING(str_name) (ge::OpTypeContainer::Instance()->IsExisting(str_name)) #endif // INC_FRAMEWORK_COMMON_OP_TYPES_H_ diff --git a/inc/framework/common/profiling_definitions.h b/inc/framework/common/profiling_definitions.h index 5506fa5d..f814ba76 100644 --- a/inc/framework/common/profiling_definitions.h +++ b/inc/framework/common/profiling_definitions.h @@ -164,9 +164,8 @@ class ProfilingContext { int64_t RegisterString(const std::string &str); int64_t RegisterStringHash(const uint64_t hash_id, const std::string &str); - void UpdateElementHashId(const MsprofReporterCallback reporter_callback); - static Status QueryHashId(const MsprofReporterCallback reporter_callback, const std::string &src_str, - uint64_t &hash_id); + void UpdateElementHashId(); + static Status QueryHashId(const std::string &src_str, uint64_t &hash_id); size_t GetRegisterStringNum() const { return strings_to_index_.size(); } diff --git a/inc/framework/common/runtime_tensor_desc.h b/inc/framework/common/runtime_tensor_desc.h new file mode 100644 index 00000000..ebd28e25 --- /dev/null +++ b/inc/framework/common/runtime_tensor_desc.h @@ -0,0 +1,38 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved. + * + * 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. + */ +#ifndef INC_FRAMEWORK_COMMON_RUNTIME_TENSOR_DESC_H_ +#define INC_FRAMEWORK_COMMON_RUNTIME_TENSOR_DESC_H_ + +#include + +namespace ge { +constexpr int64_t kMaxDimSize = 32; + +#pragma pack(push, 1) +struct RuntimeTensorDesc { + uint64_t data_addr; + int64_t data_offset_size; + int64_t dtype; + int64_t shape[kMaxDimSize + 1]; // shape:Dim_Num|DIM0|DIM1|...|DIM31 + int64_t original_shape[kMaxDimSize + 1]; // original_shape:Dim_Num|DIM0|DIM1|...|DIM31 + int64_t format; + int64_t sub_format; + uint8_t reserved[456]; // padding to 1024 bytes +}; +#pragma pack(pop) +} // namespace ge + +#endif // INC_FRAMEWORK_COMMON_RUNTIME_TENSOR_DESC_H_ \ No newline at end of file diff --git a/inc/framework/common/types.h b/inc/framework/common/types.h index a4df4e2f..ac2c0fde 100644 --- a/inc/framework/common/types.h +++ b/inc/framework/common/types.h @@ -88,6 +88,7 @@ REGISTER_OPTYPE_DECLARE(DROPOUTDOMASKV3, "DropOutDoMaskV3"); REGISTER_OPTYPE_DECLARE(DROPOUTDOMASKV3D, "DropOutDoMaskV3D"); REGISTER_OPTYPE_DECLARE(SOFTMAXV2WITHDROPOUTDOMASKV3D, "SoftmaxV2WithDropOutDoMaskV3D"); REGISTER_OPTYPE_DECLARE(DROPOUTGENMASK, "DropOutGenMask"); +REGISTER_OPTYPE_DECLARE(AXPYWITHSOFTMAXANDDROPOUTDOMASK, "AxpyWithSoftmaxAndDropOutDoMask"); REGISTER_OPTYPE_DECLARE(CONCAT, "Concat"); REGISTER_OPTYPE_DECLARE(ROIPOOLING, "ROIPooling"); REGISTER_OPTYPE_DECLARE(PROPOSAL, "Proposal"); diff --git a/inc/framework/common/util.h b/inc/framework/common/util.h index 666f5ccd..84912e64 100644 --- a/inc/framework/common/util.h +++ b/inc/framework/common/util.h @@ -118,13 +118,13 @@ } while (false) // Check if the parameter is null. If yes, return PARAM_INVALID and record the error -#define GE_CHECK_NOTNULL(val) \ - do { \ - if ((val) == nullptr) { \ - REPORT_INNER_ERROR("E19999", "Param:%s is nullptr, check invalid", #val); \ - GELOGE(ge::FAILED, "[Check][Param:%s]null is invalid.", #val); \ - return ge::PARAM_INVALID; \ - } \ +#define GE_CHECK_NOTNULL(val, ...) \ + do { \ + if ((val) == nullptr) { \ + REPORT_INNER_ERROR("E19999", "Param:" #val " is nullptr, check invalid" __VA_ARGS__); \ + GELOGE(ge::FAILED, "[Check][Param:" #val "]null is invalid" __VA_ARGS__); \ + return ge::PARAM_INVALID; \ + } \ } while (false) // Check if the parameter is null. If yes, just return and record the error diff --git a/inc/framework/omg/parser/model_parser.h b/inc/framework/omg/parser/model_parser.h index 96a5a018..8c0130c8 100644 --- a/inc/framework/omg/parser/model_parser.h +++ b/inc/framework/omg/parser/model_parser.h @@ -52,7 +52,7 @@ class GE_FUNC_VISIBILITY ModelParser { * @return SUCCESS * @return Others failed */ - virtual domi::Status Parse(const char *file, ge::Graph &graph) = 0; + virtual Status Parse(const char *file, ge::Graph &graph) = 0; /** * @ingroup domi_omg @@ -64,7 +64,7 @@ class GE_FUNC_VISIBILITY ModelParser { * @return FAILED * @author */ - virtual domi::Status ParseFromMemory(const char *data, uint32_t size, ge::ComputeGraphPtr &graph) = 0; + virtual Status ParseFromMemory(const char *data, uint32_t size, ge::ComputeGraphPtr &graph) = 0; /** * @ingroup domi_omg @@ -76,7 +76,7 @@ class GE_FUNC_VISIBILITY ModelParser { * @return FAILED * @author */ - virtual domi::Status ParseFromMemory(const char *data, uint32_t size, ge::Graph &graph) = 0; + virtual Status ParseFromMemory(const char *data, uint32_t size, ge::Graph &graph) = 0; /** * @ingroup domi_omg @@ -86,7 +86,7 @@ class GE_FUNC_VISIBILITY ModelParser { * @return SUCCESS * @return Others failed */ - virtual domi::Status ParseProto(const google::protobuf::Message *proto, ge::ComputeGraphPtr &graph) = 0; + virtual Status ParseProto(const google::protobuf::Message *proto, ge::ComputeGraphPtr &graph) = 0; /** * @ingroup domi_omg @@ -97,8 +97,8 @@ class GE_FUNC_VISIBILITY ModelParser { * @return SUCCESS * @return Others failed */ - virtual domi::Status ParseProtoWithSubgraph(const google::protobuf::Message *proto, GetGraphCallback callback, - ge::ComputeGraphPtr &graph) = 0; + virtual Status ParseProtoWithSubgraph(const google::protobuf::Message *proto, GetGraphCallback callback, + ge::ComputeGraphPtr &graph) = 0; /** * @ingroup domi_omg * @brief Convert model files to JSON format @@ -107,10 +107,10 @@ class GE_FUNC_VISIBILITY ModelParser { * @return SUCCESS * @return Others failed */ - virtual domi::Status ToJson(const char *model_file, const char *json_file) { + virtual Status ToJson(const char *model_file, const char *json_file) { (void)model_file; (void)json_file; - return domi::SUCCESS; + return SUCCESS; } /* @@ -121,7 +121,7 @@ class GE_FUNC_VISIBILITY ModelParser { */ virtual ge::DataType ConvertToGeDataType(const uint32_t type) = 0; - virtual domi::Status ParseAllGraph(const google::protobuf::Message *root_proto, ge::ComputeGraphPtr &root_graph) = 0; + virtual Status ParseAllGraph(const google::protobuf::Message *root_proto, ge::ComputeGraphPtr &root_graph) = 0; /** * @ingroup domi_omg @@ -131,7 +131,7 @@ class GE_FUNC_VISIBILITY ModelParser { * @return SUCCESS * @return Others failed */ - virtual domi::Status ParseProto(const std::string &serialized_proto, ge::ComputeGraphPtr &graph) { + virtual Status ParseProto(const std::string &serialized_proto, ge::ComputeGraphPtr &graph) { (void)serialized_proto; (void)graph; return UNSUPPORTED; @@ -146,13 +146,24 @@ class GE_FUNC_VISIBILITY ModelParser { * @return SUCCESS * @return Others failed */ - virtual domi::Status ParseProtoWithSubgraph(const std::string &serialized_proto, GetGraphCallbackV2 callback, - ge::ComputeGraphPtr &graph) { + virtual Status ParseProtoWithSubgraph(const std::string &serialized_proto, GetGraphCallbackV2 callback, + ge::ComputeGraphPtr &graph) { (void)serialized_proto; (void)callback; (void)graph; return UNSUPPORTED; } + + virtual bool HasError() { + return false; + } + + virtual Status Save(const std::string &file) { + (void)file; + return SUCCESS; + } + + virtual void Clear(){}; }; } // namespace domi diff --git a/inc/framework/omg/parser/parser_factory.h b/inc/framework/omg/parser/parser_factory.h index cd5faa73..d64a4c2d 100644 --- a/inc/framework/omg/parser/parser_factory.h +++ b/inc/framework/omg/parser/parser_factory.h @@ -23,6 +23,7 @@ #include #include "framework/omg/omg_inner_types.h" #include "framework/omg/parser/parser_types.h" +#include "external/register/register.h" namespace domi { class WeightsParser; @@ -131,6 +132,12 @@ class GE_FUNC_VISIBILITY WeightsParserRegisterar { return std::shared_ptr(ptr); \ } \ WeightsParserRegisterar g_##type##_Weights_Parser_Creator(type, Creator_##type##_Weights_Parser) -}; // namespace domi + +class GE_FUNC_VISIBILITY OpRegTbeParserFactory { + public: + static OpRegTbeParserFactory *Instance(); + void Finalize(const domi::OpRegistrationData ®_data); +}; +} // namespace domi #endif // INC_FRAMEWORK_OMG_PARSER_PARSER_FACTORY_H_ diff --git a/inc/framework/omg/parser/weights_parser.h b/inc/framework/omg/parser/weights_parser.h index 04f09b14..52c360af 100644 --- a/inc/framework/omg/parser/weights_parser.h +++ b/inc/framework/omg/parser/weights_parser.h @@ -67,6 +67,17 @@ class GE_FUNC_VISIBILITY WeightsParser { * @author */ virtual Status ParseFromMemory(const char *input, uint32_t lengt, ge::ComputeGraphPtr &graph) = 0; + + virtual bool HasError() { + return false; + } + + virtual Status Save(const std::string &file) { + (void)file; + return SUCCESS; + } + + virtual void Clear() {} }; } // namespace domi diff --git a/inc/framework/pne/process_node_engine.h b/inc/framework/pne/process_node_engine.h index 55ceac8b..bb18b553 100644 --- a/inc/framework/pne/process_node_engine.h +++ b/inc/framework/pne/process_node_engine.h @@ -27,6 +27,15 @@ #include "framework/pne/pne_model.h" namespace ge { +class ProcessNodeEngineImpl { + public: + virtual Status OptimizeGraph(const std::vector &inputs, ComputeGraphPtr &compute_graph) = 0; + + virtual Status BuildGraph(ComputeGraphPtr &compute_graph, PneModelPtr &model) = 0; +}; + +using ProcessNodeEngineImplPtr = std::shared_ptr; + class ProcessNodeEngine { public: ProcessNodeEngine() = default; @@ -45,8 +54,11 @@ class ProcessNodeEngine { virtual const std::string &GetEngineName(const ge::NodePtr &node_ptr = nullptr) const = 0; + virtual void SetImpl(ProcessNodeEngineImplPtr impl) = 0; + protected: std::string engine_id_; + ProcessNodeEngineImplPtr impl_ = nullptr; }; using ProcessNodeEnginePtr = std::shared_ptr; diff --git a/inc/framework/runtime/gert_api.h b/inc/framework/runtime/gert_api.h new file mode 100644 index 00000000..007993e8 --- /dev/null +++ b/inc/framework/runtime/gert_api.h @@ -0,0 +1,27 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. + * + * 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. + */ + +#ifndef AIR_CXX_INC_FRAMEWORK_RUNTIME_GERT_API_H_ +#define AIR_CXX_INC_FRAMEWORK_RUNTIME_GERT_API_H_ +#include "model_v2_executor.h" +#include "common/ge_types.h" + +namespace gert { +std::unique_ptr LoadExecutorFromFile(const char *file_path, ge::graphStatus &error_code); +std::unique_ptr LoadExecutorFromModelData(const ge::ModelData &model_data, + ge::graphStatus &error_code); +} // namespace gert +#endif // AIR_CXX_INC_FRAMEWORK_RUNTIME_GERT_API_H_ diff --git a/inc/framework/runtime/model_desc.h b/inc/framework/runtime/model_desc.h new file mode 100644 index 00000000..46c21636 --- /dev/null +++ b/inc/framework/runtime/model_desc.h @@ -0,0 +1,94 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. + * + * 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. + */ + +#ifndef AIR_CXX_INC_FRAMEWORK_RUNTIME_MODEL_DESC_H_ +#define AIR_CXX_INC_FRAMEWORK_RUNTIME_MODEL_DESC_H_ +#include "common/ge_types.h" +#include "exe_graph/runtime/shape.h" +#include "exe_graph/runtime/continuous_vector.h" +#include "exe_graph/runtime/storage_format.h" +#include "exe_graph/runtime/storage_shape.h" + +namespace gert { +class ShapeRange { + public: + const Shape &GetMin() const; + const Shape &GetMax() const; + Shape &MutableMin(); + Shape &MutableMax(); + + private: + Shape min_; + Shape max_; +}; + +class ModelIoDesc { + public: + const char *GetName() const; + int32_t GetDataType() const; + ge::Format GetStorageFormat() const; + ge::Format GetOriginFormat() const; + int64_t GetSize() const; + const Shape &GetStorageShape() const; + const Shape &GetOriginShape() const; + const ShapeRange &GetOriginShapeRange() const; + const ShapeRange &GetStorageShapeRange() const; + + void SetName(const char *name); + void SetDataType(int32_t data_type); + void SetStorageFormat(ge::Format format); + void SetOriginFormat(ge::Format format); + Shape &MutableStorageShape(); + Shape &MutableOriginShape(); + ShapeRange &MutableOriginShapeRange(); + ShapeRange &MutableStorageShapeRange(); + + private: + const char *name_; + int32_t data_type_; + StorageFormat format_; + StorageShape shape_; + ShapeRange storage_shape_range_; + ShapeRange origin_shape_range_; +}; + +class ModelDesc { + public: + static size_t CalcSize(size_t input_num, size_t output_num); + const ModelIoDesc *GetInputDesc(size_t index) const; + const ModelIoDesc *GetAllInputsDesc(size_t &input_num) const; + + const ModelIoDesc *GetOutputDesc(size_t index) const; + const ModelIoDesc *GetAllOutputsDesc(size_t &output_num) const; + + ModelIoDesc *MutableInputDesc(size_t index); + ModelIoDesc *MutableOutputDesc(size_t index); + ModelIoDesc *AllMutableIoDesc(size_t &input_num, size_t &output_num); + void SetInputNum(size_t input_num); + void SetOutputNum(size_t output_num); + + ge::graphStatus GetDynamicBatchInfo(std::vector> &batch_info, int32_t &dynamic_type) const; + ge::graphStatus GetUserDesignateShapeOrder(std::vector &user_designate_shape_order) const; + ge::graphStatus GetModelAttrs(std::vector &attrs) const; + + private: + size_t input_num_; + size_t output_num_; + ContinuousVector model_io_descs_; +}; +} // namespace gert + +#endif // AIR_CXX_INC_FRAMEWORK_RUNTIME_MODEL_DESC_H_ \ No newline at end of file diff --git a/inc/framework/runtime/model_v2_executor.h b/inc/framework/runtime/model_v2_executor.h new file mode 100644 index 00000000..277a23d0 --- /dev/null +++ b/inc/framework/runtime/model_v2_executor.h @@ -0,0 +1,142 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. + * + * 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. + */ + +#ifndef AIR_CXX_RUNTIME_V2_CORE_MODEL_V_2_EXECUTOR_H_ +#define AIR_CXX_RUNTIME_V2_CORE_MODEL_V_2_EXECUTOR_H_ +#include +#include "graph/compute_graph.h" +#include "graph/ge_error_codes.h" +#include "model_desc.h" +#include "runtime/stream.h" +#include "exe_graph/runtime/tensor.h" + +namespace gert { +enum SubExeGraphType { kInitExeGraph, kMainExeGraph, kDeInitExeGraph, kSubExeGraphTypeEnd }; +static constexpr char *kSubExeGraphTypeStrs[kSubExeGraphTypeEnd] = {(char *)"Init", (char *)"Main", (char *)"DeInit"}; +inline const char *GetSubExeGraphTypeStr(SubExeGraphType type) { + return kSubExeGraphTypeStrs[type]; +} + +class ResourceGuard { + public: + void *ResetExecutionData(std::unique_ptr execution_data); + void ResetAnyValue(std::unique_ptr any_values, size_t count); + void PushNode(void *node); + void PushWatcher(void *watcher); + void *ResetNodesArray(std::unique_ptr nodes_array); + void *ResetStartNodesArray(std::unique_ptr start_nodes_array); + void *ResetNodesIndgreeArray(std::unique_ptr nodes_indgree_array); + void *ResetNodesWaitIndgreeArray(std::unique_ptr nodes_indgree_array); + void *ResetInputsArray(std::unique_ptr inputs_array); + void *ResetOutputsArray(std::unique_ptr outputs_array); + void *ResetWatchersArray(std::unique_ptr watchers_array); + void *ResetReadyQueue(void *ready_queue); + void *ResetBuffer(std::unique_ptr buffer); + void *ResetComputeNodeInfo(std::unique_ptr compute_node_info); + void *ResetKernelExtendInfo(std::unique_ptr kernel_extend_info); + void *ResetModelDesc(std::unique_ptr model_desc); + + ~ResourceGuard(); + + private: + std::unique_ptr execution_data_holder_; + size_t any_values_num_; + std::unique_ptr any_values_guard_; + + std::vector> nodes_guarder_; + std::vector> watchers_guarder_; + std::unique_ptr continuous_buffer_guarder_; + std::unique_ptr buffer_guarder_; + std::unique_ptr compute_node_info_guarder_; + std::unique_ptr kernel_extend_info_guarder_; + std::unique_ptr model_desc_guarder_; + + std::unique_ptr nodes_array_guarder_; + std::unique_ptr start_nodes_array_guarder_; + std::unique_ptr nodes_indgree_array_guarder_; + std::unique_ptr nodes_wait_indgree_array_guarder_; + std::unique_ptr inputs_array_guarder_; + std::unique_ptr outputs_array_guarder_; + std::unique_ptr watchers_array_guarder_; + std::unique_ptr ready_queue_guarder_{nullptr, nullptr}; +}; + +struct ModelExecuteArg { + rtStream_t stream; +}; +static_assert(std::is_standard_layout::value, "The class ModelExecuteArg must be a POD"); + +class ExeGraphExecutor { + public: + // todo unload时释放anyvalue资源 + ge::graphStatus Load() { + return ge::GRAPH_SUCCESS; + } + ge::graphStatus UnLoad() { + return ge::GRAPH_SUCCESS; + } + + /** + * 设置图执行的输入/输出,需要注意的是,使用者需要自己保证inputs/outputs刷新完全!!! + */ + ge::graphStatus SpecifyInputs(void **inputs, size_t start, size_t num); + ge::graphStatus SpecifyOutputs(void **outputs, size_t num); + ge::graphStatus Execute(); + + const void *GetExecutionData() const { + return execution_data_; + } + + ResourceGuard &GetResourceGuard(); + void *SetExecutionData(std::unique_ptr execution_data); + + private: + friend class ModelV2ExecutorTestHelper; + + void *execution_data_; + ResourceGuard resource_guard_; +}; +class ModelV2Executor { + public: + static std::unique_ptr Create(const ge::ComputeGraphPtr &root_graph); + + ge::graphStatus Load(); + ge::graphStatus Execute(const ModelExecuteArg &arg, Tensor **inputs, size_t input_num, Tensor **outputs, + size_t output_num); + ge::graphStatus ExecuteSync(Tensor **inputs, size_t input_num, Tensor **outputs, size_t output_num); + ge::graphStatus UnLoad(); + + const ModelDesc &GetModelDesc() const; + void SetModelDesc(ModelDesc *model_desc); + ModelV2Executor(const ModelV2Executor &) = delete; + ModelV2Executor(ModelV2Executor &&) = delete; + ModelV2Executor &operator=(const ModelV2Executor &) = delete; + ModelV2Executor &operator=(ModelV2Executor &&) = delete; + + private: + friend class ModelV2ExecutorBuilder; + friend class ModelV2ExecutorTestHelper; + ModelV2Executor() = default; + + private: + std::array graphs_; + ResourceGuard resource_guard_; + ModelDesc *model_desc_ = nullptr; + rtStream_t default_stream_ = nullptr; +}; +} // namespace gert + +#endif // AIR_CXX_RUNTIME_V2_CORE_MODEL_V_2_EXECUTOR_H_ diff --git a/metadef b/metadef index f3e9df35..00261785 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit f3e9df35da67ff00a22a09ec5b369bbc4bac9e74 +Subproject commit 002617852e22767bd864db3c01595630e23f5496 diff --git a/third_party/fwkacllib/inc/hccl/base.h b/third_party/fwkacllib/inc/hccl/base.h index 8ca4015c..5b2f34be 100644 --- a/third_party/fwkacllib/inc/hccl/base.h +++ b/third_party/fwkacllib/inc/hccl/base.h @@ -211,6 +211,8 @@ typedef struct { #define HCCL_REQUEST_NULL NULL +#define HCCL_TAG_ANY (1 << 30) + #ifdef __cplusplus } #endif // __cplusplus diff --git a/third_party/fwkacllib/inc/ops/all_ops.h b/third_party/fwkacllib/inc/ops/all_ops.h index 6c4d615d..78ef3446 100644 --- a/third_party/fwkacllib/inc/ops/all_ops.h +++ b/third_party/fwkacllib/inc/ops/all_ops.h @@ -42,6 +42,7 @@ #include "list_ops.h" #include "logging_ops.h" #include "lookup_ops.h" +#include "map_ops.h" #include "math_ops.h" #include "matrix_calculation_ops.h" #include "nn_batch_norm_ops.h" @@ -79,4 +80,5 @@ #include "warp_perspective_ops.h" #include "vector_search.h" #include "deep_md.h" +#include "encoding_ops.h" #endif // OPS_BUILT_IN_OP_PROTO_INC_ALL_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/array_ops.h b/third_party/fwkacllib/inc/ops/array_ops.h index 37b0f9f5..924f98e4 100644 --- a/third_party/fwkacllib/inc/ops/array_ops.h +++ b/third_party/fwkacllib/inc/ops/array_ops.h @@ -1550,6 +1550,39 @@ REG_OP(EnsureShape) DT_FLOAT,DT_DOUBLE, DT_COMPLEX64, DT_COMPLEX128})) .REQUIRED_ATTR(shape, ListInt) .OP_END_FACTORY_REG(EnsureShape) + +/** +* @brief Finds the first unique element from every consecutive group of equivalent elements. + +* @par Inputs: +* x: A ND tensor. + +* @par Attributes: +* @li return_idx: An optional bool. Whether to also return the indices. The default value is False +* @li return_count: An optional bool. Whether to also return the counts for each element. The default is False. +* @li axis: An optional int. Which one axis to apply unique. The default is 1000, which means None. + +* @par Outputs: +* @li y: "x" in the unique output "y". +* @li idx: The index of each value of "x". +* @li count: The counts of each value of "y". + +* @attention Constraints: +* UniqueConsecutive runs on the Ascend AI CPU, which delivers poor performance. + +* @par Third-party framework compatibility +* Compatible with the PyTorch operator UniqueConsecutive. +*/ + +REG_OP(UniqueConsecutive) + .INPUT(x, TensorType::BasicType()) + .OUTPUT(y, TensorType::BasicType()) + .OUTPUT(idx, TensorType::IndexNumberType()) + .OUTPUT(count, TensorType::IndexNumberType()) + .ATTR(return_idx, Bool, false) + .ATTR(return_counts, Bool, false) + .ATTR(axis, Int, 1000) + .OP_END_FACTORY_REG(UniqueConsecutive) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_ARRAY_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/case_condition_ops.h b/third_party/fwkacllib/inc/ops/case_condition_ops.h deleted file mode 100644 index 85dba609..00000000 --- a/third_party/fwkacllib/inc/ops/case_condition_ops.h +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright 2019 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. - */ - -/*! - * \file case_condition_ops.h - * \brief - */ -#ifndef OPS_BUILT_IN_OP_PROTO_INC_CASE_CONDITION_OPS_H_ -#define OPS_BUILT_IN_OP_PROTO_INC_CASE_CONDITION_OPS_H_ - -#include "graph/operator_reg.h" - -namespace ge { -/** -*@brief x[0] is i, x[1] is j and x[2] is k when algorithm is LU, -y = 0 when i >= k && j < k, -y = 1 when i == k && j == k, -y = 2 when i > k && j == k, -y = 3 when i == k && j > k, -y = 4 when i > k && j > k, -default y = 5 -use for lu decomposition -*@par Inputs: -*x: A Tensor of type int32/int64/uint64. \n - -*@par Attributes: -*algorithm: A string, only support LU now -*@par Outputs: -*y: A Tensor of type int32 -*/ -REG_OP(CaseCondition) - .INPUT(x, TensorType({DT_INT32, DT_INT64, DT_UINT64})) - .OUTPUT(y, TensorType({DT_INT32})) - .ATTR(algorithm, String, "LU") - .OP_END_FACTORY_REG(CaseCondition) - -} // namespace ge - - -#endif // OPS_BUILT_IN_OP_PROTO_INC_CASE_CONDITION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h b/third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h deleted file mode 100644 index f52c90b0..00000000 --- a/third_party/fwkacllib/inc/ops/coordinates_1d_to_2d_ops.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Copyright 2019 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. - */ - -/*! - * \file coordinates_1d_to_2d_ops.h - * \brief - */ -#ifndef OPS_BUILT_IN_OP_PROTO_INC_COORDINATES_1D_TO_2D_OPS_H_ -#define OPS_BUILT_IN_OP_PROTO_INC_COORDINATES_1D_TO_2D_OPS_H_ - -#include "graph/operator_reg.h" - -namespace ge { -/** -*@brief Convert one-dimensional coordinates to two-dimensional coordinates. -*@par Inputs: -*@li x: A Tensor of type int32/int64/uint64. One-dimensional coordinates. -*@li shape: A Tensor of type int32/int64/uint64. 4D tensor [N,C,H,W]. -*@par Outputs: -*@li row: row of two-dimensional -*@li col: col of two-dimensional -*@li n: col number of two-dimensional -*/ -REG_OP(Coordinates1DTo2D) - .INPUT(x, TensorType({DT_INT32, DT_INT64, DT_UINT64})) - .INPUT(shape, TensorType({DT_INT32, DT_INT64, DT_UINT64})) - .OUTPUT(row, TensorType({DT_INT32, DT_INT64, DT_UINT64})) - .OUTPUT(col, TensorType({DT_INT32, DT_INT64, DT_UINT64})) - .OUTPUT(n, TensorType({DT_INT32, DT_INT64, DT_UINT64})) - .OP_END_FACTORY_REG(Coordinates1DTo2D) - -} // namespace ge - - -#endif // OPS_BUILT_IN_OP_PROTO_INC_COORDINATES_1D_TO_2D_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index c4b38d06..f8a593b0 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -1620,8 +1620,8 @@ REG_OP(Greater) * Compatible with the TensorFlow operator zeros_like. */ REG_OP(ZerosLike) - .INPUT(x, TensorType::BasicType()) - .OUTPUT(y, TensorType::BasicType()) + .INPUT(x, TensorType({BasicType(), DT_VARIANT})) + .OUTPUT(y, TensorType({BasicType(), DT_VARIANT})) .OP_END_FACTORY_REG(ZerosLike) /** diff --git a/third_party/fwkacllib/inc/ops/encoding_ops.h b/third_party/fwkacllib/inc/ops/encoding_ops.h new file mode 100644 index 00000000..f96a67e7 --- /dev/null +++ b/third_party/fwkacllib/inc/ops/encoding_ops.h @@ -0,0 +1,49 @@ +/** + * Copyright (C) Huawei Technologies Co., Ltd 2022-2022. All rights reserved. + * + * 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. + */ + +/*! + * \file encoding_ops.h + * \brief + */ +#ifndef OPS_BUILT_IN_OP_PROTO_INC_ENCODING_OPS_H_ +#define OPS_BUILT_IN_OP_PROTO_INC_ENCODING_OPS_H_ + +#include "graph/operator_reg.h" +#include "graph/operator.h" + +namespace ge { +/** +* @brief An op to decode indices for LDPC code. \n + +* @par Inputs: +* @li valid_num: an int32 tensor indicates index limit for each line. +* @li matrix_info: an int32 2D-tensor store the block indices info of connection H matrix. \n + +* @par Outputs: +* indices: an int32 2D-tensor store the concrete indices value. +* +* @par Restrictions: +* Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ + +REG_OP(LDPCDecode) + .INPUT(valid_num, TensorType({DT_INT32})) + .INPUT(matrix_info, TensorType({DT_INT32})) + .OUTPUT(indices, TensorType({DT_INT32})) + .OP_END_FACTORY_REG(LDPCDecode) +} // namespace ge + +#endif // OPS_BUILT_IN_OP_PROTO_INC_ENCODING_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/functional_ops.h b/third_party/fwkacllib/inc/ops/functional_ops.h index 7cfe39c4..005b716c 100644 --- a/third_party/fwkacllib/inc/ops/functional_ops.h +++ b/third_party/fwkacllib/inc/ops/functional_ops.h @@ -124,6 +124,30 @@ REG_OP(If) .GRAPH(else_branch) .OP_END_FACTORY_REG(If) +/** + *@brief Select one of the subgraphs to pass the input tensors and return the output tensors . \n + + *@par Inputs: + *@li branch_index: A int32 scalar which determines the selected subgraph. + *@li input: The input tensors, which will be passed to the subgraph . It's a dynamic input. \n + + *@par Graphs: + *branches: A list of subgraphs, each of which takes 'input' and returns a list of tensors, + * whose types are the same as what every other subgraph returns . \n + + *@par Outputs: + *output: The output tensors returned by one of branches . It's a dynamic output. \n + + *@par Third-party framework compatibility + *@Compatible with the TensorFlow operator Case. + */ +REG_OP(StatelessCase) + .INPUT(branch_index, DT_INT32) + .DYNAMIC_INPUT(input, TensorType::ALL()) + .DYNAMIC_OUTPUT(output, TensorType::ALL()) + .DYNAMIC_GRAPH(branches) + .OP_END_FACTORY_REG(StatelessCase) + /** *@brief Select one of the subgraphs to pass the input tensors and return the output tensors . \n diff --git a/third_party/fwkacllib/inc/ops/index_to_addr_ops.h b/third_party/fwkacllib/inc/ops/index_to_addr_ops.h deleted file mode 100644 index 3af17a45..00000000 --- a/third_party/fwkacllib/inc/ops/index_to_addr_ops.h +++ /dev/null @@ -1,63 +0,0 @@ -/** - * Copyright 2019 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. - */ - -/*! - * \file index_to_addr_ops.h - * \brief - */ -#ifndef OPS_BUILT_IN_OP_PROTO_INC_INDEX_TO_ADDR_OPS_H_ -#define OPS_BUILT_IN_OP_PROTO_INC_INDEX_TO_ADDR_OPS_H_ - -#include "graph/operator_reg.h" - -namespace ge { - -/** -*@brief get block tensor according to base addr tensor, for hccl remote read to use. -*@par Inputs: -*@li base_addr: A Tensor of type int64/uint64. \n -*@li row:A Tensor of type int64/uint64. \n -*@li col: A Tensor of type int64/uint64. - -*@par Outputs: -*addr_table: list of [rank id, host addr, device addr, read size] - -*@par Attributes: -*@li ori_shape: An required list int. Shape of base tensor. -*@li block_size: An required list int. Shape of split block tensor. -*@li ori_storage_mode: An optional string from: '"Matrix", "UT"'. Defaults to -"Matrix". Currently only support Matrix storage -*@li block_storage_mode: An optional string from: '"Matrix", "UT"'. Defaults to -"Matrix". Currently only support Matrix storage -*@li rank_id: An optional int of rank id. Defaults is 0 -*@li dtype: An optional Type of base tensor. Defaults is DT_FLOAT -*/ -REG_OP(IndexToAddr) - .INPUT(base_addr, TensorType({DT_INT64, DT_UINT64})) - .INPUT(x, TensorType({DT_INT64, DT_UINT64})) - .OUTPUT(addrs_table, TensorType({DT_INT64, DT_UINT64})) - .REQUIRED_ATTR(ori_shape, ListInt) - .REQUIRED_ATTR(block_size, ListInt) - .ATTR(ori_storage_mode, String, "Matrix") - .ATTR(block_storage_mode, String, "Matrix") - .ATTR(rank_id, Int, 0) - .ATTR(dtype, Type, DT_FLOAT) - .OP_END_FACTORY_REG(IndexToAddr) - -} // namespace ge - - -#endif // OPS_BUILT_IN_OP_PROTO_INC_INDEX_TO_ADDR_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/map_ops.h b/third_party/fwkacllib/inc/ops/map_ops.h new file mode 100644 index 00000000..6ac15bf6 --- /dev/null +++ b/third_party/fwkacllib/inc/ops/map_ops.h @@ -0,0 +1,152 @@ +/** + * Copyright (c) Huawei Technologies Co., Ltd. 2022. All rights reserved. + * + * 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. + */ + +/*! + * \file map_ops.h + * \brief + */ +#ifndef OPS_BUILT_IN_OP_PROTO_INC_MAP_OPS_H_ +#define OPS_BUILT_IN_OP_PROTO_INC_MAP_OPS_H_ +#include "graph/operator_reg.h" + +namespace ge { +/** +* @brief Returns whether the given key exists in the map. \n + +* @par Inputs: +* @li input_handle: A scalar Tensor of type variant. The original map. +* @li key: The key to check. Supports int32, int64, string. \n + +* @par Outputs: +* has_key: A scalar Tensor of type bool. Whether the key is already in the map or not. \n + +* @par Third-party framework compatibility. +* Compatible with tensorflow TensorMapHasKey operator. +*/ +REG_OP(TensorMapHasKey) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(key, TensorType({DT_INT32, DT_INT64, DT_STRING})) + .OUTPUT(has_key, TensorType({DT_BOOL})) + .OP_END_FACTORY_REG(TensorMapHasKey) + +/** +* @brief Returns a tensor map with item from given key erased. \n + +* @par Inputs: +* @li input_handle: A scalar Tensor of type variant. The original map. +* @li key: The key of the value to be erased. Supports int32, int64, string. \n + +* @par Outputs: +* output_handle: A scalar Tensor of type variant. The map with value from given key removed. \n + +* @par Third-party framework compatibility. +* Compatible with tensorflow TensorMapErase operator. +*/ +REG_OP(TensorMapErase) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(key, TensorType({DT_INT32, DT_INT64, DT_STRING})) + .OUTPUT(output_handle, TensorType({DT_VARIANT})) + .OP_END_FACTORY_REG(TensorMapErase) + +/** +* @brief Returns a map that is the 'input_handle' + with the given key-value pair inserted. \n + +* @par Inputs: +* @li input_handle: The original map, Must be type: DT_VARIANT. +* @li key: A Tensor,the key to be inserted.Must be one of + the following types: int32, int64, string. +* @li value: A Tensor,the value to be inserted.Must be + one of BasicType types. \n + +* @par Outputs: +* output_handle: The map with key and value inserted. + Must be type: DT_VARIANT. \n +*/ +REG_OP(TensorMapInsert) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(key, TensorType({DT_INT32, DT_INT64, DT_STRING})) + .INPUT(value, BasicType) + .OUTPUT(output_handle, TensorType({DT_VARIANT})) + .OP_END_FACTORY_REG(TensorMapInsert) + +/** +* @brief Returns the value from a given key in a tensor map . \n + +* @par Inputs: +* @li input_handle: The input map. Must be type: DT_VARIANT. +* @li key: A Tensor,the key to be looked up. Must be one of + the following types: int32,int64,string . \n + +* @par Attributes: +* value_dtype: A int. Representing the type of value . \n + +* @par Outputs: +* value: A Tensor,the value found from the given key. +*/ +REG_OP(TensorMapLookup) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .INPUT(key, TensorType({DT_INT32, DT_INT64, DT_STRING})) + .OUTPUT(value, BasicType) + .REQUIRED_ATTR(value_dtype, Type) + .OP_END_FACTORY_REG(TensorMapLookup) + +/** +* @brief return TensorMap Size. \n +* +* @par Inputs: +* input_handle: A Tensor. Must be one of the following types: variant. \n +* +* @par Outputs: +* size: A Tensor. Must be one of the following types: int32. \n +*/ +REG_OP(TensorMapSize) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .OUTPUT(size, TensorType({DT_INT32})) + .OP_END_FACTORY_REG(TensorMapSize) + +/** + * @brief Return TensorMapStackKeys \n + * + * @par Inputs: + * input_handle: A Tensor. Must be one of the following types: variant. \n + * + * @par Outputs: + * keys: A Tensor. Must be one of the following types: int32, int64, string. \n + * + * @par Attributes: + * key_dtype: An required param. It is the dtype of the key. + */ +REG_OP(TensorMapStackKeys) + .INPUT(input_handle, TensorType({DT_VARIANT})) + .OUTPUT(keys, TensorType({DT_INT32, DT_INT64, DT_STRING})) + .REQUIRED_ATTR(key_dtype, Type) + .OP_END_FACTORY_REG(TensorMapStackKeys) + +/** +* @brief Creates and returns an empty tensor map. \n + +* @par Outputs: +* handle: An empty tensor map . \n + +* @par Third-party framework compatibility. +* Compatible with tensorflow EmptyTensorMap operator. +*/ +REG_OP(EmptyTensorMap) + .OUTPUT(handle, TensorType({DT_VARIANT})) + .OP_END_FACTORY_REG(EmptyTensorMap) +} // namespace ge +#endif // OPS_BUILT_IN_OP_PROTO_INC_MAP_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index a7465af0..c856d9e5 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -24,6 +24,82 @@ #include "graph/operator_reg.h" namespace ge { +/** +* @brief Backprop W of AttentionLnQKV + ReduceSumD \n +* @par Inputs: +* Four inputs, including: +* @li x: A Tensor. Must be one of the following types: float16. +* @li query_dx: A Tensor. Must be one of the following types: float16. +* @li key_dw: A Tensor. Must be one of the following types: float16. +* @li value_dw: A Tensor. Must be one of the following types: float16. + +* @par Attributes: +* @li trans_a: A optional attribute, the type is bool. Defaults to True. +* @li trans_b: A optional attribute, the type is bool. Defaults to False. \n + +* @par Outputs: +* Six outputs, including: +* @li dw_query: A Tensor. Must be one of the following types: float16. +* @li dw_key: A Tensor. Must be one of the following types: float16. +* @li dw_value: A Tensor. Must be one of the following types: float16. +* @li dbias_query: A Tensor. Must be one of the following types: float16. +* @li dbias_key: A Tensor. Must be one of the following types: float16. +* @li dbias_value: A Tensor. Must be one of the following types: float16. \n + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. \n +*/ +REG_OP(AttentionQKVGradW) + .INPUT(x, TensorType({DT_FLOAT16})) + .INPUT(query_dx, TensorType({DT_FLOAT16})) + .INPUT(key_dw, TensorType({DT_FLOAT16})) + .INPUT(value_dw, TensorType({DT_FLOAT16})) + .OUTPUT(dw_query, TensorType({DT_FLOAT16})) + .OUTPUT(dw_key, TensorType({DT_FLOAT16})) + .OUTPUT(dw_value, TensorType({DT_FLOAT16})) + .OUTPUT(dbias_query, TensorType({DT_FLOAT16})) + .OUTPUT(dbias_key, TensorType({DT_FLOAT16})) + .OUTPUT(dbias_value, TensorType({DT_FLOAT16})) + .ATTR(trans_a, Bool, true) + .ATTR(trans_b, Bool, false) + .OP_END_FACTORY_REG(AttentionQKVGradW) + +/** +* @brief Backprop X of AttentionLnQKV + AddN \n +* @par Inputs: +* Seven inputs, including: +* @li ln_dx: A Tensor. Must be one of the following types: float16. +* @li query_dx: A Tensor. Must be one of the following types: float16. +* @li key_dw: A Tensor. Must be one of the following types: float16. +* @li value_dw: A Tensor. Must be one of the following types: float16. +* @li kernel_query: A Tensor. Must be one of the following types: float16. +* @li kernel_key: A Tensor. Must be one of the following types: float16. +* @li kernel_value: A Tensor. Must be one of the following types: float16. \n + +* @par Attributes: +* @li trans_a: A optional attribute, the type is bool. Defaults to False. +* @li trans_b: A optional attribute, the type is bool. Defaults to True. \n + +* @par Outputs: +* One outputs, including: +* @li dx: A Tensor. Must be one of the following types: float16. \n + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. \n +*/ +REG_OP(AttentionQKVGradX) + .INPUT(ln_dx, TensorType({DT_FLOAT16})) + .INPUT(query_dx, TensorType({DT_FLOAT16})) + .INPUT(key_dw, TensorType({DT_FLOAT16})) + .INPUT(value_dw, TensorType({DT_FLOAT16})) + .INPUT(kernel_query, TensorType({DT_FLOAT16})) + .INPUT(kernel_key, TensorType({DT_FLOAT16})) + .INPUT(kernel_value, TensorType({DT_FLOAT16})) + .OUTPUT(dx, TensorType({DT_FLOAT16})) + .ATTR(trans_a, Bool, false) + .ATTR(trans_b, Bool, true) + .OP_END_FACTORY_REG(AttentionQKVGradX) + /** * @brief / (MatMul -> ConfusionTransposeD). @@ -54,6 +130,9 @@ namespace ge { * @li value_output: A Tensor. Must be one of the following types: float16. * @li mean: A Tensor. Must be one of the following types: float16. * @li variance: A Tensor. Must be one of the following types: float16. \n + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. \n */ REG_OP(AttentionLnQKV) .INPUT(x, TensorType({DT_FLOAT16})) diff --git a/third_party/fwkacllib/inc/ops/nn_detect_ops.h b/third_party/fwkacllib/inc/ops/nn_detect_ops.h index f35f67c5..09e94523 100644 --- a/third_party/fwkacllib/inc/ops/nn_detect_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_detect_ops.h @@ -2276,6 +2276,46 @@ REG_OP(BalanceRois) .OUTPUT(balance_rois, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(index, TensorType({DT_INT32})) .OP_END_FACTORY_REG(BalanceRois) + +/** +* @brief First calculate the minimum closure area of the two boxes, IoU, +* The CIoU is obtained by combining the center distance and width to height ratio and IoU. \n + +* @par Inputs: +* Two inputs, including: +* @li bboxes: Bounding boxes, a 2D Tensor of type float16 or float32 with +* shape (4, N). "N" indicates the number of bounding boxes, and the value +* "4" refers to [x1, y1, x2, y2] or [x, y, w, h]. +* @li gtboxes: Ground-truth boxes, a 2D Tensor of type float16 or float32 +* with shape (4, M). "M" indicates the number of ground truth boxes, and +* the value "4" refers to [x1, y1, x2, y2] or [x, y, w, h] . \n + +* @par Attributes: +* @li trans: An optional bool, true for 'xywh', false for 'xyxy'. +* @li is_cross: An optional bool, control whether the output shape is [N, M] or [1, N] +* @li mode: An optional string, computation mode, a character string with the value range of [iou, iof] +* @li atan_sub_flag: An optional bool, control whether to output atan_sub. \n + +* @par Outputs: +* Two outputs, including: +* @li overlap: A 2D Tensor of type float16 or float32 with shape [N, M] or [1, N], +* specifying the IoU or IoF ratio . +* @li atan_sub: A 2D Tensor of type float16 or float32 with shape [N, M] or [1, N], +* specifying the IoU or IoF ratio . \n + +* @attention Constraints: +* "is_cross" only support false, "atan_sub_flag" only support true. +*/ +REG_OP(CIoU) + .INPUT(bboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(gtboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(overlap, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(atan_sub, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(trans, Bool, false) + .ATTR(is_cross, Bool, true) + .ATTR(mode, String, "iou") + .ATTR(atan_sub_flag, Bool, false) + .OP_END_FACTORY_REG(CIoU) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_DETECT_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h index 7930ae07..2a939e97 100644 --- a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h +++ b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h @@ -458,22 +458,22 @@ REG_OP(Softsign) .OP_END_FACTORY_REG(Softsign) /** - * @brief Computes softsignGrad: y_grad / (1 + abs(x)) ** 2 . + * @brief Computes softsignGrad: gradients / (1 + abs(features)) ** 2 . * * @par Inputs: * Two inputs, including: - * @li y_grad: A Tensor.Must be one of the following types:float16, float32, - * @li x: A Tensor of the same type and shape as "gradients". + * @li gradients: A Tensor.Must be one of the following types:float16, float32, + * @li features: A Tensor of the same type and shape as "gradients". - * @par x_grad: - * output:A Tensor. Has the same type as "y_grad". + * @par Outputs: + * output:A Tensor. Has the same type as "gradients". * @par Third-party framework compatibility * Compatible with the TensorFlow operator SoftsignGrad. */ REG_OP(SoftsignGrad) - .INPUT(y_grad, TensorType::FloatingDataType()) - .INPUT(x, TensorType::FloatingDataType()) - .OUTPUT(x_grad, TensorType::FloatingDataType()) + .INPUT(gradients, TensorType::FloatingDataType()) + .INPUT(features, TensorType::FloatingDataType()) + .OUTPUT(output, TensorType::FloatingDataType()) .OP_END_FACTORY_REG(SoftsignGrad) /** @@ -500,23 +500,23 @@ REG_OP(Selu) .OP_END_FACTORY_REG(Selu) /** -* @brief Computes SeluGrad backprops: y_grad * (y + scale * alpha) -* if y < 0, scale * y_grad otherwise . +* @brief Computes SeluGrad backprops: gradients * (outputs + scale * alpha) +* if outputs < 0, scale * gradients otherwise . * @par Inputs: * Two inputs, including: -* @li y_grad: A Tensor of type RealNumberType . -* @li y: A Tensor of type RealNumberType . +* @li gradients: A Tensor of type RealNumberType . +* @li outputs: A Tensor of type RealNumberType . * @par Outputs: -* x_grad: A Tensor. Must have the same type as "y_grad" . +* y: A Tensor. Must have the same type as "gradients" . * @par Third-party framework compatibility * Compatible with the TensorFlow operator SeluGrad. */ REG_OP(SeluGrad) - .INPUT(y_grad, TensorType::RealNumberType()) - .INPUT(y, TensorType::RealNumberType()) - .OUTPUT(x_grad, TensorType::RealNumberType()) + .INPUT(gradients, TensorType::RealNumberType()) + .INPUT(outputs, TensorType::RealNumberType()) + .OUTPUT(y, TensorType::RealNumberType()) .OP_END_FACTORY_REG(SeluGrad) /** diff --git a/third_party/fwkacllib/inc/ops/selection_ops.h b/third_party/fwkacllib/inc/ops/selection_ops.h index d29f3d63..5222bf7d 100644 --- a/third_party/fwkacllib/inc/ops/selection_ops.h +++ b/third_party/fwkacllib/inc/ops/selection_ops.h @@ -2612,6 +2612,34 @@ REG_OP(DynSeqOuter) .INPUT(seq_len2, TensorType({DT_INT32})) .OUTPUT(y, TensorType::BasicType()) .OP_END_FACTORY_REG(DynSeqOuter) + +/** +* @brief Returns sliced data based on max nmsed_num. \n + +* @par Inputs: +* Four inputs, including: +* @li input_nmsed_boxes: A Tensor. Must be the following types: float16. +* @li input_nmsed_score: A Tensor. Must be the following types: float16. +* @li input_nmsed_class: A Tensor. Must be the following types: float16. +* @li input_nmsed_num: A Tensor. Must be the following types: int32. \n + +* @par Outputs: +* output_nmsed_boxes: A Tensor. Must be the following type: float. +* output_nmsed_score: A Tensor. Must be the following type: float. +* output_nmsed_class: A Tensor. Must be the following type: float. \n + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(NonMaxSuppressionBucketize) + .INPUT(input_nmsed_boxes, TensorType({DT_FLOAT16})) + .INPUT(input_nmsed_score, TensorType({DT_FLOAT16})) + .INPUT(input_nmsed_class, TensorType({DT_FLOAT16})) + .INPUT(input_nmsed_num, TensorType({DT_INT32})) + .OUTPUT(output_nmsed_boxes, TensorType({DT_FLOAT})) + .OUTPUT(output_nmsed_score, TensorType({DT_FLOAT})) + .OUTPUT(output_nmsed_class, TensorType({DT_FLOAT})) + .OP_END_FACTORY_REG(NonMaxSuppressionBucketize) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_SELECTION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/slice_write_ops.h b/third_party/fwkacllib/inc/ops/slice_write_ops.h deleted file mode 100644 index 0c161b2d..00000000 --- a/third_party/fwkacllib/inc/ops/slice_write_ops.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - * Copyright 2019 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. - */ - -/*! - * \file slice_write_ops.h - * \brief - */ -#ifndef OPS_BUILT_IN_OP_PROTO_INC_SLICE_WRITE_OPS_H_ -#define OPS_BUILT_IN_OP_PROTO_INC_SLICE_WRITE_OPS_H_ - -#include "graph/operator_reg.h" - -namespace ge { - -/** -*@brief write tensor value to tensor x. -*@par Inputs: -*x: A Tensor of type float16/float/double/int32/int64. \n -*begin:A Tensor of type int32/int64. \n -*value: A Tensor of type float16/float/double/int32/int64. -*@par Outputs: -*x: same tensor with input x -*/ -REG_OP(SliceWrite) - .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, \ - DT_INT32, DT_INT64})) - .INPUT(begin, TensorType({DT_INT32, DT_INT64})) - .INPUT(value, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, \ - DT_INT32, DT_INT64})) - .OUTPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, \ - DT_INT32, DT_INT64})) - .OP_END_FACTORY_REG(SliceWrite) - -} // namespace ge - - -#endif // OPS_BUILT_IN_OP_PROTO_INC_SLICE_WRITE_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/sparse_ops.h b/third_party/fwkacllib/inc/ops/sparse_ops.h index 8eb7b521..bf0f670a 100644 --- a/third_party/fwkacllib/inc/ops/sparse_ops.h +++ b/third_party/fwkacllib/inc/ops/sparse_ops.h @@ -951,7 +951,7 @@ REG_OP(SerializeSparse) DT_UINT16, DT_INT32, DT_INT64, DT_DOUBLE, DT_FLOAT, DT_FLOAT16, \ DT_COMPLEX64, DT_COMPLEX128, DT_RESOURCE, DT_STRING})) .INPUT(shape, TensorType({DT_INT64})) - .OUTPUT(serialized_sparse, TensorType({DT_STRING})) + .OUTPUT(serialized_sparse, TensorType({DT_STRING, DT_VARIANT})) .ATTR(out_type, Type, DT_STRING) .OP_END_FACTORY_REG(SerializeSparse) @@ -979,7 +979,7 @@ REG_OP(SerializeManySparse) DT_UINT16, DT_INT32, DT_INT64, DT_DOUBLE, DT_FLOAT, DT_FLOAT16, \ DT_COMPLEX64, DT_COMPLEX128, DT_RESOURCE, DT_STRING})) .INPUT(shape, TensorType({DT_INT64})) - .OUTPUT(serialized_sparse, TensorType({DT_STRING})) + .OUTPUT(serialized_sparse, TensorType({DT_STRING, DT_VARIANT})) .ATTR(out_type, Type, DT_STRING) .OP_END_FACTORY_REG(SerializeManySparse) @@ -1002,7 +1002,7 @@ REG_OP(SerializeManySparse) * Compatible with the TensorFlow operator DeserializeSparse. */ REG_OP(DeserializeSparse) - .INPUT(serialized_sparse, TensorType({DT_STRING})) + .INPUT(serialized_sparse, TensorType({DT_STRING, DT_VARIANT})) .OUTPUT(indices, TensorType({DT_INT64})) .OUTPUT(values, TensorType({DT_BOOL, DT_INT8, DT_UINT8, DT_INT16, \ DT_UINT16, DT_INT32, DT_INT64, DT_DOUBLE, DT_FLOAT, DT_FLOAT16, \ diff --git a/third_party/fwkacllib/inc/ops/vector_search.h b/third_party/fwkacllib/inc/ops/vector_search.h index ab4daa70..425eb5d6 100644 --- a/third_party/fwkacllib/inc/ops/vector_search.h +++ b/third_party/fwkacllib/inc/ops/vector_search.h @@ -154,6 +154,98 @@ REG_OP(CalcBucketsLimitAndOffset) .OUTPUT(buckets_offset, TensorType({DT_INT32, DT_INT64})) .REQUIRED_ATTR(total_limit, Int) .OP_END_FACTORY_REG(CalcBucketsLimitAndOffset) + +/** +*@brief get block tensor according to base addr tensor, for hccl remote read to use. +*@par Inputs: +*@li base_addr: A Tensor of type int64/uint64. \n +*@li row:A Tensor of type int64/uint64. \n +*@li col: A Tensor of type int64/uint64. + +*@par Outputs: +*addr_table: list of [rank id, host addr, device addr, read size] + +*@par Attributes: +*@li ori_shape: An required list int. Shape of base tensor. +*@li block_size: An required list int. Shape of split block tensor. +*@li ori_storage_mode: An optional string from: '"Matrix", "UT"'. Defaults to +"Matrix". Currently only support Matrix storage +*@li block_storage_mode: An optional string from: '"Matrix", "UT"'. Defaults to +"Matrix". Currently only support Matrix storage +*@li rank_id: An optional int of rank id. Defaults is 0 +*@li dtype: An optional Type of base tensor. Defaults is DT_FLOAT +*/ +REG_OP(IndexToAddr) + .INPUT(base_addr, TensorType({DT_INT64, DT_UINT64})) + .INPUT(x, TensorType({DT_INT64, DT_UINT64})) + .OUTPUT(addrs_table, TensorType({DT_INT64, DT_UINT64})) + .REQUIRED_ATTR(ori_shape, ListInt) + .REQUIRED_ATTR(block_size, ListInt) + .ATTR(ori_storage_mode, String, "Matrix") + .ATTR(block_storage_mode, String, "Matrix") + .ATTR(rank_id, Int, 0) + .ATTR(dtype, Type, DT_FLOAT) + .OP_END_FACTORY_REG(IndexToAddr) + +/** +*@brief Convert one-dimensional coordinates to two-dimensional coordinates. +*@par Inputs: +*@li x: A Tensor of type int32/int64/uint64. One-dimensional coordinates. +*@li shape: A Tensor of type int32/int64/uint64. 4D tensor [N,C,H,W]. +*@par Outputs: +*@li row: row of two-dimensional +*@li col: col of two-dimensional +*@li n: col number of two-dimensional +*/ +REG_OP(Coordinates1DTo2D) + .INPUT(x, TensorType({DT_INT32, DT_INT64, DT_UINT64})) + .INPUT(shape, TensorType({DT_INT32, DT_INT64, DT_UINT64})) + .OUTPUT(row, TensorType({DT_INT32, DT_INT64, DT_UINT64})) + .OUTPUT(col, TensorType({DT_INT32, DT_INT64, DT_UINT64})) + .OUTPUT(n, TensorType({DT_INT32, DT_INT64, DT_UINT64})) + .OP_END_FACTORY_REG(Coordinates1DTo2D) + +/** +*@brief x[0] is i, x[1] is j and x[2] is k when algorithm is LU, +y = 0 when i >= k && j < k, +y = 1 when i == k && j == k, +y = 2 when i > k && j == k, +y = 3 when i == k && j > k, +y = 4 when i > k && j > k, +default y = 5 +use for lu decomposition +*@par Inputs: +*x: A Tensor of type int32/int64/uint64. \n + +*@par Attributes: +*algorithm: A string, only support LU now +*@par Outputs: +*y: A Tensor of type int32 +*/ +REG_OP(CaseCondition) + .INPUT(x, TensorType({DT_INT32, DT_INT64, DT_UINT64})) + .OUTPUT(y, TensorType({DT_INT32})) + .ATTR(algorithm, String, "LU") + .OP_END_FACTORY_REG(CaseCondition) + +/** +*@brief write tensor value to tensor x. +*@par Inputs: +*x: A Tensor of type float16/float/double/int32/int64. \n +*begin:A Tensor of type int32/int64. \n +*value: A Tensor of type float16/float/double/int32/int64. +*@par Outputs: +*x: same tensor with input x +*/ +REG_OP(SliceWrite) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, \ + DT_INT32, DT_INT64})) + .INPUT(begin, TensorType({DT_INT32, DT_INT64})) + .INPUT(value, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, \ + DT_INT32, DT_INT64})) + .OUTPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, \ + DT_INT32, DT_INT64})) + .OP_END_FACTORY_REG(SliceWrite) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_VECTOR_SEARCH_H_ diff --git a/third_party/fwkacllib/inc/runtime/rt_model.h b/third_party/fwkacllib/inc/runtime/rt_model.h index b4919a93..c3d4bbd1 100644 --- a/third_party/fwkacllib/inc/runtime/rt_model.h +++ b/third_party/fwkacllib/inc/runtime/rt_model.h @@ -263,6 +263,18 @@ typedef struct tagrtStreamLabelGotoTask_t { uint8_t reserved[36]; } rtStreamLabelGotoTask_t; +typedef struct tagrtNpuGetFloatStatusTask_t { + uint64_t outputAddr; + uint64_t outputSize; + uint32_t checkMode; + uint8_t reserved[20]; +} rtNpuGetFloatStatusTask_t; + +typedef struct tagrtNpuClearFloatStatusTask_t { + uint32_t checkMode; + uint8_t reserved[36]; +} rtNpuClearFloatStatusTask_t; + typedef struct tagTaskInfo { uint32_t type; uint32_t streamID; @@ -288,6 +300,8 @@ typedef struct tagTaskInfo { rtStreamSwitchNTaskInfo_t streamSwitchNTask; rtStreamLabelSwitchByIndexTask_t streamLabelSwitchIndexTask; rtStreamLabelGotoTask_t streamLabelGotoTask; + rtNpuGetFloatStatusTask_t npuGetFloatStatusTask; + rtNpuClearFloatStatusTask_t npuClearFloatStatusTask; uint32_t reserved[10]; } u; } rtTaskInfo_t; From e806034d4f787889c6b1e0295a937f58b077d418 Mon Sep 17 00:00:00 2001 From: zhangzhenghai Date: Thu, 9 Jun 2022 19:02:44 +0800 Subject: [PATCH 55/59] update Ascend package 09 Jun 22 --- inc/external/acl/error_codes/rt_error_codes.h | 89 +- inc/external/ge/ge_api_types.h | 14 +- inc/external/runtime/rt_error_codes.h | 89 +- inc/framework/common/debug/ge_log.h | 86 +- inc/framework/common/debug/log.h | 6 +- inc/framework/common/op_types.h | 6 +- inc/framework/common/types.h | 5 +- inc/framework/engine/dnnengine.h | 1 + inc/framework/executor/ge_executor.h | 2 +- inc/framework/omg/parser/parser_types.h | 1 + metadef | 2 +- .../aicpu/aicpu_schedule/aicpu_op_type_list.h | 35 +- .../inc/aicpu/common/aicpu_task_struct.h | 96 +- third_party/fwkacllib/inc/common/type_def.h | 48 +- third_party/fwkacllib/inc/ops/rnn.h | 1508 +++++++++-------- third_party/fwkacllib/inc/runtime/base.h | 6 + third_party/fwkacllib/inc/runtime/config.h | 6 - third_party/fwkacllib/inc/runtime/dev.h | 26 + third_party/fwkacllib/inc/runtime/kernel.h | 2 + third_party/fwkacllib/inc/runtime/mem.h | 29 + .../fwkacllib/inc/runtime/rt_ffts_plus.h | 9 + .../inc/runtime/rt_ffts_plus_define.h | 12 +- .../fwkacllib/inc/runtime/rt_stars_define.h | 19 +- third_party/fwkacllib/inc/runtime/stream.h | 21 + third_party/fwkacllib/inc/tdt/tsd_client.h | 34 + third_party/fwkacllib/inc/tsd/status.h | 10 +- 26 files changed, 1174 insertions(+), 988 deletions(-) diff --git a/inc/external/acl/error_codes/rt_error_codes.h b/inc/external/acl/error_codes/rt_error_codes.h index daeca17c..05122efb 100644 --- a/inc/external/acl/error_codes/rt_error_codes.h +++ b/inc/external/acl/error_codes/rt_error_codes.h @@ -64,49 +64,54 @@ static const int32_t ACL_ERROR_RT_QUEUE_EMPTY = 207013; // queue is emp static const int32_t ACL_ERROR_RT_QUEUE_FULL = 207014; // queue is full static const int32_t ACL_ERROR_RT_REPEATED_INIT = 207015; // repeated init static const int32_t ACL_ERROR_RT_AIVEC_OVER_FLOW = 207016; // aivec over flow +static const int32_t ACL_ERROR_RT_OVER_FLOW = 207017; // common over flow -static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error -static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout -static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception -static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception -static const int32_t ACL_ERROR_RT_CDQ_BATCH_ABNORMAL = 507037; // cdq alloc batch abnormal -static const int32_t ACL_ERROR_RT_DIE_MODE_CHANGE_ERROR = 507038; // can not change die mode -static const int32_t ACL_ERROR_RT_DIE_SET_ERROR = 507039; // single die mode can not set die -static const int32_t ACL_ERROR_RT_INVALID_DIEID = 507040; // invalid die id -static const int32_t ACL_ERROR_RT_DIE_MODE_NOT_SET = 507041; // die mode not set +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout +static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception +static const int32_t ACL_ERROR_RT_CDQ_BATCH_ABNORMAL = 507037; // cdq alloc batch abnormal +static const int32_t ACL_ERROR_RT_DIE_MODE_CHANGE_ERROR = 507038; // can not change die mode +static const int32_t ACL_ERROR_RT_DIE_SET_ERROR = 507039; // single die mode can not set die +static const int32_t ACL_ERROR_RT_INVALID_DIEID = 507040; // invalid die id +static const int32_t ACL_ERROR_RT_DIE_MODE_NOT_SET = 507041; // die mode not set +static const int32_t ACL_ERROR_RT_AICORE_TRAP_READ_OVERFLOW = 507042; // aic trap read overflow +static const int32_t ACL_ERROR_RT_AICORE_TRAP_WRITE_OVERFLOW = 507043; // aic trap write overflow +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_READ_OVERFLOW = 507044; // aiv trap read overflow +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_WRITE_OVERFLOW = 507045; // aiv trap write overflow static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error diff --git a/inc/external/ge/ge_api_types.h b/inc/external/ge/ge_api_types.h index 8ed1174c..7f3bf5c0 100644 --- a/inc/external/ge/ge_api_types.h +++ b/inc/external/ge/ge_api_types.h @@ -71,13 +71,15 @@ const char_t *const OPTION_EXEC_DYNAMIC_EXECUTE_MODE = "ge.exec.dynamicGraphExec const char_t *const OPTION_EXEC_DATA_INPUTS_SHAPE_RANGE = "ge.exec.dataInputsShapeRange"; const char_t *const OPTION_EXEC_ENABLE_COPY_OUTPUT_ADDR = "ge.exec.enableCopyOutputAddr"; const char_t *const OPTION_EXEC_GRAPH_EXEC_TIMEOUT = "ge.exec.graphExecTimeout"; -const char_t *const OPTION_EXEC_MODEL_EXEC_TIMEOUT = "ge.exec.modelExecTimeout"; // Option key: memory init const char_t *const GRAPH_MEMORY_MAX_SIZE = "ge.graphMemoryMaxSize"; const char_t *const VARIABLE_MEMORY_MAX_SIZE = "ge.variableMemoryMaxSize"; const char_t *const OPTION_EXEC_REUSE_ZERO_COPY_MEMORY = "ge.exec.reuseZeroCopyMemory"; +const char_t *const OPTION_EXEC_LOGICAL_DEVICE_CLUSTER_DEPLOY_MODE = "ge.exec.logicalDeviceClusterDeployMode"; +const char_t *const OPTION_EXEC_LOGICAL_DEVICE_ID = "ge.exec.logicalDeviceId"; + namespace configure_option { const char_t *const STREAM_NUM = "ge.streamNum"; const char_t *const HEAD_STREAM = "ge.headStream"; @@ -107,6 +109,7 @@ const char_t *const OPTYPELIST_FOR_IMPLMODE = "ge.optypelistForImplmode"; const char_t *const HCOM_PARALLEL = "ge.hcomParallel"; const char_t *const AUTO_TUNE_MODE = "ge.autoTuneMode"; const char_t *const SOC_VERSION = "ge.socVersion"; +const char_t *const VIRTUAL_TYPE = "ge.virtual_type"; const char_t *const CORE_TYPE = "ge.engineType"; const char_t *const AICORE_NUM = "ge.aicoreNum"; const char_t *const L1_FUSION = "ge.l1Fusion"; @@ -254,9 +257,16 @@ const std::string AUTO_TUNE_MODE = "ge.autoTuneMode"; // Configure soc version , example: "Ascend310" const std::string SOC_VERSION = "ge.socVersion"; +// configure whether to enable virtualization, +// its value should be "0" or "1", default value is "0" +const std::string VIRTUAL_TYPE = "ge.virtual_type"; + // Configure core type "VectorEngine", default value is "AIcoreEngine" const std::string CORE_TYPE = "ge.engineType"; +// Configure graph exclude one or more engines +const std::string EXCLUDE_ENGINES = "ge.exec.exclude_engines"; + // Configure AICORE NUM const std::string AICORE_NUM = "ge.aicoreNum"; @@ -420,6 +430,7 @@ static const char_t *const EXEC_DISABLE_REUSED_MEMORY = ge::OPTION_EXEC_DISABLE_ static const char_t *const AUTO_TUNE_MODE = ge::AUTO_TUNE_MODE.c_str(); static const char_t *const CORE_TYPE = ge::CORE_TYPE.c_str(); static const char_t *const SOC_VERSION = ge::SOC_VERSION.c_str(); +static const char_t *const VIRTUAL_TYPE = ge::VIRTUAL_TYPE.c_str(); static const char_t *const ENABLE_SINGLE_STREAM = ge::ENABLE_SINGLE_STREAM; static const char_t *const AICORE_NUM = ge::AICORE_NUM.c_str(); static const char_t *const FUSION_SWITCH_FILE = ge::FUSION_SWITCH_FILE.c_str(); @@ -487,6 +498,7 @@ const std::set ir_parser_suppported_options = { // for interface: aclgrphBuildInitialize const std::set global_options = {CORE_TYPE, SOC_VERSION, + VIRTUAL_TYPE, BUFFER_OPTIMIZE, ENABLE_COMPRESS_WEIGHT, COMPRESS_WEIGHT_CONF, diff --git a/inc/external/runtime/rt_error_codes.h b/inc/external/runtime/rt_error_codes.h index daeca17c..05122efb 100644 --- a/inc/external/runtime/rt_error_codes.h +++ b/inc/external/runtime/rt_error_codes.h @@ -64,49 +64,54 @@ static const int32_t ACL_ERROR_RT_QUEUE_EMPTY = 207013; // queue is emp static const int32_t ACL_ERROR_RT_QUEUE_FULL = 207014; // queue is full static const int32_t ACL_ERROR_RT_REPEATED_INIT = 207015; // repeated init static const int32_t ACL_ERROR_RT_AIVEC_OVER_FLOW = 207016; // aivec over flow +static const int32_t ACL_ERROR_RT_OVER_FLOW = 207017; // common over flow -static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error -static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout -static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception -static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception -static const int32_t ACL_ERROR_RT_CDQ_BATCH_ABNORMAL = 507037; // cdq alloc batch abnormal -static const int32_t ACL_ERROR_RT_DIE_MODE_CHANGE_ERROR = 507038; // can not change die mode -static const int32_t ACL_ERROR_RT_DIE_SET_ERROR = 507039; // single die mode can not set die -static const int32_t ACL_ERROR_RT_INVALID_DIEID = 507040; // invalid die id -static const int32_t ACL_ERROR_RT_DIE_MODE_NOT_SET = 507041; // die mode not set +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout +static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception +static const int32_t ACL_ERROR_RT_CDQ_BATCH_ABNORMAL = 507037; // cdq alloc batch abnormal +static const int32_t ACL_ERROR_RT_DIE_MODE_CHANGE_ERROR = 507038; // can not change die mode +static const int32_t ACL_ERROR_RT_DIE_SET_ERROR = 507039; // single die mode can not set die +static const int32_t ACL_ERROR_RT_INVALID_DIEID = 507040; // invalid die id +static const int32_t ACL_ERROR_RT_DIE_MODE_NOT_SET = 507041; // die mode not set +static const int32_t ACL_ERROR_RT_AICORE_TRAP_READ_OVERFLOW = 507042; // aic trap read overflow +static const int32_t ACL_ERROR_RT_AICORE_TRAP_WRITE_OVERFLOW = 507043; // aic trap write overflow +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_READ_OVERFLOW = 507044; // aiv trap read overflow +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_WRITE_OVERFLOW = 507045; // aiv trap write overflow static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error diff --git a/inc/framework/common/debug/ge_log.h b/inc/framework/common/debug/ge_log.h index 2cb56222..aff56d4f 100644 --- a/inc/framework/common/debug/ge_log.h +++ b/inc/framework/common/debug/ge_log.h @@ -17,6 +17,7 @@ #ifndef INC_FRAMEWORK_COMMON_DEBUG_GE_LOG_H_ #define INC_FRAMEWORK_COMMON_DEBUG_GE_LOG_H_ +#include #include #include "framework/common/ge_inner_error_codes.h" @@ -56,63 +57,64 @@ inline bool IsLogEnable(const int32_t module_name, const int32_t log_level) { return (enable == 1); } -#define GELOGE(ERROR_CODE, fmt, ...) \ - do { \ - dlog_error(GE_MODULE_NAME, "%lu %s: ErrorNo: %u(%s) %s" fmt, GeLog::GetTid(), &__FUNCTION__[0], (ERROR_CODE), \ - ((GE_GET_ERRORNO_STR(ERROR_CODE)).c_str()), ErrorManager::GetInstance().GetLogHeader().c_str(), \ - ##__VA_ARGS__); \ +#define GELOGE(ERROR_CODE, fmt, ...) \ + do { \ + dlog_error(GE_MODULE_NAME, "%" PRIu64 " %s: ErrorNo: %" PRIuLEAST8 "(%s) %s" fmt, GeLog::GetTid(), \ + &__FUNCTION__[0], (ERROR_CODE), ((GE_GET_ERRORNO_STR(ERROR_CODE)).c_str()), \ + ErrorManager::GetInstance().GetLogHeader().c_str(), ##__VA_ARGS__); \ } while (false) -#define GELOGW(fmt, ...) \ - do { \ - if (IsLogEnable(GE_MODULE_NAME, DLOG_WARN)) { \ - dlog_warn(GE_MODULE_NAME, "%lu %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \ - } \ +#define GELOGW(fmt, ...) \ + do { \ + if (IsLogEnable(GE_MODULE_NAME, DLOG_WARN)) { \ + dlog_warn(GE_MODULE_NAME, "%" PRIu64 " %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \ + } \ } while (false) -#define GELOGI(fmt, ...) \ - do { \ - if (IsLogEnable(GE_MODULE_NAME, DLOG_INFO)) { \ - dlog_info(GE_MODULE_NAME, "%lu %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \ - } \ +#define GELOGI(fmt, ...) \ + do { \ + if (IsLogEnable(GE_MODULE_NAME, DLOG_INFO)) { \ + dlog_info(GE_MODULE_NAME, "%" PRIu64 " %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \ + } \ } while (false) -#define GELOGD(fmt, ...) \ - do { \ - if (IsLogEnable(GE_MODULE_NAME, DLOG_DEBUG)) { \ - dlog_debug(GE_MODULE_NAME, "%lu %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \ - } \ +#define GELOGD(fmt, ...) \ + do { \ + if (IsLogEnable(GE_MODULE_NAME, DLOG_DEBUG)) { \ + dlog_debug(GE_MODULE_NAME, "%" PRIu64 " %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \ + } \ } while (false) -#define GEEVENT(fmt, ...) \ - do { \ - dlog_event(GE_MODULE_NAME, "%lu %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \ +#define GEEVENT(fmt, ...) \ + do { \ + dlog_event(GE_MODULE_NAME, "%" PRIu64 " %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \ } while (false) -#define GELOGT(VALUE, fmt, ...) \ - do { \ - TraceStatus stat = (VALUE); \ - const char_t *const TraceStatStr[] = {"INIT", "RUNNING", "WAITING", "STOP"}; \ - const int32_t idx = static_cast(stat); \ - char_t *k = const_cast("status"); \ - char_t *v = const_cast(TraceStatStr[idx]); \ - KeyValue kv = {k, v}; \ - DlogWithKV(GE_MODULE_NAME, DLOG_TRACE, &kv, 1, "%lu %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], ##__VA_ARGS__); \ +#define GELOGT(VALUE, fmt, ...) \ + do { \ + TraceStatus stat = (VALUE); \ + const char_t *const TraceStatStr[] = {"INIT", "RUNNING", "WAITING", "STOP"}; \ + const int32_t idx = static_cast(stat); \ + char_t *k = const_cast("status"); \ + char_t *v = const_cast(TraceStatStr[idx]); \ + KeyValue kv = {k, v}; \ + DlogWithKV(GE_MODULE_NAME, DLOG_TRACE, &kv, 1, "%" PRIu64 " %s:" fmt, GeLog::GetTid(), &__FUNCTION__[0], \ + ##__VA_ARGS__); \ } while (false) -#define GE_LOG_ERROR(MOD_NAME, ERROR_CODE, fmt, ...) \ - do { \ - dlog_error((MOD_NAME), "%lu %s: ErrorNo: %u(%s) %s" fmt, GeLog::GetTid(), &__FUNCTION__[0], (ERROR_CODE), \ - ((GE_GET_ERRORNO_STR(ERROR_CODE)).c_str()), ErrorManager::GetInstance().GetLogHeader().c_str(), \ - ##__VA_ARGS__); \ +#define GE_LOG_ERROR(MOD_NAME, ERROR_CODE, fmt, ...) \ + do { \ + dlog_error((MOD_NAME), "%" PRIu64 " %s: ErrorNo: %" PRIuLEAST8 "(%s) %s" fmt, GeLog::GetTid(), &__FUNCTION__[0], \ + (ERROR_CODE), ((GE_GET_ERRORNO_STR(ERROR_CODE)).c_str()), \ + ErrorManager::GetInstance().GetLogHeader().c_str(), ##__VA_ARGS__); \ } while (false) // print memory when it is greater than 1KB. -#define GE_PRINT_DYNAMIC_MEMORY(FUNC, PURPOSE, SIZE) \ - do { \ - if (static_cast(SIZE) > 1024UL) { \ - GELOGI("MallocMemory, func=%s, size=%zu, purpose=%s", (#FUNC), static_cast(SIZE), (PURPOSE)); \ - } \ +#define GE_PRINT_DYNAMIC_MEMORY(FUNC, PURPOSE, SIZE) \ + do { \ + if (static_cast(SIZE) > 1024UL) { \ + GELOGI("MallocMemory, func=%s, size=%" PRIu64 ", purpose=%s", (#FUNC), static_cast(SIZE), (PURPOSE)); \ + } \ } while (false) #ifdef __cplusplus } diff --git a/inc/framework/common/debug/log.h b/inc/framework/common/debug/log.h index 1f755faa..45c157f3 100644 --- a/inc/framework/common/debug/log.h +++ b/inc/framework/common/debug/log.h @@ -180,13 +180,13 @@ #define GE_ERRORLOG_AND_ERRORMSG(_status, errormsg) \ { \ GELOGE((_status), "[Check][InnerData]%s", (errormsg)); \ - REPORT_INNER_ERROR("E19999", "%s", (errormsg)); \ + REPORT_INNER_ERROR("E10052", "%s", (errormsg)); \ } #define GE_WARNINGLOG_AND_ERRORMSG(errormsg) \ { \ GELOGW("%s", (errormsg)); \ - ErrorManager::GetInstance().ATCReportErrMessage("E19021", {"reason"}, {(errormsg)}); \ + ErrorManager::GetInstance().ATCReportErrMessage("E10052", {"reason"}, {(errormsg)}); \ } #define GE_CHK_LOG_AND_ERRORMSG(expr, _status, errormsg) \ @@ -194,7 +194,7 @@ const bool b = (expr); \ if (!b) { \ GELOGE((_status), "%s", (errormsg)); \ - ErrorManager::GetInstance().ATCReportErrMessage("E19021", {"reason"}, {(errormsg)}); \ + ErrorManager::GetInstance().ATCReportErrMessage("E10052", {"reason"}, {(errormsg)}); \ return (_status); \ } \ } while (false) diff --git a/inc/framework/common/op_types.h b/inc/framework/common/op_types.h index 12123925..94a6b977 100644 --- a/inc/framework/common/op_types.h +++ b/inc/framework/common/op_types.h @@ -31,8 +31,8 @@ class GE_FUNC_VISIBILITY OpTypeContainer { } ~OpTypeContainer() = default; - void Register(const std::string &op_type) { - static_cast(op_type_list_.insert(op_type)); + bool Register(const std::string &op_type) { + return op_type_list_.insert(op_type).second; } bool IsExisting(const std::string &op_type) { @@ -52,7 +52,7 @@ class GE_FUNC_VISIBILITY OpTypeContainer { #define REGISTER_OPTYPE_DEFINE(var_name, str_name) \ const char_t *var_name = str_name; \ - const bool g_##var_name##_reg = (static_cast(OpTypeContainer::Instance()->Register(str_name)), true); + const bool g_##var_name##_reg = OpTypeContainer::Instance()->Register(str_name); #define IS_OPTYPE_EXISTING(str_name) (ge::OpTypeContainer::Instance()->IsExisting(str_name)) #endif // INC_FRAMEWORK_COMMON_OP_TYPES_H_ diff --git a/inc/framework/common/types.h b/inc/framework/common/types.h index ac2c0fde..ab5218c0 100644 --- a/inc/framework/common/types.h +++ b/inc/framework/common/types.h @@ -162,6 +162,7 @@ REGISTER_OPTYPE_DECLARE(_IF, "_If"); REGISTER_OPTYPE_DECLARE(STATELESSIF, "StatelessIf"); REGISTER_OPTYPE_DECLARE(IF, "If"); REGISTER_OPTYPE_DECLARE(CASE, "Case"); +REGISTER_OPTYPE_DECLARE(STATELESSCASE, "StatelessCase"); REGISTER_OPTYPE_DECLARE(_WHILE, "_While"); REGISTER_OPTYPE_DECLARE(WHILE, "While"); REGISTER_OPTYPE_DECLARE(STATELESSWHILE, "StatelessWhile"); @@ -626,8 +627,8 @@ struct ModelFileHeader { uint32_t version = MODEL_VERSION; // version 1.0 uint8_t checksum[MODEL_FILE_CHECKSUM_LENGTH] = {0U}; // signature uint32_t length = 0U; // Ciphertext length. In the non-encryption model, the length is the plaintext length. - uint8_t is_encrypt = - static_cast(ModelEncryptType::UNENCRYPTED); // whether encrypted 0:not encrypt, 1:encrypt + // whether encrypted 0:not encrypt, 1:encrypt + uint8_t is_encrypt = static_cast(ModelEncryptType::UNENCRYPTED); uint8_t is_checksum = static_cast(ModelCheckType::CHECK); // whether to check the checksum uint8_t modeltype = 0U; // 0:IR model 1:standard model 2: OM Tiny model uint8_t genmode = 0U; // 0:offline generate 1:online generate diff --git a/inc/framework/engine/dnnengine.h b/inc/framework/engine/dnnengine.h index 63c2d9de..f9a7b65b 100644 --- a/inc/framework/engine/dnnengine.h +++ b/inc/framework/engine/dnnengine.h @@ -31,6 +31,7 @@ enum class PriorityEnum { COST_1 = 1, COST_2 = 2, COST_3 = 3, + COST_4 = 4, COST_9 = 9, COST_10 = 10, }; diff --git a/inc/framework/executor/ge_executor.h b/inc/framework/executor/ge_executor.h index a3f7cea1..3c921345 100644 --- a/inc/framework/executor/ge_executor.h +++ b/inc/framework/executor/ge_executor.h @@ -178,7 +178,7 @@ class GE_FUNC_VISIBILITY GeExecutor { Status GetAippType(const uint32_t model_id, const uint32_t index, InputAippType &type, size_t &aipp_index); - Status CommandHandle(const Command &command); + Status CommandHandle(const Command &command) const; Status SetDump(const DumpConfig &dump_config); diff --git a/inc/framework/omg/parser/parser_types.h b/inc/framework/omg/parser/parser_types.h index a2452c65..c1e94a4c 100644 --- a/inc/framework/omg/parser/parser_types.h +++ b/inc/framework/omg/parser/parser_types.h @@ -133,6 +133,7 @@ FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const char *_IF; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const char *STATELESSIF; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const char *IF; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const char *CASE; +FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const char *STATELESSCASE; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const char *_WHILE; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const char *WHILE; FMK_FUNC_HOST_VISIBILITY FMK_FUNC_DEV_VISIBILITY extern const char *STATELESSWHILE; diff --git a/metadef b/metadef index 00261785..58412ad7 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit 002617852e22767bd864db3c01595630e23f5496 +Subproject commit 58412ad7aed08cd1c01cc070d80706e4253c9075 diff --git a/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h b/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h index dbf94462..37a2e412 100644 --- a/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h +++ b/third_party/fwkacllib/inc/aicpu/aicpu_schedule/aicpu_op_type_list.h @@ -18,31 +18,38 @@ #define AICPU_OP_TYPE_LIST_H_ extern "C" { -enum OpKernelType { TF_KERNEL, CPU_KERNEL }; +enum OpKernelType { + TF_KERNEL, + CPU_KERNEL +}; -enum ReturnCode { OP_TYPE_NOT_SUPPORT, FORMAT_NOT_SUPPORT, DTYPE_NOT_SUPPORT }; +enum ReturnCode { + OP_TYPE_NOT_SUPPORT, + FORMAT_NOT_SUPPORT, + DTYPE_NOT_SUPPORT +}; #pragma pack(push, 1) // One byte alignment struct SysOpInfo { - uint64_t opLen; - uint64_t opType; - OpKernelType kernelsType; + uint64_t opLen; + uint64_t opType; + OpKernelType kernelsType; }; struct SysOpCheckInfo { - uint64_t opListNum; - uint64_t offSetLen; - uint64_t sysOpInfoList; - uint64_t opParamInfoList; + uint64_t opListNum; + uint64_t offSetLen; + uint64_t sysOpInfoList; + uint64_t opParamInfoList; }; struct SysOpCheckResp { - uint64_t opListNum; - bool isWithoutJson; - uint64_t returnCodeList; - uint64_t sysOpInfoList; - uint64_t opParamInfoList; + uint64_t opListNum; + bool isWithoutJson; + uint64_t returnCodeList; + uint64_t sysOpInfoList; + uint64_t opParamInfoList; }; #pragma pack(pop) } diff --git a/third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h b/third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h index 6dd83403..2dc0b1bb 100644 --- a/third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h +++ b/third_party/fwkacllib/inc/aicpu/common/aicpu_task_struct.h @@ -24,81 +24,83 @@ namespace aicpu { using char_t = char; #pragma pack(push, 1) -struct AicpuParamHead { - uint32_t length; // Total length: include cunstom message - uint32_t ioAddrNum; // Input and output address number - uint32_t extInfoLength; // extInfo struct Length - uint64_t extInfoAddr; // extInfo address +struct AicpuParamHead +{ + uint32_t length; // Total length: include cunstom message + uint32_t ioAddrNum; // Input and output address number + uint32_t extInfoLength; // extInfo struct Length + uint64_t extInfoAddr; // extInfo address }; enum class AicpuConfigMsgType { - AICPU_CONFIG_MSG_TYPE_BUF_FREE = 0, /* free buf */ - AICPU_CONFIG_MSG_TYPE_BUF_RESET = 1, /* reset buf */ - AICPU_CONFIG_MSG_TYPE_BUF_SET_ADDR = 2, /* set buf addr to aicpu */ + AICPU_CONFIG_MSG_TYPE_BUF_FREE = 0, /* free buf */ + AICPU_CONFIG_MSG_TYPE_BUF_RESET = 1, /* reset buf */ + AICPU_CONFIG_MSG_TYPE_BUF_SET_ADDR = 2, /* set buf addr to aicpu */ }; enum class AicpuErrMsgType { - ERR_MSG_TYPE_NULL = 0, - ERR_MSG_TYPE_AICORE = 1, - ERR_MSG_TYPE_AICPU = 2, + ERR_MSG_TYPE_NULL = 0, + ERR_MSG_TYPE_AICORE = 1, + ERR_MSG_TYPE_AICPU = 2, }; enum class AicpuExtInfoMsgType { - EXT_MODEL_ID_MSG_TYPE = 0, + EXT_MODEL_ID_MSG_TYPE = 0, }; struct AicpuConfigMsg { - uint8_t msgType; - uint8_t reserved1; - uint16_t bufLen; - uint32_t offset; - uint64_t bufAddr; - uint32_t tsId; - uint32_t reserved2; + uint8_t msgType; + uint8_t reserved1; + uint16_t bufLen; + uint32_t offset; + uint64_t bufAddr; + uint32_t tsId; + uint32_t reserved2; }; struct AicpuModelIdInfo { - uint32_t modelId; - uint32_t extendModelId; - uint32_t extendInfo[13]; + uint32_t modelId; + uint32_t extendModelId; + uint32_t extendInfo[13]; }; // 64 bytes struct AicpuExtendInfo { - uint8_t msgType; - uint8_t version; - uint8_t reserved[2]; - union { - AicpuModelIdInfo modelIdMap; - }; + uint8_t msgType; + uint8_t version; + uint8_t reserved[2]; + union { + AicpuModelIdInfo modelIdMap; + }; }; struct AicoreErrMsgInfo { - uint8_t errType; - uint8_t version; - uint8_t reserved1[2]; /* reserved1, 4 byte alignment */ - uint32_t errorCode; - uint32_t modelId; - uint32_t taskId; - uint32_t streamId; - uint64_t transactionId; - uint8_t reserved2[228]; /* the total byte is 256, reserved2 len = 256 - other lens */ + uint8_t errType; + uint8_t version; + uint8_t reserved1[2]; /* reserved1, 4 byte alignment */ + uint32_t errorCode; + uint32_t modelId; + uint32_t taskId; + uint32_t streamId; + uint64_t transactionId; + uint8_t reserved2[228]; /* the total byte is 256, reserved2 len = 256 - other lens */ }; struct AicpuErrMsgInfo { - uint8_t errType; - uint8_t version; - uint8_t reserved1[2]; /* reserved1, 4 byte alignment */ - uint32_t errorCode; - uint32_t modelId; - uint32_t streamId; - uint64_t transactionId; - char_t opName[64]; /* op name str */ - char_t errDesc[128]; /* err msg desc info */ - uint8_t reserved2[40]; /* the total byte is 256, reserved2 len = 256 - other lens */ + uint8_t errType; + uint8_t version; + uint8_t reserved1[2]; /* reserved1, 4 byte alignment */ + uint32_t errorCode; + uint32_t modelId; + uint32_t streamId; + uint64_t transactionId; + char_t opName[64]; /* op name str */ + char_t errDesc[128]; /* err msg desc info */ + uint8_t reserved2[40]; /* the total byte is 256, reserved2 len = 256 - other lens */ }; #pragma pack(pop) } // namespace aicpu #endif // AICPU_TASK_STRUCT_H + diff --git a/third_party/fwkacllib/inc/common/type_def.h b/third_party/fwkacllib/inc/common/type_def.h index 043b550d..1bbaf32d 100644 --- a/third_party/fwkacllib/inc/common/type_def.h +++ b/third_party/fwkacllib/inc/common/type_def.h @@ -1,13 +1,13 @@ /** - * Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Description:interface. - * Create: 2021-12-21 - */ +* Copyright (c) Huawei Technologies Co., Ltd. 2021. All rights reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +* +* Description:interface. +* Create: 2021-12-21 +*/ #ifndef AICPU_TYPE_DEF_H #define AICPU_TYPE_DEF_H @@ -25,24 +25,28 @@ typedef float float32_t; typedef double float64_t; #endif -inline uint64_t PtrToValue(const void *ptr) { - return static_cast(reinterpret_cast(ptr)); +inline uint64_t PtrToValue(const void *ptr) +{ + return static_cast(reinterpret_cast(ptr)); } -inline void *ValueToPtr(const uint64_t value) { - return reinterpret_cast(static_cast(value)); +inline void *ValueToPtr(const uint64_t value) +{ + return reinterpret_cast(static_cast(value)); } -template -inline TO *PtrToPtr(TI *ptr) { - return reinterpret_cast(ptr); +template +inline TO *PtrToPtr(TI *ptr) +{ + return reinterpret_cast(ptr); } -template -inline T *PtrAdd(T *const ptr, const size_t maxIdx, const size_t idx) { - if ((ptr != nullptr) && (idx < maxIdx)) { - return reinterpret_cast(ptr + idx); - } - return nullptr; +template +inline T *PtrAdd(T * const ptr, const size_t maxIdx, const size_t idx) +{ + if ((ptr != nullptr) && (idx < maxIdx)) { + return reinterpret_cast(ptr + idx); + } + return nullptr; } #endif // AICPU_TYPE_DEF_H diff --git a/third_party/fwkacllib/inc/ops/rnn.h b/third_party/fwkacllib/inc/ops/rnn.h index 51784547..2ab5843f 100644 --- a/third_party/fwkacllib/inc/ops/rnn.h +++ b/third_party/fwkacllib/inc/ops/rnn.h @@ -25,31 +25,31 @@ namespace ge { /** -*@brief: Basic LSTM Cell forward calculation. -*@par Inputs: -*five inputs: -*@li x:A 4D Tensor. Must be one of the following types: float16. -*@li h:A 4D Tensor. Must be one of the following types: float16. -*@li c:A 4D Tensor. Must be one of the following types: float16, float32. -*@li w:A 4D Tensor. Must be one of the following types: float16. -*@li b:A 1D Tensor. Must be one of the following types: float16. The format must be ND . \n -*@li mask:A 1D Tensor. Must be one of the following types: uint8. - -*@par Attributes: -*@li keep_prob:An integer identifying the keep prob in the op. Default to 1. -*@li forget_bias:An integer identifying the forget bias in the op. Default to 1. -*@li state_is_tuple:An bool identifying if the hidden state and cell state is tuple. Default to true. -*@li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported . \n +* @brief: Basic LSTM Cell forward calculation. +* @par Inputs: +* five inputs: +* @li x:A 4D Tensor. Must be one of the following types: float16. +* @li h:A 4D Tensor. Must be one of the following types: float16. +* @li c:A 4D Tensor. Must be one of the following types: float16, float32. +* @li w:A 4D Tensor. Must be one of the following types: float16. +* @li b:A 1D Tensor. Must be one of the following types: float16. The format must be ND . \n +* @li mask:A 1D Tensor. Must be one of the following types: uint8. -*@par Outputs: -*seven outputs: -*@li ct:A 4D Tensor. Must be one of the following types: float16, float32. -*@li ht:A 4D Tensor. Must be one of the following types: float16. -*@li it:A 4D Tensor. Must be one of the following types: float16, float32. -*@li jt:A 4D Tensor. Must be one of the following types: float16, float32. -*@li ft:A 4D Tensor. Must be one of the following types: float16, float32. -*@li ot:A 4D Tensor. Must be one of the following types: float16, float32. -*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. +* @par Attributes: +* @li keep_prob:An integer identifying the keep prob in the op. Default to 1. +* @li forget_bias:An integer identifying the forget bias in the op. Default to 1. +* @li state_is_tuple:An bool identifying if the hidden state and cell state is tuple. Default to true. +* @li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported . \n + +* @par Outputs: +* seven outputs: +* @li ct:A 4D Tensor. Must be one of the following types: float16, float32. +* @li ht:A 4D Tensor. Must be one of the following types: float16. +* @li it:A 4D Tensor. Must be one of the following types: float16, float32. +* @li jt:A 4D Tensor. Must be one of the following types: float16, float32. +* @li ft:A 4D Tensor. Must be one of the following types: float16, float32. +* @li ot:A 4D Tensor. Must be one of the following types: float16, float32. +* @li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. */ REG_OP(BasicLSTMCell) .INPUT(x, TensorType({DT_FLOAT16})) @@ -72,18 +72,18 @@ REG_OP(BasicLSTMCell) .OP_END_FACTORY_REG(BasicLSTMCell) /** -*@brief: Dynamic LSTM forward calculation . \n +* @brief: Dynamic LSTM forward calculation . \n -*@par Inputs: -*@li x:A 4D Tensor. Must be the type float32. -*@li w:A 4D Tensor. Must be the type float32. -*@li b:A 1D Tensor. Must be the type float32. The format must be ND . \n +* @par Inputs: +* @li x:A 4D Tensor. Must be the type float32. +* @li w:A 4D Tensor. Must be the type float32. +* @li b:A 1D Tensor. Must be the type float32. The format must be ND . \n -*@par Outputs: -*output_h:A Tensor of output. Must be the type float32. +* @par Outputs: +* output_h:A Tensor of output. Must be the type float32. -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(DynamicLSTM) .INPUT(x, TensorType({DT_FLOAT32})) @@ -93,52 +93,53 @@ REG_OP(DynamicLSTM) .OP_END_FACTORY_REG(DynamicLSTM) /** -*@brief: DynamicRNNGrad calculation. -*@par Inputs: -*ten inputs: \n -*@li x:A 4D Tensor. Must be one of the following types: float16, float32. -*@li w:A 4D Tensor. Must be one of the following types: float16, float32. -*@li b:A 1D Tensor. Must be one of the following types: float16, float32. -*@li y:A 1D Tensor. Must be one of the following types: int32. -*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li init_c:A 4D Tensor. Must be one of the following types: float16, float32. -*@li h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li c:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dc:A 4D Tensor. Must be one of the following types: float16, float32. -*@li i:A 4D Tensor. Must be one of the following types: float16, float32. -*@li j:A 4D Tensor. Must be one of the following types: float16, float32. -*@li f:A 4D Tensor. Must be one of the following types: float16, float32. -*@li o:A 4D Tensor. Must be one of the following types: float16, float32. -*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. -*@li seq_length:A 1D Tensor. Must be one of the following types: int32. -*@li mask:A 1D Tensor. Must be one of the following types: int8. -*@li wci:A 4D Tensor. Must be one of the following types: float16, float32. -*@li wcf:A 4D Tensor. Must be one of the following types: float16, float32. -*@li wco:A 4D Tensor. Must be one of the following types: float16, float32. - -*@par Attributes: -*@li cell_type:An string identifying the cell type in the op. Default to "LSTM". Only LSTM is currently supported. -*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. -*@li cell_depth:An integer identifying the cell depth in the op. Default to 1. -*@li use_peephole:An bool identifying if use peephole in the op. Default to false. -*@li keep_prob:An float identifying the keep prob in the op. Default to 1. -*@li cell_clip:An float identifying the cell clip in the op. Default to -1. -*@li num_proj:An integer identifying the num projection in the op. Default to 0. -*@li time_major:An bool identifying the time major in the op. Default to false. -*@li forget_bias:An float identifying the forget bias in the op. Default to 0. +* @brief: DynamicRNNGrad calculation. +* @par Inputs: +* ten inputs: \n +* @li x:A 4D Tensor. Must be one of the following types: float16, float32. +* @li w:A 4D Tensor. Must be one of the following types: float16, float32. +* @li b:A 1D Tensor. Must be one of the following types: float16, float32. +* @li y:A 1D Tensor. Must be one of the following types: int32. +* @li init_h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li init_c:A 4D Tensor. Must be one of the following types: float16, float32. +* @li h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li c:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dy:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dh:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dc:A 4D Tensor. Must be one of the following types: float16, float32. +* @li i:A 4D Tensor. Must be one of the following types: float16, float32. +* @li j:A 4D Tensor. Must be one of the following types: float16, float32. +* @li f:A 4D Tensor. Must be one of the following types: float16, float32. +* @li o:A 4D Tensor. Must be one of the following types: float16, float32. +* @li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. +* @li seq_length:A 1D Tensor. Must be one of the following types: int32. +* @li mask:A 1D Tensor. Must be one of the following types: int8. +* @li wci:A 4D Tensor. Must be one of the following types: float16, float32. +* @li wcf:A 4D Tensor. Must be one of the following types: float16, float32. +* @li wco:A 4D Tensor. Must be one of the following types: float16, float32. -*@par Outputs: -*eight outputs: \n -*@li dw:A 4D Tensor. Must be one of the following types: float16, float32. -*@li db:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dx:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dc_prev:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dwci:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dwcf:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dwco:A 4D Tensor. Must be one of the following types: float16, float32. +* @par Attributes: +* @li cell_type:An string identifying the cell type in the op. Default to "LSTM". Only LSTM is currently supported. +* @li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. +* @li cell_depth:An integer identifying the cell depth in the op. Default to 1. +* @li use_peephole:An bool identifying if use peephole in the op. Default to false. +* @li keep_prob:An float identifying the keep prob in the op. Default to 1. +* @li cell_clip:An float identifying the cell clip in the op. Default to -1. +* @li num_proj:An integer identifying the num projection in the op. Default to 0. +* @li time_major:An bool identifying the time major in the op. Default to false. +* @li forget_bias:An float identifying the forget bias in the op. Default to 0. +* @li gate_order:An string identifying the type of gate order in the op. Support "ijfo" and "ifjo". Default to "ijfo". + +* @par Outputs: +* eight outputs: \n +* @li dw:A 4D Tensor. Must be one of the following types: float16, float32. +* @li db:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dx:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dc_prev:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dwci:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dwcf:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dwco:A 4D Tensor. Must be one of the following types: float16, float32. */ REG_OP(DynamicRNNGrad) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -179,48 +180,49 @@ REG_OP(DynamicRNNGrad) .ATTR(num_proj, Int, 0) .ATTR(time_major, Bool, true) .ATTR(forget_bias, Float, 0.0) + .ATTR(gate_order, String, "ijfo") .OP_END_FACTORY_REG(DynamicRNNGrad) /** -*@brief: DynamicRNN calculation. -*@par Inputs: -*ten inputs: -*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. -*@li w:A required 4D Tensor. Must be one of the following types: float16, float32. -*@li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. -*@li seq_length:A optional Tensor. Only Support int32 in ND. -*@li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. -*@li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. -*@li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. -*@li wcf:A 4D optional Tensor. Must be one of the following types: float16, float32. -*@li wco:A 4D optional Tensor. Must be one of the following types: float16, float32. -*@li mask:A 1D optional Tensor. Must be one of the following types: uint8. The format must be ND . \n - -*@par Attributes: -*@li cell_type:An string identifying the cell type in the op. Default to "LSTM". Only LSTM is currently supported. -*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. -*@li cell_depth:An integer identifying the cell depth in the op. Default to 1. -*@li use_peephole:An bool identifying if use peephole in the op. Default to false. -*@li keep_prob:An float identifying the keep prob in the op. Default to 1. -*@li cell_clip:An float identifying the cell clip in the op. Default to -1. -*@li num_proj:An integer identifying the num projection in the op. Default to 0. -*@li time_major:An bool identifying the time major in the op. Default to true. -*@li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported. -*@li forget_bias:An float identifying the forget bias in the op. Default to 0. -*@li gate_order:An string identifying the type of gate order in the op. Support "ijfo" and "ifjo". Default to "ijfo". -*@li is_training:An bool identifying is training in the op. Default to true . \n +* @brief: DynamicRNN calculation. +* @par Inputs: +* ten inputs: +* @li x:A required 4D Tensor. Must be one of the following types: float16, float32. +* @li w:A required 4D Tensor. Must be one of the following types: float16, float32. +* @li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. +* @li seq_length:A optional Tensor. Only Support int32 in ND. +* @li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. +* @li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. +* @li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. +* @li wcf:A 4D optional Tensor. Must be one of the following types: float16, float32. +* @li wco:A 4D optional Tensor. Must be one of the following types: float16, float32. +* @li mask:A 1D optional Tensor. Must be one of the following types: uint8. The format must be ND . \n -*@par Outputs: -*eight outputs: -*@li y:A 4D Tensor. Must be one of the following types: float16, float32. -*@li output_h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li output_c:A 4D Tensor. Must be one of the following types: float16, float32. -*@li i:A 4D Tensor. Must be one of the following types: float16, float32. -*@li j:A 4D Tensor. Must be one of the following types: float16, float32. -*@li f:A 4D Tensor. Must be one of the following types: float16, float32. -*@li o:A 4D Tensor. Must be one of the following types: float16, float32. -*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. -*@par Third-party framework compatibility: +* @par Attributes: +* @li cell_type:An string identifying the cell type in the op. Default to "LSTM". Only LSTM is currently supported. +* @li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. +* @li cell_depth:An integer identifying the cell depth in the op. Default to 1. +* @li use_peephole:An bool identifying if use peephole in the op. Default to false. +* @li keep_prob:An float identifying the keep prob in the op. Default to 1. +* @li cell_clip:An float identifying the cell clip in the op. Default to -1. +* @li num_proj:An integer identifying the num projection in the op. Default to 0. +* @li time_major:An bool identifying the time major in the op. Default to true. +* @li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported. +* @li forget_bias:An float identifying the forget bias in the op. Default to 0. +* @li gate_order:An string identifying the type of gate order in the op. Support "ijfo" and "ifjo". Default to "ijfo". +* @li is_training:An bool identifying is training in the op. Default to true . \n + +* @par Outputs: +* eight outputs: +* @li y:A 4D Tensor. Must be one of the following types: float16, float32. +* @li output_h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li output_c:A 4D Tensor. Must be one of the following types: float16, float32. +* @li i:A 4D Tensor. Must be one of the following types: float16, float32. +* @li j:A 4D Tensor. Must be one of the following types: float16, float32. +* @li f:A 4D Tensor. Must be one of the following types: float16, float32. +* @li o:A 4D Tensor. Must be one of the following types: float16, float32. +* @li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. +* @par Third-party framework compatibility: * Compatible with the TF operator LSTM. */ REG_OP(DynamicRNN) @@ -257,56 +259,56 @@ REG_OP(DynamicRNN) .OP_END_FACTORY_REG(DynamicRNN) /** -*@brief: DynamicRNNV2 calculation. -*@par Inputs: -*ten inputs: -*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. -*@li weight_input:A required 4D Tensor. Must be one of the following types: float16, float32. -*@li weight_hidden:A required 4D Tensor. Must be one of the following types: float16, float32. -*@li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. -*@li seq_length:A optional 1D Tensor. Must be one of the following types: float16, int32. -*@li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. -*@li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. -*@li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. -*@li wcf:A 4D optional Tensor. Must be one of the following types: float16, float32. -*@li wco:A 4D optional Tensor. Must be one of the following types: float16, float32. -*@li mask:A 1D optional Tensor. Must be one of the following types: uint8. The format must be ND . \n - -*@par Attributes: -*@li cell_type:An string identifying the cell type in the op. Default to "LSTM". Only LSTM is currently supported. -*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". -*Only UNIDIRECTIONAL is currently supported. -*@li cell_depth:An integer identifying the cell depth in the op. Default to 1. -*@li use_peephole:An bool identifying if use peephole in the op. Default to false. -*@li keep_prob:An float identifying the keep prob in the op. Default to 1. -*@li cell_clip:An float identifying the cell clip in the op. Default to -1. -*@li num_proj:An integer identifying the num projection in the op. Default to 0. -*@li time_major:An bool identifying the time major in the op. Default to true. -*@li activation:An string identifying the type of activation function in the op. Default to "tanh". -*Support "tanh" and "clip". -*@li recurrent_activation:An string identifying the type of activation function in the op. Default to "sigmoid". -*Support "sigmoid" and "hard_sigmoid". In general, set "hard_sigmoid" for TF Keras LSTM. -*@li forget_bias:An float identifying the forget bias in the op. Default to 0. -*@li gate_order:An string identifying the type of gate order in the op. Support "ijfo" and "ifco". Default to "ijfo". -*Set "ijfo" for TF operator LSTM, Set "ifco" for TF Keras LSTM. -*@li stateful: An bool identifying the type of stateful in the op. Default to fasle.Only false is currently supported. -*@li merge_mode: An string identifying the type of merge_modein the op. Default to "concat". -*Only "concat" is currently supported -*@li is_training:An bool identifying is training in the op. Default to true . \n +* @brief: DynamicRNNV2 calculation. +* @par Inputs: +* ten inputs: +* @li x:A required 4D Tensor. Must be one of the following types: float16, float32. +* @li weight_input:A required 4D Tensor. Must be one of the following types: float16, float32. +* @li weight_hidden:A required 4D Tensor. Must be one of the following types: float16, float32. +* @li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. +* @li seq_length:A optional 1D Tensor. Must be one of the following types: float16, int32. +* @li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. +* @li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. +* @li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. +* @li wcf:A 4D optional Tensor. Must be one of the following types: float16, float32. +* @li wco:A 4D optional Tensor. Must be one of the following types: float16, float32. +* @li mask:A 1D optional Tensor. Must be one of the following types: uint8. The format must be ND . \n -*@par Outputs: -*eight outputs: -*@li y:A 4D Tensor. Must be one of the following types: float16, float32. -*@li output_h:A 4D Tensor. Must be one of the following types: float16, float32. -*Return the last output_h. -*@li output_c:A 4D Tensor. Must be one of the following types: float16, float32. -*Return the last output_c. -*@li i:A 4D Tensor. Must be one of the following types: float16, float32. -*@li j:A 4D Tensor. Must be one of the following types: float16, float32. -*@li f:A 4D Tensor. Must be one of the following types: float16, float32. -*@li o:A 4D Tensor. Must be one of the following types: float16, float32. -*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. -*@par Third-party framework compatibility: +* @par Attributes: +* @li cell_type:An string identifying the cell type in the op. Default to "LSTM". Only LSTM is currently supported. +* @li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". +* Only UNIDIRECTIONAL is currently supported. +* @li cell_depth:An integer identifying the cell depth in the op. Default to 1. +* @li use_peephole:An bool identifying if use peephole in the op. Default to false. +* @li keep_prob:An float identifying the keep prob in the op. Default to 1. +* @li cell_clip:An float identifying the cell clip in the op. Default to -1. +* @li num_proj:An integer identifying the num projection in the op. Default to 0. +* @li time_major:An bool identifying the time major in the op. Default to true. +* @li activation:An string identifying the type of activation function in the op. Default to "tanh". +* Support "tanh" and "clip". +* @li recurrent_activation:An string identifying the type of activation function in the op. Default to "sigmoid". +* Support "sigmoid" and "hard_sigmoid". In general, set "hard_sigmoid" for TF Keras LSTM. +* @li forget_bias:An float identifying the forget bias in the op. Default to 0. +* @li gate_order:An string identifying the type of gate order in the op. Support "ijfo" and "ifco". Default to "ijfo". +* Set "ijfo" for TF operator LSTM, Set "ifco" for TF Keras LSTM. +* @li stateful: An bool identifying the type of stateful in the op. Default to fasle.Only false is currently supported. +* @li merge_mode: An string identifying the type of merge_modein the op. Default to "concat". +* Only "concat" is currently supported +* @li is_training:An bool identifying is training in the op. Default to true . \n + +* @par Outputs: +* eight outputs: +* @li y:A 4D Tensor. Must be one of the following types: float16, float32. +* @li output_h:A 4D Tensor. Must be one of the following types: float16, float32. +* Return the last output_h. +* @li output_c:A 4D Tensor. Must be one of the following types: float16, float32. +* Return the last output_c. +* @li i:A 4D Tensor. Must be one of the following types: float16, float32. +* @li j:A 4D Tensor. Must be one of the following types: float16, float32. +* @li f:A 4D Tensor. Must be one of the following types: float16, float32. +* @li o:A 4D Tensor. Must be one of the following types: float16, float32. +* @li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. +* @par Third-party framework compatibility: * Compatible with the TF operator LSTM or TF keras operator LSTM. */ @@ -459,46 +461,46 @@ REG_OP(DynamicRNNV2Grad) .OP_END_FACTORY_REG(DynamicRNNV2Grad) /** -*@brief: DynamicRNNV3 calculation. -*@par Inputs: -*ten inputs: -*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. -*@li w:A required 4D Tensor. Must be one of the following types: float16, float32. -*@li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. -*@li seq_length:A optional 1D Tensor. Must be one of the following types: int32. The format must be ND. -*@li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. -*@li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. -*@li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. -*@li wcf:A 4D optional Tensor. Must be one of the following types: float16, float32. -*@li wco:A 4D optional Tensor. Must be one of the following types: float16, float32. -*@li mask:A 1D optional Tensor. Must be one of the following types: uint8. The format must be ND . \n -*@li real_mask:A 4D optional Tensor. Must be one of the following types: float16, float32. -*@li project:A 4D optional Tensor. Must be one of the following types: float16, float32. - -*@par Attributes: -*@li cell_type:An string identifying the cell type in the op. Default to "LSTM". Only LSTM is currently supported. -*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. -*@li cell_depth:An integer identifying the cell depth in the op. Default to 1. -*@li use_peephole:An bool identifying if use peephole in the op. Default to false. -*@li keep_prob:An float identifying the keep prob in the op. Default to 1. -*@li cell_clip:An float identifying the cell clip in the op. Default to -1. -*@li num_proj:An integer identifying the num projection in the op. Default to 0. -*@li time_major:An bool identifying the time major in the op. Default to true. -*@li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported. -*@li forget_bias:An float identifying the forget bias in the op. Default to 0. -*@li is_training:An bool identifying is training in the op. Default to true . \n +* @brief: DynamicRNNV3 calculation. +* @par Inputs: +* ten inputs: +* @li x:A required 4D Tensor. Must be one of the following types: float16, float32. +* @li w:A required 4D Tensor. Must be one of the following types: float16, float32. +* @li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. +* @li seq_length:A optional 1D Tensor. Must be one of the following types: int32. The format must be ND. +* @li init_h:A optional 4D Tensor. Must be one of the following types: float16, float32. +* @li init_c:A optional 4D Tensor. Must be one of the following types: float16, float32. +* @li wci:A 4D optional Tensor. Must be one of the following types: float16, float32. +* @li wcf:A 4D optional Tensor. Must be one of the following types: float16, float32. +* @li wco:A 4D optional Tensor. Must be one of the following types: float16, float32. +* @li mask:A 1D optional Tensor. Must be one of the following types: uint8. The format must be ND . \n +* @li real_mask:A 4D optional Tensor. Must be one of the following types: float16, float32. +* @li project:A 4D optional Tensor. Must be one of the following types: float16, float32. -*@par Outputs: -*eight outputs: -*@li y:A 4D Tensor. Must be one of the following types: float16, float32. -*@li output_h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li output_c:A 4D Tensor. Must be one of the following types: float16, float32. -*@li i:A 4D Tensor. Must be one of the following types: float16, float32. -*@li j:A 4D Tensor. Must be one of the following types: float16, float32. -*@li f:A 4D Tensor. Must be one of the following types: float16, float32. -*@li o:A 4D Tensor. Must be one of the following types: float16, float32. -*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. -*@par Third-party framework compatibility: +* @par Attributes: +* @li cell_type:An string identifying the cell type in the op. Default to "LSTM". Only LSTM is currently supported. +* @li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. +* @li cell_depth:An integer identifying the cell depth in the op. Default to 1. +* @li use_peephole:An bool identifying if use peephole in the op. Default to false. +* @li keep_prob:An float identifying the keep prob in the op. Default to 1. +* @li cell_clip:An float identifying the cell clip in the op. Default to -1. +* @li num_proj:An integer identifying the num projection in the op. Default to 0. +* @li time_major:An bool identifying the time major in the op. Default to true. +* @li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported. +* @li forget_bias:An float identifying the forget bias in the op. Default to 0. +* @li is_training:An bool identifying is training in the op. Default to true . \n + +* @par Outputs: +* eight outputs: +* @li y:A 4D Tensor. Must be one of the following types: float16, float32. +* @li output_h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li output_c:A 4D Tensor. Must be one of the following types: float16, float32. +* @li i:A 4D Tensor. Must be one of the following types: float16, float32. +* @li j:A 4D Tensor. Must be one of the following types: float16, float32. +* @li f:A 4D Tensor. Must be one of the following types: float16, float32. +* @li o:A 4D Tensor. Must be one of the following types: float16, float32. +* @li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. +* @par Third-party framework compatibility: * Compatible with the TF operator LSTM. */ REG_OP(DynamicRNNV3) @@ -536,37 +538,37 @@ REG_OP(DynamicRNNV3) .OP_END_FACTORY_REG(DynamicRNNV3) /** -*@brief: DynamicLSTMV2 calculation. -*@par Inputs: -*ten inputs: -*@li x:A required 4D Tensor. Must be one of the following types: float16, float32. -*@li w:A required 4D Tensor. Must be one of the following types: float16, float32. -*@li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. -*@li cont:A required 2D Tensor. Must be one of the following types: float16, float32. The format must be ND. -*@li w_xc_x_static:A optional 2D Tensor. Must be one of the following types: float16, float32. The format must be ND. -*@li h0:A optional 4D Tensor. Must be one of the following types: float16, float32. -*@li c0:A optional 4D Tensor. Must be one of the following types: float16, float32. -*@li wci:A optional 4D Tensor. Must be one of the following types: float16, float32. -*@li wcf:A optional 4D Tensor. Must be one of the following types: float16, float32. -*@li wco:A optional 4D Tensor. Must be one of the following types: float16, float32. -*@li mask:A optional 1D Tensor. Must be one of the following types: uint8. The format must be ND . - -*@par Attributes: -*@li num_output:An integer identifying the num projection in the op. Default to 0. -*@li expose_hidden:An bool identifying the expose_hidden in the op. Default to flase. -*@li need_output_last:An bool identifying the time major in the op. Default to true. -*@li forget_bias:An float identifying the forget bias in the op. Default to 0. +* @brief: DynamicLSTMV2 calculation. +* @par Inputs: +* ten inputs: +* @li x:A required 4D Tensor. Must be one of the following types: float16, float32. +* @li w:A required 4D Tensor. Must be one of the following types: float16, float32. +* @li b:A required 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. +* @li cont:A required 2D Tensor. Must be one of the following types: float16, float32. The format must be ND. +* @li w_xc_x_static:A optional 2D Tensor. Must be one of the following types: float16, float32. The format must be ND. +* @li h0:A optional 4D Tensor. Must be one of the following types: float16, float32. +* @li c0:A optional 4D Tensor. Must be one of the following types: float16, float32. +* @li wci:A optional 4D Tensor. Must be one of the following types: float16, float32. +* @li wcf:A optional 4D Tensor. Must be one of the following types: float16, float32. +* @li wco:A optional 4D Tensor. Must be one of the following types: float16, float32. +* @li mask:A optional 1D Tensor. Must be one of the following types: uint8. The format must be ND . -*@par Outputs: -*eight outputs: -*@li y:A 4D Tensor. Must be one of the following types: float16, float32. -*@li output_h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li output_c:A 4D Tensor. Must be one of the following types: float16, float32. -*@li last_output_h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li last_output_c:A 4D Tensor. Must be one of the following types: float16, float32. -*@par Third-party framework compatibility: +* @par Attributes: +* @li num_output:An integer identifying the num projection in the op. Default to 0. +* @li expose_hidden:An bool identifying the expose_hidden in the op. Default to flase. +* @li need_output_last:An bool identifying the time major in the op. Default to true. +* @li forget_bias:An float identifying the forget bias in the op. Default to 0. + +* @par Outputs: +* eight outputs: +* @li y:A 4D Tensor. Must be one of the following types: float16, float32. +* @li output_h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li output_c:A 4D Tensor. Must be one of the following types: float16, float32. +* @li last_output_h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li last_output_c:A 4D Tensor. Must be one of the following types: float16, float32. +* @par Third-party framework compatibility: * Compatible with the Caffe operator LSTM. -*@par Restrictions: +* @par Restrictions: * Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(DynamicLSTMV2) @@ -593,28 +595,28 @@ REG_OP(DynamicLSTMV2) .OP_END_FACTORY_REG(DynamicLSTMV2) /** -*@brief: LSTMInputGrad calculation. -*@par Inputs: -*ten inputs: \n -*@li w:A 4D Tensor. Must be one of the following types: float16, float32. -*@li init_c:A 4D Tensor. Must be one of the following types: float16, float32. -*@li c:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dc:A 4D Tensor. Must be one of the following types: float16, float32. -*@li i:A 4D Tensor. Must be one of the following types: float16, float32. -*@li j:A 4D Tensor. Must be one of the following types: float16, float32. -*@li f:A 4D Tensor. Must be one of the following types: float16, float32. -*@li o:A 4D Tensor. Must be one of the following types: float16, float32. -*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. +* @brief: LSTMInputGrad calculation. +* @par Inputs: +* ten inputs: \n +* @li w:A 4D Tensor. Must be one of the following types: float16, float32. +* @li init_c:A 4D Tensor. Must be one of the following types: float16, float32. +* @li c:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dy:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dh:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dc:A 4D Tensor. Must be one of the following types: float16, float32. +* @li i:A 4D Tensor. Must be one of the following types: float16, float32. +* @li j:A 4D Tensor. Must be one of the following types: float16, float32. +* @li f:A 4D Tensor. Must be one of the following types: float16, float32. +* @li o:A 4D Tensor. Must be one of the following types: float16, float32. +* @li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. -*@par Outputs: -*four outputs: \n -*@li dx:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dc_prev:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dgate:A 4D Tensor. Must be one of the following types: float16. +* @par Outputs: +* four outputs: \n +* @li dx:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dc_prev:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dgate:A 4D Tensor. Must be one of the following types: float16. */ REG_OP(LSTMInputGrad) .INPUT(w, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -637,35 +639,35 @@ REG_OP(LSTMInputGrad) /** -*@brief: Dynamic LSTM Cell grad calculation.Calculate the gradient of gates and cell state. -*@par Inputs: -*twelve inputs: -*@li init_c:A 4D Tensor. Must be one of the following types: float16, float32. -*@li c:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dc:A 4D Tensor. Must be one of the following types: float16, float32. -*@li i:A 4D Tensor. Must be one of the following types: float16, float32. -*@li j:A 4D Tensor. Must be one of the following types: float16, float32. -*@li f:A 4D Tensor. Must be one of the following types: float16, float32. -*@li o:A 4D Tensor. Must be one of the following types: float16, float32. -*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. -*@li mask:A 4D Tensor. Must be one of the following types: float16, float32. -*@li t_state:A 4D Tensor. Must be one of the following types: float16, float32. . \n - -*@par Attributes: -*@li forget_bias:An integer identifying the forget bias in the op. Default to 1. -*@li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported . \n -*@li direction:An string that marks the calculation sequence of the operator. Default to "Forward". -*@li gate_order:An string mark the order of output 4 gate. Default to "ijfo". +* @brief: Dynamic LSTM Cell grad calculation.Calculate the gradient of gates and cell state. +* @par Inputs: +* twelve inputs: +* @li init_c:A 4D Tensor. Must be one of the following types: float16, float32. +* @li c:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dy:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dh:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dc:A 4D Tensor. Must be one of the following types: float16, float32. +* @li i:A 4D Tensor. Must be one of the following types: float16, float32. +* @li j:A 4D Tensor. Must be one of the following types: float16, float32. +* @li f:A 4D Tensor. Must be one of the following types: float16, float32. +* @li o:A 4D Tensor. Must be one of the following types: float16, float32. +* @li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. +* @li mask:A 4D Tensor. Must be one of the following types: float16, float32. +* @li t_state:A 4D Tensor. Must be one of the following types: float16, float32. . \n -*@par Outputs: -*two outputs: -*@li dgate:A 4D Tensor. Must be one of the following types: float16. -*@li dct_1:A 4D Tensor. Must be one of the following types: float16, float32. +* @par Attributes: +* @li forget_bias:An integer identifying the forget bias in the op. Default to 1. +* @li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported . \n +* @li direction:An string that marks the calculation sequence of the operator. Default to "Forward". +* @li gate_order:An string mark the order of output 4 gate. Default to "ijfo". -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* @par Outputs: +* two outputs: +* @li dgate:A 4D Tensor. Must be one of the following types: float16. +* @li dct_1:A 4D Tensor. Must be one of the following types: float16, float32. + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(DynamicLSTMGradCell) .INPUT(init_c, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -690,23 +692,23 @@ REG_OP(DynamicLSTMGradCell) /** -*@brief: Basic LSTM Cell backward calculation.Calculate the gradient of input and hidden state. -*@par Inputs: -*three inputs: -*@li dgate:A 4D Tensor. Must be one of the following types: float16. -*@li w:A 4D Tensor. Must be one of the following types: float16. -*@li dropout_mask:A 1D Tensor. Must be one of the following types: uint8. The format must be ND . \n +* @brief: Basic LSTM Cell backward calculation.Calculate the gradient of input and hidden state. +* @par Inputs: +* three inputs: +* @li dgate:A 4D Tensor. Must be one of the following types: float16. +* @li w:A 4D Tensor. Must be one of the following types: float16. +* @li dropout_mask:A 1D Tensor. Must be one of the following types: uint8. The format must be ND . \n -*@par Attributes: -*keep_prob:An integer identifying the keep prob in the op. Default to 1 . \n +* @par Attributes: +* keep_prob:An integer identifying the keep prob in the op. Default to 1 . \n -*@par Outputs: -*two outputs: -*@li dxt:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dht:A 4D Tensor. Must be one of the following types: float16, float32. +* @par Outputs: +* two outputs: +* @li dxt:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dht:A 4D Tensor. Must be one of the following types: float16, float32. -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(BasicLSTMCellInputGrad) .INPUT(dgate, TensorType({DT_FLOAT16})) @@ -718,20 +720,20 @@ REG_OP(BasicLSTMCellInputGrad) .OP_END_FACTORY_REG(BasicLSTMCellInputGrad) /** -*@brief: Basic LSTM Cell backward calculation.Calculate the gradient of weight and bias. -*@par Inputs: -*three inputs: -*@li x:A 4D Tensor. Must be one of the following types: float16. -*@li h:A 4D Tensor. Must be one of the following types: float16. -*@li dgate:A 4D Tensor. Must be one of the following types: uint8. \n +* @brief: Basic LSTM Cell backward calculation.Calculate the gradient of weight and bias. +* @par Inputs: +* three inputs: +* @li x:A 4D Tensor. Must be one of the following types: float16. +* @li h:A 4D Tensor. Must be one of the following types: float16. +* @li dgate:A 4D Tensor. Must be one of the following types: uint8. \n -*@par Outputs: -*two outputs: -*@li dw:A 4D Tensor. Must be one of the following types: float16. -*@li db:A 4D Tensor. Must be one of the following types: float16, float32. +* @par Outputs: +* two outputs: +* @li dw:A 4D Tensor. Must be one of the following types: float16. +* @li db:A 4D Tensor. Must be one of the following types: float16, float32. -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(BasicLSTMCellWeightGrad) .INPUT(x, TensorType({DT_FLOAT16})) @@ -742,29 +744,29 @@ REG_OP(BasicLSTMCellWeightGrad) .OP_END_FACTORY_REG(BasicLSTMCellWeightGrad) /** -*@brief: Basic LSTM Cell backward calculation.Calculate the gradient of gates and cell state. -*@par Inputs: -*eight inputs: -*@li c:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dht:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dct:A 4D Tensor. Must be one of the following types: float16, float32. -*@li it:A 4D Tensor. Must be one of the following types: float16, float32. -*@li jt:A 4D Tensor. Must be one of the following types: float16, float32. -*@li ft:A 4D Tensor. Must be one of the following types: float16, float32. -*@li ot:A 4D Tensor. Must be one of the following types: float16, float32. -*@li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. \n - -*@par Attributes: -*@li forget_bias:An integer identifying the forget bias in the op. Default to 1. -*@li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported . \n +* @brief: Basic LSTM Cell backward calculation.Calculate the gradient of gates and cell state. +* @par Inputs: +* eight inputs: +* @li c:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dht:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dct:A 4D Tensor. Must be one of the following types: float16, float32. +* @li it:A 4D Tensor. Must be one of the following types: float16, float32. +* @li jt:A 4D Tensor. Must be one of the following types: float16, float32. +* @li ft:A 4D Tensor. Must be one of the following types: float16, float32. +* @li ot:A 4D Tensor. Must be one of the following types: float16, float32. +* @li tanhct:A 4D Tensor. Must be one of the following types: float16, float32. \n -*@par Outputs: -*two outputs: -*@li dgate:A 4D Tensor. Must be one of the following types: float16. -*@li dct_1:A 4D Tensor. Must be one of the following types: float16, float32. +* @par Attributes: +* @li forget_bias:An integer identifying the forget bias in the op. Default to 1. +* @li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported . \n + +* @par Outputs: +* two outputs: +* @li dgate:A 4D Tensor. Must be one of the following types: float16. +* @li dct_1:A 4D Tensor. Must be one of the following types: float16, float32. -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(BasicLSTMCellCStateGrad) .INPUT(c, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -782,30 +784,30 @@ REG_OP(BasicLSTMCellCStateGrad) .OP_END_FACTORY_REG(BasicLSTMCellCStateGrad) /** -*@brief: RNN operator. -*@par Inputs: -*eight inputs: -*@li x:A 4D Tensor. Must be one of the following types: float16. -*@li cont:A 1D Tensor. Must be one of the following types: float16. The format must be ND. -*@li x_static:A 4D Tensor. Must be one of the following types: float16. -*@li h_0:A 4D Tensor. Must be one of the following types: float16, float32. -*@li w_xh:A 4D Tensor. Must be one of the following types: float16. -*@li w_sh:A 4D Tensor. Must be one of the following types: float16. -*@li w_hh:A 4D Tensor. Must be one of the following types: float16. -*@li w_ho:A 4D Tensor. Must be one of the following types: float16. -*@li bias_h:A 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. -*@li bias_o:A 1D Tensor. Must be one of the following types: float16, float32. The format must be ND . \n - -*@par Attributes: -*@li expose_hidden:An bool identifying if expose the hidden state of last time step. Default to false. -*@li num_output:An integer identifying the number of output features. Default to 0 . \n +* @brief: RNN operator. +* @par Inputs: +* eight inputs: +* @li x:A 4D Tensor. Must be one of the following types: float16. +* @li cont:A 1D Tensor. Must be one of the following types: float16. The format must be ND. +* @li x_static:A 4D Tensor. Must be one of the following types: float16. +* @li h_0:A 4D Tensor. Must be one of the following types: float16, float32. +* @li w_xh:A 4D Tensor. Must be one of the following types: float16. +* @li w_sh:A 4D Tensor. Must be one of the following types: float16. +* @li w_hh:A 4D Tensor. Must be one of the following types: float16. +* @li w_ho:A 4D Tensor. Must be one of the following types: float16. +* @li bias_h:A 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. +* @li bias_o:A 1D Tensor. Must be one of the following types: float16, float32. The format must be ND . \n -*@par Outputs: -*two outputs: -*@li o:A 4D Tensor. Must be one of the following types: float16, float32. -*@li h_t:A 4D Tensor. Must be one of the following types: float16, float32. -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* @par Attributes: +* @li expose_hidden:An bool identifying if expose the hidden state of last time step. Default to false. +* @li num_output:An integer identifying the number of output features. Default to 0 . \n + +* @par Outputs: +* two outputs: +* @li o:A 4D Tensor. Must be one of the following types: float16, float32. +* @li h_t:A 4D Tensor. Must be one of the following types: float16, float32. +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(RNN) .INPUT(x, TensorType({DT_FLOAT16})) @@ -825,30 +827,30 @@ REG_OP(RNN) .OP_END_FACTORY_REG(RNN) /** -*@brief: BasicRNNCell operator. -*@par Inputs: -*eight inputs: -*@li x:A 4D Tensor. Must be one of the following types: float16. -*@li cont:A 1D Tensor. Must be one of the following types: float16. The format must be ND. -*@li w_xh_x_static:A 4D Tensor. Must be one of the following types: float16. -*@li h_0:A 4D Tensor. Must be one of the following types: float16, float32. -*@li w_xh:A 4D Tensor. Must be one of the following types: float16. -*@li w_hh:A 4D Tensor. Must be one of the following types: float16. -*@li w_ho:A 4D Tensor. Must be one of the following types: float16. -*@li bias_h:A 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. -*@li bias_o:A 1D Tensor. Must be one of the following types: float16, float32. The format must be ND . \n - -*@par Attributes: -*@li expose_hidden:An bool identifying if expose the hidden state of last time step. Default to false. -*@li num_output:An integer identifying the number of output features. Default to 0 . \n +* @brief: BasicRNNCell operator. +* @par Inputs: +* eight inputs: +* @li x:A 4D Tensor. Must be one of the following types: float16. +* @li cont:A 1D Tensor. Must be one of the following types: float16. The format must be ND. +* @li w_xh_x_static:A 4D Tensor. Must be one of the following types: float16. +* @li h_0:A 4D Tensor. Must be one of the following types: float16, float32. +* @li w_xh:A 4D Tensor. Must be one of the following types: float16. +* @li w_hh:A 4D Tensor. Must be one of the following types: float16. +* @li w_ho:A 4D Tensor. Must be one of the following types: float16. +* @li bias_h:A 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. +* @li bias_o:A 1D Tensor. Must be one of the following types: float16, float32. The format must be ND . \n -*@par Outputs: -*two outputs: -*@li o_t:A 4D Tensor. Must be one of the following types: float16, float32. -*@li h_t:A 4D Tensor. Must be one of the following types: float16, float32. +* @par Attributes: +* @li expose_hidden:An bool identifying if expose the hidden state of last time step. Default to false. +* @li num_output:An integer identifying the number of output features. Default to 0 . \n -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* @par Outputs: +* two outputs: +* @li o_t:A 4D Tensor. Must be one of the following types: float16, float32. +* @li h_t:A 4D Tensor. Must be one of the following types: float16, float32. + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(BasicRNNCell) .INPUT(x, TensorType({DT_FLOAT16})) @@ -867,37 +869,37 @@ REG_OP(BasicRNNCell) .OP_END_FACTORY_REG(BasicRNNCell) /** -*@brief DynamicGRU calculation. -*@par Inputs: -*seven inputs: -*@li x:Must be one of the following types: float16. -*@li w:Must be one of the following types: float16. -*@li b:Must be one of the following types: float16, float32. The format must be ND. -*@li cw:Must be one of the following types: float16. -*@li cb:Must be one of the following types: float16, float32. The format must be ND. -*@li seq_length:Must be one of the following types: int32. The format must be ND. -*@li init_h:Must be one of the following types: float16, float32. - -*@par Attributes: -*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. -*@li cell_depth:An integer identifying the cell depth in the op. Default to 1. -*@li keep_prob:An float identifying the keep prob in the op. Default to 1. -*@li cell_clip:An float identifying the cell clip in the op. Default to -1. -*@li num_proj:An integer identifying the num projection in the op. Default to 0. -*@li time_major:An bool identifying the time major in the op. Default to true. -*@li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported. -*@li is_training:An bool identifying is training in the op. Default to true. +* @brief DynamicGRU calculation. +* @par Inputs: +* seven inputs: +* @li x:Must be one of the following types: float16. +* @li w:Must be one of the following types: float16. +* @li b:Must be one of the following types: float16, float32. The format must be ND. +* @li cw:Must be one of the following types: float16. +* @li cb:Must be one of the following types: float16, float32. The format must be ND. +* @li seq_length:Must be one of the following types: int32. The format must be ND. +* @li init_h:Must be one of the following types: float16, float32. -*@par Outputs: -*five outputs: -*@li y:Must be one of the following types: float16, float32. -*@li output_h:Must be one of the following types: float16, float32. -*@li r:Must be one of the following types: float16, float32. -*@li i:Must be one of the following types: float16, float32. -*@li n:Must be one of the following types: float16, float32. - -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* @par Attributes: +* @li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. +* @li cell_depth:An integer identifying the cell depth in the op. Default to 1. +* @li keep_prob:An float identifying the keep prob in the op. Default to 1. +* @li cell_clip:An float identifying the cell clip in the op. Default to -1. +* @li num_proj:An integer identifying the num projection in the op. Default to 0. +* @li time_major:An bool identifying the time major in the op. Default to true. +* @li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported. +* @li is_training:An bool identifying is training in the op. Default to true. + +* @par Outputs: +* five outputs: +* @li y:Must be one of the following types: float16, float32. +* @li output_h:Must be one of the following types: float16, float32. +* @li r:Must be one of the following types: float16, float32. +* @li i:Must be one of the following types: float16, float32. +* @li n:Must be one of the following types: float16, float32. + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(DynamicGRU) .INPUT(x, TensorType({DT_FLOAT16})) @@ -923,37 +925,37 @@ REG_OP(DynamicGRU) .OP_END_FACTORY_REG(DynamicGRU) /** -*@brief DynamicGRUV2 calculation. -*@par Inputs: -*seven inputs: -*@li x:Must be one of the following types: float16. -*@li weight_input:Must be one of the following types: float16. -*@li weight_hidden:Must be one of the following types: float16. -*@li bias_input:Must be one of the following types: float16, float32. The format must be ND. -*@li bias_hidden:Must be one of the following types: float16, float32. The format must be ND. -*@li seq_length:Must be one of the following types: int32 in ND. -*@li init_h:Must be one of the following types: float16, float32. - -*@par Attributes: -*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Support "UNIDIRECTIONAL" and "REDIRECTIONAL". -*@li cell_depth:An integer identifying the cell depth in the op. Default to 1. -*@li keep_prob:An float identifying the keep prob in the op. Default to 1. -*@li cell_clip:An float identifying the cell clip in the op. Default to -1. -*@li num_proj:An integer identifying the num projection in the op. Default to 0. -*@li time_major:An bool identifying the time major in the op. Default to true. -*@li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported. -*@li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. -*@li reset_after:An bool identifying whether to apply reset gate after matrix multiplication. Default to true. -*@li is_training:An bool identifying is training in the op. Default to true. +* @brief DynamicGRUV2 calculation. +* @par Inputs: +* seven inputs: +* @li x:Must be one of the following types: float16. +* @li weight_input:Must be one of the following types: float16. +* @li weight_hidden:Must be one of the following types: float16. +* @li bias_input:Must be one of the following types: float16, float32. The format must be ND. +* @li bias_hidden:Must be one of the following types: float16, float32. The format must be ND. +* @li seq_length:Must be one of the following types: int32 in ND. +* @li init_h:Must be one of the following types: float16, float32. -*@par Outputs: -*six outputs: -*@li y:Must be one of the following types: float16, float32. -*@li output_h:Must be one of the following types: float16, float32. -*@li update:Must be one of the following types: float16, float32. -*@li reset:Must be one of the following types: float16, float32. -*@li new:Must be one of the following types: float16, float32. -*@li hidden_new:Must be one of the following types: float16, float32. +* @par Attributes: +* @li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Support "UNIDIRECTIONAL" and "REDIRECTIONAL". +* @li cell_depth:An integer identifying the cell depth in the op. Default to 1. +* @li keep_prob:An float identifying the keep prob in the op. Default to 1. +* @li cell_clip:An float identifying the cell clip in the op. Default to -1. +* @li num_proj:An integer identifying the num projection in the op. Default to 0. +* @li time_major:An bool identifying the time major in the op. Default to true. +* @li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported. +* @li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. +* @li reset_after:An bool identifying whether to apply reset gate after matrix multiplication. Default to true. +* @li is_training:An bool identifying is training in the op. Default to true. + +* @par Outputs: +* six outputs: +* @li y:Must be one of the following types: float16, float32. +* @li output_h:Must be one of the following types: float16, float32. +* @li update:Must be one of the following types: float16, float32. +* @li reset:Must be one of the following types: float16, float32. +* @li new:Must be one of the following types: float16, float32. +* @li hidden_new:Must be one of the following types: float16, float32. */ REG_OP(DynamicGRUV2) .INPUT(x, TensorType({DT_FLOAT16})) @@ -983,39 +985,39 @@ REG_OP(DynamicGRUV2) /** -*@brief DynamicGRUV2Hidden calculation. -*@par Inputs: -*five inputs: -*@li x_weight_input:Must be one of the following types: float32. -*@li weight_hidden:Must be one of the following types: float16. -*@li bias_hidden:Must be one of the following types: float16, float32. The format must be ND. -*@li seq_length:Must be one of the following types: int32 in ND. -*@li init_h:Must be one of the following types: float16, float32. - -*@par Attributes: -*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Support "UNIDIRECTIONAL" and "REDIRECTIONAL". -*@li cell_depth:An integer identifying the cell depth in the op. Default to 1. -*@li keep_prob:An float identifying the keep prob in the op. Default to 1. -*@li cell_clip:An float identifying the cell clip in the op. Default to -1. -*@li num_proj:An integer identifying the num projection in the op. Default to 0. -*@li time_major:An bool identifying the time major in the op. Default to true. -*@li activation:An string identifying the type of activation function in the op. Default to "tanh". -Only tanh is currently supported. -*@li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. -*@li reset_after:An bool identifying whether to apply reset gate after matrix multiplication. Default to true. -*@li is_training:An bool identifying is training in the op. Default to true. +* @brief DynamicGRUV2Hidden calculation. +* @par Inputs: +* five inputs: +* @li x_weight_input:Must be one of the following types: float32. +* @li weight_hidden:Must be one of the following types: float16. +* @li bias_hidden:Must be one of the following types: float16, float32. The format must be ND. +* @li seq_length:Must be one of the following types: int32 in ND. +* @li init_h:Must be one of the following types: float16, float32. + +* @par Attributes: +* @li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Support "UNIDIRECTIONAL" and "REDIRECTIONAL". +* @li cell_depth:An integer identifying the cell depth in the op. Default to 1. +* @li keep_prob:An float identifying the keep prob in the op. Default to 1. +* @li cell_clip:An float identifying the cell clip in the op. Default to -1. +* @li num_proj:An integer identifying the num projection in the op. Default to 0. +* @li time_major:An bool identifying the time major in the op. Default to true. +* @li activation:An string identifying the type of activation function in the op. Default to "tanh". + Only tanh is currently supported. +* @li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. +* @li reset_after:An bool identifying whether to apply reset gate after matrix multiplication. Default to true. +* @li is_training:An bool identifying is training in the op. Default to true. *@par Outputs: -*six outputs: -*@li y:Must be one of the following types: float16, float32. -*@li output_h:Must be one of the following types: float16, float32. -*@li update:Must be one of the following types: float16, float32. -*@li reset:Must be one of the following types: float16, float32. -*@li new:Must be one of the following types: float16, float32. -*@li hidden_new:Must be one of the following types: float16, float32. - -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* six outputs: +* @li y:Must be one of the following types: float16, float32. +* @li output_h:Must be one of the following types: float16, float32. +* @li update:Must be one of the following types: float16, float32. +* @li reset:Must be one of the following types: float16, float32. +* @li new:Must be one of the following types: float16, float32. +* @li hidden_new:Must be one of the following types: float16, float32. + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(DynamicGRUV2Hidden) .INPUT(x_weight_input, TensorType({DT_FLOAT32})) @@ -1042,235 +1044,237 @@ REG_OP(DynamicGRUV2Hidden) .OP_END_FACTORY_REG(DynamicGRUV2Hidden) /** -*@brief DynamicAUGRU calculation. -*@par Inputs: -*eight inputs: -*@li x:Must be one of the following types: float16. -*@li weight_input:Must be one of the following types: float16. -*@li weight_hidden:Must be one of the following types: float16. -*@li weight_attr:Must be one of the following types: float16. -*@li bias_input:Must be one of the following types: float16, float32. The format must be ND. -*@li bias_hidden:Must be one of the following types: float16, float32. The format must be ND. -*@li seq_length:Must be one of the following types: int32 in ND. -*@li init_h:Must be one of the following types: float16, float32. - -*@par Attributes: -*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. -*@li cell_depth:An integer identifying the cell depth in the op. Default to 1. -*@li keep_prob:An float identifying the keep prob in the op. Default to 1. -*@li cell_clip:An float identifying the cell clip in the op. Default to -1. -*@li num_proj:An integer identifying the num projection in the op. Default to 0. -*@li time_major:An bool identifying the time major in the op. Default to true. -*@li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported. -*@li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. -*@li reset_after:An bool identifying whether to apply reset gate after matrix multiplication. Default to true. -*@li is_training:An bool identifying is training in the op. Default to true. +* @brief DynamicAUGRU calculation. +* @par Inputs: +* eight inputs: +* @li x:Must be one of the following types: float16. +* @li weight_input:Must be one of the following types: float16. +* @li weight_hidden:Must be one of the following types: float16. +* @li weight_attr:Must be one of the following types: float16. +* @li bias_input:Must be one of the following types: float16, float32. The format must be ND. +* @li bias_hidden:Must be one of the following types: float16, float32. The format must be ND. +* @li seq_length:Must be one of the following types: int32 in ND. +* @li init_h:Must be one of the following types: float16, float32. -*@par Outputs: -*seven outputs: -*@li y:Must be one of the following types: float16, float32. -*@li output_h:Must be one of the following types: float16, float32. -*@li update:Must be one of the following types: float16, float32. -*@li update_att:Must be one of the following types: float16, float32. -*@li reset:Must be one of the following types: float16, float32. -*@li new:Must be one of the following types: float16, float32. -*@li hidden_new:Must be one of the following types: float16, float32. +* @par Attributes: +* @li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. +* @li cell_depth:An integer identifying the cell depth in the op. Default to 1. +* @li keep_prob:An float identifying the keep prob in the op. Default to 1. +* @li cell_clip:An float identifying the cell clip in the op. Default to -1. +* @li num_proj:An integer identifying the num projection in the op. Default to 0. +* @li time_major:An bool identifying the time major in the op. Default to true. +* @li activation:An string identifying the type of activation function in the op. Default to "tanh". Only tanh is currently supported. +* @li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. +* @li reset_after:An bool identifying whether to apply reset gate after matrix multiplication. Default to true. +* @li is_training:An bool identifying is training in the op. Default to true. + +* @par Outputs: +* seven outputs: +* @li y:Must be one of the following types: float16, float32. +* @li output_h:Must be one of the following types: float16, float32. +* @li update:Must be one of the following types: float16, float32. +* @li update_att:Must be one of the following types: float16, float32. +* @li reset:Must be one of the following types: float16, float32. +* @li new:Must be one of the following types: float16, float32. +* @li hidden_new:Must be one of the following types: float16, float32. */ REG_OP(DynamicAUGRU) -.INPUT(x, TensorType({DT_FLOAT16})) -.INPUT(weight_input, TensorType({DT_FLOAT16})) -.INPUT(weight_hidden, TensorType({DT_FLOAT16})) -.INPUT(weight_att, TensorType({DT_FLOAT16})) -.OPTIONAL_INPUT(bias_input, TensorType({DT_FLOAT16, DT_FLOAT})) -.OPTIONAL_INPUT(bias_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) -.OPTIONAL_INPUT(seq_length, TensorType({DT_INT32, DT_FLOAT16})) -.OPTIONAL_INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) -.OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) -.OUTPUT(output_h, TensorType({DT_FLOAT16, DT_FLOAT})) -.OUTPUT(update, TensorType({DT_FLOAT16, DT_FLOAT})) -.OUTPUT(update_att, TensorType({DT_FLOAT16, DT_FLOAT})) -.OUTPUT(reset, TensorType({DT_FLOAT16, DT_FLOAT})) -.OUTPUT(new, TensorType({DT_FLOAT16, DT_FLOAT})) -.OUTPUT(hidden_new, TensorType({DT_FLOAT16, DT_FLOAT})) -.ATTR(direction, String, "UNIDIRECTIONAL") -.ATTR(cell_depth, Int, 1) -.ATTR(keep_prob, Float, 1.0) -.ATTR(cell_clip, Float, -1.0) -.ATTR(num_proj, Int, 0) -.ATTR(time_major, Bool, true) -.ATTR(activation, String, "tanh") -.ATTR(gate_order, String, "zrh") -.ATTR(reset_after, Bool, true) -.ATTR(is_training, Bool, true) -.OP_END_FACTORY_REG(DynamicAUGRU) + .INPUT(x, TensorType({DT_FLOAT16})) + .INPUT(weight_input, TensorType({DT_FLOAT16})) + .INPUT(weight_hidden, TensorType({DT_FLOAT16})) + .INPUT(weight_att, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(bias_input, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(bias_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32, DT_FLOAT16})) + .OPTIONAL_INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(output_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(update, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(update_att, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(reset, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(new, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(hidden_new, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(direction, String, "UNIDIRECTIONAL") + .ATTR(cell_depth, Int, 1) + .ATTR(keep_prob, Float, 1.0) + .ATTR(cell_clip, Float, -1.0) + .ATTR(num_proj, Int, 0) + .ATTR(time_major, Bool, true) + .ATTR(activation, String, "tanh") + .ATTR(gate_order, String, "zrh") + .ATTR(reset_after, Bool, true) + .ATTR(is_training, Bool, true) + .OP_END_FACTORY_REG(DynamicAUGRU) /** -*@brief: DynamicAUGRUGrad calculation. -*@par Inputs: -*sixteen inputs: \n -*@li x:A 4D Tensor. Must be one of the following types: float16, float32. -*@li weight_input:A 4D Tensor. Must be one of the following types: float16, float32. -*@li weight_hidden:A 4D Tensor. Must be one of the following types: float16, float32. -*@li weight_att:A 4D Tensor. Must be one of the following types: float16, float32. -*@li y:A 4D Tensor. Must be one of the following types: float16, float32. -*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. -*@li update:A 4D Tensor. Must be one of the following types: float16, float32. -*@li update_att:A 4D Tensor. Must be one of the following types: float16, float32. -*@li reset:A 4D Tensor. Must be one of the following types: float16, float32. -*@li new:A 4D Tensor. Must be one of the following types: float16, float32. -*@li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. -*@li seq_length:A 4D Tensor. Must be one of the following types: float16, float32. -*@li mask:A 4D Tensor. Must be one of the following types: float16, float32. - -*@par Attributes: -*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. -*@li cell_depth:An integer identifying the cell depth in the op. Default to 1. -*@li keep_prob:An float identifying the keep prob in the op. Default to 1. -*@li cell_clip:An float identifying the cell clip in the op. Default to -1. -*@li num_proj:An integer identifying the num projection in the op. Default to 0. -*@li time_major:An bool identifying the time major in the op. Default to true. -*@li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. -*@li reset_after:An bool identifying whether to apply reset gate after matrix multiplication. Default to true. +* @brief: DynamicAUGRUGrad calculation. +* @par Inputs: +* sixteen inputs: \n +* @li x:A 4D Tensor. Must be one of the following types: float16, float32. +* @li weight_input:A 4D Tensor. Must be one of the following types: float16, float32. +* @li weight_hidden:A 4D Tensor. Must be one of the following types: float16, float32. +* @li weight_att:A 4D Tensor. Must be one of the following types: float16, float32. +* @li y:A 4D Tensor. Must be one of the following types: float16, float32. +* @li init_h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dy:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dh:A 4D Tensor. Must be one of the following types: float16, float32. +* @li update:A 4D Tensor. Must be one of the following types: float16, float32. +* @li update_att:A 4D Tensor. Must be one of the following types: float16, float32. +* @li reset:A 4D Tensor. Must be one of the following types: float16, float32. +* @li new:A 4D Tensor. Must be one of the following types: float16, float32. +* @li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. +* @li seq_length:A 4D Tensor. Must be one of the following types: float16, float32. +* @li mask:A 4D Tensor. Must be one of the following types: float16, float32. -*@par Outputs: -*seven outputs: \n -*@li dw_input:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dw_hidden:A 4D Tensor. Must be one of the following types: float16, float32. -*@li db_input:A 4D Tensor. Must be one of the following types: float16, float32. -*@li db_hidden:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dx:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dw_att:A 4D Tensor. Must be one of the following types: float16, float32. - -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* @par Attributes: +* @li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. +* @li cell_depth:An integer identifying the cell depth in the op. Default to 1. +* @li keep_prob:An float identifying the keep prob in the op. Default to 1. +* @li cell_clip:An float identifying the cell clip in the op. Default to -1. +* @li num_proj:An integer identifying the num projection in the op. Default to 0. +* @li time_major:An bool identifying the time major in the op. Default to true. +* @li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. +* @li reset_after:An bool identifying whether to apply reset gate after matrix multiplication. Default to true. + +* @par Outputs: +* seven outputs: \n +* @li dw_input:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dw_hidden:A 4D Tensor. Must be one of the following types: float16, float32. +* @li db_input:A 4D Tensor. Must be one of the following types: float16, float32. +* @li db_hidden:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dx:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dw_att:A 4D Tensor. Must be one of the following types: float16, float32. + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(DynamicAUGRUGrad) -.INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(weight_input, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(weight_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(weight_att, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(h, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(dy, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(dh, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(update, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(update_att, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(reset, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(new, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(hidden_new, TensorType({DT_FLOAT16, DT_FLOAT})) -.OPTIONAL_INPUT(seq_length, TensorType({DT_INT32})) -.OPTIONAL_INPUT(mask, TensorType({DT_UINT8})) -.OUTPUT(dw_input, TensorType({DT_FLOAT16, DT_FLOAT})) -.OUTPUT(dw_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) -.OUTPUT(db_input, TensorType({DT_FLOAT16, DT_FLOAT})) -.OUTPUT(db_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) -.OUTPUT(dx, TensorType({DT_FLOAT16, DT_FLOAT})) -.OUTPUT(dh_prev, TensorType({DT_FLOAT16, DT_FLOAT})) -.OUTPUT(dw_att, TensorType({DT_FLOAT16, DT_FLOAT})) -.ATTR(direction, String, "UNIDIRECTIONAL") -.ATTR(cell_depth, Int, 1) -.ATTR(keep_prob, Float, -1.0) -.ATTR(cell_clip, Float, -1.0) -.ATTR(num_proj, Int, 0) -.ATTR(time_major, Bool, true) -.ATTR(gate_order, String, "zrh") -.ATTR(reset_after, Bool, true) -.OP_END_FACTORY_REG(DynamicAUGRUGrad) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(weight_input, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(weight_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(weight_att, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(h, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(dy, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(dh, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(update, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(update_att, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(reset, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(new, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(hidden_new, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(seq_length, TensorType({DT_INT32})) + .OPTIONAL_INPUT(mask, TensorType({DT_UINT8})) + .OUTPUT(dw_input, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dw_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(db_input, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(db_hidden, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dx, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dh_prev, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dw_att, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(direction, String, "UNIDIRECTIONAL") + .ATTR(cell_depth, Int, 1) + .ATTR(keep_prob, Float, -1.0) + .ATTR(cell_clip, Float, -1.0) + .ATTR(num_proj, Int, 0) + .ATTR(time_major, Bool, true) + .ATTR(gate_order, String, "zrh") + .ATTR(reset_after, Bool, true) + .OP_END_FACTORY_REG(DynamicAUGRUGrad) /** -*@brief: AUGRUHiddenGrad calculation. -*@par Inputs: -*eleven inputs: \n -*@li weight_att:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dh_pre_t:A 4D Tensor. Must be one of the following types: float16, float32. -*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. -*@li update:A 4D Tensor. Must be one of the following types: float16, float32. -*@li update_att:A 4D Tensor. Must be one of the following types: float16, float32. -*@li reset:A 4D Tensor. Must be one of the following types: float16, float32. -*@li new:A 4D Tensor. Must be one of the following types: float16, float32. -*@li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. - -*@par Attributes: -*@li t_state:An Int identifying the current t state. Default to [0, 4]. -*@li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. +* @brief: AUGRUHiddenGrad calculation. +* @par Inputs: +* twelve inputs: \n +* @li weight_att:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dh_pre_t:A 4D Tensor. Must be one of the following types: float16, float32. +* @li init_h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dy:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dh:A 4D Tensor. Must be one of the following types: float16, float32. +* @li update:A 4D Tensor. Must be one of the following types: float16, float32. +* @li update_att:A 4D Tensor. Must be one of the following types: float16, float32. +* @li reset:A 4D Tensor. Must be one of the following types: float16, float32. +* @li new:A 4D Tensor. Must be one of the following types: float16, float32. +* @li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. +* @li seq_mask:A 4D Tensor. Must be one of the following types: float16, float32. -*@par Outputs: -*four outputs: \n -*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dgate_h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dnt_x:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dw_att_t:A 4D Tensor. Must be one of the following types: float16, float32. - -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* @par Attributes: +* @li t_state:An Int identifying the current t state. Default to [0, 4]. +* @li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. + +* @par Outputs: +* four outputs: \n +* @li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dgate_h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dnt_x:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dw_att_t:A 4D Tensor. Must be one of the following types: float16, float32. + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(AUGRUHiddenGradCell) -.INPUT(weight_att, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(dh_pre_t, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(h, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(dy, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(dh, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(update, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(update_att, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(reset, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(new, TensorType({DT_FLOAT16, DT_FLOAT})) -.INPUT(hidden_new, TensorType({DT_FLOAT16, DT_FLOAT})) -.OUTPUT(dh_prev, TensorType({DT_FLOAT16, DT_FLOAT})) -.OUTPUT(dgate_h, TensorType({DT_FLOAT16, DT_FLOAT})) -.OUTPUT(dnt_x, TensorType({DT_FLOAT16, DT_FLOAT})) -.OUTPUT(dw_att_t, TensorType({DT_FLOAT16, DT_FLOAT})) -.ATTR(t_state, Int, 0) -.ATTR(gate_order, String, "zrh") -.OP_END_FACTORY_REG(AUGRUHiddenGradCell) + .INPUT(weight_att, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(dh_pre_t, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(h, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(dy, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(dh, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(update, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(update_att, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(reset, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(new, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(hidden_new, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(seq_length, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dh_prev, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dgate_h, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dnt_x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(dw_att_t, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(t_state, Int, 0) + .ATTR(gate_order, String, "zrh") + .OP_END_FACTORY_REG(AUGRUHiddenGradCell) /** -*@brief: DynamicGRUV2Grad calculation. -*@par Inputs: -*fourteen inputs: \n -*@li x:A 4D Tensor. Must be one of the following types: float16, float32. -*@li weight_input:A 4D Tensor. Must be one of the following types: float16, float32. -*@li weight_hidden:A 4D Tensor. Must be one of the following types: float16, float32. -*@li y:A 4D Tensor. Must be one of the following types: float16, float32. -*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. -*@li update:A 4D Tensor. Must be one of the following types: float16, float32. -*@li reset:A 4D Tensor. Must be one of the following types: float16, float32. -*@li new:A 4D Tensor. Must be one of the following types: float16, float32. -*@li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. -*@li seq_length:A 4D Tensor. Must be one of the following types: float16, float32. -*@li mask:A 4D Tensor. Must be one of the following types: float16, float32. - -*@par Attributes: -*@li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. -*@li cell_depth:An integer identifying the cell depth in the op. Default to 1. -*@li keep_prob:An float identifying the keep prob in the op. Default to 1. -*@li cell_clip:An float identifying the cell clip in the op. Default to -1. -*@li num_proj:An integer identifying the num projection in the op. Default to 0. -*@li time_major:An bool identifying the time major in the op. Default to true. -*@li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. -*@li reset_after:An bool identifying whether to apply reset gate after matrix multiplication. Default to true. +* @brief: DynamicGRUV2Grad calculation. +* @par Inputs: +* fourteen inputs: \n +* @li x:A 4D Tensor. Must be one of the following types: float16, float32. +* @li weight_input:A 4D Tensor. Must be one of the following types: float16, float32. +* @li weight_hidden:A 4D Tensor. Must be one of the following types: float16, float32. +* @li y:A 4D Tensor. Must be one of the following types: float16, float32. +* @li init_h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dy:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dh:A 4D Tensor. Must be one of the following types: float16, float32. +* @li update:A 4D Tensor. Must be one of the following types: float16, float32. +* @li reset:A 4D Tensor. Must be one of the following types: float16, float32. +* @li new:A 4D Tensor. Must be one of the following types: float16, float32. +* @li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. +* @li seq_length:A 4D Tensor. Must be one of the following types: float16, float32. +* @li mask:A 4D Tensor. Must be one of the following types: float16, float32. -*@par Outputs: -*six outputs: \n -*@li dw_input:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dw_hidden:A 4D Tensor. Must be one of the following types: float16, float32. -*@li db_input:A 4D Tensor. Must be one of the following types: float16, float32. -*@li db_hidden:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dx:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. - -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* @par Attributes: +* @li direction:An string identifying the direction in the op. Default to "UNIDIRECTIONAL". Only UNIDIRECTIONAL is currently supported. +* @li cell_depth:An integer identifying the cell depth in the op. Default to 1. +* @li keep_prob:An float identifying the keep prob in the op. Default to 1. +* @li cell_clip:An float identifying the cell clip in the op. Default to -1. +* @li num_proj:An integer identifying the num projection in the op. Default to 0. +* @li time_major:An bool identifying the time major in the op. Default to true. +* @li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. +* @li reset_after:An bool identifying whether to apply reset gate after matrix multiplication. Default to true. + +* @par Outputs: +* six outputs: \n +* @li dw_input:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dw_hidden:A 4D Tensor. Must be one of the following types: float16, float32. +* @li db_input:A 4D Tensor. Must be one of the following types: float16, float32. +* @li db_hidden:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dx:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(DynamicGRUV2Grad) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -1304,31 +1308,31 @@ REG_OP(DynamicGRUV2Grad) .OP_END_FACTORY_REG(DynamicGRUV2Grad) /** -*@brief: GRUV2HiddenGrad calculation. -*@par Inputs: -*nine inputs: \n -*@li dh_pre_t:A 4D Tensor. Must be one of the following types: float16, float32. -*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. -*@li update:A 4D Tensor. Must be one of the following types: float16, float32. -*@li reset:A 4D Tensor. Must be one of the following types: float16, float32. -*@li new:A 4D Tensor. Must be one of the following types: float16, float32. -*@li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. - -*@par Attributes: -*@li t_state:An Int identifying the current t state. Default to [0, 4]. -*@li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. +* @brief: GRUV2HiddenGrad calculation. +* @par Inputs: +* nine inputs: \n +* @li dh_pre_t:A 4D Tensor. Must be one of the following types: float16, float32. +* @li init_h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dy:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dh:A 4D Tensor. Must be one of the following types: float16, float32. +* @li update:A 4D Tensor. Must be one of the following types: float16, float32. +* @li reset:A 4D Tensor. Must be one of the following types: float16, float32. +* @li new:A 4D Tensor. Must be one of the following types: float16, float32. +* @li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. -*@par Outputs: -*three outputs: \n -*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dgate_h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dnt_x:A 4D Tensor. Must be one of the following types: float16, float32. +* @par Attributes: +* @li t_state:An Int identifying the current t state. Default to [0, 4]. +* @li gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. + +* @par Outputs: +* three outputs: \n +* @li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dgate_h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dnt_x:A 4D Tensor. Must be one of the following types: float16, float32. -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(GRUV2HiddenGradCell) .INPUT(dh_pre_t, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -1347,31 +1351,31 @@ REG_OP(GRUV2HiddenGradCell) .OP_END_FACTORY_REG(GRUV2HiddenGradCell) /** -*@brief: DynamicGRUCellGrad calculation. -*@par Inputs: -*ten inputs: \n -*@li dh_pre_t:A 4D Tensor. Must be one of the following types: float16, float32. -*@li h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dy:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dh:A 4D Tensor. Must be one of the following types: float16, float32. -*@li update:A 4D Tensor. Must be one of the following types: float16, float32. -*@li reset:A 4D Tensor. Must be one of the following types: float16, float32. -*@li new:A 4D Tensor. Must be one of the following types: float16, float32. -*@li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32.+ -*@li init_h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li t_state:A 1D Tensor. Must be one of the following types: int32. The format must be ND. - -*@par Attributes: -*gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. +* @brief: DynamicGRUCellGrad calculation. +* @par Inputs: +* ten inputs: \n +* @li dh_pre_t:A 4D Tensor. Must be one of the following types: float16, float32. +* @li h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dy:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dh:A 4D Tensor. Must be one of the following types: float16, float32. +* @li update:A 4D Tensor. Must be one of the following types: float16, float32. +* @li reset:A 4D Tensor. Must be one of the following types: float16, float32. +* @li new:A 4D Tensor. Must be one of the following types: float16, float32. +* @li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32.+ +* @li init_h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li t_state:A 1D Tensor. Must be one of the following types: int32. The format must be ND. -*@par Outputs: -*three outputs: \n -*@li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dgate_h:A 4D Tensor. Must be one of the following types: float16, float32. -*@li dnt_x:A 4D Tensor. Must be one of the following types: float16, float32. +* @par Attributes: +* gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* @par Outputs: +* three outputs: \n +* @li dh_prev:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dgate_h:A 4D Tensor. Must be one of the following types: float16, float32. +* @li dnt_x:A 4D Tensor. Must be one of the following types: float16, float32. + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(DynamicGRUCellGrad) .INPUT(dh_pre_t, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -1424,32 +1428,32 @@ REG_OP(EmbeddingDenseGrad) .OP_END_FACTORY_REG(EmbeddingDenseGrad) /** -*@brief CommonLSTM calculation. -*@par Inputs: -*eight inputs: \n -*@li x:Each time step is a 4D Tensor. Must be one of the following types: float16, float32. -*@li w:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. -*@li r:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. -*@li b:An optional input. Each direction is a 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. -*@li sequence_lens:An optional input. A 1D Tensor.Must be one of the following types: int32. The format must be ND. -*@li initial_h:An optional input. Each direction is a 4D Tensor. Must be one of the following types: float16, float32. -*@li initial_c:An optional input. Each direction is a 4D Tensor. Must be one of the following types: float16, float32. -*@li p:An optional input. Each direction is a 1D Tensor.Must be one of the following types: float16, float32. The format must be ND. - -*@par Attributes: -*@li activation_alpha:Optional scaling values used by some activation functions. Empty is currently supported. -*@li activation_beta:Optional scaling values used by some activation functions. Empty is currently supported. -*@li activations:The list of activation functions. Empty is currently supported. -*@li clip:An float identifying the cell clip in the op. Default to -1. -*@li direction:Specify if the RNN is forward, reverse, or bidirectional. Must be one of forward(default), reverse, or bidirectional. -*@li hidden_size:Number of neurons in the hidden layer. Reserved. -*@li input_forget:Couple the input and forget gates if 1. Reserved. +* @brief CommonLSTM calculation. +* @par Inputs: +* eight inputs: \n +* @li x:Each time step is a 4D Tensor. Must be one of the following types: float16, float32. +* @li w:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. +* @li r:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. +* @li b:An optional input. Each direction is a 1D Tensor. Must be one of the following types: float16, float32. The format must be ND. +* @li sequence_lens:An optional input. A 1D Tensor.Must be one of the following types: int32. The format must be ND. +* @li initial_h:An optional input. Each direction is a 4D Tensor. Must be one of the following types: float16, float32. +* @li initial_c:An optional input. Each direction is a 4D Tensor. Must be one of the following types: float16, float32. +* @li p:An optional input. Each direction is a 1D Tensor.Must be one of the following types: float16, float32. The format must be ND. -*@par Outputs: -*three outputs: \n -*@li y:First dimension is time step, second dimension is direction, others is a 4D Tensor. Must be one of the following types: float16, float32. -*@li y_h:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. -*@li y_c:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. +* @par Attributes: +* @li activation_alpha:Optional scaling values used by some activation functions. Empty is currently supported. +* @li activation_beta:Optional scaling values used by some activation functions. Empty is currently supported. +* @li activations:The list of activation functions. Empty is currently supported. +* @li clip:An float identifying the cell clip in the op. Default to -1. +* @li direction:Specify if the RNN is forward, reverse, or bidirectional. Must be one of forward(default), reverse, or bidirectional. +* @li hidden_size:Number of neurons in the hidden layer. Reserved. +* @li input_forget:Couple the input and forget gates if 1. Reserved. + +* @par Outputs: +* three outputs: \n +* @li y:First dimension is time step, second dimension is direction, others is a 4D Tensor. Must be one of the following types: float16, float32. +* @li y_h:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. +* @li y_c:Each direction is a 4D Tensor. Must be one of the following types: float16, float32. */ REG_OP(CommonLSTM) @@ -1591,13 +1595,13 @@ REG_OP(EmbeddingBag) * @li project: A optional Tensor. Must be one of the following types: float16, float32. * * @par Outputs: - *three outputs: - *@li y:A Tensor. Must be one of the following types: float16, float32. - *@li output_h:A Tensor. Must be one of the following types: float16, float32. - *@li output_c:A Tensor. Must be one of the following types: float16, float32. + * three outputs: + * @li y:A Tensor. Must be one of the following types: float16, float32. + * @li output_h:A Tensor. Must be one of the following types: float16, float32. + * @li output_c:A Tensor. Must be one of the following types: float16, float32. * *@par Attributes: - *time_major:An bool identifying the time major in the op. Default to false. + * time_major:An bool identifying the time major in the op. Default to false. * @par Restrictions: * Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ diff --git a/third_party/fwkacllib/inc/runtime/base.h b/third_party/fwkacllib/inc/runtime/base.h index 85740add..8650f9c4 100644 --- a/third_party/fwkacllib/inc/runtime/base.h +++ b/third_party/fwkacllib/inc/runtime/base.h @@ -92,6 +92,12 @@ typedef enum tagRtLimitType { RT_LIMIT_TYPE_LOW_POWER_TIMEOUT = 0, // timeout for power down , ms } rtLimitType_t; +typedef enum tagRtFloatOverflowMode { + RT_OVERFLOW_MODE_SATURATION = 0, + RT_OVERFLOW_MODE_INFNAN, + RT_OVERFLOW_MODE_UNDEF, +} rtFloatOverflowMode_t; + typedef struct rtExceptionInfo { uint32_t taskid; uint32_t streamid; diff --git a/third_party/fwkacllib/inc/runtime/config.h b/third_party/fwkacllib/inc/runtime/config.h index 0030fea4..f39574b3 100644 --- a/third_party/fwkacllib/inc/runtime/config.h +++ b/third_party/fwkacllib/inc/runtime/config.h @@ -145,12 +145,6 @@ typedef enum tagRTTaskTimeoutType { RT_TIMEOUT_TYPE_OP_EXECUTE, } rtTaskTimeoutType_t; -typedef enum tagRtFloatOverflowMode { - RT_OVERFLOW_MODE_SATURATION = 0, - RT_OVERFLOW_MODE_INFNAN, - RT_OVERFLOW_MODE_UNDEF, -} rtFloatOverflowMode_t; - /** * @ingroup * @brief get AI core count diff --git a/third_party/fwkacllib/inc/runtime/dev.h b/third_party/fwkacllib/inc/runtime/dev.h index 1c4586e7..b1157c2b 100644 --- a/third_party/fwkacllib/inc/runtime/dev.h +++ b/third_party/fwkacllib/inc/runtime/dev.h @@ -433,6 +433,32 @@ RTS_API rtError_t rtGetDevMsg(rtGetDevMsgType_t getMsgType, rtGetMsgCallback cal * @return RT_MEMORY_TS, RT_MEMORY_HBM, RT_MEMORY_TS | RT_MEMORY_POLICY_HUGE_PAGE_ONLY */ RTS_API uint32_t rtGetTsMemType(rtMemRequestFeature_t featureType, uint32_t memSize); + +/** + * @ingroup + * @brief set saturation mode for current device. + * @param [in] saturation mode. + * @return RT_ERROR_NONE for ok + */ +RTS_API rtError_t rtSetDeviceSatMode(rtFloatOverflowMode_t floatOverflowMode); + +/** + * @ingroup + * @brief get saturation mode for current device. + * @param [out] saturation mode. + * @return RT_ERROR_NONE for ok + */ +RTS_API rtError_t rtGetDeviceSatMode(rtFloatOverflowMode_t *floatOverflowMode); + +/** + * @ingroup + * @brief get saturation mode for target stream. + * @param [in] target stm + * @param [out] saturation mode. + * @return RT_ERROR_NONE for ok + */ +RTS_API rtError_t rtGetDeviceSatModeForStream(rtStream_t stm, rtFloatOverflowMode_t *floatOverflowMode); + #if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/runtime/kernel.h b/third_party/fwkacllib/inc/runtime/kernel.h index 83dc7a91..85c2d832 100644 --- a/third_party/fwkacllib/inc/runtime/kernel.h +++ b/third_party/fwkacllib/inc/runtime/kernel.h @@ -229,6 +229,8 @@ typedef void (*rtCallback_t)(void *fnData); #define RT_KERNEL_DUMPFLAG (0x02U) #define RT_FUSION_KERNEL_DUMPFLAG (0x04U) #define RT_KERNEL_CUSTOM_AICPU (0x08U) +#define RT_KERNEL_FFTSPLUS_DYNAMIC_SHAPE_DUMPFLAG (0x10U) +#define RT_KERNEL_FFTSPLUS_STATIC_SHAPE_DUMPFLAG (0x20U) // STARS topic scheduler sqe : topic_type #define RT_KERNEL_DEVICE_FIRST (0x10U) diff --git a/third_party/fwkacllib/inc/runtime/mem.h b/third_party/fwkacllib/inc/runtime/mem.h index 3d2b0170..368c6201 100644 --- a/third_party/fwkacllib/inc/runtime/mem.h +++ b/third_party/fwkacllib/inc/runtime/mem.h @@ -391,6 +391,18 @@ RTS_API rtError_t rtMemcpyHostTask(void * const dst, const uint64_t destMax, con RTS_API rtError_t rtMemcpyAsync(void *dst, uint64_t destMax, const void *src, uint64_t cnt, rtMemcpyKind_t kind, rtStream_t stm); +typedef struct rtMemcpyAddrInfo { + uint32_t resv0; + uint32_t resv1; + uint32_t resv2; + uint32_t len; + uint64_t src; + uint64_t dst; +} rtMemcpyAddrInfo; + +RTS_API rtError_t rtMemcpyAsyncPtr(void *memcpyAddrInfo, uint64_t destMax, uint64_t count, + rtMemcpyKind_t kind, rtStream_t stream); + /** * @ingroup dvrt_mem * @brief asynchronized reduce memcpy @@ -407,6 +419,23 @@ RTS_API rtError_t rtMemcpyAsync(void *dst, uint64_t destMax, const void *src, ui RTS_API rtError_t rtReduceAsync(void *dst, uint64_t destMax, const void *src, uint64_t cnt, rtRecudeKind_t kind, rtDataType_t type, rtStream_t stm); +/** + * @ingroup dvrt_mem + * @brief asynchronized reduce memcpy + * @param [in] dst destination address pointer + * @param [in] Max length of destination address memory + * @param [in] src source address pointer + * @param [in] count the number of byte to copy + * @param [in] kind memcpy type + * @param [in] type data type + * @param [in] stm asynchronized task stream + * @param [in] overflowAddr addr of overflow flag + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtReduceAsyncV2(void *dst, uint64_t destMax, const void *src, uint64_t count, rtRecudeKind_t kind, + rtDataType_t type, rtStream_t stm, void *overflowAddr); + /** * @ingroup dvrt_mem * @brief synchronized memcpy2D diff --git a/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h b/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h index 4b3447df..b136f880 100644 --- a/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h +++ b/third_party/fwkacllib/inc/runtime/rt_ffts_plus.h @@ -17,10 +17,19 @@ extern "C" { #pragma pack(push) #pragma pack (1) +typedef struct tagFftsPlusDumpInfo { + const void *loadDumpInfo; + const void *unloadDumpInfo; + uint32_t loadDumpInfolen; + uint32_t unloadDumpInfolen; +} rtFftsPlusDumpInfo_t; + + typedef struct tagFftsPlusTaskInfo { const rtFftsPlusSqe_t *fftsPlusSqe; const void *descBuf; // include total context size_t descBufLen; // the length of descBuf + rtFftsPlusDumpInfo_t fftsPlusDumpInfo; // used only in the dynamic shape } rtFftsPlusTaskInfo_t; #pragma pack(pop) diff --git a/third_party/fwkacllib/inc/runtime/rt_ffts_plus_define.h b/third_party/fwkacllib/inc/runtime/rt_ffts_plus_define.h index b1a6232a..9b043ee5 100644 --- a/third_party/fwkacllib/inc/runtime/rt_ffts_plus_define.h +++ b/third_party/fwkacllib/inc/runtime/rt_ffts_plus_define.h @@ -110,7 +110,8 @@ typedef struct tagFftsPlusAicAivCtx { // 0-3 bytes uint16_t contextType; uint8_t successorNum; - uint8_t resv : 7; + uint8_t resv : 6; + uint8_t dumpSwitch : 1; uint8_t aten : 1; // 4-7 uint8_t prefetchConfig; @@ -172,7 +173,8 @@ typedef struct tagFftsPlusMixAicAivCtx { // 0-3 bytes uint16_t contextType; uint8_t successorNum; - uint8_t reserved1 : 7; + uint8_t reserved1 : 6; + uint8_t dumpSwitch : 1; uint8_t aten : 1; // 4-7 uint8_t prefetchConfig; @@ -236,7 +238,8 @@ typedef struct tagFftsPlusSdmaCtx { // 0-3 bytes uint16_t contextType; uint8_t successorNum; - uint8_t res1 : 7; + uint8_t res1 : 6; + uint8_t dumpSwitch : 1; uint8_t aten : 1; // 4-7 uint8_t res2; @@ -376,7 +379,8 @@ typedef struct tagFftsPlusAiCpuCtx { // 0-3 bytes uint16_t contextType; uint8_t successorNum; - uint8_t res1 : 7; + uint8_t res1 : 6; + uint8_t dumpSwitch : 1; uint8_t aten : 1; // 4-7 uint8_t res2; diff --git a/third_party/fwkacllib/inc/runtime/rt_stars_define.h b/third_party/fwkacllib/inc/runtime/rt_stars_define.h index 4920ef00..ef18877d 100644 --- a/third_party/fwkacllib/inc/runtime/rt_stars_define.h +++ b/third_party/fwkacllib/inc/runtime/rt_stars_define.h @@ -70,10 +70,27 @@ typedef enum tagFftsPlusType { RT_FFTS_PLUS_TYPE = 4, // FFTS+ mode } rtFftsPlusType_t; +typedef struct tagStarsFftsPlusHeader { + uint8_t type : 6; + uint8_t l1Lock : 1; + uint8_t l1Unlock : 1; + + uint8_t ie : 2; + uint8_t preP : 2; + uint8_t postP : 2; + uint8_t wrCqe : 1; + /* tell mcu if this subgraph is overflow-enabled and mcu will send this flag to aicpu when aicpu ctx is excuted */ + uint8_t overflowEn : 1; + + uint16_t blockDim; + + uint16_t rtStreamId; + uint16_t taskId; +} rtStarsFftsPlusHeader_t; // ffts+ sqe typedef struct tagFftsPlusSqe { // 0-7 bytes - rtStarsSqeHeader_t sqeHeader; + rtStarsSqeHeader_t sqeHeader; // use rtStarsFftsPlusHeader_t instead // 8-11 bytes uint16_t fftsType : 3; uint16_t reserved1 : 9; diff --git a/third_party/fwkacllib/inc/runtime/stream.h b/third_party/fwkacllib/inc/runtime/stream.h index f1fe528b..a6abc8fa 100644 --- a/third_party/fwkacllib/inc/runtime/stream.h +++ b/third_party/fwkacllib/inc/runtime/stream.h @@ -27,6 +27,7 @@ extern "C" { #define RT_STREAM_HEAD (0x20U) #define RT_STREAM_PRIMARY_DEFAULT (0x40U) #define RT_STREAM_PRIMARY_FIRST_DEFAULT (0x80U) +#define RT_STREAM_OVERFLOW (0x100U) /** * @ingroup stream_type @@ -212,6 +213,26 @@ RTS_API rtError_t rtDebugRegisterForStream(rtStream_t stm, uint32_t flag, const */ RTS_API rtError_t rtDebugUnRegisterForStream(rtStream_t stm); +/* + * @ingroup dvrt_stream + * @brief enable or disable stream overflow + * @param [in] stm: stream handle + * @param [in] flag: 0:disable others:enable + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtSetStreamOverflowSwitch(rtStream_t stm, uint32_t flags); + +/* + * @ingroup dvrt_stream + * @brief get whether overflow of the stream is enable or disable + * @param [in] stm: stream handle + * @param [out] flag: 0:disable others:enable + * @return RT_ERROR_NONE for ok + * @return RT_ERROR_INVALID_VALUE for error input + */ +RTS_API rtError_t rtGetStreamOverflowSwitch(rtStream_t stm, uint32_t *flags); + #if defined(__cplusplus) } #endif diff --git a/third_party/fwkacllib/inc/tdt/tsd_client.h b/third_party/fwkacllib/inc/tdt/tsd_client.h index a6ecffec..b4accbf6 100644 --- a/third_party/fwkacllib/inc/tdt/tsd_client.h +++ b/third_party/fwkacllib/inc/tdt/tsd_client.h @@ -41,6 +41,10 @@ struct InitFlowGwInfo { char_t rsv[128]; }; +typedef enum { + TSD_CAPABILITY_PIDQOS = 0, + TSD_CAPABILITY_BUT +} TsdCapabilityType; /** * @ingroup Open * @brief Used for the Framework process to communicate with the TSDDaemon process, @@ -198,6 +202,36 @@ TDT_LIB_EXPORT uint32_t TsdSetMsprofReporterCallback(const MsprofReporterCallbac * @retval OtherValues Failure */ TDT_LIB_EXPORT uint32_t TsdSetAttr(const char * const attrKey, const char * const attrValue); + +/** +* @ingroup TsdCapabilityGet +* @brief use tsd to get some capability +* +* @par type +* capability type +* +* @par ptr +* the result +* @retval TDT_OK Success +* @retval OtherValues Failure +*/ +TDT_LIB_EXPORT uint32_t TsdCapabilityGet(const uint32_t logicDeviceId, const int32_t type, const uint64_t ptr); + + +/** +* @ingroup GetHdcConctStatus +* @brief used to get hdc connection status +* +* @par logicDeviceId +* logic device id +* +* @par hdcSessStat +* hdc session status, DRV_ERROR_SOCKET_CONNECT or DRV_ERROR_SOCKET_CLOSE +* @retval TDT_OK Success +* @retval OtherValues Failure +*/ +TDT_LIB_EXPORT uint32_t GetHdcConctStatus(const uint32_t logicDeviceId, int32_t *hdcSessStat); + #ifdef __cplusplus } #endif // __cplusplus diff --git a/third_party/fwkacllib/inc/tsd/status.h b/third_party/fwkacllib/inc/tsd/status.h index 1010aefb..e0a9b619 100644 --- a/third_party/fwkacllib/inc/tsd/status.h +++ b/third_party/fwkacllib/inc/tsd/status.h @@ -19,11 +19,11 @@ #include "common/type_def.h" namespace tsd { #ifdef __cplusplus -using TSD_StatusT = uint32_t; + using TSD_StatusT = uint32_t; #else -typedef uint32_t TSD_StatusT; + typedef uint32_t TSD_StatusT; #endif -// success code -constexpr TSD_StatusT TSD_OK = 0U; -} // namespace tsd + // success code + constexpr TSD_StatusT TSD_OK = 0U; +} #endif // INC_TDT_STATUS_H From c06d454c8cdc3cf8b958ec43f6e8cd3bee3d92d0 Mon Sep 17 00:00:00 2001 From: lujiale Date: Thu, 9 Jun 2022 19:24:10 +0800 Subject: [PATCH 56/59] fix ops --- third_party/fwkacllib/inc/ops/data_flow_ops.h | 25 + .../inc/ops/elewise_calculation_ops.h | 4 +- .../fwkacllib/inc/ops/functional_ops.h | 13 + third_party/fwkacllib/inc/ops/image_ops.h | 12 - third_party/fwkacllib/inc/ops/linalg_ops.h | 34 ++ third_party/fwkacllib/inc/ops/lookup_ops.h | 15 + third_party/fwkacllib/inc/ops/math_ops.h | 181 ++++++- .../inc/ops/matrix_calculation_ops.h | 44 ++ .../fwkacllib/inc/ops/nn_calculation_ops.h | 21 + third_party/fwkacllib/inc/ops/nn_detect_ops.h | 38 +- third_party/fwkacllib/inc/ops/nn_norm_ops.h | 85 ++-- .../fwkacllib/inc/ops/nonlinear_fuc_ops.h | 26 +- third_party/fwkacllib/inc/ops/quantize_ops.h | 153 +++--- .../fwkacllib/inc/ops/stateless_random_ops.h | 450 +++++++++++++++++- .../fwkacllib/inc/ops/transformation_ops.h | 10 +- 15 files changed, 953 insertions(+), 158 deletions(-) diff --git a/third_party/fwkacllib/inc/ops/data_flow_ops.h b/third_party/fwkacllib/inc/ops/data_flow_ops.h index 3ff6f871..de351e43 100644 --- a/third_party/fwkacllib/inc/ops/data_flow_ops.h +++ b/third_party/fwkacllib/inc/ops/data_flow_ops.h @@ -2506,6 +2506,31 @@ REG_OP(GetNextFromQueue) .ATTR(output_shapes, ListListInt, {{}, {}}) .OP_END_FACTORY_REG(GetNextFromQueue) +/** +*@brief Get the batch of data in data processing . \n + +*@par Attributes: +*@li output_types: A nested structure of DType objects corresponding to each +component of an element of this dataset. +*@li output_shapes: A nested structure of TensorShape objects corresponding +to each component of an element of this dataset. +*@li channel_name: A string. Default "" . \n + +*@par Outputs: +*y:A nested structure of Tensor objects . \n + +*@par Third-party framework compatibility +*Compatible with tensorflow GetNext operator +*/ + +REG_OP(PeekData) + .DYNAMIC_OUTPUT(y, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, DT_INT32, DT_INT64, DT_UINT32, DT_UINT64, + DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_BOOL})) + .ATTR(output_types, ListType, {}) + .ATTR(output_shapes, ListListInt, {}) + .ATTR(channel_name, String, "") + .OP_END_FACTORY_REG(PeekData) + /** * @brief OptionalGetValue * @par Inputs: diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index f8a593b0..58650670 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -42,8 +42,8 @@ namespace ge { *Compatible with the TensorFlow operator AddN. */ REG_OP(AddN) - .DYNAMIC_INPUT(x, TensorType::NumberType()) - .OUTPUT(y, TensorType::NumberType()) + .DYNAMIC_INPUT(x, TensorType({NumberType(), DT_VARIANT})) + .OUTPUT(y, TensorType({NumberType(), DT_VARIANT})) .REQUIRED_ATTR(N, Int) .OP_END_FACTORY_REG(AddN) diff --git a/third_party/fwkacllib/inc/ops/functional_ops.h b/third_party/fwkacllib/inc/ops/functional_ops.h index 005b716c..da968f5e 100644 --- a/third_party/fwkacllib/inc/ops/functional_ops.h +++ b/third_party/fwkacllib/inc/ops/functional_ops.h @@ -349,6 +349,19 @@ REG_OP(StatefulPartitionedCall) .ATTR(executor_type, String, "") .OP_END_FACTORY_REG(StatefulPartitionedCall) +/** + * @par Inputs: + * @li input: The input tensors \n + * + * @par Outputs: + * @li output: The output tensors. \n + */ +REG_OP(ToBool) + .INPUT(input, TensorType({DT_INT64, DT_INT32, DT_INT16, DT_INT8, \ + DT_UINT8, DT_FLOAT, DT_DOUBLE, DT_STRING, DT_BOOL})) + .OUTPUT(output, DT_BOOL) + .OP_END_FACTORY_REG(ToBool) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_FUNCTIONAL_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/image_ops.h b/third_party/fwkacllib/inc/ops/image_ops.h index d38f0b60..37f0e2b1 100644 --- a/third_party/fwkacllib/inc/ops/image_ops.h +++ b/third_party/fwkacllib/inc/ops/image_ops.h @@ -1931,9 +1931,6 @@ REG_OP(DenseImageWarpGrad) *@par Third-party framework compatibility *Compatible with pytorch GridSampler2D operator. - -*@par Restrictions: -*Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(GridSampler2D) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) @@ -1966,9 +1963,6 @@ REG_OP(GridSampler2D) *@par Third-party framework compatibility *Compatible with pytorch GridSampler2DGrad operator. - -*@par Restrictions: -*Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(GridSampler2DGrad) .INPUT(grad, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) @@ -2063,9 +2057,6 @@ REG_OP(IMGWarpOffsets) *@par Third-party framework compatibility *Compatible with pytorch GridSampler3D operator. - -*@par Restrictions: -*Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(GridSampler3D) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) @@ -2096,9 +2087,6 @@ REG_OP(GridSampler3D) *@par Third-party framework compatibility *Compatible with pytorch GridSampler3DGrad operator. - -*@par Restrictions: -*Warning:THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(GridSampler3DGrad) .INPUT(grad, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) diff --git a/third_party/fwkacllib/inc/ops/linalg_ops.h b/third_party/fwkacllib/inc/ops/linalg_ops.h index 5e31bebd..bd63c60c 100644 --- a/third_party/fwkacllib/inc/ops/linalg_ops.h +++ b/third_party/fwkacllib/inc/ops/linalg_ops.h @@ -491,6 +491,40 @@ REG_OP(TridiagonalSolve) .ATTR(partial_pivoting, Bool, true) .OP_END_FACTORY_REG(TridiagonalSolve) +/** +* @brief Solution of banded triangular matrix . \n + +* @par Inputs: +* The input bands has to be symmetric and positive definite. +* @li bands:A Tensor. Must be one of the following types: double, float32, + float16,complex64, complex128. Shape is [... K,M], K corresponds to the + number of bands (actually stored diagonals), and M is the data of the + diagonals. + @li rhs:shape is [...M] or [...M, N]. Has the same type as bands \n + +* @par Outputs: +* @li output:A Tensor. Has the same type as bands . \n + +* @par Attributes: +* @li lower:An optional bool. Defaults to True.True: indicates the lower + triangular matrix. False: indicates the upper triangular matrix. +* @li adjoint:An optional bool. Defaults to False.Boolean indicating whether to + solve with matrix or its (block-wise) adjoint. \n + +* @par Third-party framework compatibility +* Compatible with tensorflow BandedTriangularSolve operator. +*/ + +REG_OP(BandedTriangularSolve) + .INPUT(bands, TensorType({DT_FLOAT, DT_DOUBLE, \ + DT_FLOAT16, DT_COMPLEX64, DT_COMPLEX128})) + .INPUT(rhs, TensorType({DT_FLOAT, DT_DOUBLE, \ + DT_FLOAT16, DT_COMPLEX64, DT_COMPLEX128})) + .OUTPUT(output,TensorType({DT_FLOAT, DT_DOUBLE, \ + DT_FLOAT16, DT_COMPLEX64, DT_COMPLEX128})) + .ATTR(lower, Bool, true) + .ATTR(adjoint, Bool, false) + .OP_END_FACTORY_REG(BandedTriangularSolve) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_LINALG_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/lookup_ops.h b/third_party/fwkacllib/inc/ops/lookup_ops.h index b1fc254f..ea840d64 100644 --- a/third_party/fwkacllib/inc/ops/lookup_ops.h +++ b/third_party/fwkacllib/inc/ops/lookup_ops.h @@ -303,6 +303,21 @@ REG_OP(MutableHashTable) .REQUIRED_ATTR(key_dtype, Type) .REQUIRED_ATTR(value_dtype, Type) .OP_END_FACTORY_REG(MutableHashTable) + +/** +* @brief Remove keys in the given table . \n + +* @par Inputs: +* @li table_handle: A Tensor of type resource. Handle to the table. \n +* @li keys: A Tensor. Any shape. Keys to remove. \n + +* @par Third-party framework compatibility. +* Compatible with tensorflow LookupTableInsert operator. +*/ +REG_OP(LookupTableRemove) + .INPUT(table_handle, TensorType({DT_RESOURCE})) + .INPUT(keys,TensorType({RealNumberType, DT_BOOL, DT_STRING})) + .OP_END_FACTORY_REG(LookupTableRemove) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_LOOKUP_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/math_ops.h b/third_party/fwkacllib/inc/ops/math_ops.h index 75ef276a..94fd0600 100644 --- a/third_party/fwkacllib/inc/ops/math_ops.h +++ b/third_party/fwkacllib/inc/ops/math_ops.h @@ -377,7 +377,7 @@ to each component of an element of this dataset. REG_OP(GetNext) .DYNAMIC_OUTPUT(y, TensorType({DT_INT8, DT_UINT8, DT_INT16, DT_UINT16, DT_INT32, DT_INT64, DT_UINT32, DT_UINT64, - DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_BOOL})) + DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_BOOL})) .ATTR(output_types, ListType, {}) .ATTR(output_shapes, ListListInt, {}) .ATTR(output_num, Int, 1) @@ -1156,6 +1156,185 @@ REG_OP(CdistGrad) .ATTR(p, Float, 2.0) .OP_END_FACTORY_REG(CdistGrad) +/** +* @brief Computes the RaggedBincount. \n + +* @par Inputs: +* Four inputs, including: +* @li splits: A tensor with shpae: BxPXM. Must be one of the following types: +* int64. +* @li values: A tensor with shpae: BxPXM. Must be one of the following types: +* float16, float32. +* @li size: A tensor with shpae: BxRxM. Must be one of the following types: +* int32, int64. +* @li weights: A tensor with shpae: BxRxM. +* Must be one of the following types: int32, int64, float, double. \n + +* @par Attributes: +* @li binary_output: An optional bool \n + +* @par Outputs: +* output: Must be one of the following types: int32, int64, float, double. \n +*/ +REG_OP(RaggedBincount) + .INPUT(splits, TensorType({DT_INT64})) + .INPUT(values, TensorType({DT_INT32, DT_INT64})) + .INPUT(size, TensorType({DT_INT32, DT_INT64})) + .INPUT(weights, TensorType({DT_INT32, DT_INT64, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(output, TensorType({DT_INT32, DT_INT64, DT_FLOAT, DT_DOUBLE})) + .ATTR(binary_output, Bool, false) + .OP_END_FACTORY_REG(RaggedBincount) + +/** + * @brief Count the number of occurrences of each value in the input dense integer array, + * and output it according to the sparse matrix. \n + + * @par Inputs: + * @li values: A 1D or 2D tensor of type int32 or int64. + * @li weights: A tensor of type int32 or int64 or float or double. \n + + * @par Attributes: + * @li minlength: An optional int >=-1. Defaults to -1. + * @li maxlength: An optional int >=-1. Defaults to -1. + * @li binary_output: A required bool. \n + + * @par Outputs: + * output_indices: A tensor of type int64. + * output_values: A tensor of the same type as "weights". + * output_dense_shape: A tensor of type int64. \n + + * @par Third-party framework compatibility + * Compatible with the TensorFlow operator DenseCountSparseOutput. \n + */ +REG_OP(DenseCountSparseOutput) + .INPUT(values, TensorType({DT_INT32,DT_INT64})) + .INPUT(weights, TensorType({DT_INT32,DT_INT64,DT_FLOAT,DT_DOUBLE})) + .OUTPUT(output_indices, TensorType({DT_INT64})) + .OUTPUT(output_values, TensorType({DT_INT32,DT_INT64,DT_FLOAT,DT_DOUBLE})) + .OUTPUT(output_dense_shape, TensorType({DT_INT64})) + .ATTR(minlength, Int, -1) + .ATTR(maxlength, Int, -1) + .REQUIRED_ATTR(binary_output, Bool) + .OP_END_FACTORY_REG(DenseCountSparseOutput) + +/** + * @brief Count the number of occurrences of each value in the input ragged integer array, + * and output it according to the sparse matrix. \n + + * @par Inputs: + * @li splits: A 1D tensor of type int64. + * @li values: A 1D or 2D tensor of type int32 or int64. + * @li weights: A tensor of type int32 or int64 or float or double. \n + + * @par Attributes: + * @li minlength: An optional int >=-1. Defaults to -1. + * @li maxlength: An optional int >=-1. Defaults to -1. + * @li binary_output: A required bool. \n + + * @par Outputs: + * output_indices: A tensor of type int64. + * output_values: A tensor of the same type as "weights". + * output_dense_shape: A tensor of type int64. \n + + * @par Third-party framework compatibility + * Compatible with the TensorFlow operator RaggedCountSparseOutput. \n + */ +REG_OP(RaggedCountSparseOutput) + .INPUT(splits, TensorType({DT_INT64})) + .INPUT(values, TensorType({DT_INT32,DT_INT64})) + .INPUT(weights, TensorType({DT_INT32,DT_INT64,DT_FLOAT,DT_DOUBLE})) + .OUTPUT(output_indices, TensorType({DT_INT64})) + .OUTPUT(output_values, TensorType({DT_INT32,DT_INT64,DT_FLOAT,DT_DOUBLE})) + .OUTPUT(output_dense_shape, TensorType({DT_INT64})) + .ATTR(minlength, Int, -1) + .ATTR(maxlength, Int, -1) + .REQUIRED_ATTR(binary_output, Bool) + .OP_END_FACTORY_REG(RaggedCountSparseOutput) + +/** +* @brief SignBitsUnpack. + +* @par Inputs: +* one input, including: +* @li x: A 1D Tensor of uint8. + +* @par Attributes: +* @li size: dim of out put tensor, defaults to 1. +* @li dtype: dtype of out put tensor: DT_FLOAT(0) or DT_FLOAT16(1). + +* @par Outputs: +* @li y: A 2D Tensor of type float32 (float16) with shape (size, (x.shape * 8) / size), +*/ +REG_OP(SignBitsUnpack) + .INPUT(x, TensorType({DT_UINT8})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16})) + .REQUIRED_ATTR(size, Int) + .REQUIRED_ATTR(dtype, Type) + .OP_END_FACTORY_REG(SignBitsUnpack) + +/** +* @brief Function scaled masked softmax . \n + +* @par Inputs: +* Two inputs, including: +* @li x: A mutable Tensor. The type support float16/float32. +* @li mask: An optional Tensor. Must meet all of the following rules: +* shape of mask should be broadcastable with x. +* dtype of mask should be bool. +* mask is binary + +* @par Attributes: +* scale: A attribute used to scale tensor. The type is float. The dimension softmax would be performed on. Defaults +* to "1.0" . \n +* fixed_triu_mask: A flag used to enable or disable a fixed upper triangle mask. The type is bool. Defaults +* to "false" . \n + +* @par Outputs: +* y: A mutable Tensor. Has the same type as "x". \n + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(ScaledMaskedSoftmax) + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(mask, TensorType({DT_BOOL, DT_UINT1})) + .OUTPUT(y, TensorType({DT_FLOAT16})) + .ATTR(scale, Float, 1.0) + .ATTR(fixed_triu_mask, Bool, false) + .OP_END_FACTORY_REG(ScaledMaskedSoftmax) + +/** +* @brief Function scaled masked softmax grad . \n + +* @par Inputs: +* Three inputs, including: +* @li y_grad: A mutable Tensor. The type support float16/float32. +* @li y: A mutable Tensor. The type support float16/float32. +* @li mask: An optional Tensor. Must meet all of the following rules: +* shape of mask should be broadcastable with x. +* dtype of mask should be bool. +* mask is binary + +* @par Attributes: +* scale: A attribute used to scale tensor. The type is float. The dimension softmax would be performed on. Defaults +* to "1.0" . \n +* fixed_triu_mask: A flag used to enable or disable a fixed upper triangle mask. The type is bool. Defaults +* to "false" . \n + +* @par Outputs: +* x_grad: A mutable Tensor. Has the same type as "x". \n + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(ScaledMaskedSoftmaxGrad) + .INPUT(y_grad, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(mask, TensorType({DT_BOOL, DT_UINT1})) + .OUTPUT(x_grad, TensorType({DT_FLOAT16})) + .ATTR(scale, Float, 1.0) + .ATTR(fixed_triu_mask, Bool, false) + .OP_END_FACTORY_REG(ScaledMaskedSoftmaxGrad) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATH_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index c856d9e5..57b46398 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -1595,6 +1595,50 @@ REG_OP(Pinverse) .ATTR(rcond, Float, 1e-15) .OP_END_FACTORY_REG(Pinverse) +/** +* @brief From the input tensor and updates tensor, select the maximum value according to indices to output. \n + +* @par Inputs: +* Three inputs, including: +* @li input: Must be one of the following types: +* float16, float32, double, int32, uint8, int16, int8, complex64, int64, +* qint8, quint8, qint32, uint16, complex128, uint32, uint64. +* @li indices: Must be one of the following types: +* int32, int64. +* @li updates: Must have the same type as input. \n + +* @par Outputs: +* output: A Tensor with the same type as input. \n +*/ +REG_OP(TensorScatterMax) + .INPUT(input, TensorType::BasicType()) + .INPUT(indices, TensorType::IndexNumberType()) + .INPUT(updates, TensorType::BasicType()) + .OUTPUT(output, TensorType::BasicType()) + .OP_END_FACTORY_REG(TensorScatterMax) + +/** +* @brief From the input tensor and updates tensor, select the minimum value according to indices to output. \n + +* @par Inputs: +* Three inputs, including: +* @li input: Must be one of the following types: +* float16, float32, double, int32, uint8, int16, int8, complex64, int64, +* qint8, quint8, qint32, uint16, complex128, uint32, uint64. +* @li indices: Must be one of the following types: +* int32, int64. +* @li updates: Must have the same type as input. \n + +* @par Outputs: +* output: A Tensor with the same type as input. \n +*/ +REG_OP(TensorScatterMin) + .INPUT(input, TensorType::BasicType()) + .INPUT(indices, TensorType::IndexNumberType()) + .INPUT(updates, TensorType::BasicType()) + .OUTPUT(output, TensorType::BasicType()) + .OP_END_FACTORY_REG(TensorScatterMin) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATRIX_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h index 5cabd4db..6b3b817a 100644 --- a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h @@ -886,6 +886,7 @@ REG_OP(Conv2D) * to the input image for int8 type. Ensure that the output is within the * effective range. Defaults to 0. *@li data_format: Reserved. +* @li alg: compress algorithm, default weight_unzip. * *@par Outputs: * y: A 4D Tensor of output feature map. Has the same type as "x". With the @@ -909,6 +910,7 @@ REG_OP(Conv2DCompress) .ATTR(groups, Int, 1) .ATTR(data_format, String, "NHWC") .ATTR(offset_x, Int, 0) + .ATTR(alg, String, "weight_unzip") .OP_END_FACTORY_REG(Conv2DCompress) /** @@ -1688,5 +1690,24 @@ REG_OP(FixPipe) .ATTR(eltwise_mode, String, "") .OP_END_FACTORY_REG(FixPipe) +/** +* @brief Solves a batch of isotonic regression problems. \n + +* @par Inputs: +* @li input: A Tensor. \n + +* @par Attributes: +* @li output_dtype: The data type of output. \n + +* @par Outputs: +* @li output: A Tensor. A Tensor of type float16, float32, double. +* @li segments: A Tensor. A Tensor of type int32 \n +*/ +REG_OP(IsotonicRegression) + .INPUT(input, TensorType::RealNumberType()) + .OUTPUT(output, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(segments, TensorType({DT_INT32})) + .ATTR(output_dtype, Type, DT_FLOAT) + .OP_END_FACTORY_REG(IsotonicRegression) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_detect_ops.h b/third_party/fwkacllib/inc/ops/nn_detect_ops.h index 09e94523..15aa6c20 100644 --- a/third_party/fwkacllib/inc/ops/nn_detect_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_detect_ops.h @@ -1550,7 +1550,8 @@ REG_OP(DecodeWheelsTarget) *@li max_size_per_class: A required attribute of type int, specifying the nms output num per class. *@li max_total_size: A required attribute of type int, specifying the the nms output num per batch. *@li change_coordinate_frame: A optional attribute of type bool, whether to normalize coordinates after clipping. -*@li transpose_box: A optional attribute of type bool, whether inserted transpose before this op. must be "false" . \n +*@li transpose_box: A optional attribute of type bool, whether inserted transpose before this op. must be "false". +*@li image_size: A optional attribute of type ListInt, the size of the image. \n *@par Outputs: *@li nmsed_boxes: A 3D Tensor of type float16 with shape (batch, max_total_size, 4), @@ -1580,6 +1581,7 @@ REG_OP(BatchMultiClassNonMaxSuppression) .REQUIRED_ATTR(max_total_size, Int) .ATTR(change_coordinate_frame, Bool, false) .ATTR(transpose_box, Bool, false) + .ATTR(image_size, ListInt, {}) .OP_END_FACTORY_REG(BatchMultiClassNonMaxSuppression) /** @@ -2316,6 +2318,40 @@ REG_OP(CIoU) .ATTR(mode, String, "iou") .ATTR(atan_sub_flag, Bool, false) .OP_END_FACTORY_REG(CIoU) + +/** +* @brief First calculate the minimum closure area of the two boxes, IoU, +* The DIoU is obtained by combining the center distance and IoU. \n + +* @par Inputs: +* Two inputs, including: +* @li bboxes: Bounding boxes, a 2D Tensor of type float16 or float32 with +* shape (4, N). "N" indicates the number of bounding boxes, and the value +* "4" refers to [x1, y1, x2, y2] or [x, y, w, h]. +* @li gtboxes: Ground-truth boxes, a 2D Tensor of type float16 or float32 +* with shape (4, M). "M" indicates the number of ground truth boxes, and +* the value "4" refers to [x1, y1, x2, y2] or [x, y, w, h] . \n + +* @par Attributes: +* @li trans: An optional bool, true for 'xywh', false for 'xyxy'. +* @li is_cross: An optional bool, control whether the output shape is [N, M] or [1, N]. +* @li mode: An optional string, computation mode, a character string with the value range of [iou, iof]. \n + +* @par Outputs: +* overlap: A 2D Tensor of type float16 or float32 with shape [N, M] or [1, N], +* specifying the IoU or IoF ratio . \n + +* @attention Constraints: +* "is_cross" only support false. +*/ +REG_OP(DIoU) + .INPUT(bboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(gtboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(overlap, TensorType({DT_FLOAT16, DT_FLOAT})) + .ATTR(trans, Bool, false) + .ATTR(is_cross, Bool, true) + .ATTR(mode, String, "iou") + .OP_END_FACTORY_REG(DIoU) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_DETECT_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index 1e71c99c..5a2ee6eb 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -426,7 +426,10 @@ REG_OP(ConfusionSoftmaxGrad) *@li keepdims: A bool Scalar. If true, retains reduced dimensions with length 1 . \n *@par Outputs: -*y: A Tensor dtype of float16, float32. +*y: A Tensor dtype of float16, float32. \n + +*@attention Constraints: +*THIS OPERATOR IS DEPRECATED. It will be removed in a future version. */ REG_OP(SoftmaxGradExt) .INPUT(grad, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -1026,74 +1029,48 @@ REG_OP(RNNTLoss) .OP_END_FACTORY_REG(RNNTLoss) /** -*@brief Performs group normalization . \n +* @brief Performs group normalization . \n -*@par Inputs: -* Five inputs, including: (NHWC, NCHW supported) -*@li x: A 4D Tensor of type float16 or float32, with format NHWC or -NCHW for 4D. -*@li scale: A Tensor of type float32. Must be 1D if input "x" is with format -NHWC or NCHW. Specifies the scaling factor. -*@li offset: A Tensor of type float32. Must be 1D if input "x" is with -format NHWC or NCHW. Specifies the offset. -*@li mean: A Tensor of type float32. Must be 1D if input "x" is with format -NHWC or NCHW. Reserved. Mu -st be "None" if the operation is used for training. -*@li variance: A Tensor of type float32. Must be 1D if input "x" is with -format NHWC or NCHW. Specifies the variance used for inference. Reserved . \n +* @par Inputs: +* Three inputs +* @li x: A ND Tensor of type float16 or float32, with format NCHW for 4D. +* @li gamma: A Tensor of type float16 or float32. Must be 1D. Specifies the scaling factor. +* @li beta: A Tensor of type float16 or float32. Must be 1D. Specifies the offset. \n -*@par Attributes: -*@li epsilon: An optional float32, specifying the small value added to +* @par Attributes: +* @li num_groups: An required int32, specifying the number of group. +* @li eps: An optional float32, specifying the small value added to variance to avoid dividing by zero. Defaults to "0.0001". -*@li data_format: An optional string, specifying the format of "x". +* @li data_format: An optional string, specifying the format of "x". Defaults to "NHWC". -*@li is_training: An optional bool, specifying if the operation is used for +* @li is_training: An optional bool, specifying if the operation is used for training or inference. Defaults to "True" . \n -*@par Outputs: -* Five outputs, including: (NHWC, NCHW supported) -*@li y: A 4D Tensor of type float16 or float32 for the normalized "x", -with format NHWC or NCHW for 4D. -*@li batch_mean: A Tensor of type float32. Must be 1D if input "x" is with -format NHWC or NCHW. Specifies the mean of "x". -*@li batch_variance: A Tensor of type float32. Must be 1D if input "x" is -with format NHWC or NCHW. Specifies the variance of "x". -*@li reserve_space_1: An optional Tensor of type float32. Must be 1D if -input "x" is with format NHWC or NCHW. Specifies the mean o -f "x" for gradient computation. Pass "None" to skip this output. -*@li reserve_space_2: An optional Tensor of type float32. Must be 1D if -input "x" is with format NHWC or NCHW. Specifies the varian -ce of "x" for gradient computation. Pass "None" to skip this output . \n +* @par Outputs: +* Three outputs +* @li y: A ND Tensor of type float16 or float32 for the normalized "x", +with format NCHW for 4D. +* @li mean: A Tensor of type float16 or float32. Must be 1D. Specifies the mean of "x". +* @li variance: A Tensor of type float16 or float32. Must be 1D. Specifies the variance of "x". \n -*@attention Constraints: -*@li If the operation is used for inference and outputs "reserve_space_1" -and "reserve_space_2" are available, then "reserve_space_1" has the same -value as "mean" and "reserve_spa -ce_2" has the same value as "variance". -*@li For Ascend 310, the result accuracy fails due to the square root -instruction . \n +* @attention Constraints: +* @li For Ascend 310, only support NCHW which can be trans to 5HD. \n -*@par Third-party framework compatibility -*@li Compatible with the PyTorch operator GroupNorm. +* @par Third-party framework compatibility +* @li Compatible with the PyTorch operator GroupNorm. -*@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(GroupNorm) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) - .INPUT(scale, TensorType({DT_FLOAT,})) - .INPUT(offset, TensorType({DT_FLOAT,})) - .OPTIONAL_INPUT(mean, TensorType({DT_FLOAT})) - .OPTIONAL_INPUT(variance, TensorType({DT_FLOAT})) + .INPUT(gamma, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(beta, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT})) - .OUTPUT(batch_mean, TensorType({DT_FLOAT})) - .OUTPUT(batch_variance, TensorType({DT_FLOAT})) - .OUTPUT(reserve_space_1, TensorType({DT_FLOAT})) - .OUTPUT(reserve_space_2, TensorType({DT_FLOAT})) - .ATTR(epsilon, Float, 0.0001) + .OUTPUT(mean, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(variance, TensorType({DT_FLOAT16, DT_FLOAT})) + .REQUIRED_ATTR(num_groups, Int) .ATTR(data_format, String, "NHWC") + .ATTR(eps, Float, 0.0001) .ATTR(is_training, Bool, true) - .ATTR(num_groups, Int, 2) .OP_END_FACTORY_REG(GroupNorm) /** diff --git a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h index 2a939e97..a582d6e2 100644 --- a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h +++ b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h @@ -307,7 +307,7 @@ REG_OP(Relu6D) * @par Inputs: * @li gradients: A Tensor of type RealNumberType. The backpropagated - gradients to the corresponding Relu6 operation. + gradients to the corresponding Relu6 operation. * @li features: A Tensor with the same type as gradients.he features passed as input to the corresponding Relu6 operation, or its output; using either one produces the same result. \n @@ -325,22 +325,22 @@ REG_OP(Relu6Grad) .OUTPUT(backprops, TensorType::RealNumberType()) .OP_END_FACTORY_REG(Relu6Grad) /** -*@brief Calculate the elu_grad_v2 function. +*@brief Calculate the elu_grad_v2 function. *Applies the element-wise function: * Computes the backward for the elu: if x>0, 1; otherwise elu() + alpha . *@par Inputs: *Two inputs, including: * @li grads: A tensor. Must be one of the following types: -* float16, float32. +* float16, float32. * @li activations: A tensor. Must be one of the following types: -* float16, float32. +* float16, float32. * *@par Outputs: *y: A Tensor with the same type and shape of grads's. -* +* *@par Attributes: *alpha: scalar parameter, default value = 1.0 -*/ +*/ REG_OP(EluGradV2) .INPUT(grads, TensorType({DT_FLOAT, DT_FLOAT16})) .INPUT(activations, TensorType({DT_FLOAT, DT_FLOAT16})) @@ -972,18 +972,18 @@ REG_OP(SoftplusV2Grad) /** * @brief ThresholdedRelu takes one input data (Tensor) and produces one output data (Tensor) * where the rectified linear function, y = x for x > alpha, y = 0 otherwise, is applied to the tensor elementwise. - * + * * @par Inputs: * one input including: * x: input A Tensor. Must be one of the following types: float32, float16 - * + * * @par Attributes: * alpha: An optional float. Defaults to 1.0. \n * @par Outputs: * one output including: * y:A Tensor of the same type as x - * + * */ REG_OP(ThresholdedRelu) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -1059,7 +1059,7 @@ REG_OP(HardShrink) * @par Third-party framework compatibility * Compatible with the Pytorch operator Hardsigmoid. \n -*/ +*/ REG_OP(HardSigmoid) .INPUT(input_x, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32})) .OUTPUT(output_y, TensorType({DT_FLOAT, DT_FLOAT16})) @@ -1219,13 +1219,13 @@ REG_OP(Shrink) * Three inputs, including: * @li x: A Tensor. * Must be one of the following types on Ascend310: float16, int8, int32, uint8. -* Must be one of the following types on Ascend710 or Ascend910: float16, float32, int8, int32, uint8. \n +* Must be one of the following types on Ascend310P or Ascend910: float16, float32, int8, int32, uint8. \n * @li threshold: A Tensor which should have the shape (1,), the value to threshold at. * Must be one of the following types on Ascend310: float16, int8, int32, uint8. -* Must be one of the following types on Ascend710 or Ascend910: float16, float32, int8, int32, uint8. \n +* Must be one of the following types on Ascend310P or Ascend910: float16, float32, int8, int32, uint8. \n * @li value: A Tensor which should have the shape (1,), the value to replace with. default value is 0. * Must be one of the following types on Ascend310: float16, int8, int32, uint8. -* Must be one of the following types on Ascend710 or Ascend910: float16, float32, int8, int32, uint8. \n +* Must be one of the following types on Ascend310P or Ascend910: float16, float32, int8, int32, uint8. \n * @par Outputs: * y: A Tensor which has the same shape and type as the input x. \n diff --git a/third_party/fwkacllib/inc/ops/quantize_ops.h b/third_party/fwkacllib/inc/ops/quantize_ops.h index 1f30db61..5a66b4ee 100644 --- a/third_party/fwkacllib/inc/ops/quantize_ops.h +++ b/third_party/fwkacllib/inc/ops/quantize_ops.h @@ -61,16 +61,16 @@ REG_OP(Dequantize) .OP_END_FACTORY_REG(Dequantize) /** -*@brief Quantizes the input . \n -*@par Inputs: -*@li x: shape and dtype of input_x. \n -*@li scales: shape and dtype of input_scales. \n -*@li zero_points: shape and dtype of input_zero_points \n -*@par Attributes: -*@li dtype: required, type. -*@li axis: the processed dim. \n -*@par Outputs: -*y: shape and dtype of output_y, should be same shape as input, dtype is same as the quantified type . \n +* @brief Quantizes the input . \n +* @par Inputs: +* @li x: shape and dtype of input_x. \n +* @li scales: shape and dtype of input_scales. \n +* @li zero_points: shape and dtype of input_zero_points \n +* @par Attributes: +* @li dtype: required, type. +* @li axis: the processed dim. \n +* @par Outputs: +* y: shape and dtype of output_y, should be same shape as input, dtype is same as the quantified type . \n */ REG_OP(Quantize) .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -82,23 +82,31 @@ REG_OP(Quantize) .OP_END_FACTORY_REG(Quantize) /** -*@brief Quantizes the input . \n +* @brief Quantizes the input . \n -*@par Inputs: -*x: An tensor of type float16 or float32, specifying the input . \n +* @par Inputs: +* x: An tensor of type float16 or float32, specifying the input . \n -*@par Attributes: -*@li scale: A required float32, specifying the scaling ratio. -*@li offset: A required float16, specifying the offset. -*@li sqrt_mode: A optional bool, specifying whether to perform square root on "scale", either "True" or "False". Defaults to "False". -*@li round_mode: An optional string, specifying the float16 to int8 cast type. +* @par Attributes: +* @li scale: A required float32, specifying the scaling ratio. +* @li offset: A required float16, specifying the offset. +* @li sqrt_mode: A optional bool, specifying whether to perform square root on "scale", either "True" or "False". +* Defaults to "False". +* @li round_mode: An optional string, specifying the float16 to int8 cast type. * The value range is [Round, Floor, Ceil, Truncate]. Defaults to "Round" . -*@li dst_type: A optional int32, specifying the output data type. Defaults to "DT_INT8" . \n +* @li dst_type: A optional int32, specifying the output data type. Defaults to "DT_INT8" . \n + +* @par Outputs: +* y: The quantized output tensor of type int8 or int4. \n -*@par Outputs: -*y: The quantized output tensor of type int8 or int4. \n +* @attention Constraints: +* round_mode value range is [Round, Floor, Ceil, Truncate]. +* @li Round: round to nearest, tie to even(c language rint). +* @li Floor: round to minus infinity(c language floor). +* @li Ceil: round to positive infinity(c language ceil). +* @li Truncate: round to zero(c language trunc). \n -*@par Third-party framework compatibility +* @par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. */ REG_OP(AscendQuant) @@ -112,21 +120,22 @@ REG_OP(AscendQuant) .OP_END_FACTORY_REG(AscendQuant) /** -*@brief Dequantizes the input . \n +* @brief Dequantizes the input . \n -*@par Inputs: + *@par Inputs: * @li x: An tensor of type int32, specifying the input. * @li deq_scale: An tensor of type uint64, specifying the scaling ratio . \n -*@par Attributes: -* @li sqrt_mode: A optional bool, specifying whether to perform square root on "scale", either "True" or "False". Defaults to "False". +* @par Attributes: +* @li sqrt_mode: A optional bool, specifying whether to perform square root on "scale", either "True" or "False". +* Defaults to "False". * @li relu_flag: A optional bool, specifying whether to perform ReLU, either "True" or "False". Defaults to "False". * @li dtype: A optional int32, specifying the output data type. Defaults to "DT_FLOAT" . \n -*@par Outputs: -*y: The dequantized output tensor of type float16 or float32. \n +* @par Outputs: +* y: The dequantized output tensor of type float16 or float32. \n -*@par Third-party framework compatibility +* @par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. */ REG_OP(AscendDequant) @@ -139,21 +148,22 @@ REG_OP(AscendDequant) .OP_END_FACTORY_REG(AscendDequant) /** -*@brief Anti quantizes the input . \n +* @brief Anti quantizes the input . \n -*@par Inputs: -*x: An tensor of type int8, specifying the input . \n +* @par Inputs: +* x: An tensor of type int8, specifying the input . \n -*@par Attributes: -*@li scale: A required float32 scale. -*@li offset: A required float32 offset. -*@li dtype: A optional int32, specifying the output data type. Defaults to "DT_FLOAT". -*@li sqrt_mode: A optional bool, specifying whether to perform square root on "scale", either "True" or "False". Defaults to "False" . \n +* @par Attributes: +* @li scale: A required float32 scale. +* @li offset: A required float32 offset. +* @li dtype: A optional int32, specifying the output data type. Defaults to "DT_FLOAT". +* @li sqrt_mode: A optional bool, specifying whether to perform square root on "scale", either "True" or "False". +* Defaults to "False" . \n -*@par Outputs: -*y: The dequantized output tensor of type float16 or float32. \n +* @par Outputs: +* y: The dequantized output tensor of type float16 or float32. \n -*@par Third-party framework compatibility +* @par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. */ REG_OP(AscendAntiQuant) @@ -166,20 +176,20 @@ REG_OP(AscendAntiQuant) .OP_END_FACTORY_REG(AscendAntiQuant) /** -*@brief Dequantizes the input of int16 . \n +* @brief Dequantizes the input of int16 . \n -*@par Inputs: -*@li x0: An tensor of type int32, specifying the input. -*@li deq_scale: An tensor of type uint64, specifying the scaling ratio. -*@li x1: An tensor of type int16, specifying the input . \n +* @par Inputs: +* @li x0: An tensor of type int32, specifying the input. +* @li deq_scale: An tensor of type uint64, specifying the scaling ratio. +* @li x1: An tensor of type int16, specifying the input . \n -*@par Attributes: -*relu_flag: A optional bool, specifying whether to perform ReLU, either "True" or "False". Defaults to "False" . \n +* @par Attributes: +* relu_flag: A optional bool, specifying whether to perform ReLU, either "True" or "False". Defaults to "False" . \n -*@par Outputs: -*y: The dequantized output tensor of type int16. \n +* @par Outputs: +* y: The dequantized output tensor of type int16. \n -*@par Third-party framework compatibility +* @par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. */ REG_OP(AscendDequantS16) @@ -191,19 +201,19 @@ REG_OP(AscendDequantS16) .OP_END_FACTORY_REG(AscendDequantS16) /** -*@brief Requantizes the input . \n +* @brief Requantizes the input . \n -*@par Inputs: -*@li x: An tensor of type int32, specifying the input. -*@li req_scale: An tensor of type uint64, specifying the scaling ratio . \n +* @par Inputs: +* @li x: An tensor of type int32, specifying the input. +* @li req_scale: An tensor of type uint64, specifying the scaling ratio . \n -*@par Attributes: -*relu_flag: A optional bool, specifying whether to perform ReLU, either "True" or "False". Defaults to "False" . \n +* @par Attributes: +* relu_flag: A optional bool, specifying whether to perform ReLU, either "True" or "False". Defaults to "False" . \n -*@par Outputs: -*y: The dequantized output tensor of type int8. \n +* @par Outputs: +* y: The dequantized output tensor of type int8. \n -*@par Third-party framework compatibility +* @par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. */ REG_OP(AscendRequant) @@ -214,22 +224,23 @@ REG_OP(AscendRequant) .OP_END_FACTORY_REG(AscendRequant) /** -*@brief Requantizes the input of int16 . \n +* @brief Requantizes the input of int16 . \n -*@par Inputs: -*@li x0: An tensor of type int16, specifying the input. -*@li req_scale: An tensor of type uint64, specifying the scaling ratio. -*@li x1: An tensor of type int16 . \n +* @par Inputs: +* @li x0: An tensor of type int16, specifying the input. +* @li req_scale: An tensor of type uint64, specifying the scaling ratio. +* @li x1: An tensor of type int16 . \n -*@par Attributes: -*@li dual_output: A optional bool, specifying whether to perform dual ouput, either "True" or "False". Defaults to "False". -*@li relu_flag: A optional bool, specifying whether to perform ReLU, either "True" or "False". Defaults to "False" . \n +* @par Attributes: +* @li dual_output: A optional bool, specifying whether to perform dual ouput, either "True" or "False". +* Defaults to "False". +* @li relu_flag: A optional bool, specifying whether to perform ReLU, either "True" or "False". Defaults to "False" . \n -*@par Outputs: -*@li y0: The dequantized output tensor of type int8. -*@li y1: The dequantized output tensor of type int16. \n +* @par Outputs: +* @li y0: The dequantized output tensor of type int8. +* @li y1: The dequantized output tensor of type int16. \n -*@par Third-party framework compatibility +* @par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. */ REG_OP(AscendRequantS16) diff --git a/third_party/fwkacllib/inc/ops/stateless_random_ops.h b/third_party/fwkacllib/inc/ops/stateless_random_ops.h index ff9daaa3..5ff3e4fb 100644 --- a/third_party/fwkacllib/inc/ops/stateless_random_ops.h +++ b/third_party/fwkacllib/inc/ops/stateless_random_ops.h @@ -79,6 +79,452 @@ REG_OP(StatelessRandomUniformInt) .OUTPUT(y, TensorType({DT_INT32, DT_INT64})) .OP_END_FACTORY_REG(StatelessRandomUniformInt) -} // namespace ge +/** +* @brief Outputs random values from a normal distribution. \n + +* @par Inputs: +* Inputs include: +* @li shape: A Tensor. Must be one of the following types: int32, int64. + The shape of the output tensor. Batches are indexed by the 0th dimension. +* @li seed: 2 seeds (shape [2]). +* @li means: A Tensor. Must be one of the following types: half, bfloat16, float32, float64. +* @li stdevs: A Tensor. Must have the same type as means. +* @li min: A Tensor. Must have the same type as means. The minimum cutoff. May be -infinity. +* @li max: A Tensor. Must have the same type as means. \n + +* @par Outputs: +* y: A Tensor. Has the same type as means. \n + +* @attention Constraints: +* The implementation for StatelessParameterizedTruncatedNormal on Ascend uses AICPU, with bad performance. \n + +* @par Third-party framework compatibility +* @li compatible with tensorflow StatelessParameterizedTruncatedNormal operator. +*/ + +REG_OP(StatelessParameterizedTruncatedNormal) + .INPUT(shape, TensorType({DT_INT32, DT_INT64})) + .INPUT(seed, TensorType({DT_INT32, DT_INT64})) + .INPUT(means, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(stdevs, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(min, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(max, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OP_END_FACTORY_REG(StatelessParameterizedTruncatedNormal) + +/** +* @brief Generate a single randomly distorted bounding box for an image . \n + +* @par Inputs: +* Input images must be a 4-D tensor. Inputs include: +* @li image_size: 1-D, containing [height, width, channels]. +* @li bounding_boxes: 3-D with shape [batch, N, 4] describing the N bounding + boxes associated with the image. +* @li min_object_covered: The cropped area of the image must contain at least + this fraction of any bounding box supplied. The value of this parameter should + be non-negative. In the case of 0, the cropped area does not need to overlap + any of the bounding boxes supplied . +* @li seed: A shape [2] Tensor, the seed to the random number generator. \n + +* @par Attributes: +* @li aspect_ratio_range: The cropped area of the image must have an aspect + ratio = width / height within this range. +* @li area_range: An optional list of `floats`. Defaults to `[0.05, 1]`. The + cropped area of the image must contain a fraction of the supplied image + within this range. +* @li max_attempts: Number of attempts at generating a cropped region of the + image of the specified constraints. After max_attempts failures, return the + entire image. +* @li use_image_if_no_bounding_boxes: Controls behavior if no bounding boxes + supplied. If true, assume an implicit bounding box covering the whole input. + If false, raise an error . \n + +* @par Outputs: +* @li begin: 1-D, containing [offset_height, offset_width, 0]. +* @li size: 1-D, containing [target_height, target_width, -1]. +* @li bboxes: 3-D with shape [1, 1, 4] containing the distorted bounding box . \n + +* @attention Constraints: +* Input images can be of different types but output images are always float . \n + +* @par Third-party framework compatibility +* Compatible with tensorflow StatelessSampleDistortedBoundingBox operator. +*/ + +REG_OP(StatelessSampleDistortedBoundingBox) + .INPUT(image_size, TensorType({ DT_UINT8, DT_INT8, DT_INT16, \ + DT_INT32, DT_INT64 })) + .INPUT(bounding_boxes, TensorType({ DT_FLOAT })) + .INPUT(min_object_covered, TensorType({ DT_FLOAT })) + .INPUT(seed, TensorType({ DT_INT32, DT_INT64 })) + .OUTPUT(begin, TensorType({ DT_UINT8, DT_INT8, DT_INT16, \ + DT_INT32, DT_INT64 })) + .OUTPUT(size, TensorType({ DT_UINT8, DT_INT8, DT_INT16, \ + DT_INT32, DT_INT64 })) + .OUTPUT(bboxes, TensorType({ DT_FLOAT })) + .ATTR(aspect_ratio_range, ListFloat, { 0.75f, 1.33f }) + .ATTR(area_range, ListFloat, { 0.05f, 1.0f }) + .ATTR(max_attempts, Int, 100) + .ATTR(use_image_if_no_bounding_boxes, Bool, false) + .OP_END_FACTORY_REG(StatelessSampleDistortedBoundingBox) + +/** +* @brief Outputs random values from a truncated normal distribution. \n + +* @par Inputs: +* Inputs include: +* @li shape: A Tensor. Must be one of the following types: int32, int64. \n +* @li key: Key of RNG algorithm. Shape[1]. \n +* @li counter: Counter of RNG algorithm. Shape[2] for philox, shape[1] for threefry. \n +* @li alg: RNG algorithm. 1:philox 2:threefry. \n + +* @par Attributes: +* @li dtype: dtype: A optional attr, specifying the output data type. Defaults to "DT_FLOAT". \n + +* @par Outputs: +* y: A Tensor of types: float16, float32, double. A tensor of the specified shape + filled with random truncated normal values. \n + +* @attention Constraints: +* The implementation for StatelessTruncatedNormalV2 on Ascend uses AICPU, with bad performance. + +* @par Third-party framework compatibility +* @li compatible with tensorflow StatelessTruncatedNormalV2 operator. +*/ + +REG_OP(StatelessTruncatedNormalV2) + .INPUT(shape, TensorType({ DT_INT32, DT_INT64 })) + .INPUT(key, TensorType({ DT_UINT64 })) + .INPUT(counter, TensorType({ DT_UINT64 })) + .INPUT(alg, TensorType({ DT_INT32 })) + .OUTPUT(y, TensorType({ DT_FLOAT16, DT_FLOAT, DT_DOUBLE })) + .ATTR(dtype, Type, DT_FLOAT) + .OP_END_FACTORY_REG(StatelessTruncatedNormalV2) + +/** +* @brief Outputs deterministic pseudorandom random numbers from a gamma distribution. \n + +* @par Inputs: +* @li shape: The shape of the output tensor. +* @li seed: 2 seeds (shape [2]). +* @li alpha: The concentration of the gamma distribution. Shape must match the rightmost dimensions of shape. \n + +* @par Outputs: +* y: A Tensor. Has the same type as alpha. \n + +* @par Third-party framework compatibility +* Compatible with TensorFlow StatelessRandomGammaV2 operator. +*/ + +REG_OP(StatelessRandomGammaV2) + .INPUT(shape, TensorType({DT_INT32, DT_INT64})) + .INPUT(seed, TensorType({DT_INT32, DT_INT64})) + .INPUT(alpha, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE})) + .OP_END_FACTORY_REG(StatelessRandomGammaV2) + +/** +* @brief Outputs deterministic pseudorandom random integers from a uniform distribution . \n + +* @par Inputs: +* @li shape: The shape of the output tensor. +* @li seed: 2 seeds (shape [2]). \n + +* @par Attributes: +* dtype:Output data type . \n + +* @par Outputs: +* y: Returns Random values with specified shape . \n + +* @par Third-party framework compatibility +* Compatible with TensorFlow StatelessRandomUniformFullInt operator. +*/ + +REG_OP(StatelessRandomUniformFullInt) + .INPUT(shape, TensorType({DT_INT32, DT_INT64})) + .INPUT(seed, TensorType({DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_INT32, DT_INT64, DT_UINT32, DT_UINT64})) + .ATTR(dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(StatelessRandomUniformFullInt) + +/** +* @brief Outputs deterministic pseudorandom random integers from a uniform distribution . \n + +* @par Inputs: +* @li shape: The shape of the output tensor. +* @li key: Key for the counter-based RNG algorithm. +* @li counter: Initial counter for the counter-based RNG algorithm. +* @li alg: 0-D. The RNG algorithm. \n + +* @par Attributes: +* dtype:Output data type . \n + +* @par Outputs: +* y: Returns Random values with specified shape . \n + +* @par Third-party framework compatibility +* Compatible with TensorFlow StatelessRandomUniformFullIntV2 operator. +*/ + +REG_OP(StatelessRandomUniformFullIntV2) + .INPUT(shape, TensorType({DT_INT32, DT_INT64})) + .INPUT(key, TensorType({DT_UINT64})) + .INPUT(counter, TensorType({DT_UINT64})) + .INPUT(alg, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_INT32, DT_INT64, DT_UINT32, DT_UINT64})) + .ATTR(dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(StatelessRandomUniformFullIntV2) + +/** +* @brief Outputs deterministic pseudorandom random integers from a uniform distribution . \n + +* @par Inputs: +* @li shape: The shape of the output tensor. +* @li key: Key for the counter-based RNG algorithm. +* @li counter: Initial counter for the counter-based RNG algorithm. +* @li alg: 0-D. The RNG algorithm. +* @li minval: Minimum value (inclusive, scalar). +* @li maxval: Maximum value (exclusive, scalar) . \n + +* @par Outputs: +* y: Returns Random values with specified shape . \n + +* @par Third-party framework compatibility +* Compatible with TensorFlow StatelessRandomUniformIntV2 operator. +*/ + +REG_OP(StatelessRandomUniformIntV2) + .INPUT(shape, TensorType({DT_INT32, DT_INT64})) + .INPUT(key, TensorType({DT_UINT64})) + .INPUT(counter, TensorType({DT_UINT64})) + .INPUT(alg, TensorType({DT_INT32})) + .INPUT(minval, TensorType({DT_INT32, DT_INT64, DT_UINT32, DT_UINT64})) + .INPUT(maxval, TensorType({DT_INT32, DT_INT64, DT_UINT32, DT_UINT64})) + .OUTPUT(y, TensorType({DT_INT32, DT_INT64, DT_UINT32, DT_UINT64})) + .OP_END_FACTORY_REG(StatelessRandomUniformIntV2) + +/** +* @brief Outputs deterministic pseudorandom random integers from a binomial distribution. \n + +* @par Inputs: +* @li shape: The shape of the output tensor. +* @li seed: 2 seeds (shape [2]). +* @li counts: The counts of the binomial distribution. Must be broadcastable with probs, +* and broadcastable with the rightmost dimensions of shape. +* @li probs: The probability of success for the binomial distribution. +* Must be broadcastable with counts and broadcastable with the rightmost dimensions of shape. \n + +* @par Attributes: +* @li dtype: A optional int32, specifying the output data type. Defaults to "DT_INT32". \n + +* @par Outputs: +* @li y: Returns Random values with specified shape. \n -#endif // OPS_BUILT_IN_OP_PROTO_INC_STATELESS_RANDOM_OPS_H_ \ No newline at end of file +* @par Third-party framework compatibility +* Compatible with TensorFlow StatelessRandomBinomial operator. +*/ +REG_OP(StatelessRandomBinomial) + .INPUT(shape, TensorType({DT_INT32, DT_INT64})) + .INPUT(seed, TensorType({DT_INT32, DT_INT64})) + .INPUT(counts, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64})) + .INPUT(probs, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_INT32, DT_INT64, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .ATTR(dtype, Type, DT_INT32) + .OP_END_FACTORY_REG(StatelessRandomBinomial) + +/** +* @brief Outputs deterministic pseudorandom random integers from a poisson distribution . \n + +* @par Inputs: +* @li shape: The shape of the output tensor. +* @li seed: 2 seeds (shape [2]). +* @li lam: mean value value of poisson distribution . \n + +* @par Attributes: +* dtype:Output data type . \n + +* @par Outputs: +* y: Returns Random values with specified shape . \n + +* @par Third-party framework compatibility +* Compatible with TensorFlow StatelessRandomUniformInt operator. +*/ + +REG_OP(StatelessRandomPoisson) + .INPUT(shape, TensorType({DT_INT32, DT_INT64})) + .INPUT(seed, TensorType({DT_INT32, DT_INT64})) + .INPUT(lam, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, DT_INT32, DT_INT64})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE, DT_INT32, DT_INT64})) + .REQUIRED_ATTR(dtype, Type) + .OP_END_FACTORY_REG(StatelessRandomPoisson) + +/** +* @brief Get the counter of the RNG algorithm. \n + +* @par Outputs: +* @li alg: The RNG algorithm. \n + +* @par Third-party framework compatibility +* Compatible with TensorFlow StatelessRandomGetAlg operator. +*/ +REG_OP(StatelessRandomGetAlg) + .OUTPUT(alg, TensorType({DT_INT32})) + .OP_END_FACTORY_REG(StatelessRandomGetAlg) + +/** +* @brief This op picks the best counter-based RNG algorithm based on device, and +* scrambles a shape-[2] seed into a key and a counter, both needed by the +* counter-based algorithm. \n + +* @par Inputs: +* @li seed: 2 seeds (shape [2]). \n + +* @par Outputs: +* @li key: Key for the counter-based RNG algorithm. +* @li counter: Initial counter for the counter-based RNG algorithm. \n + +* @par Third-party framework compatibility +* Compatible with TensorFlow StatelessRandomGetKeyCounter operator. +*/ +REG_OP(StatelessRandomGetKeyCounter) + .INPUT(seed, TensorType({DT_INT32, DT_INT64})) + .OUTPUT(key, TensorType({DT_UINT64})) + .OUTPUT(counter, TensorType({DT_UINT64})) + .OP_END_FACTORY_REG(StatelessRandomGetKeyCounter) + +/** +* @brief This op picks the best counter-based RNG algorithm based on device, and +* scrambles a shape-[2] seed into a key and a counter, both needed by the +* counter-based algorithm. \n + +* @par Inputs: +* @li seed: 2 seeds (shape [2]). \n + +* @par Outputs: +* @li key: Key for the counter-based RNG algorithm. +* @li counter: Initial counter for the counter-based RNG algorithm. +* @li alg: The RNG algorithm. \n + +* @par Third-party framework compatibility +* Compatible with TensorFlow StatelessRandomGetKeyCounterAlg operator. +*/ +REG_OP(StatelessRandomGetKeyCounterAlg) + .INPUT(seed, TensorType({DT_INT32, DT_INT64})) + .OUTPUT(key, TensorType({DT_UINT64})) + .OUTPUT(counter, TensorType({DT_UINT64})) + .OUTPUT(alg, TensorType({DT_INT32})) + .OP_END_FACTORY_REG(StatelessRandomGetKeyCounterAlg) + +/** +* @brief Outputs deterministic pseudorandom values from a normal distribution. \n + +* @par Inputs: +* @li shape: The shape of the output tensor. +* @li key: Key for the counter-based RNG algorithm. +* @li counter: Initial counter for the counter-based RNG algorithm. +* @li alg: The RNG algorithm. \n + +* @par Attributes: +* @li dtype: Output data type . \n + +* @par Outputs: +* @li y: Returns Random values with specified shape . \n + +* @par Third-party framework compatibility +* Compatible with TensorFlow StatelessRandomNormalV2 operator. +*/ +REG_OP(StatelessRandomNormalV2) + .INPUT(shape, TensorType({DT_INT32, DT_INT64})) + .INPUT(key, TensorType({DT_UINT64})) + .INPUT(counter, TensorType({DT_UINT64})) + .INPUT(alg, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .ATTR(dtype, Type, DT_FLOAT) + .OP_END_FACTORY_REG(StatelessRandomNormalV2) + +/** +* @brief Outputs deterministic pseudorandom random integers from a uniform distribution . \n + +* @par Inputs: +* @li shape: The shape of the output tensor. +* @li key: Key for the counter-based RNG algorithm. +* @li counter: Initial counter for the counter-based RNG algorithm. +* @li alg: 0-D. The RNG algorithm. \n + +* @par Attributes: +* dtype:Output data type . \n + +* @par Outputs: +* y: Returns Random values with specified shape . \n + +* @par Third-party framework compatibility +* Compatible with TensorFlow StatelessRandomUniformV2 operator. +*/ + +REG_OP(StatelessRandomUniformV2) + .INPUT(shape, TensorType({DT_INT32, DT_INT64})) + .INPUT(key, TensorType({DT_UINT64})) + .INPUT(counter, TensorType({DT_UINT64})) + .INPUT(alg, TensorType({DT_INT32})) + .OUTPUT(y, TensorType({DT_FLOAT, DT_FLOAT16, DT_DOUBLE})) + .ATTR(dtype, Type, DT_FLOAT) + .OP_END_FACTORY_REG(StatelessRandomUniformV2) + +/** +* @brief Create a random number seed generator . \n + +* @par Inputs: +* include: +* @li seed:1-D Tensor,the seed to generate random. +* Must be one of the types:int32 or int64. +* @li seed2:1-D Tensor,the seed to generate random. +* Must be one of the types:int32 or int64. +* @li reshuffle:1-D Tensor.Seed selection, True:random seed, False:fixed seed. +* Must be one of the types:bool. \n + +* @par Outputs: +* handle:Handle to the random number generator. +* deleter:Handle to the remover. +* Used when deleting the random number seed generator \n + +* @see AnonymousSeedGenerator() + +* @par Third-party framework compatibility +* compatible with AnonymousSeedGenerator op of tensorflow +*/ +REG_OP(AnonymousSeedGenerator) + .INPUT(seed, TensorType({DT_INT32,DT_INT64})) + .INPUT(seed2, TensorType({DT_INT32,DT_INT64})) + .INPUT(reshuffle, TensorType({DT_BOOL})) + .OUTPUT(handle, TensorType({DT_RESOURSE})) + .OUTPUT(deleter, TensorType({DT_VARIANT})) + .OP_END_FACTORY_REG(AnonymousSeedGenerator) + +/** +* @brief DeleteSeedGenerator . \n + +* @par Inputs: +* @li handle: A Tensor of type resource. +* @li deleter: A Tensor of type variant. + +* @par Third-party framework compatibility +* Compatible with TensorFlow DeleteSeedGenerator operator. +*/ +REG_OP(DeleteSeedGenerator) + .INPUT(handle, TensorType({DT_RESOURCE})) + .INPUT(deleter, TensorType({DT_VARIANT})) + .OP_END_FACTORY_REG(DeleteSeedGenerator) + +/** +* @brief Create a placeholder handle to rewrite and pass +* to use during the graph compilation phase. \n + +* @par Outputs: +* handle:Output random number . \n +*/ +REG_OP(DummySeedGenerator) + .OUTPUT(handle, TensorType({ DT_RESOURCE })) + .OP_END_FACTORY_REG(DummySeedGenerator) + +} // namespace ge +#endif // OPS_BUILT_IN_OP_PROTO_INC_STATELESS_RANDOM_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/transformation_ops.h b/third_party/fwkacllib/inc/ops/transformation_ops.h index eef76cd5..eaaed8e4 100644 --- a/third_party/fwkacllib/inc/ops/transformation_ops.h +++ b/third_party/fwkacllib/inc/ops/transformation_ops.h @@ -60,7 +60,10 @@ REG_OP(Bitcast) *x: A Tensor. Must be 4D Tensor of type float16, float32, int32, uint16, with format HWCN . \n *@par Outputs: -*y: A 6D Tensor. Has the same type as "x", with format C1HWNCoC0. +*y: A 6D Tensor. Has the same type as "x", with format C1HWNCoC0. \n + +*@attention Constraints: +*THIS OPERATOR IS DEPRECATED. It will be removed in a future version. */ REG_OP(DepthwiseWeight4DTo6D) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_UINT16})) @@ -77,7 +80,10 @@ REG_OP(DepthwiseWeight4DTo6D) *channel_size: An optional int, specifying the channel size of 4D Tensor with format HWCN . \n *@par Outputs: -*y: A 4D Tensor. Has the same type as "x", with format HWCN. +*y: A 4D Tensor. Has the same type as "x", with format HWCN. \n + +*@attention Constraints: +*THIS OPERATOR IS DEPRECATED. It will be removed in a future version. */ REG_OP(DepthwiseWeight6DTo4D) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_UINT16})) From 00032536ea491445c05541b2262dc6468729c024 Mon Sep 17 00:00:00 2001 From: zhangzhenghai Date: Fri, 17 Jun 2022 14:08:17 +0800 Subject: [PATCH 57/59] upgrade Ascend package 17 Jun 22 --- inc/external/acl/acl.h | 4 +- inc/external/acl/acl_tdt_queue.h | 3 +- inc/framework/common/debug/log.h | 2 +- inc/framework/omg/parser/parser_factory.h | 4 +- metadef | 2 +- .../inc/external/runtime/rt_error_codes.h | 234 +++++++++--------- third_party/fwkacllib/inc/ops/encoding_ops.h | 4 +- third_party/fwkacllib/inc/ops/linalg_ops.h | 20 ++ third_party/fwkacllib/inc/ops/math_ops.h | 110 ++++++++ .../inc/ops/matrix_calculation_ops.h | 117 +++++++++ .../fwkacllib/inc/ops/nn_calculation_ops.h | 26 +- third_party/fwkacllib/inc/ops/nn_detect_ops.h | 49 +++- third_party/fwkacllib/inc/ops/nn_norm_ops.h | 4 +- .../fwkacllib/inc/ops/nn_pooling_ops.h | 160 ++++++------ third_party/fwkacllib/inc/ops/ocr_ops.h | 10 +- third_party/fwkacllib/inc/ops/rnn.h | 6 +- 16 files changed, 536 insertions(+), 219 deletions(-) diff --git a/inc/external/acl/acl.h b/inc/external/acl/acl.h index 99e87e28..5fbaccc7 100644 --- a/inc/external/acl/acl.h +++ b/inc/external/acl/acl.h @@ -25,9 +25,9 @@ extern "C" { #endif -// Current version is 1.1.0 +// Current version is 1.2.0 #define ACL_MAJOR_VERSION 1 -#define ACL_MINOR_VERSION 1 +#define ACL_MINOR_VERSION 2 #define ACL_PATCH_VERSION 0 /** diff --git a/inc/external/acl/acl_tdt_queue.h b/inc/external/acl/acl_tdt_queue.h index c8ab02a3..e940c020 100644 --- a/inc/external/acl/acl_tdt_queue.h +++ b/inc/external/acl/acl_tdt_queue.h @@ -219,6 +219,7 @@ ACL_FUNC_VISIBILITY aclError acltdtQueryQueueRoutes(const acltdtQueueRouteQueryI * @brief alloc acltdtBuf * * @param size [IN] alloc buf size + * @param type [IN] reserved parameters, need to set zero currently * @param buf [OUT] pointer to the acltdtBuf * * @retval ACL_SUCCESS The function is successfully executed. @@ -226,7 +227,7 @@ ACL_FUNC_VISIBILITY aclError acltdtQueryQueueRoutes(const acltdtQueueRouteQueryI * * @see acltdtFreeBuf */ -ACL_FUNC_VISIBILITY aclError acltdtAllocBuf(size_t size, acltdtBuf *buf); +ACL_FUNC_VISIBILITY aclError acltdtAllocBuf(size_t size, uint32_t type, acltdtBuf *buf); /** * @ingroup AscendCL diff --git a/inc/framework/common/debug/log.h b/inc/framework/common/debug/log.h index 45c157f3..c50f83c0 100644 --- a/inc/framework/common/debug/log.h +++ b/inc/framework/common/debug/log.h @@ -180,7 +180,7 @@ #define GE_ERRORLOG_AND_ERRORMSG(_status, errormsg) \ { \ GELOGE((_status), "[Check][InnerData]%s", (errormsg)); \ - REPORT_INNER_ERROR("E10052", "%s", (errormsg)); \ + REPORT_INNER_ERROR("E19999", "%s", (errormsg)); \ } #define GE_WARNINGLOG_AND_ERRORMSG(errormsg) \ diff --git a/inc/framework/omg/parser/parser_factory.h b/inc/framework/omg/parser/parser_factory.h index d64a4c2d..cf6499e9 100644 --- a/inc/framework/omg/parser/parser_factory.h +++ b/inc/framework/omg/parser/parser_factory.h @@ -62,7 +62,7 @@ class GE_FUNC_VISIBILITY ModelParserFactory { class GE_FUNC_VISIBILITY ModelParserRegisterar { public: - ModelParserRegisterar(const domi::FrameworkType type, MODEL_PARSER_CREATOR_FUN const fun) { + ModelParserRegisterar(const domi::FrameworkType type, MODEL_PARSER_CREATOR_FUN const fun) noexcept { ModelParserFactory::Instance()->RegisterCreator(type, fun); } ~ModelParserRegisterar() {} @@ -114,7 +114,7 @@ class GE_FUNC_VISIBILITY WeightsParserFactory { class GE_FUNC_VISIBILITY WeightsParserRegisterar { public: - WeightsParserRegisterar(const domi::FrameworkType type, WEIGHTS_PARSER_CREATOR_FUN const fun) { + WeightsParserRegisterar(const domi::FrameworkType type, WEIGHTS_PARSER_CREATOR_FUN const fun) noexcept { WeightsParserFactory::Instance()->RegisterCreator(type, fun); } ~WeightsParserRegisterar() {} diff --git a/metadef b/metadef index 58412ad7..2d98a178 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit 58412ad7aed08cd1c01cc070d80706e4253c9075 +Subproject commit 2d98a17884e656a2446239cdb9cee79543cb0161 diff --git a/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h b/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h index 248303ef..1c8f8e44 100644 --- a/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h +++ b/third_party/fwkacllib/inc/external/runtime/rt_error_codes.h @@ -1,117 +1,117 @@ -/** - * Copyright 2019-2020 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. - */ - -#ifndef __INC_EXTERNEL_RT_ERROR_CODES_H__ -#define __INC_EXTERNEL_RT_ERROR_CODES_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -static const int32_t ACL_RT_SUCCESS = 0; // success - -static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid -static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id -static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null -static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context -static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context -static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid -static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal -static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned -static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed -static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed -static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream -static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread -static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set -static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create -static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream -static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type -static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle -static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type -static const int32_t ACL_ERROR_RT_WAIT_TIMEOUT = 107019; // wait timeout - -static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support -static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error -static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error -static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow -static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device -static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail -static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission -static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource -static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource -static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource -static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource -static const int32_t ACL_ERROR_RT_NO_CDQ_RESOURCE = 207011; // no cdq resource -static const int32_t ACL_ERROR_RT_OVER_LIMIT = 207012; // over limit -static const int32_t ACL_ERROR_RT_QUEUE_EMPTY = 207013; // queue is empty -static const int32_t ACL_ERROR_RT_QUEUE_FULL = 207014; // queue is full -static const int32_t ACL_ERROR_RT_REPEATED_INIT = 207015; // repeated init -static const int32_t ACL_ERROR_RT_AIVEC_OVER_FLOW = 207016; // aivec over flow - -static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error -static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error -static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream -static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream -static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete -static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence -static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete -static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error -static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error -static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support -static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat -static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed -static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout -static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error -static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout -static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception -static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception -static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout -static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception -static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error -static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error -static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error -static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error -static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal -static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering -static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init -static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data -static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error -static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate -static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed -static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed -static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context -static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out -static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error -static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout -static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception -static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception -static const int32_t ACL_ERROR_RT_CDQ_BATCH_ABNORMAL = 507037; // cdq alloc batch abnormal -static const int32_t ACL_ERROR_RT_DIE_MODE_CHANGE_ERROR = 507038; // can not change die mode -static const int32_t ACL_ERROR_RT_DIE_SET_ERROR = 507039; // single die mode can not set die -static const int32_t ACL_ERROR_RT_INVALID_DIEID = 507040; // invalid die id -static const int32_t ACL_ERROR_RT_DIE_MODE_NOT_SET = 507041; // die mode not set - -static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error -static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error -static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect - -#ifdef __cplusplus -} -#endif -#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ +/** +* @file rt_error_codes.h +* +* Copyright (C) Huawei Technologies Co., Ltd. 2019-2020. All Rights Reserved. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +*/ + +#ifndef __INC_EXTERNEL_RT_ERROR_CODES_H__ +#define __INC_EXTERNEL_RT_ERROR_CODES_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +static const int32_t ACL_RT_SUCCESS = 0; // success + +static const int32_t ACL_ERROR_RT_PARAM_INVALID = 107000; // param invalid +static const int32_t ACL_ERROR_RT_INVALID_DEVICEID = 107001; // invalid device id +static const int32_t ACL_ERROR_RT_CONTEXT_NULL = 107002; // current context null +static const int32_t ACL_ERROR_RT_STREAM_CONTEXT = 107003; // stream not in current context +static const int32_t ACL_ERROR_RT_MODEL_CONTEXT = 107004; // model not in current context +static const int32_t ACL_ERROR_RT_STREAM_MODEL = 107005; // stream not in model +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_INVALID = 107006; // event timestamp invalid +static const int32_t ACL_ERROR_RT_EVENT_TIMESTAMP_REVERSAL = 107007; // event timestamp reversal +static const int32_t ACL_ERROR_RT_ADDR_UNALIGNED = 107008; // memory address unaligned +static const int32_t ACL_ERROR_RT_FILE_OPEN = 107009; // open file failed +static const int32_t ACL_ERROR_RT_FILE_WRITE = 107010; // write file failed +static const int32_t ACL_ERROR_RT_STREAM_SUBSCRIBE = 107011; // error subscribe stream +static const int32_t ACL_ERROR_RT_THREAD_SUBSCRIBE = 107012; // error subscribe thread +static const int32_t ACL_ERROR_RT_GROUP_NOT_SET = 107013; // group not set +static const int32_t ACL_ERROR_RT_GROUP_NOT_CREATE = 107014; // group not create +static const int32_t ACL_ERROR_RT_STREAM_NO_CB_REG = 107015; // callback not register to stream +static const int32_t ACL_ERROR_RT_INVALID_MEMORY_TYPE = 107016; // invalid memory type +static const int32_t ACL_ERROR_RT_INVALID_HANDLE = 107017; // invalid handle +static const int32_t ACL_ERROR_RT_INVALID_MALLOC_TYPE = 107018; // invalid malloc type +static const int32_t ACL_ERROR_RT_WAIT_TIMEOUT = 107019; // wait timeout +static const int32_t ACL_ERROR_RT_TASK_TIMEOUT = 107020; // task timeout + +static const int32_t ACL_ERROR_RT_FEATURE_NOT_SUPPORT = 207000; // feature not support +static const int32_t ACL_ERROR_RT_MEMORY_ALLOCATION = 207001; // memory allocation error +static const int32_t ACL_ERROR_RT_MEMORY_FREE = 207002; // memory free error +static const int32_t ACL_ERROR_RT_AICORE_OVER_FLOW = 207003; // aicore over flow +static const int32_t ACL_ERROR_RT_NO_DEVICE = 207004; // no device +static const int32_t ACL_ERROR_RT_RESOURCE_ALLOC_FAIL = 207005; // resource alloc fail +static const int32_t ACL_ERROR_RT_NO_PERMISSION = 207006; // no permission +static const int32_t ACL_ERROR_RT_NO_EVENT_RESOURCE = 207007; // no event resource +static const int32_t ACL_ERROR_RT_NO_STREAM_RESOURCE = 207008; // no stream resource +static const int32_t ACL_ERROR_RT_NO_NOTIFY_RESOURCE = 207009; // no notify resource +static const int32_t ACL_ERROR_RT_NO_MODEL_RESOURCE = 207010; // no model resource +static const int32_t ACL_ERROR_RT_NO_CDQ_RESOURCE = 207011; // no cdq resource +static const int32_t ACL_ERROR_RT_OVER_LIMIT = 207012; // over limit +static const int32_t ACL_ERROR_RT_QUEUE_EMPTY = 207013; // queue is empty +static const int32_t ACL_ERROR_RT_QUEUE_FULL = 207014; // queue is full +static const int32_t ACL_ERROR_RT_REPEATED_INIT = 207015; // repeated init +static const int32_t ACL_ERROR_RT_AIVEC_OVER_FLOW = 207016; // aivec over flow +static const int32_t ACL_ERROR_RT_OVER_FLOW = 207017; // common over flow + +static const int32_t ACL_ERROR_RT_INTERNAL_ERROR = 507000; // runtime internal error +static const int32_t ACL_ERROR_RT_TS_ERROR = 507001; // ts internel error +static const int32_t ACL_ERROR_RT_STREAM_TASK_FULL = 507002; // task full in stream +static const int32_t ACL_ERROR_RT_STREAM_TASK_EMPTY = 507003; // task empty in stream +static const int32_t ACL_ERROR_RT_STREAM_NOT_COMPLETE = 507004; // stream not complete +static const int32_t ACL_ERROR_RT_END_OF_SEQUENCE = 507005; // end of sequence +static const int32_t ACL_ERROR_RT_EVENT_NOT_COMPLETE = 507006; // event not complete +static const int32_t ACL_ERROR_RT_CONTEXT_RELEASE_ERROR = 507007; // context release error +static const int32_t ACL_ERROR_RT_SOC_VERSION = 507008; // soc version error +static const int32_t ACL_ERROR_RT_TASK_TYPE_NOT_SUPPORT = 507009; // task type not support +static const int32_t ACL_ERROR_RT_LOST_HEARTBEAT = 507010; // ts lost heartbeat +static const int32_t ACL_ERROR_RT_MODEL_EXECUTE = 507011; // model execute failed +static const int32_t ACL_ERROR_RT_REPORT_TIMEOUT = 507012; // report timeout +static const int32_t ACL_ERROR_RT_SYS_DMA = 507013; // sys dma error +static const int32_t ACL_ERROR_RT_AICORE_TIMEOUT = 507014; // aicore timeout +static const int32_t ACL_ERROR_RT_AICORE_EXCEPTION = 507015; // aicore exception +static const int32_t ACL_ERROR_RT_AICORE_TRAP_EXCEPTION = 507016; // aicore trap exception +static const int32_t ACL_ERROR_RT_AICPU_TIMEOUT = 507017; // aicpu timeout +static const int32_t ACL_ERROR_RT_AICPU_EXCEPTION = 507018; // aicpu exception +static const int32_t ACL_ERROR_RT_AICPU_DATADUMP_RSP_ERR = 507019; // aicpu datadump response error +static const int32_t ACL_ERROR_RT_AICPU_MODEL_RSP_ERR = 507020; // aicpu model operate response error +static const int32_t ACL_ERROR_RT_PROFILING_ERROR = 507021; // profiling error +static const int32_t ACL_ERROR_RT_IPC_ERROR = 507022; // ipc error +static const int32_t ACL_ERROR_RT_MODEL_ABORT_NORMAL = 507023; // model abort normal +static const int32_t ACL_ERROR_RT_KERNEL_UNREGISTERING = 507024; // kernel unregistering +static const int32_t ACL_ERROR_RT_RINGBUFFER_NOT_INIT = 507025; // ringbuffer not init +static const int32_t ACL_ERROR_RT_RINGBUFFER_NO_DATA = 507026; // ringbuffer no data +static const int32_t ACL_ERROR_RT_KERNEL_LOOKUP = 507027; // kernel lookup error +static const int32_t ACL_ERROR_RT_KERNEL_DUPLICATE = 507028; // kernel register duplicate +static const int32_t ACL_ERROR_RT_DEBUG_REGISTER_FAIL = 507029; // debug register failed +static const int32_t ACL_ERROR_RT_DEBUG_UNREGISTER_FAIL = 507030; // debug unregister failed +static const int32_t ACL_ERROR_RT_LABEL_CONTEXT = 507031; // label not in current context +static const int32_t ACL_ERROR_RT_PROGRAM_USE_OUT = 507032; // program register num use out +static const int32_t ACL_ERROR_RT_DEV_SETUP_ERROR = 507033; // device setup error +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TIMEOUT = 507034; // vector core timeout +static const int32_t ACL_ERROR_RT_VECTOR_CORE_EXCEPTION = 507035; // vector core exception +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_EXCEPTION = 507036; // vector core trap exception +static const int32_t ACL_ERROR_RT_CDQ_BATCH_ABNORMAL = 507037; // cdq alloc batch abnormal +static const int32_t ACL_ERROR_RT_DIE_MODE_CHANGE_ERROR = 507038; // can not change die mode +static const int32_t ACL_ERROR_RT_DIE_SET_ERROR = 507039; // single die mode can not set die +static const int32_t ACL_ERROR_RT_INVALID_DIEID = 507040; // invalid die id +static const int32_t ACL_ERROR_RT_DIE_MODE_NOT_SET = 507041; // die mode not set +static const int32_t ACL_ERROR_RT_AICORE_TRAP_READ_OVERFLOW = 507042; // aic trap read overflow +static const int32_t ACL_ERROR_RT_AICORE_TRAP_WRITE_OVERFLOW = 507043; // aic trap write overflow +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_READ_OVERFLOW = 507044; // aiv trap read overflow +static const int32_t ACL_ERROR_RT_VECTOR_CORE_TRAP_WRITE_OVERFLOW = 507045; // aiv trap write overflow + +static const int32_t ACL_ERROR_RT_DRV_INTERNAL_ERROR = 507899; // drv internal error +static const int32_t ACL_ERROR_RT_AICPU_INTERNAL_ERROR = 507900; // aicpu internal error +static const int32_t ACL_ERROR_RT_SOCKET_CLOSE = 507901; // hdc disconnect + +#ifdef __cplusplus +} +#endif +#endif // __INC_EXTERNEL_RT_ERROR_CODES_H__ diff --git a/third_party/fwkacllib/inc/ops/encoding_ops.h b/third_party/fwkacllib/inc/ops/encoding_ops.h index f96a67e7..73344353 100644 --- a/third_party/fwkacllib/inc/ops/encoding_ops.h +++ b/third_party/fwkacllib/inc/ops/encoding_ops.h @@ -1,5 +1,5 @@ -/** - * Copyright (C) Huawei Technologies Co., Ltd 2022-2022. All rights reserved. +/* + * Copyright (c) Huawei Technologies Co., Ltd 2022-2022. All rights reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/third_party/fwkacllib/inc/ops/linalg_ops.h b/third_party/fwkacllib/inc/ops/linalg_ops.h index bd63c60c..f3cc5aed 100644 --- a/third_party/fwkacllib/inc/ops/linalg_ops.h +++ b/third_party/fwkacllib/inc/ops/linalg_ops.h @@ -525,6 +525,26 @@ REG_OP(BandedTriangularSolve) .ATTR(lower, Bool, true) .ATTR(adjoint, Bool, false) .OP_END_FACTORY_REG(BandedTriangularSolve) + +/** +* @brief Returns the complex conjugatetranspose. + +* @par Inputs: +* @li x: A Tensor. Must be one of the following types: double, float32, float16, + int8, uint8, int16, uint16, int32, uint32, int64, uint64, bool +* @li perm: A Index. Must be one of the following types: int32, int64 \n +* +* @par Outputs: +* @li y: A Tensor. Has the same type as "x" . \n + +* @par Third-party framework compatibility. +* Compatible with tensorflow ConjugateTranspose operator. +*/ +REG_OP(ConjugateTranspose) + .INPUT(x, TensorType::BasicType()) + .INPUT(perm, TensorType::IndexNumberType()) + .OUTPUT(y, TensorType::BasicType()) + .OP_END_FACTORY_REG(ConjugateTranspose) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_LINALG_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/math_ops.h b/third_party/fwkacllib/inc/ops/math_ops.h index 94fd0600..8e9ee4db 100644 --- a/third_party/fwkacllib/inc/ops/math_ops.h +++ b/third_party/fwkacllib/inc/ops/math_ops.h @@ -1217,6 +1217,35 @@ REG_OP(DenseCountSparseOutput) .REQUIRED_ATTR(binary_output, Bool) .OP_END_FACTORY_REG(DenseCountSparseOutput) +/** +* @brief Computes gradients for SparseSegmentSum . \n + +* @par Inputs: +* The input grad must have be type float or double. Inputs include: +* @li grad: A Tensor. Must be one of the following types: bfloat16, float16, float32, double. + gradient propagated to the SparseSegmentSum op. +* @li indices: A Tensor. Must be one of the following types: int32, int64. + indices passed to the corresponding SparseSegmentSum op. +* @li segment_ids: A Tensor of type int32, int64. segment_ids passed to the + corresponding SparseSegmentSum op. +* @li output_dim0: A Tensor of type int32. dimension 0 of "x" passed to + SparseSegmentSum op . \n + +* @par Outputs: +* output:A Tensor. Has the same type as grad . \n + +* @par Third-party framework compatibility +* Compatible with tensorflow SparseSegmentSumGrad operator +*/ + +REG_OP(SparseSegmentSumGrad) + .INPUT(grad, TensorType({DT_BF16, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .INPUT(indices, TensorType({DT_INT32, DT_INT64})) + .INPUT(segment_ids, TensorType({DT_INT32, DT_INT64})) + .INPUT(output_dim0, TensorType({DT_INT32})) + .OUTPUT(output, TensorType({DT_BF16, DT_FLOAT16, DT_FLOAT, DT_DOUBLE})) + .OP_END_FACTORY_REG(SparseSegmentSumGrad) + /** * @brief Count the number of occurrences of each value in the input ragged integer array, * and output it according to the sparse matrix. \n @@ -1335,6 +1364,87 @@ REG_OP(ScaledMaskedSoftmaxGrad) .ATTR(scale, Float, 1.0) .ATTR(fixed_triu_mask, Bool, false) .OP_END_FACTORY_REG(ScaledMaskedSoftmaxGrad) + +/** + * @brief SignBitsPack. + + * @par Inputs: + * one input, including: + * @li x: A 1D Tensor of float32 or float16. + * + * @par Attributes: + * @li size: first dim value of output tensor. + * + * @par Outputs: + * @li y: A 2D Tensor of type uint8 with shape (size, N) + */ +REG_OP(SignBitsPack) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(y, TensorType({DT_UINT8})) + .REQUIRED_ATTR(size, Int) + .OP_END_FACTORY_REG(SignBitsPack) + +/** +* @brief Get sobol samples. \n + +* @par Inputs: +* Three inputs, including: +* @li dim: Dimension of results, which must be a scalar of type int32. +* @li num_results: Number of results, which must be a scalar of type int32. +* @li skip: Number of initial points, which must be a scalar of type int32. \n + +* @par Attributes: +* @li dtype: Data type of output samples. \n + +* @par Outputs: +* @li y: A Tensor with the DT_FLOAT or DT_DOUBLE type generated samples. \n + +* @par Third-party framework compatibility +* @li compatible with tensorflow SobolSample operator. +**/ +REG_OP(SobolSample) + .INPUT(dim, TensorType({DT_INT32})) + .INPUT(num_results, TensorType({DT_INT32})) + .INPUT(skip, TensorType({DT_INT32})) + .OUTPUT(samples, TensorType({DT_FLOAT,DT_DOUBLE})) + .ATTR(dtype, Type, DT_FLOAT) + .OP_END_FACTORY_REG(SobolSample) + +/** + * @brief Count the number of occurrences of each value in the input sparse integer array, + * and output it according to the sparse matrix. \n + + * @par Inputs: + * @li indices: A tensor of type int64. + * @li values: A tensor of type int32 or int64. + * @li dense_shape: A tensor of type int64. + * @li weights: A tensor of type int32 or int64 or float or double. \n + + * @par Attributes: + * @li minlength: An optional int >=-1. Defaults to -1. + * @li maxlength: An optional int >=-1. Defaults to -1. + * @li binary_output: A required bool. \n + + * @par Outputs: + * @li output_indices: A tensor of type int64. + * @li output_values: A tensor of the same type as "weights". + * @li output_dense_shape: A tensor of type int64. \n + + * @par Third-party framework compatibility + * Compatible with the TensorFlow operator SparseCountSparseOutput. \n + */ +REG_OP(SparseCountSparseOutput) + .INPUT(indices, TensorType({DT_INT64})) + .INPUT(values, TensorType({DT_INT32,DT_INT64})) + .INPUT(dense_shape, TensorType({DT_INT64})) + .INPUT(weights, TensorType({DT_INT32,DT_INT64,DT_FLOAT,DT_DOUBLE})) + .OUTPUT(output_indices, TensorType({DT_INT64})) + .OUTPUT(output_values, TensorType({DT_INT32,DT_INT64,DT_FLOAT,DT_DOUBLE})) + .OUTPUT(output_dense_shape, TensorType({DT_INT64})) + .ATTR(minlength, Int, -1) + .ATTR(maxlength, Int, -1) + .REQUIRED_ATTR(binary_output, Bool) + .OP_END_FACTORY_REG(SparseCountSparseOutput) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATH_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index 57b46398..38e22be8 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -155,6 +155,49 @@ REG_OP(AttentionLnQKV) .ATTR(trans_b, Bool, false) .OP_END_FACTORY_REG(AttentionLnQKV) +/** +* @brief + swin_transformer model specific structure.Operator only supports swin_transformer. \n +* @par Inputs: +* Five inputs, including: +* @li x: A Tensor. Must be one of the following types: float16. +* @li gamma: A Tensor. Must be one of the following types: float16. +* @li beta: A Tensor. Must be one of the following types: float16. +* @li weight: A Tensor. Must be one of the following types: float16. +* @li bias: A Tensor. Must be one of the following types: float16. \n + +* @par Attributes: +* @li head_num: A optional attribute, the type is int. +* @li head_dim: A optional attribute, the type is int. +* @li seq_length: A optional attribute, the type is int. +* @li shifts: A optional attribute, the type is list int. Defaults to (). +* @li epsilon: A optional attribute, the type is float. Defaults to 1e-7. \n + +* @par Outputs: +* Three outputs, including: +* @li query_output: A Tensor. Must be one of the following types: float16. +* @li key_output: A Tensor. Must be one of the following types: float16. +* @li value_output: A Tensor. Must be one of the following types: float16. \n + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. \n +*/ +REG_OP(SwinTransformerLnQKV) + .INPUT(x, TensorType({DT_FLOAT16})) + .INPUT(gamma, TensorType({DT_FLOAT16})) + .INPUT(beta, TensorType({DT_FLOAT16})) + .INPUT(weight, TensorType({DT_FLOAT16})) + .INPUT(bias, TensorType({DT_FLOAT16})) + .OUTPUT(query_output, TensorType({DT_FLOAT16})) + .OUTPUT(key_output, TensorType({DT_FLOAT16})) + .OUTPUT(value_output, TensorType({DT_FLOAT16})) + .REQUIRED_ATTR(head_num, Int) + .REQUIRED_ATTR(head_dim, Int) + .REQUIRED_ATTR(seq_length, Int) + .ATTR(shifts, ListInt, {}) + .ATTR(epsilon, Float, 0.0000001) + .OP_END_FACTORY_REG(SwinTransformerLnQKV) + /** *@brief Multiplies matrix "a" by matrix "b", producing "a * b" . \n @@ -1639,6 +1682,80 @@ REG_OP(TensorScatterMin) .OUTPUT(output, TensorType::BasicType()) .OP_END_FACTORY_REG(TensorScatterMin) +/** +* @brief: Returns the batched diagonal part of a batched tensor. \n + +* @par Inputs: +* @li x: A Tensor. Rank r tensor where r >= 2. +* @li k: A Tensor of type int32. Diagonal offset(s). Positive value means superdiagonal, + 0 refers to the main diagonal, and negative value means subdiagonals. k can be a + single integer (for a single diagonal) or a pair of integers specifying the low and + high ends of a matrix band. k[0] must not be larger than k[1]. +* @li padding_value:A Tensor. Must have the same type as input. The value to fill the area + outside the specified diagonal band with. Default is 0. \n + +* @par Outputs: +* @li y: A Tensor. Has the same type as "input". \n + +* @par Attributes: +* @li align:An optional string from: "LEFT_RIGHT", "RIGHT_LEFT", "LEFT_LEFT", "RIGHT_RIGHT". Defaults to "RIGHT_LEFT". + +* @par Third-party framework compatibility +* Compatible with the Tensorflow operator FillDiagonal. +*/ + REG_OP(MatrixDiagPartV3) + .INPUT(x, TensorType::BasicType()) + .INPUT(k, TensorType({DT_INT32})) + .INPUT(padding_value, TensorType::BasicType()) + .OUTPUT(y, TensorType::BasicType()) + .ATTR(align,String ,"RIGHT_LEFT") + .OP_END_FACTORY_REG(MatrixDiagPartV3) + +/** +* @brief Returns a batched diagonal tensor with given batched diagonal values . \n + +* @par Inputs: +* Five inputs, including: +* @li x: Rank `r`, where `r >= 1` \n + +* @li k: +* Diagonal offset(s). Positive value means superdiagonal, 0 refers to the main +* diagonal, and negative value means subdiagonals. `k` can be a single integer +* (for a single diagonal) or a pair of integers specifying the low and high ends +* of a matrix band. `k[0]` must not be larger than `k[1]`. \n + +* @li num_rows: +* The number of rows of the output matrix. If it is not provided, the op assumes +* the output matrix is a square matrix and infers the matrix size from k and the +* innermost dimension of `diagonal`. \n + +* @li num_cols: An NCHW, NHWC, or ND Tensor. +* The number of columns of the output matrix. If it is not provided, the op +* assumes the output matrix is a square matrix and infers the matrix size from +* k and the innermost dimension of `diagonal`. \n + +* @li padding_value: The number to fill the area outside the specified diagonal band with. \n + +* @par Attributes: +* @li align: An optional string from: "LEFT_RIGHT", "RIGHT_LEFT", "LEFT_LEFT", "RIGHT_RIGHT". +* Defaults to "RIGHT_LEFT" \n + +* @par Outputs: +* @li y: Has rank `r+1` when `k` is an integer or `k[0] == k[1]`, rank `r` otherwise . \n + +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator ScatterUpdate. +*/ +REG_OP(MatrixDiagV3) + .INPUT(x, TensorType::BasicType()) + .INPUT(k, TensorType({DT_INT32})) + .INPUT(num_rows, TensorType({DT_INT32})) + .INPUT(num_cols, TensorType({DT_INT32})) + .INPUT(padding_value, TensorType::BasicType()) + .OUTPUT(y, TensorType::BasicType()) + .ATTR(align, String, "RIGHT_LEFT") + .OP_END_FACTORY_REG(MatrixDiagV3) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATRIX_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h index 6b3b817a..bb0770e6 100644 --- a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h @@ -651,21 +651,21 @@ REG_OP(Deconvolution) | Name | Field | Scope |\n |------------------|----------|--------------|\n | x(fmap) | H | [1, 200000] |\n - | | W | [1, 4096] |\n - | Filter Size | H | [1, 255] |\n - | | W | [1, 255] |\n + | | W | [1, 200000] |\n + | Filter Size | H | [1, 200000] |\n + | | W | [1, 200000] |\n | out_backprop | H | [1, 200000] |\n - | | W | [1, 4096] |\n + | | W | [1, 200000] |\n | y | H | [1, 200000] |\n - | | W | [1, 4096] |\n - | Stride | H | [1, 63] |\n - | | W | [1, 63] |\n - | Padding | Top | [0, 255] |\n - | | Bottom | [0, 255] |\n - | | Left | [0, 255] |\n - | | Right | [0, 255] |\n - | Dilation | H | [1, 255] |\n - | | W | [1, 255] |\n + | | W | [1, 200000] |\n + | Stride | H | [1, 200000] |\n + | | W | [1, 200000] |\n + | Padding | Top | [0, 200000] |\n + | | Bottom | [0, 200000] |\n + | | Left | [0, 200000] |\n + | | Right | [0, 200000] |\n + | Dilation | H | [1, 200000] |\n + | | W | [1, 200000] |\n *\n *@par Outputs: * y: A Tensor. Has the same type as x, has the same format as filter_size. diff --git a/third_party/fwkacllib/inc/ops/nn_detect_ops.h b/third_party/fwkacllib/inc/ops/nn_detect_ops.h index 15aa6c20..c5724f43 100644 --- a/third_party/fwkacllib/inc/ops/nn_detect_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_detect_ops.h @@ -1550,8 +1550,8 @@ REG_OP(DecodeWheelsTarget) *@li max_size_per_class: A required attribute of type int, specifying the nms output num per class. *@li max_total_size: A required attribute of type int, specifying the the nms output num per batch. *@li change_coordinate_frame: A optional attribute of type bool, whether to normalize coordinates after clipping. -*@li transpose_box: A optional attribute of type bool, whether inserted transpose before this op. must be "false". -*@li image_size: A optional attribute of type ListInt, the size of the image. \n +* @li transpose_box: A optional attribute of type bool, whether inserted transpose before this op. must be "false". +* @li image_size: A optional attribute of type ListInt, the size of the image. \n *@par Outputs: *@li nmsed_boxes: A 3D Tensor of type float16 with shape (batch, max_total_size, 4), @@ -2352,6 +2352,51 @@ REG_OP(DIoU) .ATTR(is_cross, Bool, true) .ATTR(mode, String, "iou") .OP_END_FACTORY_REG(DIoU) + +/** +* @brief Calculate the intersection ratio of two rotated cuboids . \n + +* @par Inputs: +* @li bboxes : data of grad increment, a 3D Tensor of type float32 with +* shape (B, 7, N). "N" indicates the number of boxes, and the value +* "7" refers to [x, y, z, w, h, d, theta]. +* @li gtboxes: Bounding boxes, a 3D Tensor of type float32 with +* shape (B, 7, K). "K" indcates the number of boxes, and the value +* "7" refers to [x, y, z, w, h, d, theta]. + +* @par Outputs: +* iou: A 3D Tensor of float32 with shape [B, N, K]. + +* @attention Constraints: +* In each batch, the invalid box cannot appear before the valid box. +*/ +REG_OP(Iou3D) + .INPUT(bboxes, TensorType({DT_FLOAT})) + .INPUT(gtboxes, TensorType({DT_FLOAT})) + .OUTPUT(iou, TensorType({DT_FLOAT})) + .OP_END_FACTORY_REG(Iou3D) + +/** +* @brief Generates bounding boxes based on "priors" and "bboxes". +* It is a customized yolox operator . \n + +* @par Inputs: +* Two inputs, including: +* @li priors: prior sample boxes of origin image +* A 2D Tensor of type float32 or float16 with shape (N, 4). +* "N" indicates the number of boxes, and the value "4" refers to "x0", "x1", "y0", and "y1". +* @li bboxes_input: bboxes predicted by the model. A 2D Tensor of type float32 or float16 with shape (B, N, 4). +* "B" indicates the batch_size, N indicates the number of boxes, 4 indicates "dx", "dy", "dw", and "dh" . \n + +* @par Outputs: +* bboxes_output: Bboxes generated based on "priors" and "bboxes_input". Have the same format +* and type as "bboxes_input". +*/ +REG_OP(YoloxBoundingBoxDecode) + .INPUT(priors, TensorType({DT_FLOAT16, DT_FLOAT})) + .INPUT(bboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .OUTPUT(decoded_bboxes, TensorType({DT_FLOAT16, DT_FLOAT})) + .OP_END_FACTORY_REG(YoloxBoundingBoxDecode) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_NN_DETECT_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index 5a2ee6eb..523fb199 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -426,10 +426,10 @@ REG_OP(ConfusionSoftmaxGrad) *@li keepdims: A bool Scalar. If true, retains reduced dimensions with length 1 . \n *@par Outputs: -*y: A Tensor dtype of float16, float32. \n +* y: A Tensor dtype of float16, float32. \n *@attention Constraints: -*THIS OPERATOR IS DEPRECATED. It will be removed in a future version. +* THIS OPERATOR IS DEPRECATED. It will be removed in a future version. */ REG_OP(SoftmaxGradExt) .INPUT(grad, TensorType({DT_FLOAT16,DT_FLOAT})) diff --git a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h index e81b84c4..4c6f7293 100644 --- a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h @@ -1317,33 +1317,38 @@ REG_OP(AvgPool1DD) .ATTR(count_include_pad, Bool, false) .OP_END_FACTORY_REG(AvgPool1DD) /** -*@brief Performs max pooling on the input and outputs both max values and indices . \n +* @brief Performs max pooling on the input and outputs both max values and indices . \n -*@par Inputs: +* @par Inputs: * One input: -*x: An 4d Tensor of type float16. Must set the format, supported format list ["NCHW, NHWC"]. -*@par Attributes: -*@li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for -* each dimension of the input tensor. No default value. -*@li strides: A required list of int8, int16, int32, or int64 values, specifying the stride of the sliding window for -* each dimension of the input tensor. No default value. -*@li pads: A required string. No default value. -*@li dtype: A optional int. default value is 3. -*@li dilation: A optional list of int8, int16, int32, or int64 values. -*@li ceil_mode: A optional bool. default value is false . \n +* x: An 5hd Tensor of type float16. +* Must set the format, supported format list ["NC1HWC0"]. +* @par Attributes: +* @li ksize: A required list of int8, int16, int32, or int64 values, +* specifying the size of the window for each dimension of the input tensor. No default value. +* @li strides: A required list of int8, int16, int32, or int64 values, +* specifying the stride of the sliding window for each dimension of the input tensor. No default value. +* @li pads: A required list of int8, int16, int32, or int64 values, +* specifying the pad of the input feature map. No default value. \n +* @li dtype: A optional int. default value is 3. +* @li dilation: A optional list of int8, int16, int32, or int64 values. +* @li ceil_mode: A optional bool. default value is false . \n -*@par Outputs: -*y: A Tensor. Has the same type and format as input "x". -*argmax: A Tensor. type:uint16. -*@attention Constraints: -*@li "ksize" is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, ksize[1] * ksize[2] <= 255. -*@li "strides is a list that has length 4: strides[0] = 1 or strides[3] = 1, strides[1] <= 63, strides[0] >= 1, -* strides[2] <= 63, strides[2] >= 1. -*@li "dilation" is a list that has length 4. -*@li "ceil_mode" is a bool, default is false . \n +* @par Outputs: +* y: A Tensor. Has the same type and format as input "x". +* argmax: A Tensor. type:uint16. +* @attention Constraints: +* @li ksize: a list that has length 4: +* ksize[0] = 1, ksize[1] = 1, ksize[2] * ksize[3] <= (ub_size-8)*1024//6//2//16. +* @li strides: a list that has length 4: +* strides[0] = 1, strides[1] = 1, 1 <= strides[2] <= 2048, 1 <= strides[3] <= 2048. +* @li pads: a list that has length 4: +* pads[0] = 1, pads[1] = 1, 1 <= pads[2] <= (ksize[2]//2), 1 <= pads[3] <= (ksize[3]//2). +* @li dilation: a list that has length 4. +* @li ceil_mode: is a bool, default is false . \n -*@par Third-party framework compatibility -* Compatible with the TensorFlow operator MaxPoolWithArgmax. +* @par Third-party framework compatibility +* Compatible with the PyTorch operator max_pool2d_with_indices. */ REG_OP(MaxPoolWithArgmaxV2) .INPUT(x, TensorType({DT_FLOAT16})) @@ -1358,36 +1363,44 @@ REG_OP(MaxPoolWithArgmaxV2) .OP_END_FACTORY_REG(MaxPoolWithArgmaxV2) /** -*@brief Performs the backpropagation of MaxPoolWithArgmaxV2 . \n +* @brief Performs the backpropagation of MaxPoolWithArgmaxV2. \n -*@par Inputs: +* @par Inputs: * Three inputs, including: -*@li x: An 4d tensor of type float16. Must set the format, supported format list ["NCHW, NHWC"] -*@li grad: An 4d tensor of type float16. Must set the format, supported format list ["NCHW, NHWC"] -*@li argmx: An 4d tensor of type uint16 or int64. Must set the format, supported format list ["NCHW, NHWC"] \n +* @li x: An 5hd tensor of type float16. +* Must set the format, supported format list ["NC1HWC0"] +* @li grad: An 5hd tensor of type float16. +* Must set the format, supported format list ["NC1HWC0"] +* @li argmax: An 5hd tensor of type uint16 or int64. +* Must set the format, supported format list ["NC1HWC0"] \n -*@par Attributes: -*@li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for - * each dimension of the input tensor. No default value. -*@li strides: A required list of int8, int16, int32, or int64 values, specifying the stride of the sliding window for - * each dimension of the input tensor. No default value. -*@li pads: A required string. No default value. -*@li dtype: A optional int. default value is 3. -*@li dilation: A optional list of int8, int16, int32, or int64 values. -*@li ceil_mode: A optional bool. default value is false . \n - -*@par Outputs: -*y: A Tensor. Has the same type and format as input "x" . \n +* @par Attributes: +* @li ksize: A required list of int8, int16, int32, or int64 values, +* specifying the size of the window for each dimension of the input tensor. No default value. +* @li strides: A required list of int8, int16, int32, or int64 values, +* specifying the stride of the sliding window for each dimension of the input tensor. No default value. +* @li pads: A required list of int8, int16, int32, or int64 values, +* specifying the pad of the input feature map. No default value. \n +* @li dtype: A optional int. default value is 3. +* @li dilation: A optional list of int8, int16, int32, or int64 values. +* @li ceil_mode: A optional bool. default value is false. \n -*@attention Constraints: -*@li "ksize" is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, ksize[1] * ksize[2] <= 255. -*@li "strides" is a list that has length 4: strides[0] = 1 or strides[3] = 1 -*@li "dilation" is a list that has length 4. -*@li "ceil_mode" is a bool, default is false . \n +* @par Outputs: +* y: A Tensor. Has the same type and format as input "x". \n -*@see max_pool_grad_with_argmaxv2 -*@par Third-party framework compatibility -* Compatible with the TensorFlow operator MaxPoolGradWithArgmaxV2. +* @attention Constraints: +* @li ksize: a list that has length 4: +* ksize[0] = 1, ksize[1] = 1, ksize[2] * ksize[3] <= (ub_size-8)*1024//7//2//16. +* @li strides: a list that has length 4: +* strides[0] = 1, strides[1] = 1, 1 <= strides[2] <= 2048, 1 <= strides[3] <= 2048. +* @li pads: a list that has length 4: +* pads[0] = 1, pads[1] = 1, 1 <= pads[2] <= (ksize[2]//2), 1 <= pads[3] <= (ksize[3]//2). +* @li dilation: a list that has length 4. +* @li ceil_mode: is a bool, default is false. \n + +* @see max_pool_grad_with_argmaxv2 +* @par Third-party framework compatibility +* Compatible with the PyTorch backward operator of max_pool2d_with_indices. */ REG_OP(MaxPoolGradWithArgmaxV2) @@ -1674,24 +1687,28 @@ REG_OP(AdaptiveAvgPool2dGrad) * @li argmax: A tensor of type uint16 or int64. \n * @par Attributes: -* @li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for -* each dimension of the input tensor. No default value. -* @li strides: A required list of int8, int16, int32, or int64 values, specifying the stride of the sliding window for -* each dimension of the input tensor. No default value. -* @li pads: A required listint. \n +* @li ksize: A required list of int8, int16, int32, or int64 values, +* specifying the size of the window for each dimension of the input tensor. No default value. +* @li strides: A required list of int8, int16, int32, or int64 values, +* specifying the stride of the sliding window for each dimension of the input tensor. No default value. +* @li pads: A required list of int8, int16, int32, or int64 values, +* specifying the pad of the input feature map. No default value. \n * @par Outputs: * y: A Tensor. Has the same type and format as input "x". \n * @attention Constraints: -* @li ksize: is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, ksize[1] * ksize[2] <= 255. -* @li strides: is a list that has length 4: strides[0] = 1 or strides[3] = 1 -* @li pads: listint. -* @li ceil_mode: defaults to False. -* @li data_format: A optional string. \n +* @li The MaxPoolGradWithArgmaxV2 operator has the same function, and it is recommended to use the V2 operator. +* @li ksize: a list that has length 4: +* ksize[0] = 1, ksize[3] = 1, ksize[1] * ksize[2] <= (ub_size-8)*1024//7//2//16. +* @li strides: a list that has length 4: +* strides[0] = 1, strides[3] = 1, 1 <= strides[1] <= 2048, 1 <= strides[2] <= 2048. +* @li pads: a list that has length 4: +* pads[0] = 1, pads[3] = 1, 1 <= pads[2] <= (ksize[1]//2), 1 <= pads[2] <= (ksize[3]//2). +* @li ceil_mode: defaults to False.\n * @par Third-party framework compatibility -* Compatible with the TensorFlow operator MaxPoolGradWithArgmaxV1. +* Compatible with the Pytorch backward operator of max_pool2d_with_indices. */ REG_OP(MaxPoolGradWithArgmaxV1) @@ -1715,26 +1732,29 @@ REG_OP(MaxPoolGradWithArgmaxV1) * x: A Tensor of type float16. \n * @par Attributes: -* @li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for -* each dimension of the input tensor. No default value. -* @li strides: A required list of int8, int16, int32, or int64 values, specifying the stride of the sliding window for -* each dimension of the input tensor. No default value. -* @li pads: A required string. No default value. \n +* @li ksize: A required list of int8, int16, int32, or int64 values, +* specifying the size of the window for each dimension of the input tensor. No default value. +* @li strides: A required list of int8, int16, int32, or int64 values, +* specifying the stride of the sliding window for each dimension of the input tensor. No default value. +* @li pads: A required list of int8, int16, int32, or int64 values, +* specifying the pad of the input feature map. No default value. \n * @par Outputs: * y: A Tensor. Has the same type and format as input "x". * argmax: A Tensor. type:uint16. \n * @attention Constraints: -* @li ksize: a list that has length 4: ksize[0] = 1 or ksize[3] = 1, ksize[1] * ksize[2] <= 255. -* @li stride: a list that has length 4: strides[0] = 1 or strides[3] = 1, strides[1] <= 63, strides[0] >= 1, -* strides[2] <= 63, strides[2] >= 1. -* @li pads: listint. +* @li The MaxPoolWithArgmaxV2 operator has the same function, and it is recommended to use the V2 operator. +* @li ksize: a list that has length 4: +* ksize[0] = 1, ksize[3] = 1, ksize[1] * ksize[2] <= (ub_size-8)*1024//6//2//16. +* @li strides: a list that has length 4: +* strides[0] = 1, strides[3] = 1, 1 <= strides[1] <= 2048, 1 <= strides[2] <= 2048. +* @li pads: a list that has length 4: +* pads[0] = 1, pads[3] = 1, 1 <= pads[1] <= (ksize[1]//2), 1 <= pads[2] <= (ksize[2]//2). * @li ceil_mode: defaults to False. -* @li data_format: A optional string. \n * @par Third-party framework compatibility -* Compatible with the TensorFlow operator MaxPoolWithArgmaxV1. +* Compatible with the PyTorch operator max_pool2d_with_indices. */ REG_OP(MaxPoolWithArgmaxV1) .INPUT(x, TensorType({DT_FLOAT16})) diff --git a/third_party/fwkacllib/inc/ops/ocr_ops.h b/third_party/fwkacllib/inc/ops/ocr_ops.h index efaa7aa7..9f43c8a6 100644 --- a/third_party/fwkacllib/inc/ops/ocr_ops.h +++ b/third_party/fwkacllib/inc/ops/ocr_ops.h @@ -239,10 +239,10 @@ REG_OP(OCRDetectionPostHandle) *@li polys_data: A Tensor of type int32. point data of every poly. *@li polys_offset:A Tensor of type int32. Offset of every poly . *@li polys_size:A Tensor of type int32. Size of every poly. -*@li img_h:A Tensor of type int32. Height of original image. -*@li img_w:A Tensor of type int32. Width of original image. *@li h_scale:A Tensor of type float. Expand scale of height. -*@li w_scale:A Tensor of type float. Expand scale of width. \n +*@li w_scale:A Tensor of type float. Expand scale of width. +*@li img_h:A Tensor of type int32. Height of original image. +*@li img_w:A Tensor of type int32. Width of original image. \n *@par Outputs: *@li clipped_polys_data: A Tensor of type int32. point data of every clipped poly. \n @@ -254,10 +254,10 @@ REG_OP(ResizeAndClipPolys) .INPUT(polys_data, TensorType({DT_INT32})) .INPUT(polys_offset, TensorType({DT_INT32})) .INPUT(polys_size, TensorType({DT_INT32})) - .INPUT(img_h, TensorType({DT_INT32})) - .INPUT(img_w, TensorType({DT_INT32})) .INPUT(h_scale, TensorType({DT_FLOAT})) .INPUT(w_scale, TensorType({DT_FLOAT})) + .INPUT(img_h, TensorType({DT_INT32})) + .INPUT(img_w, TensorType({DT_INT32})) .OUTPUT(clipped_polys_data, TensorType({DT_INT32})) .OUTPUT(clipped_polys_offset, TensorType({DT_INT32})) .OUTPUT(clipped_polys_size, TensorType({DT_INT32})) diff --git a/third_party/fwkacllib/inc/ops/rnn.h b/third_party/fwkacllib/inc/ops/rnn.h index 2ab5843f..7f742957 100644 --- a/third_party/fwkacllib/inc/ops/rnn.h +++ b/third_party/fwkacllib/inc/ops/rnn.h @@ -1320,6 +1320,7 @@ REG_OP(DynamicGRUV2Grad) * @li reset:A 4D Tensor. Must be one of the following types: float16, float32. * @li new:A 4D Tensor. Must be one of the following types: float16, float32. * @li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32. +* @li seq_length:A 1D Tensor. Must be one of the following types: float16, float32. * @par Attributes: * @li t_state:An Int identifying the current t state. Default to [0, 4]. @@ -1343,6 +1344,7 @@ REG_OP(GRUV2HiddenGradCell) .INPUT(reset, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(new, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(hidden_new, TensorType({DT_FLOAT16, DT_FLOAT})) + .OPTIONAL_INPUT(seq_length, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(dh_prev, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(dgate_h, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(dnt_x, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -1353,7 +1355,7 @@ REG_OP(GRUV2HiddenGradCell) /** * @brief: DynamicGRUCellGrad calculation. * @par Inputs: -* ten inputs: \n +* eleven inputs: \n * @li dh_pre_t:A 4D Tensor. Must be one of the following types: float16, float32. * @li h:A 4D Tensor. Must be one of the following types: float16, float32. * @li dy:A 4D Tensor. Must be one of the following types: float16, float32. @@ -1364,6 +1366,7 @@ REG_OP(GRUV2HiddenGradCell) * @li hidden_new:A 4D Tensor. Must be one of the following types: float16, float32.+ * @li init_h:A 4D Tensor. Must be one of the following types: float16, float32. * @li t_state:A 1D Tensor. Must be one of the following types: int32. The format must be ND. +* @li seq_length:A 1D Tensor. Must be one of the following types: float16, float32. * @par Attributes: * gate_order:An string identifying the gate order in weight and bias. Default to "zrh". "rzh" is another option. @@ -1388,6 +1391,7 @@ REG_OP(DynamicGRUCellGrad) .INPUT(hidden_new, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(init_h, TensorType({DT_FLOAT16, DT_FLOAT})) .INPUT(t_state, TensorType({DT_INT32, DT_INT32})) + .OPTIONAL_INPUT(seq_length, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(dh_prev, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(dgate_h, TensorType({DT_FLOAT16, DT_FLOAT})) .OUTPUT(dnt_x, TensorType({DT_FLOAT16, DT_FLOAT})) From ec3d7db8441df09cd0311b9800e60852543dbfc0 Mon Sep 17 00:00:00 2001 From: majorzhang Date: Tue, 28 Jun 2022 15:55:25 +0800 Subject: [PATCH 58/59] upgrade Ascend package 28 Jun 22 --- inc/external/acl/acl_op_compiler.h | 28 ++ metadef | 2 +- third_party/fwkacllib/inc/ops/array_ops.h | 33 +++ third_party/fwkacllib/inc/ops/cluster.h | 14 +- .../inc/ops/elewise_calculation_ops.h | 228 ++++++++-------- .../inc/ops/matrix_calculation_ops.h | 245 ++++++++++------- .../fwkacllib/inc/ops/nn_batch_norm_ops.h | 27 +- .../fwkacllib/inc/ops/nn_calculation_ops.h | 246 +++++++++--------- third_party/fwkacllib/inc/ops/nn_norm_ops.h | 54 +++- third_party/fwkacllib/inc/ops/nn_ops.h | 20 +- .../fwkacllib/inc/ops/nn_pooling_ops.h | 245 ++++++++--------- .../fwkacllib/inc/ops/nn_training_ops.h | 59 ++--- .../fwkacllib/inc/ops/nonlinear_fuc_ops.h | 33 +-- third_party/fwkacllib/inc/ops/quantize_ops.h | 6 +- third_party/fwkacllib/inc/ops/reduce_ops.h | 61 +++-- third_party/fwkacllib/inc/ops/selection_ops.h | 152 +++++------ 16 files changed, 842 insertions(+), 611 deletions(-) diff --git a/inc/external/acl/acl_op_compiler.h b/inc/external/acl/acl_op_compiler.h index 9de0ee85..a0a3f786 100644 --- a/inc/external/acl/acl_op_compiler.h +++ b/inc/external/acl/acl_op_compiler.h @@ -92,6 +92,34 @@ ACL_FUNC_VISIBILITY aclError aclopCompileAndExecute( int numOutputs, const aclTensorDesc *const outputDesc[], aclDataBuffer *const outputs[], const aclopAttr *attr, aclopEngineType engineType, aclopCompileType compileFlag, const char *opPath, aclrtStream stream); +/** + * @ingroup AscendCL + * @brief compile and execute op + * + * @param opType [IN] op type + * @param numInputs [IN] number of inputs + * @param inputDesc [IN] pointer to array of input tensor descriptions + * @param inputs [IN] pointer to array of input buffers + * @param numOutputs [IN] number of outputs + * @param outputDesc [IN|OUT] pointer to array of output tensor descriptions + * @param outputs [IN] pointer to array of outputs buffers + * @param attr [IN] pointer to instance of aclopAttr. + * may pass nullptr if the op has no attribute + * @param engineType [IN] engine type + * @param compileFlag [IN] compile flag + * @param opPath [IN] path of op + * @param stream [IN] stream handle + * + * @retval ACL_SUCCESS The function is successfully executed. + * @retval OtherValues Failure + */ +ACL_FUNC_VISIBILITY aclError aclopCompileAndExecuteV2(const char *opType, int numInputs, aclTensorDesc *inputDesc[], + aclDataBuffer *inputs[], int numOutputs, + aclTensorDesc *outputDesc[], aclDataBuffer *outputs[], + aclopAttr *attr, aclopEngineType engineType, + aclopCompileType compileFlag, const char *opPath, + aclrtStream stream); + /** * @ingroup AscendCL * @brief set compile option diff --git a/metadef b/metadef index 2d98a178..175dce71 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit 2d98a17884e656a2446239cdb9cee79543cb0161 +Subproject commit 175dce710e744666c6204540857634f362aafd61 diff --git a/third_party/fwkacllib/inc/ops/array_ops.h b/third_party/fwkacllib/inc/ops/array_ops.h index 924f98e4..17ab4322 100644 --- a/third_party/fwkacllib/inc/ops/array_ops.h +++ b/third_party/fwkacllib/inc/ops/array_ops.h @@ -1583,6 +1583,39 @@ REG_OP(UniqueConsecutive) .ATTR(return_counts, Bool, false) .ATTR(axis, Int, 1000) .OP_END_FACTORY_REG(UniqueConsecutive) + +/** +* @brief Decodes a variant Tensor into a RaggedTensor. \n +* +* @par Input: +* @li encoded_ragged: A Tensor of type variant. A variant Tensor containing encoded RaggedTensors. \n +* +* @par Outputs: +* @li output_nested_splits: A list of output_ragged_rank Tensor objects with type int32 or int64. +* @li output_dense_values: A Tensor, which must be one of the following types: +* double, float32, float16, int8, uint8, int16, uint16, int32, uint32, int64, uint64, bool. \n +* +* @par Attributes: +* @li input_ragged_rank: An int that is >= -1. The ragged rank of each encoded RaggedTensor component in the input. +* If set to -1, this is inferred as output_n - rank(encoded_ragged). +* @li output_ragged_rank: An int that is >= 0. The expected ragged rank of the output RaggedTensor. +* The following must hold: output_n = rank(encoded_ragged) + input_n. +* @li Tvalues: The data type of output_dense_values. +* @li Tsplits: The data type of output_nested_splits. An optional DType of "int32, int64". Defaults to `int64`. \n +* +* @par Third-party framework compatibility. +* Compatible with tensorflow RaggedTensorFromVariant operator. +*/ +REG_OP(RaggedTensorFromVariant) + .INPUT(encoded_ragged, TensorType({DT_VARIANT})) + .DYNAMIC_OUTPUT(output_nested_splits, TensorType({DT_INT32, DT_INT64})) + .OUTPUT(output_dense_values, TensorType::BasicType()) + .REQUIRED_ATTR(input_ragged_rank, Int) + .REQUIRED_ATTR(output_ragged_rank, Int) + .REQUIRED_ATTR(Tvalues, Type) + .ATTR(Tsplits, Type, DT_INT64) + .OP_END_FACTORY_REG(RaggedTensorFromVariant) + } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_ARRAY_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/cluster.h b/third_party/fwkacllib/inc/ops/cluster.h index 19b4ea05..6e41e569 100644 --- a/third_party/fwkacllib/inc/ops/cluster.h +++ b/third_party/fwkacllib/inc/ops/cluster.h @@ -29,19 +29,19 @@ namespace ge { * @brief Perform k-means clustering on a data matrix. \n * @par Inputs: -* Three required inputs and one optional inputs, including: \n -* @li x: A 2D tensor of data type float32. \n -* @li y: A 2D tensor of data type float32. \n -* @li sum_square_x: An optional 2D tensor of data type float32. \n +* Three required inputs and one optional inputs, including: +* @li x: A 2D tensor of data type float32. +* @li y: A 2D tensor of data type float32. +* @li sum_square_x: An optional 2D tensor of data type float32. * @li sum_square_y: A 2D tensor of data type float32. \n * @par Attributes: * use_actual_distance: Indicates whether to calculate the complete distance. \n * @par Outputs: -* @li segment_sum: A tensor of data type float32. \n -* @li segment_count: A tensor of data type float32. \n -* @li k_mean_total_sum: A tensor of data type float32. \n +* @li segment_sum: A tensor of data type float32. +* @li segment_count: A tensor of data type float32. +* @li k_mean_total_sum: A tensor of data type float32. */ REG_OP(KMeansCentroids) .INPUT(x, TensorType({DT_FLOAT})) diff --git a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h index 58650670..29cfa4f5 100644 --- a/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/elewise_calculation_ops.h @@ -48,29 +48,29 @@ REG_OP(AddN) .OP_END_FACTORY_REG(AddN) /** -*@brief Calculates the reversed outputs of the function "maximum" +*@brief Calculates the reversed outputs of the function "maximum". *@par Inputs: -*Three inputs, including: -* @li grads: A mutable Tensor. Must be one of the following types: -* float16, float32, int32. -* @li x1: A mutable Tensor of the same type as "grads". -* @li x2: A mutable Tensor of the same type as "grads". \n +* Three inputs, including: +*@li grads: A mutable Tensor. Must be one of the following types: +* float16, float32, int32. +*@li x1: A mutable Tensor of the same type as "grads". +*@li x2: A mutable Tensor of the same type as "grads". \n *@par Attributes: *@li grad_x: An optional bool. Defaults to "True". -* If "True", "y1" will be output. -* If "False", "y1" will not be output. \n +* If "True", "y1" will be output. +* If "False", "y1" will not be output. \n *@li grad_y: An optional bool. Defaults to "True". -* If "True", "y2" will be output. -* If "False", "y2" will not be output. \n +* If "True", "y2" will be output. +* If "False", "y2" will not be output. \n *@par Outputs: -* @li y1: A mutable Tensor. Has the same type as "grads". -* @li y2: A mutable Tensor. Has the same type as "grads". \n +*@li y1: A mutable Tensor. Has the same type as "grads". +*@li y2: A mutable Tensor. Has the same type as "grads". \n -*@par Third-party framework compatibility +*@par Third-party framework compatibility: * Compatible with the TensorFlow operator MaximumGrad. */ REG_OP(MaximumGrad) @@ -84,29 +84,29 @@ REG_OP(MaximumGrad) .OP_END_FACTORY_REG(MaximumGrad) /** -*@brief Calculates the reversed outputs of the function "minimum" +*@brief Calculates the reversed outputs of the function "minimum". *@par Inputs: -*Three inputs, including: -* @li grads: A mutable Tensor. Must be one of the following types: -* float16, float32, int32. -* @li x1: A mutable Tensor of the same type as "grads". -* @li x2: A mutable Tensor of the same type as "grads". \n +* Three inputs, including: +*@li grads: A mutable Tensor. Must be one of the following types: +* float16, float32, int32. +*@li x1: A mutable Tensor of the same type as "grads". +*@li x2: A mutable Tensor of the same type as "grads". \n *@par Attributes: *@li grad_x: An optional bool. Defaults to "True". -* If "True", "y1" will be output. -* If "False", "y1" will not be output. \n +* If "True", "y1" will be output. +* If "False", "y1" will not be output. \n *@li grad_y: An optional bool. Defaults to "True". -* If "True", "y2" will be output. -* If "False", "y2" will not be output. \n +* If "True", "y2" will be output. +* If "False", "y2" will not be output. \n *@par Outputs: -* @li y1: A mutable Tensor. Has the same type as "grads". -* @li y2: A mutable Tensor. Has the same type as "grads". \n +*@li y1: A mutable Tensor. Has the same type as "grads". +*@li y2: A mutable Tensor. Has the same type as "grads". \n -*@par Third-party framework compatibility +*@par Third-party framework compatibility: * Compatible with the TensorFlow operator MinimumGrad. */ REG_OP(MinimumGrad) @@ -552,15 +552,16 @@ REG_OP(Expint) .OP_END_FACTORY_REG(Expint) /** -*@brief: Computes the reciprocal of "x". \n +*@brief: Computes the reciprocal of "x". -*@par Inputs:\n -*x: A Tensor. Must be one of the following types: float16, float32, int32, int64, double, complex64, complex128. \n +*@par Inputs: +*x: A Tensor. Must be one of the following types: float16, float32, +* int32, int64, double, complex64, complex128. \n *@par Outputs: -*y: A Tensor. Has the same type as "x". \n +*y: A Tensor. Must be one of the following type: float16, float32, int32. \n -*@par Third-party framework compatibility +*@par Third-party framework compatibility: * Compatible with the TensorFlow operator Inv. */ REG_OP(Inv) @@ -569,18 +570,19 @@ REG_OP(Inv) .OP_END_FACTORY_REG(Inv) /** -*@brief: Computes "x" reciprocal grad, dx = -1*dy*y*y, where, "y = 1/x", and "dy" - is the corresponding input gradient. \n +*@brief: Computes "x" reciprocal grad, dx = -1*dy*y*y, where, "y = 1/x", +* and "dy" is the corresponding input gradient. *@par Inputs: * Two inputs, including: -* @li x: A Tensor. Must be one of the following types: float16, float32, int32, int8. -* @li grad: A Tensor. Has the same type as "x". \n +*@li x: A Tensor. Must be one of the following types: float16, float32, +* int32, int8. +*@li grad: A Tensor. Has the same type as "x". \n *@par Outputs: *y: A Tensor, Has the same type as "x". \n -*@par Third-party framework compatibility +*@par Third-party framework compatibility: * Compatible with the TensorFlow operator InvGrad. */ REG_OP(InvGrad) @@ -633,25 +635,27 @@ REG_OP(Log1p) /** *@brief Returns element-wise remainder of division. + *@par Inputs: -*Two inputs, including: -* @li x1: A Tensor. Must be one of the following types: float16, float32, - * int32, int64, int8, uint8, double. -* @li x2: A Tensor of the same type as "x1". \n +* Two inputs, including: +*@li x1: A Tensor. Must be one of the following types: float16, float32, +* int32, int64, int8, uint8, double. +*@li x2: A Tensor of the same type as "x1". \n *@par Outputs: -*y: A Tensor. Has the same type as "x1". +*y: A Tensor. Has the same type as "x1". \n *@attention Constraints: -*@li x2: The input data does not support 0 +*@li x2: The input data does not support 0. *@li When NUM exceeds 2048 , the accuracy of operator cannot guarantee the -*requirement of double thousandths in the mini form +* requirement of double thousandths in the mini form. *@li Due to different architectures, the calculation results of this operator -*on NPU and CPU may be inconsistent -*@li If shape is expressed as (D1,D2... ,Dn), then D1*D2... *DN<=1000000,n<=8 +* on NPU and CPU may be inconsistent. +*@li If shape is expressed as (D1,D2... ,Dn), +* then D1*D2... *DN<=1000000,n<=8. \n -*@par Third-party framework compatibility -*Compatible with the TensorFlow operator Mod. +*@par Third-party framework compatibility: +* Compatible with the TensorFlow operator Mod. */ REG_OP(Mod) .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32, DT_INT8, DT_UINT8, @@ -663,18 +667,18 @@ REG_OP(Mod) .OP_END_FACTORY_REG(Mod) /** -*@brief: Returns the truth value of (x != y) element-wise. \n +*@brief Returns the truth value of (x != y) element-wise. *@par Inputs: * Two inputs, including: *@li x1: A Tensor. Must be one of the following types: float16, float32, int32, - * int8, uint8, double, int16, int64, uint16, half, uint32, uint64 +* int8, uint8, double, int16, int64, uint16, half, uint32, uint64. *@li x2: A Tensor of the same type as "x1". \n *@par Outputs: *y: A Tensor of type bool. \n -*@par Third-party framework compatibility +*@par Third-party framework compatibility: * Compatible with the TensorFlow operator NotEqual. */ REG_OP(NotEqual) @@ -684,16 +688,17 @@ REG_OP(NotEqual) .OP_END_FACTORY_REG(NotEqual) /** -* @brief Computes ndtri element-wise (y = sqrt(2) * erfinv(2 * x - 1)) +*@brief Computes ndtri element-wise (y = sqrt(2) * erfinv(2 * x - 1)). -* @par Inputs: -* One input: -* x: A Tensor. Must be one of the following types: bfloat16, float16, float32, double \n +*@par Inputs: +* One input, including: \n +*x: A Tensor. Must be one of the following types: bfloat16, float16, +* float32, double. \n -* @par Outputs: -* y: A Tensor. Has the same type and format as input "x". \n +*@par Outputs: +*y: A Tensor. Has the same type and format as input "x". \n -* @par Third-party framework compatibility +*@par Third-party framework compatibility: * Compatible with the TensorFlow operator Ndtri. */ REG_OP(Ndtri) @@ -721,13 +726,12 @@ REG_OP(Neg) .OP_END_FACTORY_REG(Neg) /** -*@brief Returns x1/x2 element-wise for integer types. \n +*@brief Returns x1/x2 element-wise for integer types. *@par Inputs: *@li x1: A Tensor. Must be one of the following types: -* float32, float64, int32, uint8, int16, int8, -* complex64, int64, qint8, quint8, qint32, uint16, -* complex128, float16, uint32, uint64, complex64, complex128. +* float32, float16, int8, uint8, int32, int16, +* uint16, double, int64, complex64, complex128. *@li x2: A Tensor of the same data type as "x1". \n *@par Outputs: @@ -778,7 +782,7 @@ REG_OP(Xdivy) /** * @brief Computes "x" multiplied by the logarithm of y element-wise, -* if "x" == 0, return "0". \n +* if "x" == 0, return "0". * @par Inputs: * Two inputs, including: @@ -803,7 +807,7 @@ REG_OP(Xlog1py) /** *@brief Computes "x" multiplied by the logarithm of y element-wise, -* if "x" == 0, return "0". \n +* if "x" == 0, return "0". *@par Inputs: * Two inputs, including: @@ -1032,7 +1036,7 @@ REG_OP(LogicalOr) .OP_END_FACTORY_REG(LogicalOr) /** -* @brief Computes spence of x element-wise. \n +* @brief Computes spence of x element-wise. * * @par Inputs: @@ -1423,7 +1427,7 @@ REG_OP(RsqrtGrad) .OP_END_FACTORY_REG(RsqrtGrad) /** -*@brief Computes hyperbolic sine of "x" element-wise. \n +*@brief Computes hyperbolic sine of "x" element-wise. *@par Inputs: *x: An NCHW, NHWC,or ND Tensor of type float, double, complex64, @@ -1509,18 +1513,18 @@ REG_OP(DivNoNan) .OP_END_FACTORY_REG(DivNoNan) /** -*@brief Reverses specific dimensions of a tensor. \n +*@brief Reverses specific dimensions of a tensor. *@par Inputs: * One input: \n *x: A Tensor, Must be one of the following types: -* int32, uint8, int16, int8, int64, int64, uint16, uint32, uint64, -* and format can be [NCHW,NHWC,ND] +* int32, uint8, int16, int8, int64, int64, uint16, uint32, uint64, +* and format can be [NCHW,NHWC,ND]. \n *@par Outputs: -*y: A Tensor. Has the same type and format as "x" +*y: A Tensor. Has the same type and format as "x". \n -*@par Third-party framework compatibility +*@par Third-party framework compatibility: * Compatible with the TensorFlow operator Invert. */ REG_OP(Invert) @@ -1768,16 +1772,16 @@ REG_OP(Atan2) .OP_END_FACTORY_REG(Atan2) /** -* @brief Computes fresnel_cos of x element-wise. \n - +*@brief Computes fresnel_cos of x element-wise. * -* @par Inputs: -* x: A tensor. Must be one of the following types: bfloat16, float16, float32, double. +*@par Inputs: +*x: A tensor. Must be one of the following types: bfloat16, float16, float32, +* double. \n * -* @par Outputs: -* y: A tensor. Has the same type as "x". +*@par Outputs: +*y: A tensor. Has the same type as "x". \n * -* @par Third-party framework compatibility +*@par Third-party framework compatibility * Compatible with the TensorFlow operator FresnelCos. * */ @@ -1787,16 +1791,17 @@ REG_OP(FresnelCos) .OP_END_FACTORY_REG(FresnelCos) /** -* @brief Computes fresnel_sin of x element-wise. \n +*@brief Computes fresnel_sin of x element-wise. * -* @par Inputs: -* x: A tensor. Must be one of the following types: bfloat16, float16, float32, double. +*@par Inputs: +*x: A tensor. Must be one of the following types: bfloat16, float16, float32, +* double. \n * -* @par Outputs: -* y: A tensor. Has the same type as "x". +*@par Outputs: +*y: A tensor. Has the same type as "x". \n * -* @par Third-party framework compatibility +*@par Third-party framework compatibility: * Compatible with the TensorFlow operator FresnelSin. * */ @@ -2312,7 +2317,7 @@ REG_OP(Sin) .OP_END_FACTORY_REG(Sin) /** -*@brief: Computes tan of "x" element-wise. \n +*@brief: Computes tan of "x" element-wise. *@par Inputs: *One input: @@ -2332,7 +2337,7 @@ REG_OP(Tan) .OP_END_FACTORY_REG(Tan) /** -*@brief Returns element-wise remainder of division. \n +*@brief Returns element-wise remainder of division. *@par Inputs: *Two inputs, including: @@ -2352,7 +2357,7 @@ REG_OP(Tan) *@li If shape is expressed as (D1,D2... ,Dn), then D1*D2... *DN<=1000000,n<=8 *@par Third-party framework compatibility -*@li Compatible with the TensorFlow operator TruncateMod. +*Compatible with the TensorFlow operator TruncateMod. */ REG_OP(TruncateMod) .INPUT(x1, TensorType({DT_FLOAT16, DT_FLOAT, DT_DOUBLE, DT_INT64, @@ -3133,7 +3138,7 @@ REG_OP(SquareSumV2) .OP_END_FACTORY_REG(SquareSumV2) /** -*@brief Confuse reducesumd and square. \n +*@brief Confuse reducesumd and square. *@par Inputs: *x: A Tensor of type float16, float32. \n @@ -3178,19 +3183,20 @@ REG_OP(SquareSumAll) .OP_END_FACTORY_REG(SquareSumAll) /** -*@brief Confuse broadcast, addn and mul. \n +*@brief Confuse broadcast, addn and mul. *@par Inputs: *Three inputs, including: -* @li x1: A Tensor. Must be one of the following types:int32, int16, float16, float32. -* @li x2: A Tensor of the same type as "x1". -* @li x3: A Tensor of the same type as "x1". \n +*@li x1: A Tensor. Must be one of the following types:int32, int16, +* float16, float32. +*@li x2: A Tensor of the same type as "x1". +*@li x3: A Tensor of the same type as "x1". \n *@par Outputs: -* y: A Tensor. Has the same type as "x1". +*y: A Tensor. Has the same type as "x1". \n *@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(FusedMulAddN) .INPUT(x1, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT32, DT_INT16})) @@ -3200,7 +3206,7 @@ REG_OP(FusedMulAddN) .OP_END_FACTORY_REG(FusedMulAddN) /** -*@brief Add 'bias' to 'x'. \n +*@brief Add 'bias' to 'x'. *@par Inputs: * Two inputs, including: @@ -3209,22 +3215,31 @@ REG_OP(FusedMulAddN) *@par Attributes: *@li axis: An optional int32 used to compute the shape of bias input from the online bottoms. Defaults to "1". -*@li num_axes: An optional int32 used to compute the shape of bias input from a Caffe model trained offline. Defaults to "1". -*@li bias_from_blob: An optional bool. If "true", bias is input from a Caffe model trained offline. If "false", bias is input from online bottoms. Defaults to "true". \n +*@li num_axes: An optional int32 used to compute the shape of +* bias input from a Caffe model trained offline. Defaults to "1". +*@li bias_from_blob: An optional bool. If "true", bias is input from a Caffe model trained offline. +* If "false", bias is input from online bottoms. Defaults to "true". \n *@par Outputs: *y: An ND tensor of type float16 or float32. \n -*@attention Constraints:\n +*@attention Constraints: * Assume that the shape length of "x" is "n" and that of "bias" is "m". *@li "axis" is within the range [-n, n-1]. num_axes >= -1. -*@li If "bias_from_blob = true", "num_axes = -1", and "axis >= 0", the ith axis of "bias" and the (i+"axis")th axis of "x" must have the same size (0 <= i < n-axis).\n +*@li If "bias_from_blob = true", "num_axes = -1", and "axis >= 0", +* the ith axis of "bias" and the (i+"axis")th axis of "x" must have the same size (0 <= i < n-axis). * If "axis < 0", the ith axis of "bias" and the (i+n+"axis")th axis of "x" must have the same size (0 <= i < -axis). *@li If "bias_from_blob = true" and "num_axes = 0", "bias" is a scalar with shape length 1 and dimension size 1. -*@li If "bias_from_blob = true", "num_axes > 0, and "axis >= 0", "axis + num_axes" must be less than or equal to "n" and the ith axis of "bias" and the (i+"axis")th axis of "x" must have the same size (0 <= i < num_axes).\n -* If "axis < 0", "n + axis + num_axes" must be less than or equal to "n" and the ith axis of "bias" and the (i+n+"axis")th axis of "x" must have the same size (0 <= i < num_axes). -*@li If "bias_from_blob = false", "bias" is not a scalar, and "axis >= 0","axis + m" must be less than or equal to "n" and the ith axis of "bias" and the (i+"axis")th axis of "x" must have the same size (0 <= i < m).\n -* If "axis < 0", "n + axis + m" must be less than or equal to "n" and the ith axis of "bias" and the (i+n+"axis")th axis of "x" must have the same size (0 <= i < m). +*@li If "bias_from_blob = true", "num_axes > 0, and "axis >= 0", +* "axis + num_axes" must be less than or equal to "n" and the ith axis of "bias" and +* the (i+"axis")th axis of "x" must have the same size (0 <= i < num_axes). +* If "axis < 0", "n + axis + num_axes" must be less than or equal to "n" and +* the ith axis of "bias" and the (i+n+"axis")th axis of "x" must have the same size (0 <= i < num_axes). +*@li If "bias_from_blob = false", "bias" is not a scalar, and "axis >= 0", +* "axis + m" must be less than or equal to "n" and the ith axis of "bias" and +* the (i+"axis")th axis of "x" must have the same size (0 <= i < m). +* If "axis < 0", "n + axis + m" must be less than or equal to "n" and +* the ith axis of "bias" and the (i+n+"axis")th axis of "x" must have the same size (0 <= i < m). \n *@par Third-party framework compatibility * Compatible with the Caffe operator Bias. */ @@ -3405,11 +3420,14 @@ REG_OP(Fills) .OP_END_FACTORY_REG(Adds) /** -*@brief Computes the product of x and y and returns 0 if the y is zero, even if x is NaN or infinite. \n +*@brief Computes the product of x and y and returns 0 if the y is zero, +* even if x is NaN or infinite. *@par Inputs: -* @li x1: A Tensor. Must be one of the following types:float16, float32, double, complex64, complex128. -* @li x2: A Tensor. Has the same type and shape as "x1". \n +* Two inputs, including: \n +*@li x1: A Tensor. Must be one of the following types:float16, float32, +* double, complex64, complex128. +*@li x2: A Tensor. Has the same type and shape as "x1". \n *@par Outputs: *y: A Tensor. Has the same type and shape as "x1". \n diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index 38e22be8..61336fb0 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -52,8 +52,8 @@ namespace ge { REG_OP(AttentionQKVGradW) .INPUT(x, TensorType({DT_FLOAT16})) .INPUT(query_dx, TensorType({DT_FLOAT16})) - .INPUT(key_dw, TensorType({DT_FLOAT16})) - .INPUT(value_dw, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(key_dw, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(value_dw, TensorType({DT_FLOAT16})) .OUTPUT(dw_query, TensorType({DT_FLOAT16})) .OUTPUT(dw_key, TensorType({DT_FLOAT16})) .OUTPUT(dw_value, TensorType({DT_FLOAT16})) @@ -199,24 +199,25 @@ REG_OP(SwinTransformerLnQKV) .OP_END_FACTORY_REG(SwinTransformerLnQKV) /** -*@brief Multiplies matrix "a" by matrix "b", producing "a * b" . \n - +*@brief Multiplies matrix "a" by matrix "b", producing "a * b". \n *@par Inputs: *Three inputs, including: * @li x1: A matrix Tensor. 2D. Must be one of the following types: float16, -* float32, int32. Has format [ND, NHWC]. +* float32, int32, bfloat16. Has format [ND, NHWC]. * @li x2: A matrix Tensor. 2D. Must be one of the following types: float16, -* float32, int32. Has format [ND, NHWC]. +* float32, int32, bfloat16. Has format [ND, NHWC]. * @li bias: A optional 1D Tensor. Must be one of the following types: float16, -* float32, int32. Has format [ND, NHWC] . \n +* float32, int32, bfloat16. Has format [ND, NHWC]. \n *@par Attributes: -*@li transpose_x1: A bool. If True, changes the shape of "x1" from [M, K] to [K, M]. -*@li transpose_x2: A bool. If True, changes the shape of "x2" from [M, K] to [K, M] . \n +*@li transpose_x1: A bool. If True, changes the shape of "x1" from [M, K] to +* [K, M]. +*@li transpose_x2: A bool. If True, changes the shape of "x2" from [M, K] to +* [K, M]. \n *@par Outputs: *y: The result matrix Tensor. 2D. Must be one of the following types: float16, -* float32, int32. Has format [ND, NHWC] . \n +* float32, int32, bfloat16. Has format [ND, NHWC]. \n *@par Third-party framework compatibility * Compatible with the TensorFlow operator BatchMatmul. @@ -231,35 +232,34 @@ REG_OP(MatMul) .OP_END_FACTORY_REG(MatMul) /** -*@brief Multiplies matrix "a" by matrix "b", producing "a * b" . \n - +*@brief Multiplies matrix "a" by matrix "b", producing "a * b". \n *@par Inputs: *Four inputs, including: * @li x1: A matrix Tensor. 2D. Must be one of the following types: float32, - float16, int32, int8. Has format [ND, NHWC]. +* float16, int32, int8, int4, bfloat16. Has format [ND, NHWC]. * @li x2: A matrix Tensor. 2D. Must be one of the following types: float32, - float16, int32, int8. Has format [ND, NHWC]. +* float16, int32, int8, int4, bfloat16. Has format [ND, NHWC]. * @li bias: A 1D Tensor. Must be one of the following types: float32, - float16, int32. Has format [ND, NHWC]. +* float16, int32 bfloat16. Has format [ND, NHWC]. * @li offset_w: A Optional 1D Tensor for quantized inference. Type is int8. - Reserved. \n +* Reserved. \n *@par Attributes: * @li transpose_x1: A bool. If True, changes the shape of "x1" from [K, M] to - [M, K]. +* [M, K]. * @li transpose_x2: A bool. If True, changes the shape of "x2" from [N, K] to [K, N]. * @li offset_x: An optional integer for quantized MatMulV2. * The negative offset added to the input x1 for int8 type. Ensure offset_x - within the effective range of int8 [-128, 127]. Defaults to "0". \n +* within the effective range of int8 [-128, 127]. Defaults to "0". \n *@par Outputs: *y: The result matrix Tensor. 2D. Must be one of the following types: float32, - float16, int32. Has format [ND, NHWC]. \n +* float16, int32, bfloat16. Has format [ND, NHWC]. \n *@attention Constraints: * if performances better in format NZ, please close - "MatmulTransdataFusionPass" in fusion configuration. \n +* "MatmulTransdataFusionPass" in fusion configuration. \n *@par Third-party framework compatibility * Compatible with the TensorFlow operator BatchMatmul. @@ -276,26 +276,25 @@ REG_OP(MatMulV2) .OP_END_FACTORY_REG(MatMulV2) /** -*@brief Multiplies matrix "a" by matrix "b", producing "a * b" . \n - +*@brief Multiplies matrix "a" by matrix "b", producing "a * b". \n *@par Inputs: *Five inputs, including: * @li x1: A matrix Tensor. 2D. Must be one of the following types: int8. * @li x2: A matrix Tensor. 2D. Must be one of the following types: int8. * @li compress_index: A compress index matrix of type int8. * @li bias: An optional Tensor. 1D. Must be one of the following types: int32, - float16. +* float16. * @li offset_w: An optional matrix Tensor. 2D. Must be one of the following - types: int8. \n +* types: int8. \n *@par Attributes: *@li transpose_x1: A bool. If True, changes the shape of "x1" from [K, M] to - [M, K]. +* [M, K]. *@li transpose_x2: A bool. If True, changes the shape of "x2" from [N, K] to - [K, N]. +* [K, N]. *@li offset_x: An optional integer for quantized MatMulV2Compress. *The negative offset added to the input x1 for int8 type. Ensure offset_x - within the effective range of int8 [-128, 127]. Defaults to "0". \n +* within the effective range of int8 [-128, 127]. Defaults to "0". \n *@par Outputs: *y: The result matrix Tensor. 2D. Must be one of the following types: int32, @@ -303,7 +302,7 @@ REG_OP(MatMulV2) *@attention Constraints: * if performances better in format NZ, please close - "MatmulTransdataFusionPass" in fusion configuration. +* "MatmulTransdataFusionPass" in fusion configuration. */ REG_OP(MatMulV2Compress) @@ -319,29 +318,29 @@ REG_OP(MatMulV2Compress) .OP_END_FACTORY_REG(MatMulV2Compress) /** -*@brief Performs Matrix-to-matrix Multiply, producing y=alpha[0]*a*b+beta[0]*c . \n - +*@brief Performs Matrix-to-matrix Multiply, +* producing y=alpha[0]*a*b+beta[0]*c. \n *@attention Constraints: * For better performance, The k-axis must be aligned to 16 (input type * is float16) or 32 (input type is int8). \n *@par Inputs: *Five inputs, including: -*@li a: A matrix Tensor. Must be one of the following types: float16, int8. -* Has format [ND]. -*@li b: A matrix Tensor. Must be one of the following types: float16, int8. -* Has format ND. -*@li c: A matrix Tensor. Must be one of the following types: float16, int32, -* float32. has format ND. -*@li alpha: A 1D Tensor. The shape of alpha is [1].Must be one of the following -* types: float16, int32, float32. Has format [ND]. +* @li a: A matrix Tensor. Must be one of the following types:float32, float16, +* int8, int32. Has format ND. +* @li b: A matrix Tensor. Must be one of the following types:float32, float16, +* int8, int32. Has format ND. +*@li c: A matrix Tensor. Must be one of the following types:float32, float16, +* int8, int32. Has format ND. +* @li alpha: A 1D Tensor. The shape of alpha is [1].Must be one of the +* following types: float16, int32, float32, int8. Has format ND. *@li beta: A 1D Tensor. The shape of beta is [1]. Must be one of the following -* types: float16, int32, float32. Has format [ND]. +* types: float16, int32, float32, int8. Has format ND.\n * The format of a, b, c has restriction:\n * When type of a is int8 and type of c is int32, the format of a, b, c should * all be ND.\n -* When type of a is int8 and type of c is float32, the format of a, b, c should -* all be ND.\n +* When type of a is int8 and type of c is float32, the format of a, b, c +* should all be ND.\n * When type of a is float16 and type of c is float16, the format of a, b, c * should all be ND.\n * When type of a is float16 and type of c is float32, the format of a, b, c @@ -352,7 +351,7 @@ REG_OP(MatMulV2Compress) *@li transpose_a: Optional. A bool. If True, changes the shape of "a" from * [M, K] to [K, M]. *@li transpose_b: Optional. A bool. If True, changes the shape of "b" from -* [K, N] to [N, K] . \n +* [K, N] to [N, K]. \n *@par Outputs: *y: The result matrix Tensor. Must be one of the following types: float16, @@ -371,22 +370,25 @@ REG_OP(GEMM) .OP_END_FACTORY_REG(GEMM) /** -*@brief Multiplies matrix "a" by matrix "b", producing "a * b" . \n - +*@brief Multiplies matrix "a" by matrix "b", producing "a * b". \n *@par Inputs: *Two inputs, including: * @li x1: A matrix Tensor. Must be one of the following types: float16, -* float32, int32. 2D or higher. Has format [ND, NHWC]. +* float32, int32, bfloat16. 2D or higher. Has format [ND, NHWC]. * @li x2: A matrix Tensor. Must be one of the following types: float16, -* float32, int32. 2D or higher. Has format [ND, NHWC] . \n +* float32, int32, bfloat16. 2D or higher. Has format [ND, NHWC]. \n *@par Attributes: -*@li adj_x1: A bool. If True, changes the shape of "x1" from [B, M, K] to [B, K, M]. -*@li adj_x2: A bool. If True, changes the shape of "x2" from [B, M, K] to [B, K, M] . \n +*@li adj_x1: A bool. If True, changes the shape of "x1" from [B, M, K] +* to [B, K, M]. +*@li adj_x2: A bool. If True, changes the shape of "x2" from [B, M, K] +* to [B, K, M]. \n *@par Outputs: -*y: The result matrix Tensor. 2D or higher. Must be one of the following types: float16, -* float32, int32. 2D or higher. Has format [ND, NHWC]. Has the same shape length as "x1" and "x2" . \n +* y: The result matrix Tensor. 2D or higher. Must be one of the following +* types: float16, bfloat16, +* float32, int32. 2D or higher. Has format [ND, NHWC]. Has the same shape +* length as "x1" and "x2". \n *@par Third-party framework compatibility * Compatible with the TensorFlow operator BatchMatmul. @@ -403,27 +405,33 @@ REG_OP(BatchMatMul) /** * @brief Multiplies matrix "a" by matrix "b", producing "a * b" . \n - * @par Inputs: * Three inputs, including: * @li x1: A matrix Tensor. Must be one of the following types: float16, -* float32, int32. 2D or higher. Has format [ND, NHWC]. +* float32, int32, int8, int4, bfloat16. 2D or higher. Has format [ND, NHWC]. * @li x2: A matrix Tensor. Must be one of the following types: float16, -* float32, int32. 2D or higher. Has format [ND, NHWC] . \n -* @li bias: A matrix Tensor. Must be one of the following types: float16, -* float32, int32. 2D or higher. Has format [ND, NHWC] . \n +* float32, int32, int8, int4, bfloat16. 2D or higher. Has format [ND, NHWC]. +* @li bias: A optional Tensor. Must be one of the following types: +* float16, +* float32, int32, int8, int4, bfloat16. Has format [ND, NHWC]. +* @li offset_w: A optional Tensor. Must be one of the following types: +* int8, int4. Has format [ND, NHWC]. \n * @par Attributes: -* @li adj_x1: A bool. If True, changes the shape of "x1" from [B, M, K] to [B, K, M]. -* @li adj_x2: A bool. If True, changes the shape of "x2" from [B, M, K] to [B, K, M] . \n +* @li adj_x1: A bool. If True, changes the shape of "x1" from [B, M, K] to +* [B, K, M]. +* @li adj_x2: A bool. If True, changes the shape of "x2" from [B, M, K] to +* [B, K, M]. \n * @par Outputs: -* y: The result matrix Tensor. 2D or higher. Must be one of the following types: float16, -* float32, int32. 2D or higher. Has format [ND, NHWC]. Has the same shape length as "x1" and "x2" . \n +* y: The result matrix Tensor. 2D or higher. Must be one of the following +* types: float16, +* float32, int32. 2D or higher. Has format [ND, NHWC]. Has the same shape +* length as "x1" and "x2". \n *@attention Constraints: * if performances better in format NZ, please close - "MatmulTransdataFusionPass" in fusion configuration. \n +* "MatmulTransdataFusionPass" in fusion configuration. \n * @par Third-party framework compatibility * Compatible with the TensorFlow operator BatchMatmul. @@ -1025,29 +1033,33 @@ REG_OP(DiagPart) .OP_END_FACTORY_REG(DiagPart) /** -*@brief Also known as a "fully-connected" layer, computes an inner product with a set of learned weights, and (optionally) adds biases . \n - +*@brief Also known as a "fully-connected" layer, computes an inner product +* with a set of learned weights, and (optionally) adds biases. \n *@par Inputs: * Four inputs, including: -*@li x: A Tensor of type float16, int8. -*@li w: A weight matrix of type float16, int8. -*@li b: An optional Tensor of type float16, int32, float32. -*@li offset_w: An optional Tensor of type int8. Reserved. Only None Supported. \n +*@li x: A Tensor of type float16, int8, int4, float32, bfloat16. +*@li w: A weight matrix of type float16, int8, int4, float32, bfloat16. +*@li b: An optional Tensor of type float16, int8, int4, float32, bfloat16. +*@li offset_w: An optional Tensor of type int8, int4. +* Reserved. Only None Supported. \n *@par Attributes: *@li num_output: Required. An int, output neuron number. Reserved. -*@li transpose: A bool, specifying weight whether to transpose input w, either "true" or "false". Defaults to "false". -*@li axis: Optional. An int, 1 or 2, specifying which dimension the input "K" starts from. Defaults to 1. -* The product of the subsequent dimensions starting form first dimension or the second dimension is "K". +*@li transpose: A bool, specifying weight whether to transpose input w, +* either "true" or "false". Defaults to "false". +*@li axis: Optional. An int, 1 or 2, specifying which dimension the input +* "K" starts from. Defaults to 1. +* The product of the subsequent dimensions starting form first dimension +* or the second dimension is "K". *@li offset_x: An optional integer for quantized FullyConnection. -*The negative offset added to the input image for int8 type. Ensure offset_x within the -*effective range of int8 [-128, 127]. Defaults to "0". \n +*The negative offset added to the input image for int8 type. Ensure offset_x +* within the effective range of int8 [-128, 127]. Defaults to "0". \n *@par Outputs: -*y: The result tensor of type float16, int32, float32 . \n +*y: The result tensor of type float16, int32, float32, bfloat16. \n *@par Third-party framework compatibility -* Compatible with the Caffe operator InnerProduct . \n +* Compatible with the Caffe operator InnerProduct. \n *@par Quantization supported or not * Yes @@ -1066,27 +1078,26 @@ REG_OP(FullyConnection) /** *@brief Also known as a "fully-connected-compress" layer, computes an inner -product with a set of learned weights, and (optionally) adds biases . \n - +* product with a set of learned weights, and (optionally) adds biases. \n *@par Inputs: * Five inputs, including: *@li x: A Tensor of type uint8, int8. *@li w: A weight matrix of type int8. *@li compress_index: A compress index matrix of type int8. -*@li b: A Tensor of type int32. -*@li offset_w: A Tensor of type int8. +*@li b: A optional Tensor of type int32. +*@li offset_w: A optional Tensor of type int8. *@par Attributes: *@li num_output: A int, specifying the number of outputs. *@li transpose: A bool, specifying whether to transpose input w, either "true" - or "false". Defaults to "false". +* or "false". Defaults to "false". *@li axis: Optional. A int, 1 or 2, specifying which dimension the input "K" -starts from. Defaults to "1". -* The product of the subsequent dimensions starting form first dimension or the -second dimension is "K". +* starts from. Defaults to "1". +*The product of the subsequent dimensions starting form first dimension or the +* second dimension is "K". *@li offset_x: An optional integer for quantized FullyConnectionCompress. *The negative offset added to the input image for int8 type. Ensure offset_x -within the effective range of int8 [-128, 127]. Defaults to "0". \n +* within the effective range of int8 [-128, 127]. Defaults to "0". \n *@par Outputs: *y: The result tensor of type int32. \n @@ -1520,21 +1531,18 @@ REG_OP(Tril) /** *@brief Concatenates a list of N tensors along the first dimension. *@par Inputs: -* Two inputs, including: -* @li values: A list of Tensors. Must be one of the following types: int32, float16, float32. -* Tensors to be concatenated. All must have size 1 in the first dimension and same shape. -* It's a dynamic input. -* @li shape: A Tensor of the same type as "x". -* The final shape of the result. Should be equal to the shapes of any input -* but with the number of input values in the first dimension . \n +* @li x: A list of Tensors. Must be one of the following types: int32, +* float16, float32. Tensors to be concatenated. All must have size 1 in +* the first dimension and same shape.It's a dynamic input. \n *@par Attributes: -*equation: The subscripts for the Einstein summation. \n -*N: tensor size of input \n +* @li equation: The subscripts for the Einstein summation. \n +* @li N: tensor size of input. \n *@par Outputs: -*@li y: Sums the product of the elements of the input operands along dimensions specified - using a notation based on the Einstein summation convention. \n +*@li y: Sums the product of the elements of the input operands along +* dimensions specified +* using a notation based on the Einstein summation convention. \n *@attention Constraints: *Input N must be Int. \n @@ -1756,6 +1764,57 @@ REG_OP(MatrixDiagV3) .ATTR(align, String, "RIGHT_LEFT") .OP_END_FACTORY_REG(MatrixDiagV3) +/** +* @brief Function SwinAttentionScore. \n + +* @par Inputs: +* six inputs, including: +* @li query: A matrix Tensor. The type only support float16. +* @li key: A matrix Tensor. The type only support float16. +* @li value: A matrix Tensor. The type only support float16. +* @li padding_mask1: A matrix Tensor. The type only support float16. +* @li padding_mask2: A matrix Tensor. The type only support float16. +* @li scale: A scalar. The type only support float16. +* @li drop_mask: A matrix Tensor. The type only support uint8. \n + +* @par Attributes: +* @li keep_prob: A mutable Tensor. Must met all of the following rules: + shape of "keep_prob" should be (1,) or [1,]. +* @li query_transpose: A bool. If True, changes the shape of "query" from [K, M] to + [M, K]. +* @li key_transpose: A bool. If True, changes the shape of "key" from [N, K] to + [K, N]. +* @li bmm_score_transpose_a: A bool. If True, changes the shape of "mid_data" from [K, M] to + [M, K]. +* @li bmm_score_transpose_b: A bool. If True, changes the shape of "value" from [N, K] to + [K, N]. +* @li axes: A list of int. The dimension softmax would be performed on. Defaults + to "[]" . \n + +* @par Outputs: +* attention_score: The result matrix Tensor. The type only support float16. +* softmax: The result matrix Tensor. The type only support float16. + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(SwinAttentionScore) + .INPUT(query, TensorType({DT_FLOAT16})) + .INPUT(key, TensorType({DT_FLOAT16})) + .INPUT(value, TensorType({DT_FLOAT16})) + .INPUT(padding_mask1, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(padding_mask2, TensorType({DT_FLOAT16})) + .INPUT(scale, TensorType({DT_FLOAT16})) + .OPTIONAL_INPUT(drop_mask, TensorType({DT_INT8})) + .OUTPUT(attention_score, TensorType({DT_FLOAT16})) + .OUTPUT(softmax, TensorType({DT_FLOAT16})) + .ATTR(keep_prob, Float, 1.0) + .ATTR(query_transpose, Bool, false) + .ATTR(key_transpose, Bool, false) + .ATTR(bmm_score_transpose_a, Bool, false) + .ATTR(bmm_score_transpose_b, Bool, false) + .ATTR(softmax_axes, ListInt, {}) + .OP_END_FACTORY_REG(SwinAttentionScore) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATRIX_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h index c6aad6dc..96213764 100644 --- a/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_batch_norm_ops.h @@ -544,23 +544,30 @@ REG_OP(BNInference) .OP_END_FACTORY_REG(BNInference) /** -*@brief Performs batch normalization . \n +*@brief Performs batch normalization . *@par Inputs: *@li x: A 4D or 5D Tensor of type float16 or float32, with format NHWC or NCHW. -*@li mean: A Tensor of type float32 or float16. Must be 1D if input "x" Specifies the mean used for inference. -*@li variance: A Tensor of type float32 or float16 . Must be 1D if input "x" Specifies the variance used for inference. -*@li scale: An optional tensor of type float16 or float32, no use -*@li offset: An optional tensor of type float16 or float32, no use +*@li mean: A Tensor of type float32 or float16. Must be 1D if input "x" +* Specifies the mean used for inference. +*@li variance: A Tensor of type float32 or float16 . Must be 1D if input "x" +* Specifies the variance used for inference. +*@li scale: An optional tensor of type float16 or float32, no use. +*@li offset: An optional tensor of type float16 or float32, no use. \n + *@par Attributes: -*@li momentum: An optional float32 num, represents the mean and the variance's scale factor -*@li epsilon: An optional float32, specifying the small value added to variance to avoid dividing by zero. Defaults to "0.00001". +*@li momentum: An optional float32 num, represents the mean and +* the variance's scale factor. +*@li epsilon: An optional float32, specifying the small value +* added to variance to avoid dividing by zero. Defaults to "0.00001". *@li use_global_stats: mean inference mode , only can be "True". -*@li mode: An optional attr, not use +*@li mode: An optional attr, not use. \n + *@par Outputs: -*@li y: A 4D or 5D Tensor of type float16 or float32 for the normalized "x" +*@li y: A 4D or 5D Tensor of type float16 or float32 for the normalized "x". \n + *@par Restrictions: -*Warning: THIS FUNCTION IS DEPRECATED. Please use BNInference instead. +* Warning: THIS FUNCTION IS DEPRECATED. Please use BNInference instead. */ REG_OP(BNInferenceD) .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) diff --git a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h index bb0770e6..4c55eac0 100644 --- a/third_party/fwkacllib/inc/ops/nn_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_calculation_ops.h @@ -26,15 +26,14 @@ namespace ge { /** * @brief Computes the gradients of depthwise convolution with respect to -* the filter . \n - +* the filter. \n * @par Inputs: -* Three inputs include: \n +* Three inputs include: * @li input: 4D origin shape of input tensor [N, C, H, W] or [N, H, W, C], -* support float16, float32, double -* @li filter_size: A 4D tensor of type int32, with shape [H, W, C, K] +* support float16. +* @li filter_size: A 4D tensor of type int32, int64, with shape [H, W, C, K] * @li out_backprop: 4D tensor with shape [N, C, H, W] or [N, H, W, C]. -* Must be one of the following types: float16, float32, double . \n +* Must be one of the following types: float16. \n * @par Attributes: * @li strides: A required list or tuple. The stride of the sliding window @@ -49,7 +48,7 @@ namespace ge { * @li pads: A required list or tuple. Padding added to each dimension of the * input. * @li data_format: An optional string. Input data format, either "NHWC" or -* "NCHW" . \n +* "NCHW". \n * @par Outputs: * filter_grad: Gradient of the deep convolution relative to the filter with @@ -65,8 +64,9 @@ namespace ge { * Output backprop is 4D with shape [N, C, Ho, Wo] or [N, Ho, Wo, C], but the * data is 5D with shape [N, C1, Ho, Wo, C0], * where C is the same as that of the feature map and C0 is 16.\n -* Limited by Tiling and L1 / L0 buffer memory: 512 * ceil(Wo, 16) + (480 * -* stride_h + 32 * filter_h) * ceil(Wi, 16) <= l1_size and Hf*Wf <= l0b_size/512 . \n +* Limited by Tiling and L1 / L0 buffer memory: 512 * ceil(Wo, 16) + +* (480 * stride_h + 32 * filter_h) * ceil(Wi, 16) <= l1_size and Hf*Wf +* <= l0b_size/512. \n * @par Third-party framework compatibility * @li Compatible with the TensorFlow operator DepthwiseConv2DBackpropFilter. @@ -146,34 +146,34 @@ REG_OP(DepthwiseConv2DBackpropFilterD) /** * @brief Computes the gradients of depthwise convolution with respect to the -* input . \n - +* input. \n * @par Inputs: * Three inputs include: \n * @li input_size: 4D shape of input tensor [N, C, H, W] or [N, H, W, C], -* support int32, int64 +* support int32, int64. * @li filter: 4D filter tensor with shape of [H, W, C, K], support float16. * @li out_backprop: 4D tensor with shape [N, C, H, W] or [N, H, W, C]. * Must be one of the following types: float16 . \n * @par Attributes: -* @li strides: A required list or tuple of int32. The stride of the sliding window for -* height and width of input "x" of the convolution. +* @li strides: A required list or tuple of int32. The stride of the sliding +* window for height and width of input "x" of the convolution. * Must be with shape [1, 1, stride_height, stride_width] or [1, stride_height, * stride_width, 1]. -* @li dilations: An optional list or tuple of int32. The dilation factor for each -* dimension of input "x". Defaults to "[1, 1, 1, 1]". +* @li dilations: An optional list or tuple of int32. The dilation factor for +* each dimension of input "x". Defaults to "[1, 1, 1, 1]". * If set to k > 1, there will be k-1 skipped cells between each filter element * on that dimension. Must be with shape [1, 1, dilation_height, dilation_width] * or [1, dilation_height, dilation_width, 1]. -* @li pads: A required list or tuple of int32. Padding added to each dimension of the -* input. +* @li pads: A required list or tuple of int32. Padding added to each dimension +* of the input. * @li data_format: An optional string. Input data format, either "NHWC" or * "NCHW". Defaults to "NHWC" . \n * @par Outputs: * input_grad: Gradient of the deep convolution relative to the input with shape -* [N, C, H, W] or [N, H, W, C] Must be one of the following types: float16 . \n +* [N, C, H, W] or [N, H, W, C] Must be one of the following types: +* float16, float32. \n * @attention Constraints:\n * The feature map is 4D with shape [N, C, Hi, Wi] or [N, Hi, Wi, C], but @@ -331,13 +331,13 @@ REG_OP(DepthwiseConv2D) * For NCHW data format, the feature dimension is the third-to-last . \n *@par Inputs: -*x: A Tensor of type NumberType . \n +* x: A Tensor of type NumberType . \n *@par Attributes: -*data_format: Data format. Defaults to "NHWC" . \n +* data_format: Data format. Defaults to "NHWC" . \n *@par Outputs: -*y: A Tensor.Has the same type as "x" . \n +* y: A Tensor.Has the same type as "x" . \n *@par Third-party framework compatibility * Compatible with the TensorFlow operator BiasAddGrad. @@ -378,8 +378,8 @@ REG_OP(BiasAddGrad) | Format | NCHW | NCHW | NCHW |\n | | NHWC | HWCN | NHWC |\n *\n - * For float32 and float64 type, the actual calculation on the chip is based on - * float16. + * For float32 and float64 type, the actual calculation on the chip is based + * on float16. *\n * *@par Attributes: @@ -419,11 +419,11 @@ REG_OP(BiasAddGrad) | | W | [1, 255] |\n *\n - * In Ascend910, fmap or out_backprop's H and W not support 1 when + * In Ascend910, fmap or out_backprop's H and W not support 1 when\n * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 - * and filter_width > fmap_width - * If filter_h = 1 and filter_w = 1, out_backprop_w * stride_h * stride_w < 4096 - *\n + * and filter_width > fmap_width. + * If filter_h = 1 and filter_w = 1, out_backprop_w * stride_h * + * stride_w < 4096. \n * *@par Outputs: * y: A Tensor. Has the same type as filter,and has same format as input_size. @@ -482,7 +482,7 @@ REG_OP(Conv2DBackpropInput) *@par Outputs: * y: A Tensor. Has the same type as filter,4-D tensor [batch, height, width, * channels] or [batch, channels, height, width]. -*@par Third-party framework compatibility +* @par Third-party framework compatibility * Compatible with Tensorflow's conv2d_backprop_input *@par Restrictions: * Warning: THIS FUNCTION IS DEPRECATED. Please use Conv2DBackpropInput instead. @@ -503,7 +503,7 @@ REG_OP(Conv2DBackpropInputD) *@brief Computes the Deconvolution with respect to the input. *@par Inputs: * Two required inputs: - * @li x: A Tensor of type float16 or int8. 4D with shape + * @li x: A Tensor of type float16 or int8. 4D with shape * [batch, out_channels, out_height, out_width]. Gradients with respect * to the output of the convolution. * @li filter: A Tensor. Must have the same type as "x". @@ -511,7 +511,7 @@ REG_OP(Conv2DBackpropInputD) * Two optional inputs: * @li bias: An optional tensor. Must have the same type as "y". * @li offset_w: An optional 1D tensor for quantized deconvolution. - * Type is int8. Reserved.\n + * Type is int8. Reserved. *\n *\n * The following are the supported data types and data formats:\n @@ -535,9 +535,9 @@ REG_OP(Conv2DBackpropInputD) * @li dilations: A tuple or list of 4 integers. The dilation factor for each * dimension of input, defaults to [1,1,1,1]. * @li groups: Number of blocked connections from input channels to - output channels. Defaults to "1". + * output channels. Defaults to "1". * @li data_format: An optional string from: "NCHW". Defaults to "NCHW". \n - Specify the data format of the input and output data. + * Specify the data format of the input and output data. * @li offset_x: An optional integer for quantized deconvolution. * The negative offset added to the input image for int8 type. Ensure offset_x * within the effective range of int8 [-128, 127]. Defaults to "0". @@ -564,10 +564,11 @@ REG_OP(Conv2DBackpropInputD) | | W | [1, 255] |\n | Offset_x | | [-128, 127] |\n *\n - * In Ascend910, fmap or out_backprop's H and W not support 1 when + * In Ascend910, fmap or out_backprop's H and W not support 1 when\n * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 * and filter_width > fmap_width - * If filter_h = 1 and filter_w = 1, out_backprop_w * stride_h * stride_w < 4096 + * If filter_h = 1 and filter_w = 1, + * out_backprop_w * stride_h * stride_w < 4096 *\n * *@par Outputs: @@ -603,7 +604,7 @@ REG_OP(Deconvolution) *@par Inputs: * Three inputs: * @li x: A Tensor. Must be one of the following types: float16, float32, - * float64.4-D with shape [batch, in_height, in_width, in_channels] or + * float64. 4-D with shape [batch, in_height, in_width, in_channels] or * [batch, in_channels, in_height, in_width]. * @li filter_size: A const Tensor of type int32. Currently does not support * data tensor. An integer vector representing the tensor shape of filter, @@ -627,8 +628,8 @@ REG_OP(Deconvolution) | Format | NCHW | NCHW | NCHW |\n | | NHWC | NHWC | HWCN |\n *\n - * For float32 and float64 type of x and outbackprop, the actual calculation on the chip - * is based on float16. + * For float32 and float64 type of x and outbackprop, the actual calculation + * on the chip is based on float16. *\n * *@par Attributes: @@ -651,21 +652,21 @@ REG_OP(Deconvolution) | Name | Field | Scope |\n |------------------|----------|--------------|\n | x(fmap) | H | [1, 200000] |\n - | | W | [1, 200000] |\n - | Filter Size | H | [1, 200000] |\n - | | W | [1, 200000] |\n + | | W | [1, 4096] |\n + | Filter Size | H | [1, 255] |\n + | | W | [1, 255] |\n | out_backprop | H | [1, 200000] |\n - | | W | [1, 200000] |\n + | | W | [1, 4096] |\n | y | H | [1, 200000] |\n - | | W | [1, 200000] |\n - | Stride | H | [1, 200000] |\n - | | W | [1, 200000] |\n - | Padding | Top | [0, 200000] |\n - | | Bottom | [0, 200000] |\n - | | Left | [0, 200000] |\n - | | Right | [0, 200000] |\n - | Dilation | H | [1, 200000] |\n - | | W | [1, 200000] |\n + | | W | [1, 4096] |\n + | Stride | H | [1, 63] |\n + | | W | [1, 63] |\n + | Padding | Top | [0, 255] |\n + | | Bottom | [0, 255] |\n + | | Left | [0, 255] |\n + | | Right | [0, 255] |\n + | Dilation | H | [1, 255] |\n + | | W | [1, 255] |\n *\n *@par Outputs: * y: A Tensor. Has the same type as x, has the same format as filter_size. @@ -743,16 +744,16 @@ REG_OP(Conv2DBackpropFilterD) .OP_END_FACTORY_REG(Conv2DBackpropFilterD) /** -*@brief Computes a 2D convolution given 4D "x" and "filter" tensors. -*@par Inputs: -*@li x: A 4D tensor of input image. With the format "NHWC", the data is stored +* @brief Computes a 2D convolution given 4D "x" and "filter" tensors. +* @par Inputs: +* @li x: A 4D tensor of input image. With the format "NHWC", the data is stored * in the order of: [batch, in_height, in_width, in_channels]. -*@li filter: A 4D tensor of learnable filters. Must have the same type as "x". +* @li filter: A 4D tensor of learnable filters. Must have the same type as "x". * With the format "HWCN" , the data is stored in the order of: [filter_height, * filter_width, in_channels / groups, out_channels]. -*@li bias: An optional 1D tensor of additive biases to the filter outputs. +* @li bias: An optional 1D tensor of additive biases to the filter outputs. * The data is stored in the order of: [out_channels]. -*@li offset_w: Reserved. +* @li offset_w: Reserved. *\n *\n * The following are the supported data types and data formats: @@ -770,22 +771,22 @@ REG_OP(Conv2DBackpropFilterD) * float16. *\n * -*@par Attributes: -*@li strides: Required. A list of 4 integers. The stride of the sliding window +* @par Attributes: +* @li strides: Required. A list of 4 integers. The stride of the sliding window * for each dimension of input. The dimension order is determined by the data * format of "x". The N and C dimensions must be set to 1. -*@li pads: Required. A list of 4 integers. The number of pixels to add to each +* @li pads: Required. A list of 4 integers. The number of pixels to add to each * (top, bottom, left, right) side of the input. -*@li dilations: Optional. A list of 4 integers. The dilation factor for each +* @li dilations: Optional. A list of 4 integers. The dilation factor for each * dimension of input. The dimension order is determined by the data format of * "x". The N and C dimensions must be set to 1. Defaults to [1, 1, 1, 1]. -*@li groups: Optional. An integer of type int32. The number of blocked +* @li groups: Optional. An integer of type int32. The number of blocked * connections from input channels to output channels. In_channels and * out_channels must both be divisible by "groups". Defaults to 1. -*@li offset_x: Optional. An integer of type int32. The negative offset added +* @li offset_x: Optional. An integer of type int32. The negative offset added * to the input image for int8 type. Ensure that the output is within the * effective range. Defaults to 0. -*@li data_format: Reserved. +* @li data_format: Reserved. *\n *\n * The following value range restrictions must be met: @@ -825,10 +826,10 @@ REG_OP(Conv2DBackpropFilterD) * / stride_w + 1 *\n * -*@par Quantization supported or not -*@li Yes +* @par Quantization supported or not +* Yes * -*@par Third-party framework compatibility +* @par Third-party framework compatibility *@li Compatible with the TensorFlow operator "conv2d". *@li Compatible with the Caffe operator 2D "Convolution". */ @@ -847,14 +848,14 @@ REG_OP(Conv2D) .OP_END_FACTORY_REG(Conv2D) /** -*@brief Computes a 2D convolution given 4D "x" and "filter_compress" tensors. -*@par Inputs: -*@li x: A 4D tensor of input images. -*@li filter_compress: A 4D tensor of compressed filter data blocks. -*@li compress_index: A 1D tensor of index for decompression. -*@li bias: An optional 1D tensor of additive biases to the filter outputs. +* @brief Computes a 2D convolution given 4D "x" and "filter_compress" tensors. +* @par Inputs: +* @li x: A 4D tensor of input images. +* @li filter_compress: A 4D tensor of compressed filter data blocks. +* @li compress_index: A 1D tensor of index for decompression. +* @li bias: An optional 1D tensor of additive biases to the filter outputs. * The data is stored in the order of: [out_channels]. -*@li offset_w: Reserved. +* @li offset_w: Reserved. *\n *\n * The following are the supported data types and data formats: @@ -870,8 +871,8 @@ REG_OP(Conv2D) * float16. *\n * -*@par Attributes: -*@li strides: Required. A list of 4 integers. The stride of the sliding window +* @par Attributes: +* @li strides: Required. A list of 4 integers. The stride of the sliding window * for each dimension of input. The dimension order is determined by the data * format of "x". The N and C dimensions must be set to 1. *@li pads: Required. A list of 4 integers. The number of pixels to add to each @@ -1014,7 +1015,6 @@ REG_OP(DeformableConv2D) /** *@brief Computes a 3D convolution given 5D "x" and "filter" tensors. - *@par Inputs: * @li x: A 5D tensor. Must be one of the following types: float16, * (Currently does not support int8). The format of x is NCDHW or NDHWC. @@ -1025,16 +1025,16 @@ REG_OP(DeformableConv2D) * @li offset_w: Optional. An 1D tensor for quantized deconvolution. Reserved. \n *@par Attributes: - * @li strides: Required. A list of 5 integers. Specifies the stride of the sliding window - * for each dimension of "x". + * @li strides: Required. A list of 5 integers. Specifies the stride of the + * sliding window for each dimension of "x". * The N and C dimensions must be 1. Has the same format as "x". * @li pads: Required. A list of 6 integers. * Supports only padding along the D, H and W dimensions in sequence of head, * tail, top, bottom, left and right. - * @li dilations: Optional. A list of 5 integers. Specifies the dilation factor for each - * dimension of "x". - * @li groups: Optional. Number of blocked connections from input channels to output - * channels. + * @li dilations: Optional. A list of 5 integers. Specifies the dilation + * factor for each dimension of "x". + * @li groups: Optional. Number of blocked connections from input channels + * to output channels. * @li data_format: Optional. An string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. * The N, C and D dimensions must be 1. Has the same format as "x". @@ -1068,10 +1068,9 @@ REG_OP(Conv3D) /** *@brief Computes the gradients of convolution 3d with respect to the input. - *@par Inputs: - * @li input_size: A Tensor of type int32, int64. An integer vector representing - * the shape of input, where input is a 5-D tensor + * @li input_size: A Tensor of type int32, int64. An integer vector + * representing the shape of input, where input is a 5-D tensor * [batch, depth, height, width, channels] or * [batch, channels, depth, height, width]. * @li filter: A Tensor. Must be one of the following types: float16, float32. @@ -1082,22 +1081,23 @@ REG_OP(Conv3D) * respect to the output of the convolution. \n *@par Attributes: - * @li strides: Required. A list of 5 integers. Specifies the stride of the sliding window - * for each dimension of "out_backprop". + * @li strides: Required. A list of 5 integers. Specifies the stride of the + * sliding window for each dimension of "out_backprop". * The N and C dimensions must be 1. Has the same format as "out_backprop". * @li pads: Required. A list of 6 integers. * Supports only padding along the D, H and W dimensions in sequence of head, * tail, top, bottom, left and right. - * @li dilations: Optional. A tuple/list of 5 integers, The dilation factor for each - * dimension of the input. + * @li dilations: Optional. A tuple/list of 5 integers, The dilation factor + * for each dimension of the input. * The N, C and D dimensions must be 1. Has the same format as "out_backprop". - * @li groups: Optional. Number of blocked connections from input channels to output - * channels. + * @li groups: Optional. Number of blocked connections from input channels + * to output channels. * @li data_format: Optional. An string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. \n *@par Outputs: - * y: A Tensor. Has the same type as filter,and has same format as "input_size". \n + * y: A Tensor. Has the same type as filter,and has same format as + * "input_size". \n *@par Third-party framework compatibility * Compatible with Tensorflow's conv3d_backprop_input @@ -1207,10 +1207,9 @@ REG_OP(LSTM) /** *@brief Computes the gradients of convolution3D with respect to the filter - *@par Inputs: - * @li x: A Tensor. Must be one of the following types: float16, float32. - * Currently does not support double. + * @li x: A Tensor. Must be one of the following types: float16, float32, + * double. Currently does not support double. * 5-D with shape [batch, in_depth, in_height, in_width, in_channels] * or [batch, in_channels, in_depth, in_height, in_width]. * @li filter_size: A Tensor of type int32. An integer vector representing the @@ -1224,21 +1223,22 @@ REG_OP(LSTM) * Gradients with respect to the output of the convolution. \n *@par Attributes: - * @li strides: Required. A tuple/list of 5 integers. Specifies the stride of the sliding - * window for each dimension of "x". The N and C dimensions must be 1. - * Has the same format as "x". - * @li pads: Required. A tuple/list of 6 integers, [front, back, top, bottom, left, right] - * pads on feature map. - * @li dilations: Optional. A tuple/list of 5 integers, The dilation factor for each - * dimension of input. + * @li strides: Required. A tuple/list of 5 integers. Specifies the stride + * of the sliding window for each dimension of "x". The N and C dimensions + * must be 1. Has the same format as "x". + * @li pads: Required. A tuple/list of 6 integers, [front, back, top, bottom, + * left, right] pads on feature map. + * @li dilations: Optional. A tuple/list of 5 integers, The dilation factor + * for each dimension of input. * The N, C and D dimensions must be 1. Has the same format as "x". - * @li groups: Optional. Number of blocked connections from input channels to output - * channels. + * @li groups: Optional. Number of blocked connections from input channels + * to output channels. * @li data_format: Optional. An string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. \n *@par Outputs: - * y: A Tensor that has the same type as "x" and the format is NDHWC, NCDHW or DHWCN. \n + * y: A Tensor that has the same type as "x" and the format is NDHWC, NCDHW + * or DHWCN. \n *@par Third-party framework compatibility * Compatible with Tensorflow's conv3d_backprop_filter @@ -1311,25 +1311,26 @@ REG_OP(Conv3DBackpropFilterD) *@brief Computes the transpose of convolution 3d with respect to the input. *@par Inputs: - * @li input_size: A Tensor of type int32. An integer vector representing the - * shape of input. + * @li input_size: A Tensor of type int32, int64. An integer vector + * representing the shape of input. * @li x: A Tensor of type float16, currently does not support int8. The format * is NDHWC or NCDHW. * @li filter: A Tensor of type float16, currently does not support int8. * The format is NDHWC, NCDHW or DHWCN. * @li bias: Optional. An optional 1D tensor of the same type as "x". Reserved. - * @li offset_w: Optional. An optional 1D tensor for quantized deconvolution. Reserved. \n + * @li offset_w: Optional. An optional 1D tensor for quantized deconvolution. + * Reserved. \n *@par Attributes: - * @li strides: Required. A tuple/list of 5 integers. Specifies the stride of the sliding - * window for each dimension of "x". + * @li strides: Required. A tuple/list of 5 integers. Specifies the stride of + * the sliding window for each dimension of "x". * The N and C dimensions must be 1. Has the same format as "x". * @li pads: Required. A tuple/list of 6 integers. * @li dilations: Optional. A tuple/list of 5 integers, * The dilation factor for each dimension of input. * The N, C and D dimensions must be 1. Has the same format as "x". - * @li groups: Optional. Number of blocked connections from input channels to output - * channels. + * @li groups: Optional. Number of blocked connections from input channels to + * output channels. * @li data_format: Optional. An string from: "NDHWC", "NCDHW". * Defaults to "NDHWC". Specify the data format of the input and output data. * @li output_padding: Optional. The size will be added in the output shape. @@ -1417,7 +1418,8 @@ REG_OP(Conv3DTransposeD) * 4-D with shape [filter_height, filter_width, in_channels, out_channels] * or [out_channels, filter_height, filter_width, in_channels] * or [out_channels, in_channel, filter_height, filter_width]. - * @li bias: An optional 1D tensor of type float16 or int32. Format is "ND". + * @li bias: An optional 1D tensor of type float16, float32, int32. + * Format is "ND". * @li offset_w: An optional 1D tensor for quantized inference. Reserved. *\n *\n @@ -1446,8 +1448,8 @@ REG_OP(Conv3DTransposeD) * Defaults to "1". * @li dilations: A tuple/list of 4 integers, The dilation factor for each * dimension of input. Must be [1, 1, 1, 1]. - * @li data_format: An optional string from: "NHWC", "NCHW". Defaults to "NHWC". - * Specify the data format of the input and output data. + * @li data_format: An optional string from: "NHWC", "NCHW". + * Defaults to "NHWC". Specify the data format of the input and output data. * @li output_padding: The size will be added in the output shape. Defaults * to [0, 0, 0, 0]. * @li offset_x: An optional int. Input offset, used for quantized inference. @@ -1478,15 +1480,15 @@ REG_OP(Conv3DTransposeD) | | W | [1, 255] |\n | Offset_x | | [-128, 127] |\n *\n - * In Ascend910, fmap or out_backprop's H and W not support 1 when + * In Ascend910, fmap or out_backprop's H and W not support 1 when\n * fmap_h + pad_top + pad_bottom != (filter_height - 1) * dilation_h + 1 - * and filter_width > fmap_width - * If filter_h = 1 and filter_w = 1, out_backprop_w * stride_h * stride_w < 4096 - *\n + * and filter_width > fmap_width. + * If filter_h = 1 and filter_w = 1, out_backprop_w * stride_h * stride_w + * < 4096. \n * *@par Outputs: - * y: A Tensor. A Tensor of type float16 or int32, and has same format as - * input_size. + * y: A Tensor. A Tensor of type float16, int32, float32, and has + * same format as input_size. *\n * out_backprop_height = (fmap_height + pad_top + pad_bottom - * (dilation_h * (filter_height - 1) + 1)) diff --git a/third_party/fwkacllib/inc/ops/nn_norm_ops.h b/third_party/fwkacllib/inc/ops/nn_norm_ops.h index 523fb199..65411e2a 100644 --- a/third_party/fwkacllib/inc/ops/nn_norm_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_norm_ops.h @@ -124,7 +124,7 @@ REG_OP(SoftmaxGrad) .OP_END_FACTORY_REG(SoftmaxGrad) /** -*@brief Computes the sigmoid cross entropy loss of "predict" and "target" . \n +* @brief Computes the sigmoid cross entropy loss of "predict" and "target" . *@par Inputs: * Three inputs, including: @@ -146,7 +146,7 @@ REG_OP(SigmoidCrossEntropyWithLogitsGrad) .OP_END_FACTORY_REG(SigmoidCrossEntropyWithLogitsGrad) /** -*@brief Performs the backpropagation of SigmoidCrossEntropyWithLogits for training scenarios . \n +* @brief Performs the backpropagation of SigmoidCrossEntropyWithLogits for training scenarios . *@par Inputs: * Two inputs, including: @@ -194,7 +194,7 @@ REG_OP(SigmoidCrossEntropyWithLogitsV2) .OP_END_FACTORY_REG(SigmoidCrossEntropyWithLogitsV2) /** -*@brief Computes the regression box of the RPN. It is a FasterRCNN operator . \n +* @brief Computes the regression box of the RPN. It is a FasterRCNN operator . *@par Inputs: * Two inputs, including: @@ -221,7 +221,7 @@ REG_OP(SmoothL1Loss) .OP_END_FACTORY_REG(SmoothL1Loss) /** -*@brief Performs the backpropagation of SmoothL1Loss for training scenarios . \n +* @brief Performs the backpropagation of SmoothL1Loss for training scenarios . *@par Inputs: * Three inputs, including: @@ -796,6 +796,52 @@ REG_OP(LayerNormBetaGammaBackpropV2) .REQUIRED_ATTR(shape_gamma, ListInt) .OP_END_FACTORY_REG(LayerNormBetaGammaBackpropV2) +/** +* @brief LNDropoutGrad operator interface implementation +* calculating: dy, x, variance, mean, gamma +* pd_xl = dy*gamma +* sub_x_mean = x - mean +* var_elta_2 = np.power((variance + EPSLON), (-0.5)) +* pd_var = sum(pd_xl * sub_x_mean, reduce_axis, keepdims=True) * var_elta_2 * var_elta_2 * var_elta_2 * (-0.5) +* pd_mean = sum(pd_xl, reduce_axis, keepdims=True) * var_elta_2 * (-1.0) +* pd_x = pd_xl * var_elta_2 + pd_var * (2.0 / m) * sub_x_mean + pd_mean * (1.0 / m) +* pd_x_dropout = pd_x * mask * (1 / keep_prob) +* pd_gamma = sum(dy * sub_x_mean * var_elta_2, param_axis, keepdims=True) +* pd_beta = sum(dy, param_axis, keepdims=True) + +* @par Inputs: +* Six inputs, including: +* @li dy: A Tensor. Must be one of the following types: float16, float32. +* @li x: A Tensor. Must be one of the following types: float16, float32. +* @li variance: A Tensor. Must be one of the following types: float16, float32. +* @li mean: A Tensor. Must be one of the following types: float16, float32. +* @li gamma: A Tensor. Must be one of the following types: float16, float32. +* @li mask: A Tensor. Must be one of the following types: uint8.\n + +* @par Outputs: +* Four outputs, including: +* @li pd_x: A Tensor. Must be one of the following types: float16, float32. +* @li pd_x_dropout: A Tensor. Must be one of the following types: float16, float32. +* @li pd_gamma: A Tensor. Must be one of the following types: float16, float32. +* @li pd_beta: A Tensor. Must be one of the following types: float16, float32. + +* @par Restrictions: +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +*/ +REG_OP(LNDropoutGrad) + .INPUT(dy, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(variance, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(mean, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(gamma, TensorType({DT_FLOAT, DT_FLOAT16})) + .INPUT(mask, TensorType({DT_UINT8})) + .OUTPUT(pd_x, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(pd_x_dropout, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(pd_gamma, TensorType({DT_FLOAT, DT_FLOAT16})) + .OUTPUT(pd_beta, TensorType({DT_FLOAT, DT_FLOAT16})) + .REQUIRED_ATTR(keep_prob, Float) + .OP_END_FACTORY_REG(LNDropoutGrad) + /** *@brief Return "output" according to the algorithm of dropout_do_mask: * scale_x = x *(1 / keep_prob) diff --git a/third_party/fwkacllib/inc/ops/nn_ops.h b/third_party/fwkacllib/inc/ops/nn_ops.h index 83aa30d2..8c6987ca 100644 --- a/third_party/fwkacllib/inc/ops/nn_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_ops.h @@ -112,7 +112,10 @@ REG_OP(FusedBatchNormV2) * @li input_data: A Tensor. Data to be sorted. Support float16 or float32. * @li input_index: A Tensor. Range(0, 2048). Support float16 or int32. * @par Attributes: - * k_num: Int.Number to be sorted. + * @li k_num: Int.Number to be sorted. + * @li largest: An optional bool, controls whether to return largest or smallest elements. Defaults to true. + * If "True", the "k" largest elements are returned in descending order. + * If "False", the "k" smallest elements are returned in ascending order. * @par Outputs: * One output, including: * output_proposal: A Tensor. Datatype and format is same as input_data. Proposal sorted for each channel. @@ -124,6 +127,7 @@ REG_OP(SegmentSort) .INPUT(input_index, TensorType({DT_FLOAT16,DT_INT32})) .OUTPUT(output_proposal, TensorType({DT_FLOAT16,DT_FLOAT})) .REQUIRED_ATTR(k_num, Int) + .ATTR(largest, Bool, true) .OP_END_FACTORY_REG(SegmentSort) /** @@ -132,8 +136,11 @@ REG_OP(SegmentSort) * One input, including: * input_proposal: A Tensor. Proposal sorted for each channel. Support float16 or float32 * @par Attributes: - * k_num: Int.Number to be sorted. - * include_index: Bool.include_index is false,output proposal. include_index is true, output data and index. + * @li k_num: Int.Number to be sorted. + * @li include_index: Bool.include_index is false,output proposal. include_index is true, output data and index. + * @li largest: An optional bool, controls whether to return largest or smallest elements. Defaults to true. + * If "True", the "k" largest elements are returned in descending order. + * If "False", the "k" smallest elements are returned in ascending order. * @par Outputs: * Two output, including: * output_proposal: A Tensor. Datatype and format is same as input_data. Proposal sorted for each channel. @@ -147,6 +154,7 @@ REG_OP(MultiMerge) .OUTPUT(output_index, TensorType({DT_INT32})) .REQUIRED_ATTR(k_num, Int) .ATTR(include_index, Bool, false) + .ATTR(largest, Bool, true) .OP_END_FACTORY_REG(MultiMerge) /** @@ -155,7 +163,10 @@ REG_OP(MultiMerge) * One input, including: * input_proposal: A Tensor. Proposal sorted for each channel. Support float16 * @par Attributes: - * k_num: Int.Number to be sorted. + * @li k_num: Int.Number to be sorted. + * @li largest: An optional bool, controls whether to return largest or smallest elements. Defaults to true. + * If "True", the "k" largest elements are returned in descending order. + * If "False", the "k" smallest elements are returned in ascending order. * @par Outputs: * Two output, including: * @li output_data: A Tensor. Datatype and format is same as input_data. Data sorted. @@ -168,6 +179,7 @@ REG_OP(SingleMerge) .OUTPUT(output_data, TensorType({ DT_FLOAT16 })) .OUTPUT(output_index, TensorType({ DT_INT32 })) .REQUIRED_ATTR(k_num, Int) + .ATTR(largest, Bool, true) .OP_END_FACTORY_REG(SingleMerge) /** diff --git a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h index 4c6f7293..f34de163 100644 --- a/third_party/fwkacllib/inc/ops/nn_pooling_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_pooling_ops.h @@ -75,33 +75,36 @@ REG_OP(Pooling) .OP_END_FACTORY_REG(Pooling) /** -*@brief Performs average pooling on the input . \n - +*@brief Performs average pooling on the input. \n *@par Inputs: -*x: A tensor of type float16, float32, double . \n +*x: A tensor of type float16, float32, double. \n *@par Attributes: -*@li ksize: A required list of 4 ints, specifying the size (N, C, H, and W) of the sliding window, - * where N = C = 1, and H and W are positive integers within the range [1, 255]. -*@li strides: A required list of 4 ints, specifying the stride of the sliding window. - * The strides of the N and C dimensions are 1. - * The strides of the H and W dimensions are positive integers within the range [1, 63]. +*@li ksize: A required list of 4 ints, specifying the size (N, C, H, and W) +* of the sliding window, where N = C = 1, and H and W are positive integers +* within the range [1, 255]. +* @li strides: A required list of 4 ints, specifying the stride of the +* sliding window. The strides of the N and C dimensions are 1. The strides of +* the H and W dimensions are positive integers within the range [1, 63]. *@li padding: A required string, specifying the padding algorithm, - * either "VALID" or "SAME". With "SAME" means that the outputs will have the same spatial dimensions as its inputs. - * With "VALID" means no padding. -*@li data_format: An optional string, specifying the data format of "ksize" and "strides", - * either "NCHW", or "NHWC" (default) . \n + * either "VALID" or "SAME". With "SAME" means that the outputs will have the + * same spatial dimensions as its inputs. With "VALID" means no padding. +*@li data_format: An optional string, specifying the data format of "ksize" +* and "strides", either "NCHW", or "NHWC" (default). \n *@par Outputs: -*y: The average pooled output tensor. Has the same type and format as input "x" . \n +* y: The average pooled output tensor. Has the same type and format +* as input "x". \n -*@attention Constraints: -*@li This operator applies only to a TensorFlow network. -*@li Only single input and single output are supported. +* @attention Constraints: +* @li This operator applies only to a TensorFlow network. +* @li Only single input and single output are supported. *@li Global pooling is supported. -*@li "ksize_H" and "ksize_W" are positive integers within the range [1, 255]. ksize_H * ksize_W < 256 +* @li "ksize_H" and "ksize_W" are positive integers within the range [1, 255]. +* ksize_H * ksize_W < 256 *@li Due to instruction restrictions, - * the values of "strides_h" and "strides_w" are positive integers within the range [1, 63]. + * the values of "strides_h" and "strides_w" are positive integers within + * the range [1, 63]. *@par Third-party framework compatibility * Compatible with the TensorFlow operator AvgPool. */ @@ -116,7 +119,6 @@ REG_OP(AvgPool) /** *@brief Performs average pooling on the input. - *@par Inputs: *x: A tensor of type float16, float32, double. @@ -130,19 +132,19 @@ REG_OP(AvgPool) * either "VALID", "SAME" and "CALCULATED". * With "SAME" means that the outputs will have the same spatial dimensions as its inputs. * With "VALID" means no padding. -*@li pads: Pad value when padding_mode is "CALCULATED". -*@li data_format: An optional string, specifying the data format of "ksize" and "strides", +* @li pads: Pad value when padding_mode is "CALCULATED". +* @li data_format: An optional string, specifying the data format of "ksize" and "strides", * either "NCHW", or "NHWC" (default). -*@li global_pooling: Global or not. If true, pads will change to {0,0,0,0} and ksize will change to [input_h, input_w] -*@li ceil_mode: Use ceil or floor to calculate the output size when padding_mode is "CALCULATED". -*@li exclusive: Ignore padding area or not when calculating average. +* @li global_pooling: Global or not. If true, pads will change to {0,0,0,0} and ksize will change to [input_h, input_w] +* @li ceil_mode: Use ceil or floor to calculate the output size when padding_mode is "CALCULATED". +* @li exclusive: Ignore padding area or not when calculating average. -*@par Outputs: -*y: The average pooled output tensor. Has the same type and format as input "x". +* @par Outputs: +* y: The average pooled output tensor. Has the same type and format as input "x". *@attention Constraints: *@li Only single input and single output are supported. -*@li Global pooling is supported. +* @li Global pooling is supported. *@li "ksize_H" and "ksize_W" are positive integers within the range [1, 255]. ksize_H * ksize_W < 256 *@li Due to instruction restrictions, * the values of "strides_h" and "strides_w" are positive integers within the range [1, 63]. @@ -163,25 +165,30 @@ REG_OP(AvgPoolV2) .OP_END_FACTORY_REG(AvgPoolV2) /** -*@brief Performs average pooling on the input. - -*@par Inputs: -*x: A 5-D Tensor of shape [batch, depth, height, width, channels] and type float16, float32, double. +* @brief Performs average pooling on the input. \n +* @par Inputs: +* x: A 5-D Tensor of shape [batch, depth, height, width, channels] and type +* float16, float32, double. \n -*@par Attributes: -*@li ksize: List of ints that has length 1, 3 or 5. The size of the window for each dimension of the input tensor. -*@li strides:List of ints that has length 1, 3 or 5. The stride of the sliding window for each dimension of the input tensor. -*@li pads: List of ints, implicit zero paddings on both sides of the input. -*@li ceil_mode: When true, will use ceil instead of floor in the formula to compute the output shape. -*@li count_include_pad: When true, will include the zero-padding in the averaging calculation. -*@li divisor_override: if specified, it will be used as divisor, otherwise size of the pooling region will be used. -*@li data_format: A string, format of input data . \n +* @par Attributes: +* @li ksize: List of ints that has length 1, 3 or 5. The size of the window +* for each dimension of the input tensor. +*@li strides:List of ints that has length 1, 3 or 5. The stride of the sliding +* window for each dimension of the input tensor. +* @li pads: List of ints, implicit zero paddings on both sides of the input. +* @li ceil_mode: When true, will use ceil instead of floor in the formula to +* compute the output shape. +* @li count_include_pad: When true, will include the zero-padding in the +* averaging calculation. +* @li divisor_override: if specified, it will be used as divisor, otherwise +* size of the pooling region will be used. +* @li data_format: A string, format of input data. \n *@par Outputs: -*y: The average pooled output tensor . \n +*y: The average pooled output tensor. \n *@attention Constraints: -*@li "ksize" is in the range [1, 255]. "strides" is in the range [1, 63] +* @li "ksize" is in the range [1, 255]. "strides" is in the range [1, 63]. *@par Third-party framework compatibility * Compatible with the TensorFlow operator AvgPool3D. @@ -200,19 +207,18 @@ REG_OP(AvgPool3D) /** -*@brief Performs average pooling on the input. - -*@par Inputs: -*@li x: A 5-D Tensor of shape [batch, depth, height, width, channels] and type float16, float32, double. -*@li filter: An optional tensor of type float16, float32, double, fractal_z_3d layout. +* @brief Performs average pooling on the input. +* @par Inputs: +* @li x: A 5-D Tensor of shape [batch, depth, height, width, channels] and type float16, float32, double. +* @li filter: An optional tensor of type float16, float32, double, fractal_z_3d layout. *@li multiplier: An optional tensor of float16, float32, double. -*@par Attributes: +* @par Attributes: *@li ksize: List of ints that has length 1, 3 or 5. The size of the window for each dimension of the input tensor. -*@li strides:List of ints that has length 1, 3 or 5. The stride of the sliding window for each dimension of the input tensor. +* @li strides:List of ints that has length 1, 3 or 5. The stride of the sliding window for each dimension of the input tensor. *@li pads: List of ints, implicit zero paddings on both sides of the input. *@li ceil_mode: When true, will use ceil instead of floor in the formula to compute the output shape. -*@li count_include_pad: When true, will include the zero-padding in the averaging calculation. +* @li count_include_pad: When true, will include the zero-padding in the averaging calculation. *@li divisor_override: if specified, it will be used as divisor, otherwise size of the pooling region will be used. *@li data_format: A string, format of input data . \n @@ -240,26 +246,30 @@ REG_OP(AvgPool3DD) .OP_END_FACTORY_REG(AvgPool3DD) /** -* @brief Computes AvgPool3DGrad function. - +* @brief Computes AvgPool3DGrad function. \n * @par Inputs: * @li orig_input_shape: An NDHWC tensor of type int32. -* @li grads: An NDHWC tensor of type float16, float32, or double. +* @li grads: An NDHWC tensor of type float16, float32, or double. \n * @par Attributes: -* @li ksize: List of ints that has length 5. The size of the window for each dimension of the input tensor. -* @li strides:List of ints that has length 5. The stride of the sliding window for each dimension of the input tensor. +* @li ksize: List of ints that has length 5. The size of the window for +* each dimension of the input tensor. +* @li strides:List of ints that has length 5. The stride of the sliding +* window for each dimension of the input tensor. * @li pads: List of ints, implicit zero paddings on both sides of the input. -* @li ceil_mode: When true, will use ceil instead of floor in the formula to compute the output shape. -* @li count_include_pad: When true, will include the zero-padding in the averaging calculation. -* @li divisor_override: if specified, it will be used as divisor, otherwise size of the pooling region will be used. -* @li data_format: A string, format of input data. +* @li ceil_mode: When true, will use ceil instead of floor in the formula to +* compute the output shape. +* @li count_include_pad: When true, will include the zero-padding in the +* averaging calculation. +* @li divisor_override: if specified, it will be used as divisor, otherwise +* size of the pooling region will be used. +* @li data_format: A string, format of input data. \n * @par Outputs: -* @output: A mutable tensor with the same shape and type as "orig_input_shape". +* @li output: A mutable tensor with the same shape and type as "grads". * @attention Constraints: -* @li "ksize" is in the range [1, 255]. "strides" is in the range [1, 63] +* @li "ksize" is in the range [1, 255]. "strides" is in the range [1, 63]. \n * @par Third-party framework compatibility * @li Compatible with the TensorFlow operator AvgPoolGrad. @@ -280,21 +290,26 @@ REG_OP(AvgPool3DGrad) /** * @brief Performs average pooling on the input. - * @par Inputs: * @li grads: An NDHWC tensor of type float16. * @li filter: An optional tensor of type float16, fractal_z_3d layout. * @li multiplier: An optional tensor of float16. * @par Attributes: -* @li orig_input_shape: List of ints that has length 5. The size of the window for each dimension of the input tensor. -* @li ksize: List of ints that has length 5. The size of the window for each dimension of the input tensor. -* @li strides:List of ints that has length 5. The stride of the sliding window for each dimension of the input tensor. +* @li orig_input_shape: List of ints that has length 5. +* The size of the window for each dimension of the input tensor. +* @li ksize: List of ints that has length 5. +* The size of the window for each dimension of the input tensor. +* @li strides:List of ints that has length 5. +* The stride of the sliding window for each dimension of the input tensor. * @li pads: List of ints, implicit zero paddings on both sides of the input. -* @li ceil_mode: When true, will use ceil instead of floor in the formula to compute the output shape. -* @li count_include_pad: When true, will include the zero-padding in the averaging calculation. -* @li divisor_override: if specified, it will be used as divisor, otherwise size of the pooling region will be used. -* @li data_format: A string, format of input data . \n +* @li ceil_mode: When true, will use ceil instead of floor +* in the formula to compute the output shape. +* @li count_include_pad: When true, will include the zero-padding +* in the averaging calculation. +* @li divisor_override: if specified, it will be used as divisor, +* otherwise size of the pooling region will be used. +* @li data_format: A string, format of input data. \n * @par Outputs: * output: The average pooled output tensor . \n @@ -364,9 +379,9 @@ REG_OP(MaxPoolExt2) /** *@brief Performs max pooling on the input . \n -*@par Inputs: +* @par Inputs: * One input: -*x: A Tensor. Supported type:float16, float32, double, int8, int16, +* x: A Tensor. Supported type:float16, float32, double, int8, int16, * int32, int64, uint8, uint16, qint8 *@par Attributes: @@ -406,10 +421,10 @@ REG_OP(MaxPool) .OP_END_FACTORY_REG(MaxPool) /** -*@brief Performs max 3d pooling on the input . \n +* @brief Performs max 3d pooling on the input . \n *@par Inputs: -*x: A Tensor. Supported type float16, float32, double . \n +* x: A Tensor. Supported type float16, float32, double . \n *@par Attributes: *@li ksize: A required list of int8, int16, int32, or int64 values, @@ -680,7 +695,7 @@ REG_OP(MaxPoolV2) .OP_END_FACTORY_REG(MaxPoolV2) /** -*@brief Performs max pooling on the input and outputs both max values and +* @brief Performs max pooling on the input and outputs both max values and * indices . \n *@par Inputs: @@ -702,7 +717,7 @@ REG_OP(MaxPoolV2) *@par Outputs: *@li y: A Tensor. Has the same type and format as input "x". *@li argmax: A Tensor. Has the same type and format as input "x". -*@attention Constraints: +* @attention Constraints: *@li "ksize" is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, * ksize[1] * ksize[2] <= 255. *@li "stride is a list that has length 4: strides[0] = 1 or strides[3] = 1, @@ -723,39 +738,39 @@ REG_OP(MaxPoolWithArgmax) .OP_END_FACTORY_REG(MaxPoolWithArgmax) /** -*@brief Performs the backpropagation of MaxPoolWithArgmax . \n +* @brief Performs the backpropagation of MaxPoolWithArgmax . \n -*@par Inputs: +* @par Inputs: * Three inputs, including: -*@li x: An 4d tensor. Supported type: float, double, int32, +* @li x: An 4d tensor. Supported type: float, double, int32, * uint8, int16, int8, int64, uint16, half, uint32, uint64. * Must set the format, supported format list ["NCHW, NHWC"] -*@li grad: An 4d tensor. Supported type: float, double, int32, +* @li grad: An 4d tensor. Supported type: float, double, int32, * uint8, int16, int8, int64, uint16, half, uint32, uint64. * Must set the format, supported format list ["NCHW, NHWC"] *@li argmx: A tensor of type int32 or int64 . \n -*@par Attributes: -*@li ksize: A required list of int8, int16, int32, or int64 values, +* @par Attributes: +* @li ksize: A required list of int8, int16, int32, or int64 values, * specifying the size of the window for each dimension of the input tensor. * No default value. -*@li strides: A required list of int8, int16, int32, or int64 values, +* @li strides: A required list of int8, int16, int32, or int64 values, * specifying the stride of the sliding window for each dimension of * the input tensor. No default value. -*@li padding: A required string. No default value . \n +* @li padding: A required string. No default value . \n -*@par Outputs: +* @par Outputs: *y: A Tensor. Has the same type and format as input "x" . \n -*@attention Constraints: -*@li "ksize" is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, +* @attention Constraints: +* @li "ksize" is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, * ksize[1] * ksize[2] <= 255. -*@li "strides" is a list that has length 4: strides[0] = 1 or strides[3] = 1 -*@li "padding" is either "SAME" or "VALID". +* @li "strides" is a list that has length 4: strides[0] = 1 or strides[3] = 1 +* @li "padding" is either "SAME" or "VALID". \n -*@see max_pool_with_argmax -*@par Third-party framework compatibility +* @see max_pool_with_argmax +* @par Third-party framework compatibility * Compatible with the TensorFlow operator MaxPoolGradWithArgmax. */ REG_OP(MaxPoolGradWithArgmax) @@ -769,23 +784,23 @@ REG_OP(MaxPoolGradWithArgmax) .OP_END_FACTORY_REG(MaxPoolGradWithArgmax) /** -*@brief Performs transform mask to argmax . \n +* @brief Performs transform mask to argmax . \n -*@par Inputs: +* @par Inputs: * Two inputs: -*@li x: A Tensor of type float16. -*@li mask: A Tensor of type uint16 . \n +* @li x: A Tensor of type float16. +* @li mask: A Tensor of type uint16 . \n -*@par Attributes: -*@li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for each dimension of the input tensor. No default value. -*@li strides: A required list of int8, int16, int32, or int64 values, specifying the stride of the sliding window for each dimension of the input tensor. No default value. -*@li padding: A required string. No default value . -*@li originshape:A required list of int8, int16, int32, or int64 values, No default value. \n +* @par Attributes: +* @li ksize: A required list of int8, int16, int32, or int64 values, specifying the size of the window for each dimension of the input tensor. No default value. +* @li strides: A required list of int8, int16, int32, or int64 values, specifying the stride of the sliding window for each dimension of the input tensor. No default value. +* @li padding: A required string. No default value . +* @li originshape:A required list of int8, int16, int32, or int64 values, No default value. \n -*@par Outputs: +* @par Outputs: *argmax: A Tensor of type int32 . \n -*@attention Constraints: +* @attention Constraints: *@li "ksize" is a list that has length 4: ksize[0] = 1 or ksize[3] = 1, ksize[1] * ksize[2] <= 255. *@li "stride is a list that has length 4: strides[0] = 1 or strides[3] = 1, strides[1] <= 63, strides[0] >= 1, strides[2] <= 63, strides[2] >= 1. *@li "padding" is either "SAME" or "VALID" . \n @@ -843,11 +858,10 @@ REG_OP(MaxPoolGradGradWithArgmax) .OP_END_FACTORY_REG(MaxPoolGradGradWithArgmax) /** -* @brief Computes avgpoograd function . \n - +* @brief Computes avgpoograd function. \n * @par Inputs: * @li orig_input_shape: An NHWC tensor of type int32. -* @li input_grad: An NHWC tensor of type float16, float32, or double . \n +* @li input_grad: An NHWC tensor of type float16, float32, or double. \n * @par Attributes: * @li ksize: A required tuple or list, specifying the size of the window for @@ -856,10 +870,10 @@ REG_OP(MaxPoolGradGradWithArgmax) * window for each dimension of the input tensor. * @li padding: A required string, specifying the type of * the padding algorithm to use. -* @li data_format: An optional string. Defaults to "NHWC" . \n +* @li data_format: An optional string. Defaults to "NHWC". \n * @par Outputs: -* @out_grad: A mutable tensor with the same shape and type as "orig_input" . \n +* out_grad: A mutable tensor with the same shape and type as "input_grad". \n * @par Third-party framework compatibility * @li Compatible with the TensorFlow operator AvgPoolGrad. @@ -876,7 +890,6 @@ REG_OP(AvgPoolGrad) /** * @brief Computes gradients of average pooling function . \n - * @par Inputs: * @input_grad: An NHWC tensor of type float16. * @mean_matrix: Assist matrix, an NHWC tensor of type float16. @@ -911,11 +924,10 @@ REG_OP(AvgPoolGradD) .OP_END_FACTORY_REG(AvgPoolGradD) /** -* @brief Computes avgpoolv2grad function. - +* @brief Computes avgpoolv2grad function. \n * @par Inputs: * @li orig_input_shape: An NHWC tensor of type int32. -* @li input_grad: An NHWC tensor of type float16, float32, or double. +* @li input_grad: An NHWC tensor of type float16, float32, or double. \n * @par Attributes: * @li ksize: A required tuple or list, specifying the size of the window for @@ -924,15 +936,15 @@ REG_OP(AvgPoolGradD) * window for each dimension of the input tensor. * @li padding_mode: A required string, specifying the type of * the padding algorithm to use. -* @li global_pooling: Whether to use the global pooling. If global_pooling=true, -* ksize and pads will be ignored. Default False. -* @li ceil_mode: Whether to use the ceil function to calculate output height and -* width. Default False. +* @li global_pooling: Whether to use the global pooling. If global_pooling = +* true, ksize and pads will be ignored. Default False. +* @li ceil_mode: Whether to use the ceil function to calculate output height +* and width. Default False. * @li exclusive: Whether to exclude padding points. default is true. -* @li data_format: An optional string. Defaults to "NHWC". +* @li data_format: An optional string. Defaults to "NHWC". \n * @par Outputs: -* @out_grad: A mutable tensor with the same shape and type as "orig_input". +* @li out_grad: A mutable tensor with the same shape and type as "orig_input". \n * @par Third-party framework compatibility * @li Compatible with the TensorFlow operator AvgPoolGrad. @@ -952,7 +964,6 @@ REG_OP(AvgPoolV2Grad) .OP_END_FACTORY_REG(AvgPoolV2Grad) /** * @brief Computes gradients of averagev2 pooling function. - * @par Inputs: *input_grad: An NHWC tensor of type float16, float32, or double. @@ -1257,7 +1268,6 @@ REG_OP(MaxPool3DGrad) /** *@brief Performs AvgPool1D on the input . \n - *@par Inputs: *x: A Tensor. Must be one of the following types: int8, uint8, int16, int32, int64, float16, float32, float64 . \n @@ -1286,7 +1296,6 @@ REG_OP(AvgPool1D) /** *@brief Performs AvgPool1D on the input . \n - *@par Inputs: *x: A Tensor. Must be one of the following types: int8, uint8, int16, int32, int64, float16, float32, float64 . \n diff --git a/third_party/fwkacllib/inc/ops/nn_training_ops.h b/third_party/fwkacllib/inc/ops/nn_training_ops.h index 21ee90ab..32da707e 100644 --- a/third_party/fwkacllib/inc/ops/nn_training_ops.h +++ b/third_party/fwkacllib/inc/ops/nn_training_ops.h @@ -2002,40 +2002,41 @@ REG_OP(ApplyAdadeltaD) .OP_END_FACTORY_REG(ApplyAdadeltaD) /** -* @brief Updates "var" according to the ApplyMomentum algorithm. -* accum = accum * momentum + x1 * x2 -* if use_nesterov is True: -* var -= x1 * x2 * lr + accum * momentum * lr -* else: -* var -= accum * lr +*@brief Updates "var" according to the ApplyMomentum algorithm. +* accum = accum * momentum + x1 * x2 +* if use_nesterov is True: +* var -= x1 * x2 * lr + accum * momentum * lr +* else: var -= accum * lr * -* @par Inputs: -* Six inputs, including: -* @li var: A mutable Tensor has type TensorType::NumberType(). -* Should be a Variable Tensor. -* @li accum: A mutable Tensor has the same type as "var". -* Should be a Variable Tensor. -* @li lr: A scalar has the same type as "var", for the scaling factor. -* @li x1: A Tensor has type TensorType::NumberType(). -* @li momentum: A scalar has the same type as "var". -* @li x2: A scalar has the same type as "var". +*@par Inputs: +* Six inputs, including: +*@li var: A mutable Tensor has type TensorType::NumberType(). +* Should be a Variable Tensor. +*@li accum: A mutable Tensor has the same type as "var". +* Should be a Variable Tensor. +*@li lr: A scalar has the same type as "var", for the scaling factor. +*@li x1: A Tensor has type TensorType::NumberType(). +*@li momentum: A scalar has the same type as "var". +*@li x2: A scalar has the same type as "var". \n * -* @par Attributes: -* Two attributes, including: -* @li use_nesterov: An optional bool. Defaults to "False". -* If True, the tensor passed to compute grad will be var - lr * momentum * accum, -* so in the end, the var you get is actually var - lr * momentum * accum. -* @li use_locking: An optional bool. Defaults to "False". -* If "True", updating of the "var", m", and "v" tensors will be protected -* by a lock; otherwise the behavior is undefined, but may exhibit less contention. +*@par Attributes: +* Two attributes, including: +*@li use_nesterov: An optional bool. Defaults to "False". +* If True, the tensor passed to compute grad will be +* var - lr * momentum * accum, so in the end, +* the var you get is actually var - lr * momentum * accum. +*@li use_locking: An optional bool. Defaults to "False". +* If "True", updating of the "var", m", and "v" tensors will be protected +* by a lock; otherwise the behavior is undefined, but may exhibit +* less contention. \n * -* @par Outputs: -* Two outputs, including: -* @li var: A mutable Tensor has the same type as "var". -* @li accum: A mutable Tensor has the same type as "var". +*@par Outputs: +* Two outputs, including: +*@li var: A mutable Tensor has the same type as "var". +*@li accum: A mutable Tensor has the same type as "var". \n *@par Restrictions: -*Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. +* Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. */ REG_OP(FusedMulApplyMomentum) .INPUT(var, TensorType::NumberType()) diff --git a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h index a582d6e2..e4d7936c 100644 --- a/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h +++ b/third_party/fwkacllib/inc/ops/nonlinear_fuc_ops.h @@ -26,16 +26,17 @@ namespace ge { /** *@brief The GELU activation function is x*Φ(x), -* where Φ(x) the standard Gaussian cumulative distribution function. \n +* where Φ(x) the standard Gaussian cumulative distribution function. *@par Inputs: -*One input, including: -*x: A Tensor. Must be one of the following types: float16, float32 +*One input, including: \n +*x: A Tensor. Must be one of the following types: float16, float32. \n *@par Outputs: -*y: A Tensor. Has the same type as "x". -*@par Third-party framework compatibility -*Compatible with the TensorFlow operator Gelu +*y: A Tensor. Has the same type as "x". \n + +*@par Third-party framework compatibility: +* Compatible with the TensorFlow operator Gelu. */ REG_OP(Gelu) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -124,18 +125,18 @@ REG_OP(SwishGrad) .OP_END_FACTORY_REG(SwishGrad) /** -*@brief Computes the gradient for the gelu of "x" . \n +*@brief Computes the gradient for the gelu of "x" . *@par Inputs: -*Three inputs, including: -* @li dy: A Tensor. Must be one of the following types: float16, float32 -* @li x: A Tensor of the same type as "dy". -* @li y: A Tensor of the same type as "dy" . \n +* Three inputs, including: +*@li dy: A Tensor. Must be one of the following types: float16, float32. +*@li x: A Tensor of the same type as "dy". +*@li y: A Tensor of the same type as "dy" . \n *@par Outputs: *z: A Tensor. Has the same type as "dy". *@par Third-party framework compatibility -*Compatible with the TensorFlow operator GeluGrad +* Compatible with the TensorFlow operator GeluGrad. */ REG_OP(GeluGrad) .INPUT(dy, TensorType({DT_FLOAT16, DT_FLOAT})) @@ -419,7 +420,7 @@ REG_OP(Softplus) .OP_END_FACTORY_REG(Softplus) /** -*@brief Computes softplus gradients for a softplus operation . \n +* @brief Computes softplus gradients for a softplus operation . *@par Inputs: *Two inputs: @@ -440,7 +441,7 @@ REG_OP(SoftplusGrad) .OP_END_FACTORY_REG(SoftplusGrad) /** -*@brief Computes softsign: x/(abs(x) + 1) . \n +* @brief Computes softsign: x/(abs(x) + 1) . *@par Inputs: * One input: @@ -798,7 +799,7 @@ REG_OP(LeakyReluGrad) .OP_END_FACTORY_REG(LeakyReluGrad) /** -*@brief Thresholds grad each element of the input Tensor . \n +*@brief Thresholds grad each element of the input Tensor . *@par Inputs: * @li gradients: A Tensor shape and dtype of input gradients. Support float16, int32. @@ -821,7 +822,7 @@ REG_OP(ThresholdGradV2D) .OP_END_FACTORY_REG(ThresholdGradV2D) /** -*@brief Thresholds each element of the input Tensor y = (x > threshold) ? x : value . \n +*@brief Thresholds each element of the input Tensor y = (x > threshold) ? x : value . *@par Inputs: *x: A Tensor dtype of real number . \n diff --git a/third_party/fwkacllib/inc/ops/quantize_ops.h b/third_party/fwkacllib/inc/ops/quantize_ops.h index 5a66b4ee..ae701295 100644 --- a/third_party/fwkacllib/inc/ops/quantize_ops.h +++ b/third_party/fwkacllib/inc/ops/quantize_ops.h @@ -93,18 +93,18 @@ REG_OP(Quantize) * @li sqrt_mode: A optional bool, specifying whether to perform square root on "scale", either "True" or "False". * Defaults to "False". * @li round_mode: An optional string, specifying the float16 to int8 cast type. -* The value range is [Round, Floor, Ceil, Truncate]. Defaults to "Round" . +* The value range is [Round, Floor, Ceil, Trunc]. Defaults to "Round" . * @li dst_type: A optional int32, specifying the output data type. Defaults to "DT_INT8" . \n * @par Outputs: * y: The quantized output tensor of type int8 or int4. \n * @attention Constraints: -* round_mode value range is [Round, Floor, Ceil, Truncate]. +* round_mode value range is [Round, Floor, Ceil, Trunc]. * @li Round: round to nearest, tie to even(c language rint). * @li Floor: round to minus infinity(c language floor). * @li Ceil: round to positive infinity(c language ceil). -* @li Truncate: round to zero(c language trunc). \n +* @li Trunc: round to zero(c language trunc). \n * @par Third-party framework compatibility * It is a custom operator. It has no corresponding operator in Caffe. diff --git a/third_party/fwkacllib/inc/ops/reduce_ops.h b/third_party/fwkacllib/inc/ops/reduce_ops.h index 2c4b3059..079982db 100644 --- a/third_party/fwkacllib/inc/ops/reduce_ops.h +++ b/third_party/fwkacllib/inc/ops/reduce_ops.h @@ -25,7 +25,7 @@ namespace ge { /** -*@brief Performs reduced batch normalization . \n +*@brief Performs reduced batch normalization . *@par Inputs: *x: A tensor of type float16 or float32. \n @@ -67,7 +67,7 @@ REG_OP(BN3DTrainingReduce) .OP_END_FACTORY_REG(BN3DTrainingReduce) /** -*@brief Performs the backpropagation of BatchNorm . \n +*@brief Performs the backpropagation of BatchNorm . *@par Inputs: * Seven inputs, including: @@ -153,7 +153,7 @@ REG_OP(BN3DTrainingReduceGrad) .OP_END_FACTORY_REG(BN3DTrainingReduceGrad) /** -*@brief Performs reduced batch normalization . \n +*@brief Performs reduced batch normalization . *@par Inputs: * Seven inputs, including: @@ -183,10 +183,10 @@ REG_OP(BN3DTrainingReduceGrad) *@attention Constraints: *@li This operator is a BatchNorm fusion operator for updating the moving -averages for training. -*This operator is used in conjunction with BNTrainingUpdate. -*@li For Ascend 310, the result accuracy fails to reach 1/1000 due to the square -* root instruction. +* averages for training. This operator is used in conjunction with +* BNTrainingUpdate. +*@li For Ascend 310, the result accuracy fails to reach 1/1000 due to the +* square root instruction. */ REG_OP(BNTrainingUpdate) .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -259,7 +259,7 @@ REG_OP(BN3DTrainingUpdate) .OP_END_FACTORY_REG(BN3DTrainingUpdate) /** -*@brief Performs batch normalization for inference . \n +*@brief Performs batch normalization for inference . *@par Inputs: * Five inputs, including: @@ -277,8 +277,8 @@ REG_OP(BN3DTrainingUpdate) *y: A tensor of type float16 or float32 for the normalized "x" . \n *@attention Constraints: -*For Ascend 310, the result accuracy fails to reach 1/1000 due to the square root -* instruction. +*For Ascend 310, the result accuracy fails to reach 1/1000 due to the +* square root instruction. */ REG_OP(BNInfer) .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -291,19 +291,21 @@ REG_OP(BNInfer) .OP_END_FACTORY_REG(BNInfer) /** -*@brief Performs reduced batch normalization. For some scene which don't contain -assignmoving average . \n +*@brief Performs reduced batch normalization. For some scenes which don't +* contain assign moving average . *@par Inputs: *Five inputs, including: *@li x: A tensor of type float16 or float32. *@li sum: A tensor of type float32 for the output of operator BNTrainingReduce. -*@li square_sum: A tensor of type float32 for the output of operator BNTrainingReduce. +*@li square_sum: A tensor of type float32 for the output of operator +* BNTrainingReduce. *@li scale: A tensor of type float32, for the scaling factor. *@li offset: A tensor of type float32, for the scaling offset . \n *@par Attributes: -*epsilon: A required float32, specifying the small value added to variance to avoid dividing by zero . \n +*epsilon: A required float32, specifying the small value added to +* variance to avoid dividing by zero . \n *@par Outputs: *Three outputs, including: @@ -313,7 +315,8 @@ assignmoving average . \n *@attention Constraints: *This operator is used in conjunction with BNTrainingReduce. -For Ascend 310, the result accuracy fails to reach 1/1000 due to the square root instruction. +*For Ascend 310, the result accuracy fails to reach 1/1000 due to +* the square root instruction. */ REG_OP(BNTrainingUpdateV2) .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -328,30 +331,35 @@ REG_OP(BNTrainingUpdateV2) .OP_END_FACTORY_REG(BNTrainingUpdateV2) /** -*@brief Performs reduced batch normalization v3. For some scene which don't contain -assign moving average . \n +*@brief Performs reduced batch normalization v3. For some scenes which +* don't contain assign moving average . *@par Inputs: * Five inputs, including: *@li x: A tensor of type float16 or float32. *@li sum: A tensor of type float32 for the output of operator BNTrainingReduce. -*@li square_sum: A tensor of type float32 for the output of operator BNTrainingReduce. +*@li square_sum: A tensor of type float32 for the output of operator +* BNTrainingReduce. *@li scale: A tensor of type float32, for the scaling factor. *@li offset: A tensor of type float32, for the scaling offset . \n *@par Attributes: -*epsilon: A required float32, specifying the small value added to variance to avoid dividing by zero . \n +*epsilon: A required float32, specifying the small value added to variance +* to avoid dividing by zero . \n *@par Outputs: *@li y: A tensor of type float16 or float32, for normalized "x". *@li batch_mean: A tensor of type float32, for the mean of "x". *@li batch_variance: A tensor of type float32, for the variance of "x". -*@li reserve_1: A tensor of type float32, for the mean of batch "x". Has the same type as batch_mean. -*@li reserve_2: A tensor of type float32, for the variance of batch "x". Has the same type as batch_mean . \n +*@li reserve_1: A tensor of type float32, for the mean of batch "x". +* Has the same type as batch_mean. +*@li reserve_2: A tensor of type float32, for the variance of batch "x". +* Has the same type as batch_mean . \n *@attention Constraints: *@li This operator is used in conjunction with BNTrainingReduce. -*@li For Ascend 310, the result accuracy fails to reach 1/1000 due to the square root instruction. +*@li For Ascend 310, the result accuracy fails to reach 1/1000 due to +* the square root instruction. */ REG_OP(BNTrainingUpdateV3) .INPUT(x, TensorType({DT_FLOAT16,DT_FLOAT})) @@ -368,7 +376,7 @@ REG_OP(BNTrainingUpdateV3) .OP_END_FACTORY_REG(BNTrainingUpdateV3) /** -*@brief Performs the backpropagation of BatchNorm . \n +*@brief Performs the backpropagation of BatchNorm . *@par Inputs: * Four inputs, including: @@ -436,16 +444,17 @@ REG_OP(BN3DTrainingUpdateGrad) .OP_END_FACTORY_REG(BN3DTrainingUpdateGrad) /** -*@brief Performs the backpropagation of BatchNorm for inference . \n +*@brief Performs the backpropagation of BatchNorm for inference . *@par Inputs: * Three inputs, including: -*@li grads: A tensor of type loat16 or float32, for the gradient. +*@li grads: A tensor of type float16 or float32, for the gradient. *@li scale: A tensor of type float32. *@li batch_variance: A tensor of type float32. It is an output of BatchNorm . \n *@par Attributes: -*epsilon: An optional float32. Defaults to "0.0001". A small float number added to the variance of "x" . \n +*epsilon: An optional float32. Defaults to "0.0001". A small float number +* added to the variance of "x" . \n *@par Outputs: *x_backprop: A Tensor of type float16 or float32, for the offset of "x" . \n diff --git a/third_party/fwkacllib/inc/ops/selection_ops.h b/third_party/fwkacllib/inc/ops/selection_ops.h index 5222bf7d..810d024b 100644 --- a/third_party/fwkacllib/inc/ops/selection_ops.h +++ b/third_party/fwkacllib/inc/ops/selection_ops.h @@ -2029,26 +2029,29 @@ REG_OP(Cummax) /** *@brief Extends the input with copies of data along a specified dimension. For example: -*(1) If x = [[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]]], with shape (2, 3, 2); -*(2) axis = 1; -*(3) tiles = 2; -*(4) Then, y = [[[1, 2], [3, 4], [5, 6], [1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12], [7, 8], [9, 10], [11, 12]]], with shape (2, 6, 2) . \n +*(1) If x = [[[1, 2], [3, 4], [5, 6]], [[7, 8], [9, 10], [11, 12]]], with shape (2, 3, 2); \n +*(2) axis = 1; \n +*(3) tiles = 2; \n +*(4) Then, y = [[[1, 2], [3, 4], [5, 6], [1, 2], [3, 4], [5, 6]], [[7, 8], +* [9, 10], [11, 12], [7, 8], [9, 10], [11, 12]]], +* with shape (2, 6, 2) . \n *@par Inputs: * One input: *input_x: A Tensor with any format. Must be one of the following types: float16, float32, int8, int16, int32, int64, uint8, uint16, uint32, uint64 . \n -*@par Attributes: -*@li axis: An optional int32, specifying the axis to tile. Defaults to 1. -*@li tiles: A required int32, specifying the number of copies (tiles) to output . \n +* @par Attributes: +* @li axis: An optional int32, specifying the axis to tile. Defaults to 1. +* @li tiles: A required int32, specifying the number of copies (tiles) to output . \n *@par Outputs: -*output_y: A Tensor of any format. Must be one of the following types: float16, float32, int8, int16, int32, int64, uint8, uint16, uint32, uint64 . \n +* output_y: A Tensor of any format. Must be one of the following types: +* float16, float32, int8, int16, int32, int64, uint8, uint16, uint32, uint64 . \n -*@attention Constraints: -*@li "axis" must be within the rank of the input tensor. -*@li "tiles" must be greater than 1. -*@par Third-party framework compatibility +* @attention Constraints: +* @li "axis" must be within the rank of the input tensor. +* @li "tiles" must be greater than 1. +* @par Third-party framework compatibility * Compatible with the Caffe operator Tile. */ REG_OP(TileWithAxis) @@ -2061,17 +2064,17 @@ REG_OP(TileWithAxis) .OP_END_FACTORY_REG(TileWithAxis) /** -*@brief Read data with offset and stride . \n +* @brief Read data with offset and stride . -*@par Inputs: -*One input: -*x: A Tensor. Must be one of the following types: float16, int8 . \n +* @par Inputs: +* One input: +* x: A Tensor. Must be one of the following types: float16, int8 . \n -*@par Attributes: -*@li stride_list: An optional 5D list of type int32. Defaults to "[1,1,1,1,1]" . \n +* @par Attributes: +* stride_list: An optional 5D list of type int32. Defaults to "[1,1,1,1,1]" . \n -*@par Outputs: -*y: A Tensor of the same type as "x". +* @par Outputs: +* y: A Tensor of the same type as "x". *@par Restrictions: *Warning: THIS FUNCTION IS EXPERIMENTAL. Please do not use. @@ -2083,10 +2086,10 @@ REG_OP(ReadSelect) .OP_END_FACTORY_REG(ReadSelect) /** -*@brief: Write data with offset . \n +* @brief: Write data with offset . -*@par Inputs: -*x: A Tensor. Must be one of the following types: int32, float32, float16, int8 . \n +* @par Inputs: +* x: A Tensor. Must be one of the following types: int32, float32, float16, int8 . \n *@par Outputs: *y: A Tensor. Has the same type as "x". @@ -2100,14 +2103,14 @@ REG_OP(WriteSelect) .OP_END_FACTORY_REG(WriteSelect) /** -*@brief Read data by stride. +* @brief Read data by stride. -*@par Inputs: -*x: A Tensor. Must be one of the following types: float16, int8. \n +* @par Inputs: +* x: A Tensor. Must be one of the following types: float16, int8. \n -*@par Attributes: -*@li axis: A required int32, specifying the index of axis to read by stride. \n -*@li stride: A required int32, specifying the value of reading stride. \n +* @par Attributes: +* @li axis: A required int32, specifying the index of axis to read by stride. +* @li stride: A required int32, specifying the value of reading stride. \n *@par Outputs: *y: A Tensor of the same type as "x". @@ -2120,14 +2123,14 @@ REG_OP(StridedRead) .OP_END_FACTORY_REG(StridedRead) /** -*@brief Write data by stride. +* @brief Write data by stride. -*@par Inputs: -*x: A Tensor. Must be one of the following types: float16, int8. \n +* @par Inputs: +* x: A Tensor. Must be one of the following types: float16, int8. \n -*@par Attributes: -*@li axis: A required int32, specifying the index of axis to write by stride. \n -*@li stride: A required int32, specifying the value of writing stride. \n +* @par Attributes: +* @li axis: A required int32, specifying the index of axis to write by stride. +* @li stride: A required int32, specifying the value of writing stride. \n *@par Outputs: *y: A Tensor. Has the same type as "x". @@ -2140,20 +2143,20 @@ REG_OP(StridedWrite) .OP_END_FACTORY_REG(StridedWrite) /** -*@brief Computes the cumulative log sum exp of the tensor "x" along "axis" . \n +* @brief Computes the cumulative log sum exp of the tensor "x" along "axis" . -*@par Inputs: +* @par Inputs: * Two inputs, including: -*@li x: A Tensor. Must be one of the following types: float32, float16. -*@li axis A Tensor of type int32 or int16. Defaults to "0". +* @li x: A Tensor. Must be one of the following types: float32, float16. +* @li axis A Tensor of type int32 or int16. Defaults to "0". * *@par Attributes: *@li exclusive: If "False", performs inclusive CumulativeLogsumexp, which means that the first element of the input is identical to the first element of the output. If "True", performs exclusive CumulativeLogsumexp. *@li reverse: A bool. Defaults to "False". * -*@par Outputs: -*@li y: A Tensor. Has the same type as "x". -*@par Third-party framework compatibility +* @par Outputs: +* y: A Tensor. Has the same type as "x". +* @par Third-party framework compatibility * Compatible with the TensorFlow operator Cumsum. */ REG_OP(CumulativeLogsumexp) @@ -2169,7 +2172,7 @@ REG_OP(CumulativeLogsumexp) * *@par Inputs: * One input: -*x: A Tensor. Must be one of the following types: float32, float16. +* x: A Tensor. Must be one of the following types: float32, float16. * *@par Attributes: *@li axis A Tensor of type int32 or int16. Defaults to "0". @@ -2224,15 +2227,16 @@ REG_OP(InplaceIndexAdd) /** * @brief Replace the value of X with value according to mask. + * @par Inputs: -* three inputs, including: -* @li x: A Tensor of dtype is float16 or float32 or int64 or int32 or int8. -* @li mask: A Tensor of dtype bool. -* @li value: A Tensor of dtype float16 or float32 or int64 or int32 or int8. +* Three inputs, including: +* @li x: A Tensor of dtype is float16 or float32 or int64 or int32 or int8. +* @li mask: A Tensor of dtype bool. +* @li value: A Tensor of dtype float16 or float32 or int64 or int32 or int8. \n * @par Outputs: -* y: A tensor. Must be one of the following dtypes: -* float16, float32, int64, int32, int8. +* y: A tensor. Must be one of the following dtypes: +* float16, float32, int64, int32, int8. */ REG_OP(MaskedFill) .INPUT(x, TensorType({DT_FLOAT, DT_FLOAT16, DT_INT8, DT_INT32, DT_INT64})) @@ -2362,25 +2366,25 @@ REG_OP(StridedSliceV2) .OP_END_FACTORY_REG(StridedSliceV2) /** -*@brief Fills the elements of the input tensor with value val by selecting the indices in the order given in index. \n +* @brief Fills the elements of the input tensor with value val by selecting the indices in the order given in index. -*@par Inputs: -*Three inputs, including: +* @par Inputs: +* Three inputs, including: * @li x: A tensor. Must be one of the following types: * float16, float32, int32. \n -*@li assist1: A tensor. Must be one of the following types: +* @li assist1: A tensor. Must be one of the following types: * float16, float32, int32. \n -*@li assist2: A tensor. Must be one of the following types: +* @li assist2: A tensor. Must be one of the following types: * float16, float32, int32. \n * @par Attributes: * dim: A required int. Used to select the dimension of this tensor. \n -*@par Outputs: -*y: A Tensor with the same type and shape of input_x's. \n +* @par Outputs: +* y: A Tensor with the same type and shape of input_x's. \n -*@par Third-party framework compatibility -*Compatible with the Pytorch operator IndexFill. \n +* @par Third-party framework compatibility +* Compatible with the Pytorch operator IndexFill. \n */ REG_OP(IndexFillD) .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_INT32})) @@ -2417,27 +2421,27 @@ REG_OP(AddRowRanges) .OP_END_FACTORY_REG(AddRowRanges) /** -*@brief masked fill tensor along with one axis by range. +* @brief masked fill tensor along with one axis by range. * boxes. It is a customized masked fill range operator . \n -*@par Inputs: +* @par Inputs: * Four inputs, including: -*@li x: input tensor. A ND Tensor of float32/float16/int32/int8 with shapes +* @li x: input tensor. A ND Tensor of float32/float16/int32/int8 with shapes * 1-D (D,), 2-D(N, D), 3-D(N, C, D) -*@li start: masked fill start pos. A 3D Tensor of int32 with +* @li start: masked fill start pos. A 3D Tensor of int32 with * shape (num, N). "num" indicates the number of loop masked fill, and the value N -* indicates the batch of ND Tensor, if input x shape is 1-D, N = 1. \n -*@li end: masked fill end pos. A 3D Tensor of int32 with +* indicates the batch of ND Tensor, if input x shape is 1-D, N = 1. +* @li end: masked fill end pos. A 3D Tensor of int32 with * shape (num, N). "num" indicates the number of loop masked fill, and the value N -* indicates the batch of ND Tensor. \n -*@li value: masked fill value. A 2D Tensor of float32/float16/int32/int8 with -* shape (num,). "num" indicates the number of loop masked fill +* indicates the batch of ND Tensor. +* @li value: masked fill value. A 2D Tensor of float32/float16/int32/int8 with +* shape (num,). "num" indicates the number of loop masked fill. \n -*@par Attributes: -*@li axis: axis with masked fill of int32. Defaults to -1. +* @par Attributes: +* @li axis: axis with masked fill of int32. Defaults to -1. -*@par Outputs: -*y: A ND Tensor of float32/float16/int32/int8 with shapes 1-D (D,), 2-D(N, D), 3-D(N, C, D) +* @par Outputs: +* y: A ND Tensor of float32/float16/int32/int8 with shapes 1-D (D,), 2-D(N, D), 3-D(N, C, D) *@attention Constraints: * Warning: input shape's length must not be bigger than 1024 * 1024 * 1024. @@ -2456,10 +2460,12 @@ REG_OP(MaskedFillRange) * * @par Inputs: * Six inputs, including: -* @li topk_pq_distance: A sorted Tensor, Will be updated after calculation. Must be one of the following types: float32, float16. +* @li topk_pq_distance: A sorted Tensor, Will be updated after calculation. +* Must be one of the following types: float32, float16. * @li topk_pq_index: A Tensor of type int32, index corresponding to topk_pq_distance. * @li topk_pq_ivf: A Tensor of type int32 , the bucket number corresponding to topk_pq_distance. -* @li pq_distance: A Tensor of type float32 or float16, the new data set will be reordered with topk_pq_distance and updated to topk_pq_distance. +* @li pq_distance: A Tensor of type float32 or float16, +* the new data set will be reordered with topk_pq_distance and updated to topk_pq_distance. * @li pq_index: A Tensor of type int32, index corresponding to pq_distance. * @li pq_ivf: A scalar of type int32 , the bucket number corresponding to pq_distance. \n * From 529e7afed2213a2853897863f0ba022473b9fb55 Mon Sep 17 00:00:00 2001 From: yanghaoran Date: Fri, 15 Jul 2022 14:21:00 +0800 Subject: [PATCH 59/59] upgrad Ascend software package 15 Jul 22 --- inc/external/ge/ge_api_types.h | 2 + metadef | 2 +- third_party/fwkacllib/inc/ops/array_ops.h | 28 +++++----- .../inc/ops/matrix_calculation_ops.h | 54 +++++++++++++++++++ .../fwkacllib/inc/toolchain/prof_callback.h | 2 +- 5 files changed, 72 insertions(+), 16 deletions(-) diff --git a/inc/external/ge/ge_api_types.h b/inc/external/ge/ge_api_types.h index 7f3bf5c0..208b7eab 100644 --- a/inc/external/ge/ge_api_types.h +++ b/inc/external/ge/ge_api_types.h @@ -77,6 +77,8 @@ const char_t *const GRAPH_MEMORY_MAX_SIZE = "ge.graphMemoryMaxSize"; const char_t *const VARIABLE_MEMORY_MAX_SIZE = "ge.variableMemoryMaxSize"; const char_t *const OPTION_EXEC_REUSE_ZERO_COPY_MEMORY = "ge.exec.reuseZeroCopyMemory"; +const std::string ATOMIC_CLEAN_POLICY = "ge.exec.atomicCleanPolicy"; + const char_t *const OPTION_EXEC_LOGICAL_DEVICE_CLUSTER_DEPLOY_MODE = "ge.exec.logicalDeviceClusterDeployMode"; const char_t *const OPTION_EXEC_LOGICAL_DEVICE_ID = "ge.exec.logicalDeviceId"; diff --git a/metadef b/metadef index 175dce71..e4d1efc4 160000 --- a/metadef +++ b/metadef @@ -1 +1 @@ -Subproject commit 175dce710e744666c6204540857634f362aafd61 +Subproject commit e4d1efc47349f13af1bcdb53ba408118779fc27e diff --git a/third_party/fwkacllib/inc/ops/array_ops.h b/third_party/fwkacllib/inc/ops/array_ops.h index 17ab4322..9eaa779d 100644 --- a/third_party/fwkacllib/inc/ops/array_ops.h +++ b/third_party/fwkacllib/inc/ops/array_ops.h @@ -1160,27 +1160,27 @@ REG_OP(MirrorPadGrad) .OP_END_FACTORY_REG(MirrorPadGrad) /** -*@brief Returns locations of nonzero / true values in a tensor. \n +* @brief Returns locations of nonzero / true values in a tensor. \n -*@par Inputs: -*Including: -*x: A Tensor. Must be one of the following types: -DT_DOUBLE, DT_FLOAT, DT_FLOAT16, DT_INT8, DT_UINT8, DT_INT16, -DT_UINT16, DT_INT32, DT_UINT32, DT_INT64, DT_UINT64, DT_BOOL. \n +* @par Inputs: +* Including: +* @li x: A Tensor. Must be one of the following types: + DT_DOUBLE, DT_FLOAT, DT_FLOAT16, DT_INT8, DT_UINT8, DT_QINT8, + DT_QUINT8, DT_INT16, DT_UINT16, DT_INT32, DT_UINT32, DT_QINT32, + DT_INT64, DT_UINT64, DT_BOOL, DT_COMPLEX64, DT_COMPLEX128 \n -*@par Outputs: -*y: A Tensor of type DT_INT64. \n +* @par Outputs: +* @li y: A Tensor of type DT_INT64. \n -*@attention Constraints: -*Where runs on the Ascend AI CPU, which delivers poor performance.\n +* @attention Constraints: +* Where runs on the Ascend AI CPU, which delivers poor performance.\n -*@par Third-party framework compatibility -*Compatible with the TensorFlow operator Where. +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator Where. */ REG_OP(Where) - .INPUT(x, TensorType({DT_DOUBLE, DT_FLOAT, DT_FLOAT16, DT_INT8, DT_UINT8, DT_INT16, \ - DT_UINT16, DT_INT32, DT_UINT32, DT_INT64, DT_UINT64, DT_BOOL})) + .INPUT(x, TensorType({BasicType(), DT_BOOL})) .OUTPUT(y, TensorType({DT_INT64})) .OP_END_FACTORY_REG(Where) diff --git a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h index 61336fb0..15f648f0 100644 --- a/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h +++ b/third_party/fwkacllib/inc/ops/matrix_calculation_ops.h @@ -1815,6 +1815,60 @@ REG_OP(SwinAttentionScore) .ATTR(bmm_score_transpose_b, Bool, false) .ATTR(softmax_axes, ListInt, {}) .OP_END_FACTORY_REG(SwinAttentionScore) + +/** +* @brief Uses "updates" to update tensor "data" by "indices". \n + +* @par Inputs: +* Three inputs, including: +* @li var: A Tensor of type BasicType. +* @li indices: An ND Tensor of type int32 or int64. +* @li updates: An Tensor with the same dtype as 'var'. Same shape as indices. \n + +* @par Attributes: +* @li use_locking: An optional bool. Defaults to "False". If "True", +* the operation will be protected by a lock . \n + +* @par Outputs: +* var: A Tensor. Has the same type and format as input "var" . \n + +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator ScatterNdMax. +*/ +REG_OP(ScatterNdMax) + .INPUT(var, TensorType::BasicType()) + .INPUT(indices, TensorType::IndexNumberType()) + .INPUT(updates, TensorType::BasicType()) + .OUTPUT(var, TensorType::BasicType()) + .ATTR(use_locking, Bool, false) + .OP_END_FACTORY_REG(ScatterNdMax) + +/** +* @brief Uses "updates" to update tensor "data" by "indices". \n + +* @par Inputs: +* Three inputs, including: +* @li var: A Tensor of type BasicType. +* @li indices: A ND Tensor of type int32 or int64. +* @li updates: A Tensor with the same dtype as 'var'. Same shape as indices. \n + +* @par Attributes: +* use_locking: An optional bool. Defaults to "False". If "True", +* the operation will be protected by a lock . \n + +* @par Outputs: +* var: A Tensor. Has the same type and format as input "var" . \n + +* @par Third-party framework compatibility +* Compatible with the TensorFlow operator ScatterNdMin. +*/ +REG_OP(ScatterNdMin) + .INPUT(var, TensorType::BasicType()) + .INPUT(indices, TensorType::IndexNumberType()) + .INPUT(updates, TensorType::BasicType()) + .OUTPUT(var, TensorType::BasicType()) + .ATTR(use_locking, Bool, false) + .OP_END_FACTORY_REG(ScatterNdMin) } // namespace ge #endif // OPS_BUILT_IN_OP_PROTO_INC_MATRIX_CALCULATION_OPS_H_ diff --git a/third_party/fwkacllib/inc/toolchain/prof_callback.h b/third_party/fwkacllib/inc/toolchain/prof_callback.h index 7b7551fd..47d33a9e 100644 --- a/third_party/fwkacllib/inc/toolchain/prof_callback.h +++ b/third_party/fwkacllib/inc/toolchain/prof_callback.h @@ -170,7 +170,7 @@ MSVP_PROF_API int32_t MsprofInit(uint32_t moduleId, void *data, uint32_t dataLen * @param moduleId [IN] module Id * @param handle [IN] the pointer of callback */ -MSVP_PROF_API int32_t MsprofRegisterCallback(uint32_t moduleId, ProfCommandHandle handle); +MSVP_PROF_API int32_t MsprofRegisterCallback(uint32_t moduleId, ProfCommandHandle callback); /* * @name profReportData * @brief start reporter/stop reporter/report date

*>JS|bHmP4SG5(!fx%_mpsKhg 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

+<{~9M4X5x;Z!^s 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⋘!B9aVI1f#@t9)R`Ter;&`ax>t6bE$g^(ZoO5x{aM)&+U&%5 z=zD|aCmLrxbO`I6d@HMU=gF0pqdV?Kp4V@AsD<%0|4wxs?j7qS=TUsAfpasE^E0{X z`R39C&gJOPdl6i3f!@vc@h*klwcvUgG!TBs`;4_pyhCw%X;zv4%@=cC2X&B-(ajIh zUhh+Ib@e&-ql0JvMyHxN&jVa%G(SOou5VB_bqM~QzI%|1x454(GQPi0a>D&`&Ro&+ zySaab`x57C=>AUbUr>F2zmWUqxS#6pZ{dCg_cee21MZ*ZzSZB~!2O@N7p$*fr>fT@ zbJw>ms$LUcb)MgElV0L{6nB5#_3r*;?$vII zVnk?`hua~&;`zOL4sH58_jbwqFSl+J@t%y@xc#&9!FfKivj#Z71+O@BV^OcivG@1! znH@IPHu&nEua3vi`(W<5aAwS<85+>Q!3W$7Eo=PmUA6dq;?*I*q}{@X zysovaAM4tV<@OQMHMM^io$&32e-kqFA&t>JYo7I}Xu|*K?6nS$hHSR0v(eNWK|NPK zS~=-Wlk!H&bw-ZEXZ3t1E4M)R7{)q>N5eNy>b^}(l)%oxdCi{X%3q*-YmZ-a_WKTx z*4ZL~_pG%!n|^Zb{*pXn9Jyz|vuC;TrIc&!$MbbzYqUW^|BpleV^f|lZ0${-9TAqd zG$m~g4a+-5C*=o)<<$+7@@Zjt??y@aZ_u@7XyiUmTYA?vj)*3d>t2B;|L6ZHiqcGDjPEAn`%lO6^ZnY!>;oEVIvH zOxLqsG@}Qe?}!Pk1<+R`;!3=iqD#oXs4Z^9BQlbHp^ZgFT#$d-tvU!NJ)WIGZ>)rwj%T z{!(xzc{m%kO{x6O!PyWv8#y?7e{R5W5w{4=wjNGXbxP$42d4=*qaB=s1_K8>FE|?l zC()bUJrjA+yPuk)U9>7bkMlx*o$If2{PjG4J;z^XbG7-_TQjE-Ywl01dBB2Iv*UAA zl6~HO?t-6xHOY_KdN*vd zjB@)H%DDr7r0@kd`DW*z7+a!){NEaQ>lXC01?5}#a^jbTt>sAxZ=B7i?V%dOXkuVs zH(y0etLxpw@6hBrgV{56lF?yUoiUXt*M1U>buYmbzQ7RvV?E3&*9)nm{vwTu{(2}Y zTR&!3fbr5-S6}l|JP%nJ1^quqc@YhkQ@$f`dISD!0v=IM^iiE5_&m7e`S3&l%h9K8 zuY^9%=7YyDPalUbcq?{FU=kB+eywptj6?dJ@8e$jaQS3lg*>~9a>-MO?~BZ#bpD{@ z0aquVw;-?dxiPS<-;1GL5x=V*rf~Qpum-As74@4u&TjnC-pTmCTQHW3sc*E8>+h4) zulV}+2K{aaP4e{kGBE5MS%Y1{Iy<^*=v&6WIs#AznM@O@2%;Ovk&L}#Y z^iHssBH`GJNUjh<3snt{dnX{cCE$pu&GK8 z&(p3Md_-r_Tsa) lrNoc;5SbNIdhFV=+C&s<$@e}))BdN36`?$)oy_szL{_bZlj zv9l0;-oH*R_$$&|WXskGEZ56e`pwrhV#nfk#W}f+k<3ZH5{T|EU zyh`OU^eiGT)=K?L@a5HuhA+5*xaY=$<92$c+;XFTCs6AFGsrttFB-N$-^{ML|05Pu zXEwNVEvIV!=V5*lzchn!V3!s~J(HbWs2@GQLVZb|`7inUC-k(ngms{Slckv@cRtSZ zUy5P=Qn@4gb!WJZX{fA)Ox3_aeK+#|M&#j!37nsKD0_$x2QK5NGLFAB4(WatdPy$T z-${926DlkvUjb~jyo)udExM;+J8zw>Q|LKrtqmsw$XoEd(nDY+_reFL+cmHVOEtJaynV8Tl3hf zl6~&;s_Z>6+LWM6&GOU06rF@qFEOq9xc5viWBwU5{8jYsv@5mV*d-kJmC#9zMLg{F zXE}FrFW$(X{8Bte{$9jaseZyY%JO`3@Swl0TZ2mjJa2{PCGngx<&-rh@L#GJRqJ$l z-hKw&TCUaXRPQkAp_>jT{g36rjU`=c2=+6OmzCbtrbml9N0laZK_kiP80?ki1JG!e zptEit!>Cf_BJ{%Ear`-UIo{J?>olXgI~u0^PVg)~Pxqh& z-x;TG_n!RXXp)WF@oh?KzjUtHLUR4#TtzrejeYaHhVojKo``ct+gyCixufw}m7V*S z+mDo?2g+LjD0u)y4>;jfeT)i&qL2=VF$o* zlJ-YG#ki}B~h%eVenowxk)tf{Z3E}Z8{e0H?N2LYWf$9 zZv`;6_Au^7H*E~~`q)Q7&&~Yv`_Q-Kc|AF3+tqw+ z?%siiW~X?XiEp2Q-Wl3Z{|&{lj9WVRed$b&Rzp3lJ|2wodEe%eL5*XI8^?Yh;_U8Z z9Hq(&@-0EGq<@`=VVn<)N&sV{KqqDrAEf)TOO^S0|7gnK@`Ytl=_<+8OuMIt^zE1VH2-fS=6W_G1 zyq~@EIwgCKT7>+p1#jFufHr^iZO)^wwc)qy*Q(j^cT~c4*_z@o`3S{Dvi-zaQ;3m! zfM@xrke#@Fw9?I$DA)T`R$tG)+P|N3ej@MZM$pFX`^E<; z)>^=Nr{crvlBlu_`9z z+TybF;P+4~>xe3!_54?z6vs5q?Zba!UT0st>}PO~HYvpYnXSw1zYy-eO&<3i?986R ziRVq=p43B5#}oTi$x|sG63c8;_vhhNE^Z;WlOi1AitzybidyJ=nlJ9GHr+-94~ZLr>|q$qPzyF1sJFl|uUvr+M*%a+3bhy~}1Wc|pPo#g@7sUZaA6vsJBP*iI=K{K% z5z?h2rpx{E5dmG=HZ8aB>FKhyr^`}s?~g9?po{1#o@hU)=glPf#)!2lT`!jY;Umke zIUNaIvfP-ejH%I&=_T?u;`R0akGnUI z^QtWW|Id2{WLE?ccLs4uFmXpjn?c-C6C2GXw?Wj@RK%s+9i={QSqxg5Tkio(AwPvn z*=Plbx#SXI^|3S?#LB{QOOurNJzw{^uXFBm-sk(vxDB~GKZoqUp(%b-EJ?LT{Fjsz*-`6OgLs|Q+=L{YqFQ{uSmY~c^`AYp( zjKSaApi%o1bY7=+;DhQb&$b93(XvjoYG;4n-s4r04bs***iAb*W4-V20_G1b{mD;L zR`UM4{D$m+c4s3Cr+-VLws#nh^OuZ0e%_ZD6&m!OPwZr7)Y3b7XZrgZJN=lgv~1Jb zyhQYK?GEFg{?hKJV?Hh@eZ|?#g6OcU&Ge(Kz~3!!v0%=2B4VX&px_T65UQqVzT-h_i-;8BLUw478dnAUr_96N#;&2P8~>>I*>bh_1+H27 z7O+6`Da%2?Kez8q?;mo{g44&Qn!8Y6b&ntp7M{2ByDVSdvUi*Et1HMMD#xmPr?B-p zWaa3s=X);duOVs!uVbAXo5kxUX!t&T#4$>oyEh&xo=W4Ss`;aoZ@K(YgZH~pkWK66W7~WL=NPolp(c{>z%Nw*tZ3lyEmOr{>dd$19y$0GV${+n4UWNIi`|vSN z7E?=Ycb-F=HS$MSp?j3A$RC}9T&u~hC;6j0J#AtBXf5sdpFf&|?aP0ndvDpEK#{L#Lq2lOF)6P@b?eKdJKiH7O^zU7bpfNvDfWDmcE z<_vEre~K@!xy^>Mmt6kn0?(^3e{{63^KT!ki%-?Zk>-zvB;zQx9SdHGN1+Z^ZDUcI zKPm-n{12F8Hu1c4xv>=I3>!*q>&Yi~Gk^3Ux+HxVWwH$NM~iYc%I}$B{^$>idy&88 zkFNCmmTqp5)6xG?{KWM$DdXf&kUzT5)1v&*NtBb^eEukYpF1A`c0XP%@*L<*N}N0 z&!)-e^Z?H$c-lieJHfZ{&$Cnhgm`wOzyChCVf;&MIIjl*o((oV0Dt!LZM+!t5#pKN zm!xqRp3U<-la9}Z<_vFWZzo?~c=ihVpU1O_o>w8BZRP7c-mP(@c=odJ(qVt8ZQCB% zM2ct625mIUhxv8k?@Z%7z_S>`8Q~CY}Yd$>Z5PPmkf*X96Aln`jDjwAt(E z9;TxOcy^hmMR>LY<$8)|BYmAm=xcxE9pc&QOL`uQ{nW>uA=V^1yJ%ol?3!wF0=r%l zj(a)n22b)>SPi>Q^1LwYx{mm&BzuN8FEX}T*foNfs|dRW5tEzkeH`qX;Aso7>sH2W zZRfG;32fM~>*SnXJcB(+PwuBo#y$(M>v-gw$F3&D20g&8fu8mdyOjS@8$UlQ9Ycs+ z+xq)Y5%b#^tLj03UCT8O@$ueK0@qT*WWkny4dqfHgFy^XLtj4)%o(mt_P$K zxmZl`lXw+k*So?U#(8t)IF{DM`n=T7EtW>?!&OdHYk5CN#!+f}-{;E_OqU?ML!{IMjt|c(#M*kKx&TemhKnU(aI`weU>O%M{_+@5r^7J$@WK>*Hw)@$6K_ zY;EW9>_%i|c(!9sS8l;Br8}2XCS$V&c(xt-l*hAy-bTASw|s&A)kcVCAINXfU)!1K z7(zUI$KU@ZF^`SW;~6%S(}Mud{#P-Q$Fo;_8y5zBgn0IQf8X$If6p`7MI-#q@CH14 z&X*USU4j1R@l5ek9?us0I#atfjug)>NybrXdyL$gco6DvRbB*mc1F;~8^Q-~6MIRQ zgIMfBtsQhT7CXhuvdY{tFPjXW?eFO^Jo_8^YdU(hXbSM`4aJB2{tacE918Gk6Hklq z>}ksN6wiL<>l}?ete~wB&uYYCRk7>yHRUv{Dt1LCC$Q_Qft;3ky$$7F4ZGIBKk1%f z*8qI0Vb|@@RSUa*66bR(@?!JJ?V9a<9PE0*(-vaaIL2&k=dtVLKrc!;y*So$5AZ#MUu1`z1yNO-9ds$Y;t_(dH>>BRrG3GP0yVh1LwoNVBHEmfH z&z_NQlpcd;pABSpr`P4~;MvojKZa+cES`a1|J1rojXb}emq9iac=jc7zh;jg2hZku z+Cn_54{RilXFCSE@+>?Eb!9iNE1R0G)WEaHDU-*udGa|uz_SZH?IE7s;@jBajFdki zp3U_4cSf$pzXZ?ndJy2*L8b@9PFMIgh6R0uc=ly~-|%b&{FHskE?$D>Jf3~gmlvLG z2HxfIOz~45&rYy9-5N)VXB#EsD78%?=UNrd^1KM}tWVI!*W|-Ip8XDfgm^X#o9ix~ z)p=P~#j`9u89ZAdAApS-o?Y$vE#2HIr=wrP59s>2l&OYi4^hYP>@><5o^8o#15-ub_>!(|xd^@LRwqCN$V{Pr-Z1*b7%ggVu;kP3&QSj$PIg9ed~KFl@&*SQDl{ z=yv<#c>Y1_<=n6MCP%Gn$(|hTzhzw7kCPdj?Z;tkT911Qy)g`+oLd*S_n%%4E<=y| z{_9HVJA5!3{s7x^zja-0K{pue_J^q5FU!|(ZP4jy`woMAztjBv^@ILX4BA@0Xo1fQ zEr>h@UA1*<^LEm6-^K~Pjenk&_R-|WAR3PJ_ZYb}1P``cJ^y7rPVoNMO>dJyW`ul@Zm70HnISya=tubT|f zr6s_g{w>rl*PBHhi+Gp7b*QqbK8i8@~+t2=!zqf8X@v-8i;&nDh$$ znx1Uy%SlgOfS(~IHTZjvc8ktbPkwLh=k+8zwv3)U>+6`FJmu*X-}lV%|4aV&amN2H z^yFei04mM;ChXCNadv(UY0M`15*l7j2v0 zc@9~GbUy0oyvOLw>B*-&e}8>ys)wPT?C$Ts0M479CV0Yoi>m3#o0K;k*xI-8NYF>9 zC!72GrYF<=c;t7s3ECOz%SlfjLmnZX4D|QD-z_>*J$c;Puh5gs*fM(3;p>>5>=*F= z>>U43^87#0_}_(|ocb~KWSts%@;!@#(A&L~uL$&c4^QV7MrTe>^nOC&$w7e(Lp{;^ z33dO_BK}7^SJjhKjsM`uZN812f<8h$xzXP@J^8X9kMu?3vS(tNgvK zxL&In&SW zX4;y+=1lh+omoA}*I5wGneOs+Oiu;{{C}CfR3ZNl_59z}_#fj*{JdwuoT<4&Pty63 z=0msQoSUAP)LII@$vwZSJ^uG#Z*|Oxm3OiJir(9u|90wg=#srRrl`EV_d>dP zBKjDQHGam@XsRrh9sJAR>3J_XC!9Y2w`!d?%3Wde?XK`lZjeb8T0>O9h^O z-P5f7xw79w(Yu9|cX>kirsrX9fQK9CoHl+2-n;iO(1z7HMsse}QQobIxw+1%cLnua zo``zxc_03M-|AD=>VMkmb3b2xHs!@rEBjq^U=HO(OUcuu=f>^5G?I0bdk@LJH|m<+ zF{1ZfIle%1Np?tG4m+`jQpy%cE9+7dBq1^`mtZyfK)%6a$6Ez2> z9od3nw%MX9;4$T|7tZVXr;We?_k1^H&hldt4U*4v#w40%LyKf{2lPgi*E3JEuq(+$ z{(l^{9Op=%@Xywzwk}MNU9MAs2ifPv&2~HWd<*6EJiGHn=e{p9WnEs7b79Cl zKL;w)$D6z-F00ci4JvyOdRGgN=G(dmWe-<>{9Vmh!#ZZ8!X#bixBuo*wlA$Uor)dQ zw(YczcvPqSupif&pl&j+lx?EF?bz0AY*gPLn~RM~KEEVxa?hdh4wEw(r+Z!t8ybe5 zzly9@U_-AUt9G7alV0>;eO2_wGPCC)Q+b$vNsq&CcG&mB{-v04sLR>K{)fIsQZ{_w z!2Qsa;%9cOHqK`g9I|%-RpM8Ov*W>;SRVE)d)lt#wU}`k&xAgU`(Kj1ID0|`h^1^4nD)HK_QRFcDdrrRg-uUboq&sh*cj-8? z_m`rl>Ajd=@A$O{<;yk3>yf+D2gafGN8Y8sl9{N_n~dE#9rd;~DT+&zg0z1`@r0#q&{Ax?Wf}k9v82XMJe;9DV4goDX5# zSE3&dGr;)xxyyKcMOH+-IDR9e9hjQ>~z_5G<)w!WF-u)R`+)LcKGA} zD!2b4I2!A5ahq4vh_Tex(>1Wn@K$_?)@faKp)gF(T_HzeyABuM@eK#}PAa~4^D1($ zMT_!buD*Y_TsqET**A4zU%iTCkFAaVn6f|A_M_%x{|V3Qc+OO8bKfHlPsf#&?;iNM zYWMa-->S(zBZvCdWgB`q5Ca^s5c{vi^XEmgWR~N(VNg$O;$E}G9A9RM9{GS8Ht`vF zT5ar`)Zp1{%{TU=H7jVf4l~KwRfNGN8Q+eZixRJmc)9K;ho-L z(ObGqTWb5y#6TVFb5r{Vb6>I1De5ozW{j=fdb=T(Z}4$kg`Wja^v;)d+Ud&Az5wk- zm?=M!#wP`~3jQuehU#0G?cz^({ur`Ju2uQwSXTdn?}Ph!N@iSs-k?4{iyVd9Iv=7~ zj#$R|$3OC%K5>k6qAWkfx$fy1Wu1>g4)RU0&loy?EHuX7c!}T7)~fj)<@N)s>b3sK z`98=(ed)VxF76psYWs}%`Nz0UllO<`6TfPH(#~EUJp--h$t^!2%$!}%bI~i9J8*xH z>ht~QjnxNbPlpaiBRX^>_&yt+O7A55b+}ipoevm~+ELt{y!Vav)W^Q!5%<`uQ1u(r z$0GCCZsT}6#D%COlzSG-B4mA&(EQKLorskv85OWKZb<$(hF zvpSuY*PK^%esNNWh1qw}_=7qC_LJ_-HJzfa-<={vMcwYUoXUf}0(uDs@;=)Ux-!QMB8T@6OB9qsh_ zI(Df1i~CLAdf#jE8ycjKvKQ_5(mOUbg8n)9$L!oBl}CQAbS85M)8EyX6vu~id|doj z`moqn`{U#HS~4$U-XzR8i)*P4#<4=EQ`PiISbLS5E0~YU(rfdb{g7FxuSIi|aK5AW zy~gFu9#Y?7_7Ewq)I1PBeh2e)hm*ohboQq{S7`nr?_WjtV<(3EEB@A|bimC$;gQ~x z*~mL^S~X8c_Ge;)dY|cNpDR#&>o8t=p>u5EZN0;t-}0GzfL+oVwYeSVufuc6*zck_9kCB(T|d1m=9+j`mKUMi#FnCi5ooY`#JmXkI8o~OJ&a=)t^{obCm zXV_BQ??Fkq%6<(it^}j1jZ^gOS0x`KA8zl+Qamo(eK^1x$>Y!Hn*PSNTSV#M(lfV|EvBF;y<32(85Od9*W#`VOnFr{v*{*(VhFM3|cXr08ISm#5b+g(G)&c*)4gZ#HP`{HLbE^E8!UFTyGeKTy% z>OlLp@wa-0LPz<=sO>1<7vmZ&j2VM{RPrv)3zXw|bsCE^w=4M=p8c#H?wgI$8_6o# zJ1eVBFRP)g&7VR(%*{GfE{ftfrd92bYtY=!#W>j5VDeq=9lV^cQVhhr)y0$K5*mq< zco*mqveSrfh%nFWkX+6aKl$tE;d_*S_ju@jzsmQAg5RY@(PzmobTl+9+C<|gx6whq zbO3a8=sk2vJ5edy&PJtdJ1pP8ZOxKdSmH2038)*&0JJ&k!Vd}E#B zCyM`|TXyn2@P?cT-rOyevz0*^%H+Tw$k5!t3|d_`ED`! ziXz-X9?5l!!)>lA9e)KMZJ2v3IvxG<^53NaN)9f%?4>_v3N1Kj2f+!KK0r{=OM?#^bKzJ&Jc|+`_Zqn@IOCPPOx} zVhH6@IG^h0(ZYPUrV)Gxq|<*p=eM$F?qlm6)+YM-#r*d$Bad@@AE86#oeb5F&Z%2e zrv;fR9@M-J`Md9Wc5==7aeB)*E`oNq*2wvljCrL0PMGRAj1Kzy1v;ZP(|mnp+|!N? zm6?;SA&zo=MbYXwZm{^HvW_e7a}CwzMH9eX*%kWQh40G76Q>YQtKNy=uCq&U@;HC) z^6lVaZ9Grkx$+tq{ukCq{>&QfE36eSukS@(srUSQz?Zv;F}{mkX&o?L^MOwArk#1! zR>Vc+K79WK`xEvyxZi!|&4o{Q!S~q{__j$SeA|WlH3@WNOJs(ct*Wn zSw4jG=QwwB&?R6B_CwrfUyd~q=@a((C!5{Wj=(nDaVxHW*ll;tz z_`Dr?4?2F$&2t;kgGtn(+#GbKj1IJ;6Spdlz&CE>E938|qX!39>H&Gl`28G{E1y%^ zO?-0i*p0u@=jM`q;@A-!?%}s-KE5qXA^r_*;duAEx-Ipf|EwV&^sK3W@L9A9*;h-TsFUBq$t z6Bnm5uNg1Q+a8^l4QoGHcd+=Tf;JY0>k{2;=cv?ct1(-OSHf+DtzttCgC@-j7j5~*>R_f*VS}n2ql(qVQv-;4U zFaHqbL;8jzukP*5nw0F#`XA*^#TRI{IlKI;^ho}~efx`hBP;i2Ik~itbMaD=7q`7x z?+b%yhu9*!H_P+5A=sPMhCg%h5_DYU$0QmgpI7)T`fP93=b=~ccaonSgTBiD>_@I( zDVQH)vhB_CF)O;NIb%j&@i~dU%5Lyo;rFo|X3arX$mwT_Kk?y-9z#oBkME;zi{C`93I@dlMca1r~8$Q=#v47%Ei)=9P z85)Ch+_fj%3ECaO9v;^|eNGcrsekxmxKh@;b(_|8bIMXHxa#JX@pn7w1~A{!Jkr;p z-gx}=bjrBz2Sm(G-M3|DL~WP)@o4Q`*tf3YWv*WyUT3U*xxP?xfpD&Wf0PS7h^G5 zWofTm?~cOv9^l8F-+(72;SIVXdAa$W&qdg}cdP$a#+~>s4;y|b^& zi@&GbH*t!sW4FSCvy@-s+EMs9tz-A5jOfreL>xW2Z;1SyIK{>t*u~PimSKf_p1pHx zb5jjIx4>u9nL6ywjg!B^3GJo+6XQ@$)O4q=$(P};m1*^5;Y>yFiHCr*iSHvYe&1x&N=MJ8DMF=_c1z9FRLML*A} zMay+LS`3rJIlabpzQv=+YC7i{lk-7duR}XY#)EI6+;}j0y7{WqXJ`GC!%2AZDaMfc zhg=!%H`BMXEpW9m?#aeuk1`#8?0mfHSTxHT5}nSD2AW9C-c z)gFmAXv6BCL;X3>u5svn$l}{%aP9ZZxw1LAoX#LSXdN$EyJx%5p?=8H(ITxe&|~J$F{Lsl^hxC5$$beq_Ri57Sh}VtYmZWY>Zxgzfr#G?lkHE{* zz@3n`(~w;)UcP{zG1`tv>c+JF9UWeqv`tK873VeF`g;vI-xtufb5b{^?NolRP1>}- zH00X}%7@pW?Ye+AJ^v8bjcGf|`|21!vTG&zXGywaA2VDmkUk6dhH$P1ZBql<&QI#b zwCVZawaK^F(UFjE_b9HcLEBydZGTAW#nH8U`lk2c)uL@!KwDi>H>Pdf zLYbyML74bM+86zX^@cmTX1HV5G(Wa$;e1zl7`N_*KXG^|Ur5_KqmQ4F+&R}C6y+q| zV-2sUzbN|8tZHqC`}>wN-!fX0JcQy?pEuX~U^(|})mGqDJ|1zo313H;yoNX=rmGhI z1~D=D6kFr6y`l~NSx(DgDlYhp)=r6^ZXbCi^biVMea#HAV`xxd7=-wRW z4s)@gD17#&(d#*O_@U-V#QnEg-grr=Z7A6GL;gyio9O#NbW`gPvb8e5r7O${-ztNJ zbLLDOuV;nYXG|O~`WnD&&Gq$sk*!_meIT8bIUbx4?M6#`BRBwWz?NUgexu&_d_~mO z3!k8z2IHCDDPIAP|Hw6GU)*mAWZ7GDQm&n+cvYCFSk*9*-d7AaU2BSHD?+|dd+P$~1;ZWYmxZWw<-}JfV zA8Win!|&L5-@rb?@jihZ)o&bM7LWHIHRv8dEK_Yv&jj_7@$^7WGl`pw?o;4TNcZx? zyQcd>bh8?5Tf>uT_a3HgyH`wist>~0Fb>*<{Jzy)9elUg*;y_ZB8+-keg(Wy-s1@7 z)i&PsnUlQA_5Aw)j>?SN-UpDS$JSF01kXa9GORY7&hKY9+GCtyNvOZ(OTzChwt{&M z)0kV!uWLV2I`#s*0tdc9yyIenDn9Nn@FVeY?BlcN%?E*VDP3uf+dWsRI3?h%`1(8K z>z)&ZuX^8_o)di#U*UWK&suK|f6W&tm-9;fhG70M=j+d)eBKW{1#jdBUi5Lf!}(+P znO68nF8Lz&t0*XxSaXcv@P{@6EuxP zM*V3orOod%&S9nWQF4ml)iTkDj}u>K(1z)&zV~GMdOG+X+UFhAkq_7wJheFd6X@=X zzP{dHA|G%y{H%pNyWlH|XmzoI$9B>BIrKyFeh?a+j7zP{=0bzXxCI%TeAgkq%ggt( zUcOU9`8q#tm{`Db^!WgMK`njWMgEa?qE|0|{y5~*6CG~wW77D315Rgjm}d~r491t& z;X4XqnT`AyM~7pqp~Ld&Gbk(F`4fIEtAnX-nV#<9eP=4K0-nK(>+rd?^z`D4?G&^D z-`f~VEx!K-xg!(1{#~H=oWw|Yof7zZd|KvR z-(6kH`+?BkJ%N67CGXMLx|0=h6K#qIm6s^x_IY*XpQOK`-W2&}yGDOi_X|j0%}0K@ zi+Pde|FfK~*u1Gg9~sLj=&bP1)(LMwz9Fp^lPcF@bBGf2hj7j3eQZ{~S@yOY`j)Ku z%;EjpV3uERjNjt}&W)sg_#E9L7cU!LrS_@zT>e{m3(t4$W3=m%jn+gzK_4;AHr8w# zKPEoO%lf0_Aoc#(&{zBxx}_7I#)_Qxce(F;4%pF{)Qxj#Nxme=(TDo##t5IB{xRm2 z%oW2in!d`h;C@Sr~JFfylr74ohvTBzpQ)!GTRco9R$B!+$ud;v}RT#>p#~h{?u=LtKv`9 z$z!^=w*|?5Y+^;1C!^gb@mJ-m>*lGCx6u9a)%Ek-bNblZV&*mEs1~?==G#`<+Ml4O zDE1S!g!uU7j4$)C7G=VDsp6{T=z+ymFLNH|p0;58+1yi_Gx@0Uov!f)@;%G_uD;*; zsmUtev;EeqFZuX-I4P%xjX6D>(1jj8fX#NF?wlS5`D^L@ap-gw(+hk7<(hNlLX1iA zrHU?~&o4u>+e>FLII-+oT(dkA`&yiD3w6T!kl*X9m!EBNF@XH7XiodBnoCY?B*-P- zZP<&BHsO<|bdgJ*s(6>O@?TD$Ip0~nOmnm)6zlS~xYg>X`@^+MQ7(FJ=eOfO0 zYWfeaTQ2!Zt_Qi~*iOe*+UWG$j4TrjKrSPpIrO)$ z(sqhBu`Zau(7K1PX&gABv6}zd#s6mP1jK5Wg+w`Ag?9PMDL#=WI@3f;%&VvAy$1KmU( zk=}E{drPFt?WU6}qPA^h)BG(n=ht82+-2HNrF|l9zdSk?@AIgi@7B}#U4rj!yvSr- z^v~%Ob>nj6_o*-4ln(4be$euu6PY)X=XkTOW!ttE?e|->oBqBTMfL8P$5&2kZN8Ja zhU(r9Ph20I|4w*G`|B}p(>yoPqnwUv-llo7)q9$HlCS$s{Wav!RR5>UzYa`fV!B+L z=TAacwOA+BlkV|+Klw`N33@DK?e>8S@aGd3~;Q71AEYI@~h25U#*D|&Wp11B* zmFE*Z&xe~_X=kS5XJ|aZ^Q^l(zlwSx&kyzWTj2T1&*t%?HqX~E=8)&fH>l+EYv}Z! z7)PGJFA-xD@ppg8g7G$R-*kEyJ}1xLdk;EBZ?-m3SS@r$wxj0}dd%5r(!tNWeZ|6std#P<*%e+rY_py(Ql;6>MvV2Z2-X~X3794VA zcPB5DuGd?xuaX9vi$0o*N5Z+N{7eRC$*BngwFc$pqI06QW@u}lgzYbh+Aaa(Ts{wc zKMk7|?TMY?>qo+;&_`~HeDiDkc^^3hKO+7*U1t32`rj?iM;5Q+%70g-9okB?=bnk- zU8N0r?nkj4W6>D?My^IVwOVxlopGjg2kU2Q2iatJW^;-eu`il0T!W9|&5g8E#!t1^ zvnIKM_aop3%?_25Ec-foAC%eh|4?T(e2_iM&VGcv)s~wdH~DvEkUP;F!LG+;>*jw0 z-#31$?2+HwRbvljB(BMEzQA)a~X>-wiZ6a7x8(P`cpg5 z`vGHdIb+(?etgY!lQj-#RqS}baGdivFKlZZmGKoam}&b}e~K=;{0n`EXXCM1(HoD` zXs+GHz2H>X#`(knJ#AwQV-4GoynEWld-#yBjhDgVYHc{ZMjy47Bbj~A#sGiC?*aT) z-84=uet*1pnZ#P-VhkY8S&)B!e4~8N82Um^haJMX={9!tCO8v5qj(OuQQn2JyFd%N zkUXQ9dw=}po@QHfm;L15AHN#Cwr3P~@P09TM)4_h)#)306OprX=g{;9^&E~vuf0Eh z3#(6A>$Ah^Q!ZbA2<0UYE4v|nwR_Jfrtgm*<tCc6i}(pgO02uzpo}3^Z4Hf4s@1 zeH>-LG_cI=H?U_Ee~G@yR^(R{tJZpd{59B~^3bB=4`wgam3)?eCZ^AxQ5*!l=TKgD zTZb*lrZyvnyPMc9wo7|Pu^2l#kiFAkuZMRfv8dVN$J4{Du}#y%mxYgk9-b{(GGB1~ zhPUeqPm1&~_pI#KJk2KOCl9XFLp|SWde|3CRD2fd;aG=V^bKDlzb8UI=ZDnG>(%?n z&ef-^^*O@o7wF;Z9$T#JA@tupJxrgKeMEe#rH7s;BXiHncBO}(tfq$r&&oayhL|2c z9@Eg$k9J(kyY{6eh4=)BEdUsO~$I)J>hkr!IYZDJYke~B-I1qga z_3&QdU!aHE6N4A(VGa-bdzwwo{qYBRJnTT{O%MM@`Me%}RX8pGD?JSGQ12Vd>*4RM zexQdJSp5P$d@e`dGWE+^Ln^Ddbk+>-5os~ONEXrLvTXe({PT!z>fv&1HPpk^w7)j}@~}V;x5??@KEwYYm^sHjlS3M13lHl_5MqG zc$elE-NeHa&@02k2mF}KFFz#T7U1CueA5124`0BRrH5~Wiw|9I9KzQZusTdx%sH_-FZFSDbT}{ zOpgLRTrK-3(8Ey$df06B13dh@)i2P){d0PF&_~e2vlO$?c2DQaCYNgS<@z4z;ZLvy z)5G<1dN?enhZCW9F6D)XyL&x63_W}iTA$e4oxF*1=CiN`%b8=}?zxl_I;t`1{>A8u`qx+=5yo=uGVE3SwOG$RtH*Dx zwbsFV$3OZx58eL}wyU-d^!z#reuepQ<5g#$aDBZpmn^!S&N9};^lvmhEUe&On2RoI z)2@Xwv1?)9$+g_GFv+@()+lB~2^sO_oTA03puq9|(CU)wX7&UsSv z;5oeh5qRcwfiZ~Z5&LD7A5;#Y1)B9-<-6F8#@3Y#jEDK>H|@K1&x3g;*L$%u+1^m) z`B>*TjQObD`yKg{w7=p#6mzi)<4u0g;#tf$s@=PsxWVojPeYyQY7GBC=Z(%^?w=jQ z1K7OXI}khRY7BaRg3*#6!~6KbYWJSSH>UTB_o^7rPX#lKrfn5Z1w6l+-*)dSwAmHC zSEDOwzp4Ie?PRYS_x3}d(t5=>sC>C-sfL3)Vmpd6-SeB|MR~Tx?L|KlAC_Wby0@>| z^N?nrTH|bQjIbZpYq#ZlnQorL^Q-8dqhkrrLm~rv9`ZwQE_oi3@7!rWo9w3A^N?>+ zSMg8yJY*kutbOYnb5FcBTG|^cvEp{@%q^9a#kwm?5OVT)!9!)Rac>2|nC znG1Y>-%I+7F)85-SexQ(mha(y*0K24R6YfEfE-T+*TT8|!yZRW$BX*3YfkAn)%tB3e#f$=^Y43m(SHB;c65BGA6Z^VPvz&10V}e) zTAS9tD&7lZ^}_(u{!J_s%1ZfK>4x5K7SeCJnpyKj?hivtE!-J`9VWPA&(wiGd!VPa zWK!54x_&D@Ftn`@_hqLR2SgRNn(|V790*TRT}t;8INVeG#~elPjuPJn5mUJ5yX+Z0 z@N0YcWcbxWTxidCY5#2=w|)m+3Aa`%E|6X%xKw?Afo%T@>RC*u_YEp;slE>=9bd?Y z|6rG)u9(g#=23h6&crtv`NF3<^dPjSSsr^$c8Q#b_rT+&NnV0D(D?@1P^_iBCKEJY zLWavJ=k~TU#{8b09h{BVUYE%9@=@_4CdH_vJj8cOE8x73ASAgirbW zNBb_sreo9h881YB;hgROXwA<#pCk6RIp=zeH$Ufm6unP!AMCYq=Sz?Q_40GhHI&Wg z;O@8jvS;Kc{j|LW?{F`qPx#)QIj8FAJM)t@f1y2%TXC^F$G2;rfa3-0+4;3ulSTWu ztPftq`x`gI2RyDeX+!bwNWVwG_}UP>!}t@(%JLnH{W#jGSB92vG7iyV^USSj^EB*R z_V;gWQ+TxjviS~JRFvwu4inAHq3VH zy2{tQwpO06N%t=F^!ba0SCqyl-*=Edho@yQO?-Y|aS+dB$Yv!U_k9Os`VP+mY0s2+ ztXxZ$zbWPjQ&+-I!&KvmaK?C&V1?$0L%~-tL;U^&^=kQ$E0L?@qh}}QGtViKN7{$? zh52WS8EYSp*_to);@qAeE^!{(jh;7&$LW3dT9Mnwe;#F_@GN+4<`MTheJ<)|<<9z4 ze=cfMVPLnPqp{~v{yX~i=6>;5K90WqfVsxSE~jJhc&d-`fnn_UK5>KTW}=7Hd=|b+ z&tgo_J_PixmcP1+Ijrep(r%#NbD$&qZo@46PFg;tSN5}p*uiM*iTzmnM}c3luQ&hc zV`SMG?KjHCp-na?-!DvVP)>_`PvZY%19mTt=pE_E1s(O9!@rr?tlZwsKB>?7xK0{MgOz(0~67n{p=D z3;AQkKJsUZjSBr5IwQTEP0S!#BH~`NqkUZ-miy?Q?)CC{2Yr)}SR;Nmnr{$hWm|n- zcl$nZ{3BoXZO+4IHs>*}?A$GDS2jm_Ub4^RJpA)G_)hn3ld;e{hVd{TnnUcY_hFTZ z0X3$G_YSPY-@w1O6eItHILyuWxqmuib-tCjVrOvPy}N)o<2Gzf?=Da*cOiA-{ns1v ze%)coy7BJdwDRP8Ag6ZPQrjC7@4Zf4wSPIfr�`^{081dxwNQlT={q@cMJ;7I?Q> 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 #J>@Tcj^2oNqoutut9#0q9+=Um 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