Integrate api trace into tim-vx source as an experimental feature. (#623)
* Add support for different input dtype of MaxPoolGrad. Type: Code improvement * Integrate api trace into tim-vx source code, as part of experimeantal. Type: New Feature
This commit is contained in:
parent
0885a0d797
commit
315adcf076
|
|
@ -338,3 +338,9 @@ ASALocalRun/
|
||||||
build/
|
build/
|
||||||
*_build/
|
*_build/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# experimental api trace
|
||||||
|
trace_log.cc
|
||||||
|
trace_bin.bin
|
||||||
|
trace_log.rpl.cc
|
||||||
|
trace_bin.rpl.bin
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ option(TIM_VX_ENABLE_PLATFORM_LITE "Enable lite multi-device support"
|
||||||
option(TIM_VX_ENABLE_GRPC "Enable gPRC support" OFF)
|
option(TIM_VX_ENABLE_GRPC "Enable gPRC support" OFF)
|
||||||
option(TIM_VX_DBG_ENABLE_TENSOR_HNDL "Enable built-in tensor from handle: use malloced memory instead of VideoMemory by kernel driver" ON)
|
option(TIM_VX_DBG_ENABLE_TENSOR_HNDL "Enable built-in tensor from handle: use malloced memory instead of VideoMemory by kernel driver" ON)
|
||||||
option(TIM_VX_ENABLE_TENSOR_CACHE "Enable tensor cache for const tensor" OFF)
|
option(TIM_VX_ENABLE_TENSOR_CACHE "Enable tensor cache for const tensor" OFF)
|
||||||
|
option(TIM_VX_ENABLE_API_TRACE "Enable trace and replay of graph apis" OFF)
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 14)
|
set(CMAKE_CXX_STANDARD 14)
|
||||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
# ApiTracer - Header only Cpp OO programs trace and replay tool
|
||||||
|
|
||||||
|
ApiTracer is a header only library provides macros and template functions to trace the C++ object-oriented programs, it not only trace the call-stacks, but also trace the C++ Apis runtime parameters. With the trace log and binary, it's convenient to replay the program execute scene, which helps developer to reproduce bugs and debug.
|
||||||
|
|
||||||
|
## Coding work
|
||||||
|
ApiTracer was implemented by warp original Apis in traced Apis, they got same class names, same function names, but different namespace. So you need implement the traced Apis for specific programs at first.
|
||||||
|
|
||||||
|
### Examples of implement traced class
|
||||||
|
Original TensorSpec:
|
||||||
|
``` C++
|
||||||
|
namespace tvx {
|
||||||
|
struct TensorSpec {
|
||||||
|
TensorSpec() {}
|
||||||
|
TensorSpec(DataType datatype, const ShapeType& shape, TensorAttribute attr)
|
||||||
|
: datatype_(datatype), shape_(shape), attr_(attr) {}
|
||||||
|
|
||||||
|
TensorSpec(DataType datatype, const ShapeType& shape, TensorAttribute attr,
|
||||||
|
const Quantization& quantization)
|
||||||
|
: TensorSpec(datatype, shape, attr) {
|
||||||
|
this->quantization_ = quantization;
|
||||||
|
}
|
||||||
|
|
||||||
|
TensorSpec(const TensorSpec& other);
|
||||||
|
|
||||||
|
TensorSpec& operator=(const TensorSpec& other);
|
||||||
|
|
||||||
|
TensorSpec& SetDataType(DataType datatype);
|
||||||
|
|
||||||
|
TensorSpec& SetShape(ShapeType& shape);
|
||||||
|
|
||||||
|
TensorSpec& SetAttribute(TensorAttribute attr);
|
||||||
|
...
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace tvx */
|
||||||
|
```
|
||||||
|
Define traced TensorSpec
|
||||||
|
``` C++
|
||||||
|
namespace trace {
|
||||||
|
// all traced classes should derive from TraceClassBase<T>
|
||||||
|
struct TensorSpec : public TraceClassBase<target::TensorSpec> {
|
||||||
|
DEF_CONSTRUCTOR(TensorSpec)
|
||||||
|
|
||||||
|
DEF_CONSTRUCTOR(TensorSpec, ((DataType))
|
||||||
|
((const ShapeType&))
|
||||||
|
((TensorAttribute))
|
||||||
|
)
|
||||||
|
|
||||||
|
DEF_CONSTRUCTOR(TensorSpec, ((DataType))
|
||||||
|
((const ShapeType&))
|
||||||
|
((TensorAttribute))
|
||||||
|
((const Quantization&))
|
||||||
|
)
|
||||||
|
|
||||||
|
DEF_CONSTRUCTOR(TensorSpec, ((const TensorSpec&))
|
||||||
|
)
|
||||||
|
|
||||||
|
DEF_TRACED_API(TensorSpec&, operator=)
|
||||||
|
|
||||||
|
DEF_TRACED_API(TensorSpec&, SetDataType)
|
||||||
|
|
||||||
|
DEF_TRACED_API(TensorSpec&, SetShape)
|
||||||
|
|
||||||
|
DEF_TRACED_API(TensorSpec&, SetAttribute)
|
||||||
|
...
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Macros definition
|
||||||
|
- DEF_CONSTRUCTOR(class_name, optional_arguments_description, optional_macro_to_handle_pointer):
|
||||||
|
arguments_description must follow the format `((arg0))((arg1)(arg1_default_value))`
|
||||||
|
- DEF_TRACED_API(return_type, member_function_name, optional_lambda_to_handle_pointer):
|
||||||
|
this macro can define most member functions, except:
|
||||||
|
- function with default parameters
|
||||||
|
- static functions
|
||||||
|
- readonly functions
|
||||||
|
|
||||||
|
- DEF_MEMFN_SP(return_type_removed_shared_pointer, member_function_name,optional_arguments_description, optional_macro_to_handle_pointer):
|
||||||
|
the macro can define those functions with `shared_ptr<TracedClass>`
|
||||||
|
- DEF_MEMFN(return_type, member_function_name, optional_arguments_description, optional_macro_to_handle_pointer)
|
||||||
|
- DEF_INPLACE_MEMFN(member_function_name, optional_arguments_description, optional_macro_to_handle_pointer)
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2023 Vivante Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
#ifndef TIM_EXPERIMENTAL_TRACE_TRACE_TVX_H_
|
||||||
|
#define TIM_EXPERIMENTAL_TRACE_TRACE_TVX_H_
|
||||||
|
#include "tim/experimental/trace/tvx/context.h"
|
||||||
|
#include "tim/experimental/trace/tvx/graph.h"
|
||||||
|
#include "tim/experimental/trace/tvx/ops.h"
|
||||||
|
#include "tim/experimental/trace/tvx/tensor.h"
|
||||||
|
#include "tim/experimental/trace/tvx/types.h"
|
||||||
|
#endif // TIM_EXPERIMENTAL_TRACE_TRACE_TVX_H_
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,58 @@
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2023 Vivante Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
#ifndef TIM_EXPERIMENTAL_TRACE_TVX_CONTEXT_H_
|
||||||
|
#define TIM_EXPERIMENTAL_TRACE_TVX_CONTEXT_H_
|
||||||
|
#include "tim/vx/context.h"
|
||||||
|
#include "tim/experimental/trace/tvx/graph.h"
|
||||||
|
#include "tim/experimental/trace/tracer.h"
|
||||||
|
|
||||||
|
namespace trace {
|
||||||
|
|
||||||
|
namespace target = ::tim::vx;
|
||||||
|
|
||||||
|
struct Context : public TraceClassBase<target::Context> {
|
||||||
|
DEF_INTERFACE_CONSTRUCTOR(Context)
|
||||||
|
|
||||||
|
DEF_MEMFN_SP(Graph, CreateGraph)
|
||||||
|
|
||||||
|
DEF_TRACED_API(bool, isClOnly)
|
||||||
|
|
||||||
|
static inline std::shared_ptr<Context> Create() {
|
||||||
|
std::string obj_name = Tracer::allocate_obj_name("ctx_");
|
||||||
|
std::string pf(__PRETTY_FUNCTION__);
|
||||||
|
pf.replace(pf.rfind("trace"), 5, target_namespace_name_);
|
||||||
|
char log_msg[1024] = {0};
|
||||||
|
snprintf(log_msg, 1024, "auto %s =%s;\n", obj_name.c_str(),
|
||||||
|
pf.substr(pf.rfind(" "), pf.size()).c_str());
|
||||||
|
Tracer::logging_msg(log_msg);
|
||||||
|
auto obj = std::make_shared<Context>(target::Context::Create());
|
||||||
|
Tracer::insert_obj_name(static_cast<void*>(
|
||||||
|
obj->TraceGetImplSp().get()), obj_name);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace trace */
|
||||||
|
|
||||||
|
#endif // TIM_EXPERIMENTAL_TRACE_TVX_CONTEXT_H_
|
||||||
|
|
@ -0,0 +1,360 @@
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2023 Vivante Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
#ifndef TIM_EXPERIMENTAL_TRACE_TVX_GRAPH_H_
|
||||||
|
#define TIM_EXPERIMENTAL_TRACE_TVX_GRAPH_H_
|
||||||
|
#include "tim/vx/graph.h"
|
||||||
|
#include "tim/experimental/trace/tvx/ops.h"
|
||||||
|
#include "tim/experimental/trace/tvx/tensor.h"
|
||||||
|
#include "tim/experimental/trace/tracer.h"
|
||||||
|
|
||||||
|
namespace trace {
|
||||||
|
|
||||||
|
namespace target = ::tim::vx;
|
||||||
|
|
||||||
|
#define DECL_CREATE_OP_IMPL_(r, _, opname) \
|
||||||
|
template <class... Params> \
|
||||||
|
std::shared_ptr<trace::ops::opname> CreateOperationImpl( \
|
||||||
|
BOOST_PP_CAT(ops::_VSI_Tag_of_, opname), Params... params);
|
||||||
|
|
||||||
|
#define DECL_CREATE_OPS(ops_seq) \
|
||||||
|
BOOST_PP_SEQ_FOR_EACH(DECL_CREATE_OP_IMPL_, _, ops_seq)
|
||||||
|
|
||||||
|
#define TO_STRING_(expr) #expr
|
||||||
|
|
||||||
|
#define DEF_CREATE_OP_IMPL_(r, _, opname) \
|
||||||
|
template <class... Params> \
|
||||||
|
std::shared_ptr<trace::ops::opname> Graph::CreateOperationImpl( \
|
||||||
|
BOOST_PP_CAT(ops::_VSI_Tag_of_, opname), Params... params) { \
|
||||||
|
std::string this_obj_name = TraceGetObjName(); \
|
||||||
|
std::string obj_name = \
|
||||||
|
Tracer::allocate_obj_name(std::string(TO_STRING_(opname)) + "_"); \
|
||||||
|
Tracer::logging_msg( \
|
||||||
|
"auto %s = %s->CreateOperation<%s::ops::%s>(", obj_name.c_str(), \
|
||||||
|
this_obj_name.c_str(), target_namespace_name_, TO_STRING_(opname)); \
|
||||||
|
Tracer::clear_params_log_cache(); \
|
||||||
|
boost::hana::tuple<Params...> params_tuple = {params...}; \
|
||||||
|
boost::hana::for_each(params_tuple, [&] (auto x) { \
|
||||||
|
Tracer::logging_param(x, -1); \
|
||||||
|
}); \
|
||||||
|
Tracer::dump_params_log_cache(); \
|
||||||
|
Tracer::logging_msg(");\n"); \
|
||||||
|
auto CreateOpImpl = [&] (auto&&... ts) { \
|
||||||
|
return impl_->CreateOperation<target::ops::opname>(ts...); \
|
||||||
|
}; \
|
||||||
|
auto proc_param_lambda = [] (auto&& t) { \
|
||||||
|
return Tracer::proc_param(t); \
|
||||||
|
}; \
|
||||||
|
auto params_impl = boost::hana::transform(params_tuple, proc_param_lambda); \
|
||||||
|
auto op_impl_sp = boost::hana::unpack(params_impl, CreateOpImpl); \
|
||||||
|
auto op_sp = std::make_shared<trace::ops::opname>(op_impl_sp); \
|
||||||
|
Tracer::insert_obj_name(static_cast<void*>(op_impl_sp.get()), obj_name); \
|
||||||
|
return op_sp; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DEF_CREATE_OP_IMPLS(ops_seq) \
|
||||||
|
BOOST_PP_SEQ_FOR_EACH(DEF_CREATE_OP_IMPL_, _, ops_seq)
|
||||||
|
|
||||||
|
#define SPECIALIZATION_CREATE_OP(opname, args_desc, SPECIAL_MACRO_) \
|
||||||
|
template <> \
|
||||||
|
inline std::shared_ptr<trace::ops::opname> Graph::CreateOperation( \
|
||||||
|
ARGS_DESC_TO_DECLARATION(args_desc)) { \
|
||||||
|
std::string this_obj_name = TraceGetObjName(); \
|
||||||
|
std::string obj_name = Tracer::allocate_obj_name(std::string(#opname) + "_");\
|
||||||
|
Tracer::push_back_msg_cache( \
|
||||||
|
"auto " + obj_name + " = " + this_obj_name + \
|
||||||
|
"->CreateOperation<target::ops::" + #opname + ">("); \
|
||||||
|
LOG_PARAMS(ARGS_DESC_TO_PARAMS(args_desc)) \
|
||||||
|
SPECIAL_MACRO_(ARGS_DESC_TO_PARAMS(args_desc)) \
|
||||||
|
Tracer::pop_params_log_cache(); \
|
||||||
|
Tracer::amend_last_msg_cache(");\n"); \
|
||||||
|
Tracer::msg_cache_sync_to_file(); \
|
||||||
|
auto op_impl_sp = impl_->CreateOperation<target::ops::opname>( \
|
||||||
|
SEQ_TO_VARIADICS(ARGS_DESC_TO_PARAMS(args_desc))); \
|
||||||
|
auto op_sp = std::make_shared<trace::ops::opname>(op_impl_sp); \
|
||||||
|
Tracer::insert_obj_name(static_cast<void*>(op_impl_sp.get()), obj_name); \
|
||||||
|
return op_sp; \
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Graph : public TraceClassBase<target::Graph> {
|
||||||
|
DEF_INTERFACE_CONSTRUCTOR(Graph)
|
||||||
|
|
||||||
|
#define SPECIAL_MACRO_(params) \
|
||||||
|
if (BOOST_PP_SEQ_ELEM(1, params) == nullptr) { \
|
||||||
|
Tracer::insert_params_log_cache("nullptr", 1); \
|
||||||
|
} else { \
|
||||||
|
uint32_t count = \
|
||||||
|
BOOST_PP_SEQ_ELEM(0, params).TraceGetImpl().GetByteSize(); \
|
||||||
|
uint32_t offset = \
|
||||||
|
Tracer::dump_data( \
|
||||||
|
BOOST_PP_SEQ_ELEM(1, params), sizeof(char), count); \
|
||||||
|
LOGGING_POINTER_MSG(offset, count, 0) \
|
||||||
|
}
|
||||||
|
|
||||||
|
// DEF_MEMFN_SP(Tensor,
|
||||||
|
// CreateTensor,
|
||||||
|
// ((const TensorSpec&))((const void*)(nullptr)),
|
||||||
|
// SPECIAL_MACRO_)
|
||||||
|
std::shared_ptr<Tensor> CreateTensor(
|
||||||
|
const TensorSpec ¶m_0, const void *param_1 = nullptr) {
|
||||||
|
std::string this_obj_name = TraceGetObjName();
|
||||||
|
std::string obj_name =
|
||||||
|
Tracer::allocate_obj_name(Tracer::get_obj_prefix("Tensor"));
|
||||||
|
Tracer::push_back_msg_cache("auto " + obj_name + " = " + this_obj_name
|
||||||
|
+ "->" + __FUNCTION__ + "(");
|
||||||
|
Tracer::init_params_log_cache(2);
|
||||||
|
Tracer::logging_param(param_0, 0);
|
||||||
|
Tracer::logging_param(param_1, 1);
|
||||||
|
SPECIAL_MACRO_((param_0)(param_1))
|
||||||
|
Tracer::pop_params_log_cache();
|
||||||
|
Tracer::amend_last_msg_cache(");\n");
|
||||||
|
Tracer::msg_cache_sync_to_file();
|
||||||
|
|
||||||
|
#if 1 /* if use fake input data */
|
||||||
|
if (param_0.TraceGetImpl().GetTensorAttribute() ==
|
||||||
|
TensorAttribute::TRANSIENT && param_1 == nullptr) {
|
||||||
|
auto fake_vec_name = Tracer::allocate_obj_name("fake_vec_");
|
||||||
|
switch (param_0.TraceGetImpl().GetDataType()) {
|
||||||
|
case DataType::INT32:
|
||||||
|
Tracer::logging_msg("std::vector<int> %s(%d, 42);\n"
|
||||||
|
"%s->CopyDataToTensor(%s.data());\n",
|
||||||
|
fake_vec_name.c_str(), (int)param_0.TraceGetImpl().GetElementNum(),
|
||||||
|
obj_name.c_str(), fake_vec_name.c_str());
|
||||||
|
break;
|
||||||
|
case DataType::FLOAT32:
|
||||||
|
Tracer::logging_msg("std::vector<float> %s(%d, 0.42);\n"
|
||||||
|
"%s->CopyDataToTensor(%s.data());\n",
|
||||||
|
fake_vec_name.c_str(), (int)param_0.TraceGetImpl().GetElementNum(),
|
||||||
|
obj_name.c_str(), fake_vec_name.c_str());
|
||||||
|
break;
|
||||||
|
case DataType::FLOAT16:
|
||||||
|
Tracer::logging_msg("std::vector<int16_t> %s(%d, 0);\n"
|
||||||
|
"%s->CopyDataToTensor(%s.data());\n",
|
||||||
|
fake_vec_name.c_str(), (int)param_0.TraceGetImpl().GetElementNum(),
|
||||||
|
obj_name.c_str(), fake_vec_name.c_str());
|
||||||
|
break;
|
||||||
|
case DataType::BOOL8:
|
||||||
|
Tracer::logging_msg("std::vector<char> %s(%d, 0);\n"
|
||||||
|
"%s->CopyDataToTensor(%s.data());\n",
|
||||||
|
fake_vec_name.c_str(), (int)param_0.TraceGetImpl().GetElementNum(),
|
||||||
|
obj_name.c_str(), fake_vec_name.c_str());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
TCLOGE("Unimplemented fake data type:%d\n",
|
||||||
|
(int)param_0.TraceGetImpl().GetDataType());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* if use fake input data */
|
||||||
|
|
||||||
|
auto obj_impl_sp = impl_->CreateTensor(
|
||||||
|
Tracer::proc_param(param_0), Tracer::proc_param(param_1));
|
||||||
|
auto obj_sp = std::make_shared<Tensor>(obj_impl_sp, param_0);
|
||||||
|
Tracer::insert_obj_name(static_cast<void *>(obj_impl_sp.get()), obj_name);
|
||||||
|
tensor_sp_keeper_[obj_impl_sp] = obj_sp; // need keep obj_sp alive.
|
||||||
|
spec_keeper_.push_back(param_0);
|
||||||
|
return obj_sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DEF_MEMFN_SP(Tensor,
|
||||||
|
// CreateIOTensor,
|
||||||
|
// ((const TensorSpec&))((void*)(nullptr)),
|
||||||
|
// SPECIAL_MACRO_)
|
||||||
|
std::shared_ptr<Tensor> CreateIOTensor(
|
||||||
|
const TensorSpec ¶m_0, void *param_1 = nullptr) {
|
||||||
|
std::string this_obj_name = TraceGetObjName();
|
||||||
|
std::string obj_name =
|
||||||
|
Tracer::allocate_obj_name(Tracer::get_obj_prefix("Tensor"));
|
||||||
|
Tracer::push_back_msg_cache("auto " + obj_name + " = " + this_obj_name
|
||||||
|
+ "->" + __FUNCTION__ + "(");
|
||||||
|
Tracer::init_params_log_cache(2);
|
||||||
|
Tracer::logging_param(param_0, 0);
|
||||||
|
Tracer::logging_param(param_1, 1);
|
||||||
|
SPECIAL_MACRO_((param_0)(param_1))
|
||||||
|
Tracer::pop_params_log_cache();
|
||||||
|
Tracer::amend_last_msg_cache(");\n");
|
||||||
|
Tracer::msg_cache_sync_to_file();
|
||||||
|
auto obj_impl_sp = impl_->CreateIOTensor(
|
||||||
|
Tracer::proc_param(param_0), Tracer::proc_param(param_1));
|
||||||
|
auto obj_sp = std::make_shared<Tensor>(obj_impl_sp);
|
||||||
|
Tracer::insert_obj_name(static_cast<void *>(obj_impl_sp.get()), obj_name);
|
||||||
|
tensor_sp_keeper_[obj_impl_sp] = obj_sp; // need keep obj_sp alive.
|
||||||
|
spec_keeper_.push_back(param_0);
|
||||||
|
return obj_sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef SPECIAL_MACRO_
|
||||||
|
|
||||||
|
// DEF_MEMFN_SP(Tensor, CreateTensor,
|
||||||
|
// ((const TensorSpec&))((const DmaBufferDesc&))
|
||||||
|
// )
|
||||||
|
std::shared_ptr<Tensor> CreateTensor(
|
||||||
|
const TensorSpec ¶m_0, const DmaBufferDesc ¶m_1) {
|
||||||
|
std::string this_obj_name = TraceGetObjName();
|
||||||
|
std::string obj_name =
|
||||||
|
Tracer::allocate_obj_name(Tracer::get_obj_prefix("Tensor"));
|
||||||
|
Tracer::logging_msg("auto %s = %s->%s(", obj_name.c_str(),
|
||||||
|
this_obj_name.c_str(), __FUNCTION__);
|
||||||
|
Tracer::init_params_log_cache(2);
|
||||||
|
Tracer::logging_param(param_0, 0);
|
||||||
|
Tracer::logging_param(param_1, 1);
|
||||||
|
Tracer::dump_params_log_cache();
|
||||||
|
Tracer::logging_msg(");\n");
|
||||||
|
auto obj_impl_sp = impl_->CreateTensor(Tracer::proc_param(param_0),
|
||||||
|
Tracer::proc_param(param_1));
|
||||||
|
auto obj_sp = std::make_shared<Tensor>(obj_impl_sp);
|
||||||
|
Tracer::insert_obj_name(static_cast<void *>(obj_impl_sp.get()), obj_name);
|
||||||
|
tensor_sp_keeper_[obj_impl_sp] = obj_sp; // need keep obj_sp alive.
|
||||||
|
spec_keeper_.push_back(param_0);
|
||||||
|
return obj_sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DEF_MEMFN_SP(Tensor, CreateTensorPlaceHolder)
|
||||||
|
std::shared_ptr<Tensor> CreateTensorPlaceHolder() {
|
||||||
|
std::string this_obj_name = TraceGetObjName();
|
||||||
|
std::string obj_name =
|
||||||
|
Tracer::allocate_obj_name(Tracer::get_obj_prefix("Tensor"));
|
||||||
|
Tracer::logging_msg("auto %s = %s->%s();\n", obj_name.c_str(),
|
||||||
|
this_obj_name.c_str(), __FUNCTION__);
|
||||||
|
auto obj_impl_sp = impl_->CreateTensorPlaceHolder();
|
||||||
|
auto obj_sp = std::make_shared<Tensor>(obj_impl_sp);
|
||||||
|
Tracer::insert_obj_name(static_cast<void *>(obj_impl_sp.get()), obj_name);
|
||||||
|
tensor_sp_keeper_[obj_impl_sp] = obj_sp; // need keep obj_sp alive.
|
||||||
|
return obj_sp;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEF_TRACED_API(bool, Compile)
|
||||||
|
|
||||||
|
// DEF_TRACED_API(bool, CompileToBinary, [&] () {
|
||||||
|
// if (boost::hana::at_c<0>(params_tuple) == nullptr) {
|
||||||
|
// auto nbg_size_var = Tracer::allocate_obj_name("nbg_size_");
|
||||||
|
// Tracer::insert_obj_name(boost::hana::at_c<1>(params_tuple), nbg_size_var);
|
||||||
|
// Tracer::insert_before_last_msg_cache(
|
||||||
|
// "size_t " + nbg_size_var + " = -1;\n");
|
||||||
|
// Tracer::insert_params_log_cache("nullptr", 0);
|
||||||
|
// } else {
|
||||||
|
// uint32_t count = *boost::hana::at_c<1>(params_tuple);
|
||||||
|
// uint32_t offset = Tracer::dump_data(boost::hana::at_c<0>(params_tuple),
|
||||||
|
// sizeof(char), count);
|
||||||
|
// LOGGING_POINTER_MSG(offset, count, 0)
|
||||||
|
// }
|
||||||
|
// Tracer::insert_params_log_cache(
|
||||||
|
// "&" + Tracer::get_obj_name(boost::hana::at_c<1>(params_tuple)), 1);
|
||||||
|
// })
|
||||||
|
|
||||||
|
#define SPECIAL_MACRO_(params) \
|
||||||
|
if (BOOST_PP_SEQ_ELEM(0, params) == nullptr) { \
|
||||||
|
std::string size_name = Tracer::allocate_obj_name("nbg_size_"); \
|
||||||
|
Tracer::insert_obj_name(BOOST_PP_SEQ_ELEM(1, params), size_name); \
|
||||||
|
Tracer::insert_before_last_msg_cache( \
|
||||||
|
"size_t " + size_name + " = -1;\n"); \
|
||||||
|
Tracer::insert_params_log_cache("nullptr", 0); \
|
||||||
|
} else { \
|
||||||
|
uint32_t data_length = *BOOST_PP_SEQ_ELEM(1, params); \
|
||||||
|
uint32_t offset = Tracer::dump_data( \
|
||||||
|
BOOST_PP_SEQ_ELEM(0, params), sizeof(char), data_length); \
|
||||||
|
LOGGING_POINTER_MSG(offset, data_length, 0) \
|
||||||
|
} \
|
||||||
|
Tracer::insert_params_log_cache( \
|
||||||
|
"&" + Tracer::get_obj_name(BOOST_PP_SEQ_ELEM(1, params)), 1);
|
||||||
|
|
||||||
|
DEF_MEMFN(bool,
|
||||||
|
CompileToBinary,
|
||||||
|
((void*))((size_t*)),
|
||||||
|
SPECIAL_MACRO_)
|
||||||
|
|
||||||
|
#undef SPECIAL_MACRO_
|
||||||
|
|
||||||
|
DEF_TRACED_API(bool, Run)
|
||||||
|
|
||||||
|
template <class OpType, class... Params>
|
||||||
|
std::shared_ptr<OpType> CreateOperation(Params... params) {
|
||||||
|
return CreateOperationImpl(
|
||||||
|
typename ops::TagDispatchTrait<OpType>::tag {}, params...);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::shared_ptr<Tensor>> InputsTensor() {
|
||||||
|
std::vector<std::shared_ptr<Tensor>> ret;
|
||||||
|
for (auto& x : impl_->InputsTensor()) {
|
||||||
|
ret.push_back(tensor_sp_keeper_[x]);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::shared_ptr<Tensor>> OutputsTensor() {
|
||||||
|
std::vector<std::shared_ptr<Tensor>> ret;
|
||||||
|
for (auto& x : impl_->OutputsTensor()) {
|
||||||
|
ret.push_back(tensor_sp_keeper_[x]);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEF_TRACED_API(void, UpdateTensorConsumersMap)
|
||||||
|
|
||||||
|
DEF_TRACED_API(void, UpdateTensorProducerMap)
|
||||||
|
|
||||||
|
// DEF_TRACED_API(cosnt std::vector<std::shared_ptr<Operation>>, GetConsumersOp)
|
||||||
|
|
||||||
|
// DEF_TRACED_API(std::shared_ptr<Operation>, GetProducerOp)
|
||||||
|
|
||||||
|
DEF_TRACED_API(void, PrintGraph)
|
||||||
|
|
||||||
|
// DEF_TRACED_API(const std::vector<std::shared_ptr<Tensor>>, GetConstantInputs)
|
||||||
|
|
||||||
|
// DEF_TRACED_API(const std::vector<std::shared_ptr<Operation>>, GetOpVector)
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::shared_ptr<target::Tensor>, std::shared_ptr<Tensor>>
|
||||||
|
tensor_sp_keeper_;
|
||||||
|
std::vector<TensorSpec> spec_keeper_;
|
||||||
|
|
||||||
|
DECL_CREATE_OPS(TVX_OPS_SEQ)
|
||||||
|
DECL_CREATE_OP_IMPL_(_, _, Pad)
|
||||||
|
DECL_CREATE_OP_IMPL_(_, _, PadV2)
|
||||||
|
|
||||||
|
};
|
||||||
|
#define SPECIAL_MACRO_(params) \
|
||||||
|
std::string buf_name = Tracer::allocate_obj_name("nbg_buf_vec_"); \
|
||||||
|
FILE* nbg_dumped = fopen("network_binary_graph.nb", "r"); \
|
||||||
|
fseek(nbg_dumped, 0L, SEEK_END); \
|
||||||
|
uint32_t count = ftell(nbg_dumped); \
|
||||||
|
fclose(nbg_dumped); \
|
||||||
|
uint32_t offset = Tracer::dump_data( \
|
||||||
|
BOOST_PP_SEQ_ELEM(0, params), sizeof(char), count); \
|
||||||
|
Tracer::insert_before_last_msg_cache("std::vector<char> " + buf_name + \
|
||||||
|
" = trace::Replayer::get_vector<char>(" + std::to_string(offset) + \
|
||||||
|
"," + std::to_string(count) + ");\n"); \
|
||||||
|
Tracer::insert_params_log_cache(buf_name + ".data()", 0);
|
||||||
|
|
||||||
|
SPECIALIZATION_CREATE_OP(NBG, ((const char*))((size_t))((size_t)),
|
||||||
|
SPECIAL_MACRO_)
|
||||||
|
|
||||||
|
#undef SPECIAL_MACRO_
|
||||||
|
|
||||||
|
DEF_CREATE_OP_IMPLS(TVX_OPS_SEQ)
|
||||||
|
DEF_CREATE_OP_IMPL_(_, _, Pad)
|
||||||
|
DEF_CREATE_OP_IMPL_(_, _, PadV2)
|
||||||
|
|
||||||
|
} /* namespace trace */
|
||||||
|
|
||||||
|
#endif // TIM_EXPERIMENTAL_TRACE_TVX_GRAPH_H_
|
||||||
|
|
@ -0,0 +1,323 @@
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2023 Vivante Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
#ifndef TIM_EXPERIMENTAL_TRACE_TVX_OPS_H_
|
||||||
|
#define TIM_EXPERIMENTAL_TRACE_TVX_OPS_H_
|
||||||
|
#include "tim/vx/operation.h"
|
||||||
|
#include "tim/vx/ops.h"
|
||||||
|
#include "tim/experimental/trace/tvx/tensor.h"
|
||||||
|
#include "tim/experimental/trace/tracer.h"
|
||||||
|
|
||||||
|
#define TVX_OPS_SEQ \
|
||||||
|
(Relu) \
|
||||||
|
(Relu1) \
|
||||||
|
(Relu6) \
|
||||||
|
(Tanh) \
|
||||||
|
(Sigmoid) \
|
||||||
|
(Swish) \
|
||||||
|
(HardSwish) \
|
||||||
|
(Mish) \
|
||||||
|
(SoftRelu) \
|
||||||
|
(Sign) \
|
||||||
|
(SoftSign) \
|
||||||
|
(Elu) \
|
||||||
|
(Prelu) \
|
||||||
|
(HardSigmoid) \
|
||||||
|
(LeakyRelu) \
|
||||||
|
(Linear) \
|
||||||
|
(Gelu) \
|
||||||
|
(Selu) \
|
||||||
|
(Celu) \
|
||||||
|
(AddN) \
|
||||||
|
(ArgMin) \
|
||||||
|
(ArgMax) \
|
||||||
|
(Batch2Space) \
|
||||||
|
(BatchNorm) \
|
||||||
|
(BidirectionalSequenceRnn) \
|
||||||
|
(BidirectionalSequenceRnnExt) \
|
||||||
|
(Broadcast) \
|
||||||
|
(Clip) \
|
||||||
|
(Concat) \
|
||||||
|
(Conv1d) \
|
||||||
|
(Conv2d) \
|
||||||
|
(DeConv1d) \
|
||||||
|
(DeConv2d) \
|
||||||
|
(DepthToSpace) \
|
||||||
|
(Dropout) \
|
||||||
|
(Minimum) \
|
||||||
|
(Maximum) \
|
||||||
|
(Add) \
|
||||||
|
(Sub) \
|
||||||
|
(Pow) \
|
||||||
|
(FloorDiv) \
|
||||||
|
(Multiply) \
|
||||||
|
(Div) \
|
||||||
|
(Erf) \
|
||||||
|
(FullyConnected) \
|
||||||
|
(Gather) \
|
||||||
|
(GatherElements) \
|
||||||
|
(GatherNd) \
|
||||||
|
(GroupedConv2d) \
|
||||||
|
(InstanceNormalization) \
|
||||||
|
(L2Normalization) \
|
||||||
|
(LayerNormalization) \
|
||||||
|
(LRN) \
|
||||||
|
(LogicalAnd) \
|
||||||
|
(LogicalOr) \
|
||||||
|
(LogSoftmax) \
|
||||||
|
(Matmul) \
|
||||||
|
(MaxpoolWithArgmax) \
|
||||||
|
(MaxpoolWithArgmax2) \
|
||||||
|
(MaxpoolGrad) \
|
||||||
|
(MaxUnpool2d) \
|
||||||
|
(Moments) \
|
||||||
|
(OneHot) \
|
||||||
|
/* (Pad) enum defined in class */ \
|
||||||
|
/* (PadV2) enum defined in class */ \
|
||||||
|
(Pool1d) \
|
||||||
|
(Pool2d) \
|
||||||
|
(ReduceMin) \
|
||||||
|
(ReduceMax) \
|
||||||
|
(ReduceAny) \
|
||||||
|
(ReduceAll) \
|
||||||
|
(ReduceProd) \
|
||||||
|
(ReduceMean) \
|
||||||
|
(ReduceSum) \
|
||||||
|
(Greater) \
|
||||||
|
(GreaterOrEqual) \
|
||||||
|
(Less) \
|
||||||
|
(LessOrEqual) \
|
||||||
|
(NotEqual) \
|
||||||
|
(Equal) \
|
||||||
|
(Reorg) \
|
||||||
|
(Reshape) \
|
||||||
|
(Resize1d) \
|
||||||
|
(Resize) \
|
||||||
|
(Reverse) \
|
||||||
|
(RNNCell) \
|
||||||
|
(RoiAlign) \
|
||||||
|
(RoiPool) \
|
||||||
|
(ScatterND) \
|
||||||
|
(Select) \
|
||||||
|
(ShuffleChannel) \
|
||||||
|
(DataConvert) \
|
||||||
|
(Neg) \
|
||||||
|
(Abs) \
|
||||||
|
(Sin) \
|
||||||
|
(Exp) \
|
||||||
|
(Log) \
|
||||||
|
(Sqrt) \
|
||||||
|
(Rsqrt) \
|
||||||
|
(Square) \
|
||||||
|
(LogicalNot) \
|
||||||
|
(Floor) \
|
||||||
|
(Ceil) \
|
||||||
|
(Round) \
|
||||||
|
(Cast) \
|
||||||
|
(Rcp) \
|
||||||
|
(SignalFrame) \
|
||||||
|
(Slice) \
|
||||||
|
(Softmax) \
|
||||||
|
(Space2Batch) \
|
||||||
|
(SpaceToDepth) \
|
||||||
|
(SpatialTransformer) \
|
||||||
|
(Split) \
|
||||||
|
(Squeeze) \
|
||||||
|
(Stack) \
|
||||||
|
(StridedSlice) \
|
||||||
|
(Svdf) \
|
||||||
|
(Tile) \
|
||||||
|
(Transpose) \
|
||||||
|
(UnidirectionalSequenceLstm) \
|
||||||
|
(UnidirectionalSequenceRnn) \
|
||||||
|
(UnidirectionalSequenceRnnExt) \
|
||||||
|
(Unstack) \
|
||||||
|
(Conv3d) \
|
||||||
|
(CustomOpBase) \
|
||||||
|
(Topk) \
|
||||||
|
(BidirectionalSequenceLstm) \
|
||||||
|
(HashtableLookup) \
|
||||||
|
(EmbeddingLookup) \
|
||||||
|
(NBG)
|
||||||
|
|
||||||
|
namespace trace {
|
||||||
|
|
||||||
|
namespace target = ::tim::vx;
|
||||||
|
|
||||||
|
struct Operation : public TraceClassBase<target::Operation> {
|
||||||
|
DEF_INTERFACE_CONSTRUCTOR(Operation)
|
||||||
|
|
||||||
|
DEF_TRACED_API(std::shared_ptr<Operation>, Clone)
|
||||||
|
|
||||||
|
// unfixed issue when use DEF_TRACED_API to define BindOutput
|
||||||
|
DEF_INPLACE_MEMFN(Operation&, BindInput, ((const std::shared_ptr<Tensor>&)))
|
||||||
|
DEF_INPLACE_MEMFN(Operation&, BindOutput, ((const std::shared_ptr<Tensor>&)))
|
||||||
|
// DEF_TRACED_API(Operation&, BindInput)
|
||||||
|
// template <class R = Operation &, class... Args>
|
||||||
|
// typename std::enable_if_t<is_traced_obj<R>::value, R> BindInput(Args... params)
|
||||||
|
// {
|
||||||
|
// std::string this_obj_name = TraceGetObjName();
|
||||||
|
// Tracer::push_back_msg_cache(this_obj_name + "->" + __FUNCTION__ + "(");
|
||||||
|
// Tracer::clear_params_log_cache();
|
||||||
|
// boost::hana::tuple<Args...> params_tuple = {params...};
|
||||||
|
// boost::hana::for_each(params_tuple, [&](auto x)
|
||||||
|
// { Tracer::logging_param(x, -1); });
|
||||||
|
// Tracer::pop_params_log_cache();
|
||||||
|
// Tracer::amend_last_msg_cache(");\n");
|
||||||
|
// Tracer::msg_cache_sync_to_file();
|
||||||
|
// auto api_impl = [&](auto &&...ts)
|
||||||
|
// { return &(impl_->BindInput(ts...)); };
|
||||||
|
// auto proc_param_lambda = [](auto &&t)
|
||||||
|
// { return Tracer::proc_param(t); };
|
||||||
|
// auto params_impl = boost::hana::transform(params_tuple, proc_param_lambda);
|
||||||
|
// auto ret_impl_p = boost::hana::unpack(params_impl, api_impl);
|
||||||
|
// return *this;
|
||||||
|
// // return *static_cast<std::decay_t<R> *>(Tracer::get_traced_obj(ret_impl_p));
|
||||||
|
// }
|
||||||
|
// DEF_TRACED_API(Operation&, BindOutput)
|
||||||
|
// template <class R = Operation &, class... Args>
|
||||||
|
// typename std::enable_if_t<is_traced_obj<R>::value, R> BindOutput(Args... params)
|
||||||
|
// {
|
||||||
|
// std::string this_obj_name = TraceGetObjName();
|
||||||
|
// Tracer::push_back_msg_cache(this_obj_name + "->" + __FUNCTION__ + "(");
|
||||||
|
// Tracer::clear_params_log_cache();
|
||||||
|
// boost::hana::tuple<Args...> params_tuple = {params...};
|
||||||
|
// boost::hana::for_each(params_tuple, [&](auto x)
|
||||||
|
// { Tracer::logging_param(x, -1); });
|
||||||
|
// Tracer::pop_params_log_cache();
|
||||||
|
// Tracer::amend_last_msg_cache(");\n");
|
||||||
|
// Tracer::msg_cache_sync_to_file();
|
||||||
|
// auto api_impl = [&](auto &&...ts)
|
||||||
|
// { return &(impl_->BindOutput(ts...)); };
|
||||||
|
// auto proc_param_lambda = [](auto &&t)
|
||||||
|
// { return Tracer::proc_param(t); };
|
||||||
|
// auto params_impl = boost::hana::transform(params_tuple, proc_param_lambda);
|
||||||
|
// auto ret_impl_p = boost::hana::unpack(params_impl, api_impl);
|
||||||
|
// return *this;
|
||||||
|
// // return *static_cast<std::decay_t<R> *>(Tracer::get_traced_obj(ret_impl_p));
|
||||||
|
// }
|
||||||
|
|
||||||
|
// compiler can not deduce the <brace-enclosed initializer list> type for
|
||||||
|
// template variadic, so can't use DEF_TRACED_API to define BindInputs/Outputs
|
||||||
|
// DEF_INPLACE_MEMFN(Operation&, BindInputs,
|
||||||
|
// ((const std::vector<std::shared_ptr<Tensor>>&))
|
||||||
|
// )
|
||||||
|
Operation &BindInputs(const std::vector<std::shared_ptr<Tensor>> ¶m_0)
|
||||||
|
{
|
||||||
|
std::string this_obj_name = TraceGetObjName();
|
||||||
|
Tracer::logging_msg("%s->%s(", this_obj_name.c_str(), __FUNCTION__);
|
||||||
|
Tracer::init_params_log_cache(1);
|
||||||
|
Tracer::logging_param(param_0, 0);
|
||||||
|
Tracer::dump_params_log_cache();
|
||||||
|
Tracer::logging_msg(");\n");
|
||||||
|
impl_->BindInputs(Tracer::proc_param(param_0));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
// DEF_INPLACE_MEMFN(Operation&, BindOutputs,
|
||||||
|
// ((const std::vector<std::shared_ptr<Tensor>>&))
|
||||||
|
// )
|
||||||
|
Operation &BindOutputs(const std::vector<std::shared_ptr<Tensor>> ¶m_0)
|
||||||
|
{
|
||||||
|
std::string this_obj_name = TraceGetObjName();
|
||||||
|
Tracer::logging_msg("%s->%s(", this_obj_name.c_str(), __FUNCTION__);
|
||||||
|
Tracer::init_params_log_cache(1);
|
||||||
|
Tracer::logging_param(param_0, 0);
|
||||||
|
Tracer::dump_params_log_cache();
|
||||||
|
Tracer::logging_msg(");\n");
|
||||||
|
impl_->BindOutputs(Tracer::proc_param(param_0));
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
DEF_INPLACE_MEMFN(Operation&, SetRoundingPolicy,
|
||||||
|
((OverflowPolicy)(OverflowPolicy::SATURATE))
|
||||||
|
((RoundingPolicy)(RoundingPolicy::RTNE))
|
||||||
|
((RoundType)(RoundType::FLOOR))
|
||||||
|
((uint32_t)(0))
|
||||||
|
)
|
||||||
|
|
||||||
|
// do not support unique_ptr and OpImpl by now
|
||||||
|
// DEF_TRACED_API(std::unique_ptr<OpImpl>&, impl)
|
||||||
|
|
||||||
|
// do not support unique_ptr and OpImpl by now
|
||||||
|
// DEF_TRACED_API(const std::unique_ptr<OpImpl>&, impl)
|
||||||
|
|
||||||
|
DEF_TRACED_API(const std::vector<std::shared_ptr<Tensor>>, ConstantInputsTensor)
|
||||||
|
|
||||||
|
protected:
|
||||||
|
DEF_TRACED_API(bool, IsAllInputsConst)
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace trace */
|
||||||
|
|
||||||
|
namespace trace {
|
||||||
|
namespace ops {
|
||||||
|
|
||||||
|
struct DefaultTag {};
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
struct TagDispatchTrait {
|
||||||
|
using tag = DefaultTag;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEF_TIMVX_OP_AND_TAG_IMPL_(r, _, op) \
|
||||||
|
struct op : Operation { \
|
||||||
|
op(const std::shared_ptr<target::ops::op>& impl) : Operation(impl) {} \
|
||||||
|
}; \
|
||||||
|
struct BOOST_PP_CAT(_VSI_Tag_of_, op) {}; \
|
||||||
|
template<> \
|
||||||
|
struct TagDispatchTrait<op> { \
|
||||||
|
using tag = BOOST_PP_CAT(_VSI_Tag_of_, op); \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DEF_TIMVX_OPS_AND_TAGS(ops) \
|
||||||
|
BOOST_PP_SEQ_FOR_EACH(DEF_TIMVX_OP_AND_TAG_IMPL_, _, ops)
|
||||||
|
|
||||||
|
DEF_TIMVX_OPS_AND_TAGS(TVX_OPS_SEQ)
|
||||||
|
|
||||||
|
// DEF_TIMVX_OP_AND_TAG_IMPL_(_, _, Pad)
|
||||||
|
struct Pad : Operation {
|
||||||
|
// must be used as tvx::ops::Pad::pad_mode_type::PAD_MODE_CONSTANT, but not
|
||||||
|
// tvx::ops::Pad::PAD_MODE_CONSTANT
|
||||||
|
using pad_mode_type = target::ops::Pad::pad_mode_type;
|
||||||
|
Pad(const std::shared_ptr<target::ops::Pad> &impl) : Operation(impl) {}
|
||||||
|
};
|
||||||
|
struct _VSI_Tag_of_Pad {};
|
||||||
|
template <>
|
||||||
|
struct TagDispatchTrait<Pad> {
|
||||||
|
using tag = _VSI_Tag_of_Pad;
|
||||||
|
};
|
||||||
|
|
||||||
|
// DEF_TIMVX_OP_AND_TAG_IMPL_(_, _, PadV2)
|
||||||
|
struct PadV2 : Operation {
|
||||||
|
using pad_mode_type = target::ops::PadV2::pad_mode_type;
|
||||||
|
PadV2(const std::shared_ptr<target::ops::PadV2> &impl) : Operation(impl) {}
|
||||||
|
};
|
||||||
|
struct _VSI_Tag_of_PadV2 {};
|
||||||
|
template <>
|
||||||
|
struct TagDispatchTrait<PadV2> {
|
||||||
|
using tag = _VSI_Tag_of_PadV2;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace ops */
|
||||||
|
} /* namespace trace */
|
||||||
|
|
||||||
|
#endif // TIM_EXPERIMENTAL_TRACE_TVX_OPS_H_
|
||||||
|
|
@ -0,0 +1,246 @@
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2023 Vivante Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
#ifndef TIM_EXPERIMENTAL_TRACE_TVX_TENSOR_H_
|
||||||
|
#define TIM_EXPERIMENTAL_TRACE_TVX_TENSOR_H_
|
||||||
|
#include "tim/vx/tensor.h"
|
||||||
|
#include "tim/experimental/trace/tvx/types.h"
|
||||||
|
#include "tim/experimental/trace/tracer.h"
|
||||||
|
|
||||||
|
namespace trace {
|
||||||
|
|
||||||
|
namespace target = ::tim::vx;
|
||||||
|
|
||||||
|
struct Quantization : public TraceClassBase<target::Quantization> {
|
||||||
|
DEF_CONSTRUCTOR(Quantization)
|
||||||
|
|
||||||
|
DEF_CONSTRUCTOR(Quantization, ((QuantType))
|
||||||
|
((float))
|
||||||
|
((int32_t))
|
||||||
|
)
|
||||||
|
|
||||||
|
DEF_CONSTRUCTOR(Quantization, ((QuantType))
|
||||||
|
((int32_t))
|
||||||
|
((std::vector<float>))
|
||||||
|
((std::vector<int32_t>))
|
||||||
|
)
|
||||||
|
|
||||||
|
DEF_CONSTRUCTOR(Quantization, ((QuantType))
|
||||||
|
((int8_t))
|
||||||
|
)
|
||||||
|
|
||||||
|
DEF_TRACED_API(QuantType&, Type)
|
||||||
|
|
||||||
|
// DEF_TRACED_API(const QuantType&, Type)
|
||||||
|
template <class R = const QuantType &, class... Args>
|
||||||
|
typename std::enable_if_t<is_not_traced_obj_like<R>::value, R> Type(
|
||||||
|
Args... params) const {
|
||||||
|
std::string this_obj_name = TraceGetObjName();
|
||||||
|
Tracer::push_back_msg_cache(this_obj_name + "->" + __FUNCTION__ + "(");
|
||||||
|
Tracer::clear_params_log_cache();
|
||||||
|
boost::hana::tuple<Args...> params_tuple = {params...};
|
||||||
|
boost::hana::for_each(params_tuple, [&](auto x) {
|
||||||
|
Tracer::logging_param(x, -1);});
|
||||||
|
Tracer::pop_params_log_cache();
|
||||||
|
Tracer::amend_last_msg_cache(");\n");
|
||||||
|
Tracer::msg_cache_sync_to_file();
|
||||||
|
auto api_impl = [&](auto &&...ts) { return impl_->Type(ts...); };
|
||||||
|
auto proc_param_lambda = [](auto &&t) { return Tracer::proc_param(t); };
|
||||||
|
auto params_impl = boost::hana::transform(params_tuple, proc_param_lambda);
|
||||||
|
return boost::hana::unpack(params_impl, api_impl);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEF_TRACED_API(int32_t&, ChannelDim)
|
||||||
|
|
||||||
|
// DEF_TRACED_API(const int32_t&, ChannelDim)
|
||||||
|
template <class R = const int32_t &, class... Args>
|
||||||
|
typename std::enable_if_t<is_not_traced_obj_like<R>::value, R> ChannelDim(
|
||||||
|
Args... params) const {
|
||||||
|
std::string this_obj_name = TraceGetObjName();
|
||||||
|
Tracer::push_back_msg_cache(this_obj_name + "->" + __FUNCTION__ + "(");
|
||||||
|
Tracer::clear_params_log_cache();
|
||||||
|
boost::hana::tuple<Args...> params_tuple = {params...};
|
||||||
|
boost::hana::for_each(params_tuple, [&](auto x) {
|
||||||
|
Tracer::logging_param(x, -1); });
|
||||||
|
Tracer::pop_params_log_cache();
|
||||||
|
Tracer::amend_last_msg_cache(");\n");
|
||||||
|
Tracer::msg_cache_sync_to_file();
|
||||||
|
auto api_impl = [&](auto &&...ts) { return impl_->ChannelDim(ts...); };
|
||||||
|
auto proc_param_lambda = [](auto &&t) { return Tracer::proc_param(t); };
|
||||||
|
auto params_impl = boost::hana::transform(params_tuple, proc_param_lambda);
|
||||||
|
return boost::hana::unpack(params_impl, api_impl);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEF_TRACED_API(Quantization&, SetChannelDim)
|
||||||
|
|
||||||
|
DEF_TRACED_API(std::vector<float>&, Scales)
|
||||||
|
|
||||||
|
DEF_TRACED_API(std::vector<int32_t>&, ZeroPoints)
|
||||||
|
|
||||||
|
// DEF_TRACED_API(const std::vector<int32_t>&, ZeroPoints)
|
||||||
|
template <class R = const std::vector<int32_t> &, class... Args>
|
||||||
|
typename std::enable_if_t<is_not_traced_obj_like<R>::value, R> ZeroPoints(
|
||||||
|
Args... params) const {
|
||||||
|
std::string this_obj_name = TraceGetObjName();
|
||||||
|
Tracer::push_back_msg_cache(this_obj_name + "->" + __FUNCTION__ + "(");
|
||||||
|
Tracer::clear_params_log_cache();
|
||||||
|
boost::hana::tuple<Args...> params_tuple = {params...};
|
||||||
|
boost::hana::for_each(params_tuple, [&](auto x) {
|
||||||
|
Tracer::logging_param(x, -1); });
|
||||||
|
Tracer::pop_params_log_cache();
|
||||||
|
Tracer::amend_last_msg_cache(");\n");
|
||||||
|
Tracer::msg_cache_sync_to_file();
|
||||||
|
auto api_impl = [&](auto &&...ts) { return impl_->ZeroPoints(ts...); };
|
||||||
|
auto proc_param_lambda = [](auto &&t) { return Tracer::proc_param(t); };
|
||||||
|
auto params_impl = boost::hana::transform(params_tuple, proc_param_lambda);
|
||||||
|
return boost::hana::unpack(params_impl, api_impl);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEF_TRACED_API(Quantization&, SetZeroPoints)
|
||||||
|
|
||||||
|
DEF_TRACED_API(const std::int8_t&, Fl)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TensorSpec : public TraceClassBase<target::TensorSpec> {
|
||||||
|
DEF_CONSTRUCTOR(TensorSpec)
|
||||||
|
|
||||||
|
DEF_CONSTRUCTOR(TensorSpec, ((DataType))
|
||||||
|
((const ShapeType&))
|
||||||
|
((TensorAttribute))
|
||||||
|
)
|
||||||
|
|
||||||
|
DEF_CONSTRUCTOR(TensorSpec, ((DataType))
|
||||||
|
((const ShapeType&))
|
||||||
|
((TensorAttribute))
|
||||||
|
((const Quantization&))
|
||||||
|
)
|
||||||
|
|
||||||
|
// DEF_CONSTRUCTOR(TensorSpec, ((const TensorSpec&))
|
||||||
|
// )
|
||||||
|
|
||||||
|
DEF_TRACED_API(TensorSpec&, operator=)
|
||||||
|
|
||||||
|
DEF_TRACED_API(TensorSpec&, SetDataType)
|
||||||
|
|
||||||
|
DEF_TRACED_API(TensorSpec&, SetShape)
|
||||||
|
|
||||||
|
DEF_TRACED_API(TensorSpec&, SetAttribute)
|
||||||
|
|
||||||
|
DEF_TRACED_API(TensorSpec&, SetQuantization)
|
||||||
|
|
||||||
|
DEF_TRACED_API(TensorSpec&, AsTransientSpec)
|
||||||
|
|
||||||
|
DEF_TRACED_API(int64_t, GetElementNum)
|
||||||
|
|
||||||
|
DEF_TRACED_API(int64_t, GetElementByteSize)
|
||||||
|
|
||||||
|
DEF_TRACED_API(int64_t, GetByteSize)
|
||||||
|
|
||||||
|
DEF_SIMPLE_UNTRACED_API(DataType&, GetDataType)
|
||||||
|
|
||||||
|
DEF_SIMPLE_UNTRACED_API(ShapeType&, GetShapeType)
|
||||||
|
|
||||||
|
DEF_SIMPLE_UNTRACED_API(TensorAttribute&, GetTensorAttribute)
|
||||||
|
|
||||||
|
DEF_TRACED_API(Quantization&, GetQuantization)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DmaBufferDesc : public TraceClassBase<target::DmaBufferDesc> {
|
||||||
|
DEF_CONSTRUCTOR(DmaBufferDesc)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Tensor : public TraceClassBase<target::Tensor> {
|
||||||
|
// DEF_INTERFACE_CONSTRUCTOR(Tensor)
|
||||||
|
Tensor(const std::shared_ptr<target::Tensor> &impl) {
|
||||||
|
Tracer::insert_traced_obj(static_cast<void *>(impl.get()),
|
||||||
|
static_cast<void *>(this));
|
||||||
|
impl_ = impl;
|
||||||
|
}
|
||||||
|
Tensor(const std::shared_ptr<target::Tensor> &impl, const TensorSpec& spec) {
|
||||||
|
Tracer::insert_traced_obj(static_cast<void *>(impl.get()),
|
||||||
|
static_cast<void *>(this));
|
||||||
|
impl_ = impl;
|
||||||
|
spec_ = spec;
|
||||||
|
}
|
||||||
|
// DEF_TRACED_API(const ShapeType&, GetShape)
|
||||||
|
// unfixed issue of trace GetShape
|
||||||
|
DEF_SIMPLE_UNTRACED_API(const ShapeType&, GetShape)
|
||||||
|
|
||||||
|
DEF_TRACED_API(DataType, GetDataType)
|
||||||
|
|
||||||
|
DEF_TRACED_API(const Quantization&, GetQuantization)
|
||||||
|
|
||||||
|
// DEF_TRACED_API(TensorSpec&, GetSpec)
|
||||||
|
TensorSpec& GetSpec() {
|
||||||
|
return spec_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// DEF_TRACED_API(uint32_t, GetId)
|
||||||
|
DEF_SIMPLE_UNTRACED_API(uint32_t, GetId)
|
||||||
|
|
||||||
|
#define SPECIAL_MACRO_(params) \
|
||||||
|
uint32_t count = BOOST_PP_SEQ_ELEM(1, params); \
|
||||||
|
uint32_t offset = \
|
||||||
|
Tracer::dump_data(BOOST_PP_SEQ_ELEM(0, params), \
|
||||||
|
sizeof(char), count); \
|
||||||
|
LOGGING_POINTER_MSG(offset, count, 0)
|
||||||
|
|
||||||
|
DEF_MEMFN(bool, CopyDataToTensor, ((const void*))((uint32_t)(0)),
|
||||||
|
SPECIAL_MACRO_
|
||||||
|
)
|
||||||
|
|
||||||
|
#undef SPECIAL_MACRO_
|
||||||
|
|
||||||
|
DEF_TRACED_API(bool, CopyDataFromTensor, [&]() {
|
||||||
|
uint32_t count = impl_->GetSpec().GetByteSize();
|
||||||
|
uint32_t offset = Tracer::dump_data(boost::hana::at_c<0>(params_tuple),
|
||||||
|
sizeof(char), count);
|
||||||
|
LOGGING_POINTER_MSG(offset, count, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
DEF_TRACED_API(bool, FlushCacheForHandle)
|
||||||
|
|
||||||
|
DEF_TRACED_API(bool, InvalidateCacheForHandle)
|
||||||
|
|
||||||
|
DEF_MEMFN(void*, map, ((bool)(false))
|
||||||
|
)
|
||||||
|
|
||||||
|
DEF_TRACED_API(void, unmap)
|
||||||
|
|
||||||
|
DEF_TRACED_API(bool, IsPlaceHolder)
|
||||||
|
|
||||||
|
DEF_TRACED_API(bool, IsConstTensor)
|
||||||
|
|
||||||
|
DEF_TRACED_API(bool, SaveTensorToTextByFp32)
|
||||||
|
|
||||||
|
DEF_TRACED_API(void*, ConvertTensorToData)
|
||||||
|
|
||||||
|
private:
|
||||||
|
TensorSpec spec_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace trace */
|
||||||
|
|
||||||
|
|
||||||
|
#endif // TIM_EXPERIMENTAL_TRACE_TVX_TENSOR_H_
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
/****************************************************************************
|
||||||
|
*
|
||||||
|
* Copyright (c) 2020-2023 Vivante Corporation
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||||
|
* copy of this software and associated documentation files (the "Software"),
|
||||||
|
* to deal in the Software without restriction, including without limitation
|
||||||
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||||
|
* and/or sell copies of the Software, and to permit persons to whom the
|
||||||
|
* Software is furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
* DEALINGS IN THE SOFTWARE.
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
#ifndef TIM_EXPERIMENTAL_TRACE_TVX_TYPES_H_
|
||||||
|
#define TIM_EXPERIMENTAL_TRACE_TVX_TYPES_H_
|
||||||
|
#include "tim/vx/types.h"
|
||||||
|
|
||||||
|
namespace trace {
|
||||||
|
|
||||||
|
namespace target = ::tim::vx;
|
||||||
|
|
||||||
|
using ShapeType = std::vector<uint32_t>;
|
||||||
|
|
||||||
|
using DataType = target::DataType;
|
||||||
|
|
||||||
|
using QuantType = target::QuantType;
|
||||||
|
|
||||||
|
using TensorAttribute = target::TensorAttribute;
|
||||||
|
|
||||||
|
using PadType = target::PadType;
|
||||||
|
|
||||||
|
using PoolType = target::PoolType;
|
||||||
|
|
||||||
|
using RoundType = target::RoundType;
|
||||||
|
|
||||||
|
using OverflowPolicy = target::OverflowPolicy;
|
||||||
|
|
||||||
|
using RoundingPolicy = target::RoundingPolicy;
|
||||||
|
|
||||||
|
using ResizeType = target::ResizeType;
|
||||||
|
|
||||||
|
using DataLayout = target::DataLayout;
|
||||||
|
|
||||||
|
} /* namespace trace */
|
||||||
|
|
||||||
|
#endif // TIM_EXPERIMENTAL_TRACE_TVX_TYPES_H_
|
||||||
|
|
@ -122,6 +122,14 @@ struct TensorSpec {
|
||||||
|
|
||||||
int64_t GetByteSize() const;
|
int64_t GetByteSize() const;
|
||||||
|
|
||||||
|
inline DataType& GetDataType() { return datatype_; }
|
||||||
|
|
||||||
|
inline ShapeType& GetShapeType() { return shape_; }
|
||||||
|
|
||||||
|
inline TensorAttribute& GetTensorAttribute() { return attr_; }
|
||||||
|
|
||||||
|
inline Quantization& GetQuantization() { return quantization_; }
|
||||||
|
|
||||||
DataType datatype_;
|
DataType datatype_;
|
||||||
ShapeType shape_;
|
ShapeType shape_;
|
||||||
TensorAttribute attr_;
|
TensorAttribute attr_;
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,10 @@ endif()
|
||||||
if(TIM_VX_ENABLE_TEST)
|
if(TIM_VX_ENABLE_TEST)
|
||||||
include(GoogleTest)
|
include(GoogleTest)
|
||||||
|
|
||||||
|
if(TIM_VX_ENABLE_API_TRACE)
|
||||||
|
add_definitions("-DENABLE_API_TRACE")
|
||||||
|
endif()
|
||||||
|
|
||||||
add_executable(unit_test ${${TARGET_NAME}_TEST_SRCS})
|
add_executable(unit_test ${${TARGET_NAME}_TEST_SRCS})
|
||||||
target_link_libraries(unit_test PRIVATE
|
target_link_libraries(unit_test PRIVATE
|
||||||
-Wl,--whole-archive ${TARGET_NAME}
|
-Wl,--whole-archive ${TARGET_NAME}
|
||||||
|
|
@ -235,7 +239,9 @@ if(TIM_VX_ENABLE_TEST)
|
||||||
${PROJECT_SOURCE_DIR}/include
|
${PROJECT_SOURCE_DIR}/include
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/vx
|
${CMAKE_CURRENT_SOURCE_DIR}/vx
|
||||||
${OVXLIB_INCLUDE_DIR}
|
${OVXLIB_INCLUDE_DIR}
|
||||||
${LITE_INC_DIRS})
|
${LITE_INC_DIRS}
|
||||||
|
${PROJECT_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
install(TARGETS unit_test DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR})
|
install(TARGETS unit_test DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR})
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -90,3 +90,65 @@ TEST(graph, gen_binary_graph_with_simple_add) {
|
||||||
EXPECT_TRUE(nbg_out->CopyDataFromTensor(&output));
|
EXPECT_TRUE(nbg_out->CopyDataFromTensor(&output));
|
||||||
EXPECT_EQ(output, expected_out);
|
EXPECT_EQ(output, expected_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef ENABLE_API_TRACE
|
||||||
|
#define API_REPLAYER_IMPLEMENTATION
|
||||||
|
#define API_TRACER_IMPLEMENTATION
|
||||||
|
#define TARGET_NAMESPACE_NAME "tim::vx"
|
||||||
|
#include "tim/experimental/trace/trace_tvx.h"
|
||||||
|
|
||||||
|
namespace tvx = trace;
|
||||||
|
|
||||||
|
TEST(graph, trace_test) {
|
||||||
|
auto ctx = tvx::Context::Create();
|
||||||
|
auto graph = ctx->CreateGraph();
|
||||||
|
|
||||||
|
tvx::ShapeType io_shape({1,2,2,1});
|
||||||
|
tvx::TensorSpec input_spec(tvx::DataType::FLOAT32, io_shape, tvx::TensorAttribute::INPUT);
|
||||||
|
tvx::TensorSpec output_spec(tvx::DataType::FLOAT32, io_shape, tvx::TensorAttribute::OUTPUT);
|
||||||
|
auto input_t0 = graph->CreateTensor(input_spec);
|
||||||
|
auto input_t1 = graph->CreateTensor(input_spec);
|
||||||
|
auto input_t2 = graph->CreateTensor(input_spec);
|
||||||
|
auto output_t0 = graph->CreateTensor(output_spec);
|
||||||
|
|
||||||
|
auto reshape = graph->CreateOperation<tvx::ops::Reshape>(io_shape);
|
||||||
|
(*reshape).BindInput(input_t0).BindOutput(input_t1);
|
||||||
|
auto add = graph->CreateOperation<tvx::ops::Add>();
|
||||||
|
(*add).BindInputs({input_t0, input_t2}).BindOutputs({output_t0});
|
||||||
|
|
||||||
|
size_t bin_size = -1;
|
||||||
|
EXPECT_TRUE(graph->CompileToBinary(nullptr, &bin_size));
|
||||||
|
EXPECT_NE(bin_size, -1);
|
||||||
|
std::vector<char> nbg_buf(bin_size);
|
||||||
|
|
||||||
|
// generate binary graph does't require input data
|
||||||
|
EXPECT_TRUE(graph->CompileToBinary(nbg_buf.data(), &bin_size));
|
||||||
|
|
||||||
|
// binary graph compilation doesn't impact current graph's execution
|
||||||
|
std::vector<float> in = {1.1f, 2.2f, 3.3f, 4.4f};
|
||||||
|
std::vector<float> expected_out = {2.2f, 4.4f, 6.6f, 8.8f};;
|
||||||
|
EXPECT_TRUE(input_t0->CopyDataToTensor(in.data(), sizeof(float) * in.size()));
|
||||||
|
EXPECT_TRUE(input_t2->CopyDataToTensor(in.data(), sizeof(float) * in.size()));
|
||||||
|
|
||||||
|
EXPECT_TRUE(graph->Run());
|
||||||
|
std::vector<float> output(in.size());
|
||||||
|
EXPECT_TRUE(output_t0->CopyDataFromTensor(output.data()));
|
||||||
|
EXPECT_EQ(output, expected_out);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(graph, replay_test) {
|
||||||
|
/*
|
||||||
|
* Copy trace_log.cc in the root dir of tim-vx, rename with trace_log.rpl.cc
|
||||||
|
* and copy the trace_bin.bin file to the runtime workspace,
|
||||||
|
* rename with trace_bin.rpl.bin
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "trace_log.rpl.cc"
|
||||||
|
// manual compile and run the selected graph, like:
|
||||||
|
// graph_12->Compile();
|
||||||
|
// graph_12->Run();
|
||||||
|
// Last rebuild unit-test and execute this case
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* #ifdef ENABLE_API_TRACE */
|
||||||
|
|
|
||||||
|
|
@ -67,19 +67,25 @@ class MaxpoolGradImpl : public OpImpl {
|
||||||
tim::vx::ShapeType idx_flattened_shape({CalFlattenedShape(grad_shape)});
|
tim::vx::ShapeType idx_flattened_shape({CalFlattenedShape(grad_shape)});
|
||||||
tim::vx::ShapeType out_flattened_shape({CalFlattenedShape(in_shape)});
|
tim::vx::ShapeType out_flattened_shape({CalFlattenedShape(in_shape)});
|
||||||
|
|
||||||
tim::vx::TensorSpec pool_out_spec_values(tim::vx::DataType::FLOAT32,
|
auto in_type = in_tensors_[POOL_INPUT_TENSOR]->GetDataType();
|
||||||
grad_shape, tim::vx::TensorAttribute::TRANSIENT);
|
auto in_quant = in_tensors_[POOL_INPUT_TENSOR]->GetQuantization();
|
||||||
|
if (in_quant.Type() != tim::vx::QuantType::NONE) {
|
||||||
|
VSILOGW("MaxPoolGrad deal with quantization tensor not validate yet!");
|
||||||
|
}
|
||||||
|
tim::vx::TensorSpec pool_out_spec_values(in_type,
|
||||||
|
grad_shape, tim::vx::TensorAttribute::TRANSIENT, in_quant);
|
||||||
tim::vx::TensorSpec pool_out_spec_indices(tim::vx::DataType::INT32,
|
tim::vx::TensorSpec pool_out_spec_indices(tim::vx::DataType::INT32,
|
||||||
grad_shape, tim::vx::TensorAttribute::TRANSIENT);
|
grad_shape, tim::vx::TensorAttribute::TRANSIENT);
|
||||||
tim::vx::TensorSpec idx_flattened_spec(tim::vx::DataType::INT32,
|
tim::vx::TensorSpec idx_flattened_spec(tim::vx::DataType::INT32,
|
||||||
idx_flattened_shape,tim::vx::TensorAttribute::TRANSIENT);
|
idx_flattened_shape,tim::vx::TensorAttribute::TRANSIENT);
|
||||||
tim::vx::TensorSpec upd_flattened_spec(tim::vx::DataType::FLOAT32,
|
tim::vx::TensorSpec upd_flattened_spec(in_type,
|
||||||
idx_flattened_shape, tim::vx::TensorAttribute::TRANSIENT);
|
idx_flattened_shape, tim::vx::TensorAttribute::TRANSIENT, in_quant);
|
||||||
tim::vx::TensorSpec out_flattened_spec(tim::vx::DataType::FLOAT32,
|
tim::vx::TensorSpec out_flattened_spec(in_type,
|
||||||
out_flattened_shape, tim::vx::TensorAttribute::TRANSIENT);
|
out_flattened_shape, tim::vx::TensorAttribute::TRANSIENT, in_quant);
|
||||||
|
|
||||||
auto pool_out_values_tensor = graph_->CreateTensor(pool_out_spec_values);
|
auto pool_out_values_tensor = graph_->CreateTensor(pool_out_spec_values);
|
||||||
auto pool_out_indices_tensor = graph_->CreateTensor(pool_out_spec_indices);
|
auto pool_out_indices_tensor =
|
||||||
|
graph_->CreateTensor(pool_out_spec_indices);
|
||||||
auto idx_flattened_tensor = graph_->CreateTensor(idx_flattened_spec);
|
auto idx_flattened_tensor = graph_->CreateTensor(idx_flattened_spec);
|
||||||
auto upd_flattened_tensor = graph_->CreateTensor(upd_flattened_spec);
|
auto upd_flattened_tensor = graph_->CreateTensor(upd_flattened_spec);
|
||||||
auto out_flattened_tensor = graph_->CreateTensor(out_flattened_spec);
|
auto out_flattened_tensor = graph_->CreateTensor(out_flattened_spec);
|
||||||
|
|
@ -88,36 +94,43 @@ class MaxpoolGradImpl : public OpImpl {
|
||||||
.BindOutputs({pool_out_values_tensor, pool_out_indices_tensor});
|
.BindOutputs({pool_out_values_tensor, pool_out_indices_tensor});
|
||||||
|
|
||||||
// eliminate pool out of maxpoolwithargmax begin
|
// eliminate pool out of maxpoolwithargmax begin
|
||||||
tim::vx::TensorSpec sliced_spec(tim::vx::DataType::FLOAT32,
|
tim::vx::TensorSpec sliced_spec(in_type,
|
||||||
{1, 1, 1, 1}, tim::vx::TensorAttribute::TRANSIENT);
|
{1, 1, 1, 1}, tim::vx::TensorAttribute::TRANSIENT, in_quant);
|
||||||
auto sliced_tensor = graph_->CreateTensor(sliced_spec);
|
auto sliced_tensor = graph_->CreateTensor(sliced_spec);
|
||||||
auto one_zero_tensor = graph_->CreateTensor(sliced_spec);
|
auto one_zero_tensor = graph_->CreateTensor(sliced_spec);
|
||||||
auto grad_tensor = graph_->CreateTensor(pool_out_spec_values);
|
auto grad_tensor = graph_->CreateTensor(pool_out_spec_values);
|
||||||
|
|
||||||
std::vector<int32_t> start = {0, 0, 0, 0};
|
std::vector<int32_t> start = {0, 0, 0, 0};
|
||||||
std::vector<int32_t> length = {1, 1, 1, 1};
|
std::vector<int32_t> length = {1, 1, 1, 1};
|
||||||
slice_one_ = graph_->CreateOperation<tim::vx::ops::Slice>(0, start, length);
|
auto slice_one =
|
||||||
(*slice_one_).BindInput(pool_out_values_tensor).BindOutput(sliced_tensor);
|
graph_->CreateOperation<tim::vx::ops::Slice>(0, start, length);
|
||||||
|
(*slice_one).BindInput(pool_out_values_tensor).BindOutput(sliced_tensor);
|
||||||
|
|
||||||
self_sub_ = graph_->CreateOperation<tim::vx::ops::Sub>();
|
auto self_sub = graph_->CreateOperation<tim::vx::ops::Sub>();
|
||||||
(*self_sub_).BindInputs({sliced_tensor, sliced_tensor}).BindOutput(one_zero_tensor);
|
(*self_sub).BindInputs({sliced_tensor, sliced_tensor})
|
||||||
|
.BindOutput(one_zero_tensor);
|
||||||
|
|
||||||
add_zeros_ = graph_->CreateOperation<tim::vx::ops::Add>();
|
auto add_zeros = graph_->CreateOperation<tim::vx::ops::Add>();
|
||||||
(*add_zeros_).BindInputs({one_zero_tensor, in_tensors_[GRADIENT_TENSOR]})
|
(*add_zeros).BindInputs({one_zero_tensor, in_tensors_[GRADIENT_TENSOR]})
|
||||||
.BindOutput(grad_tensor);
|
.BindOutput(grad_tensor);
|
||||||
// eliminate pool out of maxpoolwithargmax end
|
// eliminate pool out of maxpoolwithargmax end
|
||||||
|
|
||||||
flatten_idx_ = graph_->CreateOperation<tim::vx::ops::Reshape>(idx_flattened_shape);
|
auto flatten_idx =
|
||||||
(*flatten_idx_).BindInput(pool_out_indices_tensor).BindOutput(idx_flattened_tensor);
|
graph_->CreateOperation<tim::vx::ops::Reshape>(idx_flattened_shape);
|
||||||
|
(*flatten_idx).BindInput(pool_out_indices_tensor)
|
||||||
|
.BindOutput(idx_flattened_tensor);
|
||||||
|
|
||||||
flatten_upd_ = graph_->CreateOperation<tim::vx::ops::Reshape>(idx_flattened_shape);
|
auto flatten_upd =
|
||||||
(*flatten_upd_).BindInput(grad_tensor).BindOutput(upd_flattened_tensor);
|
graph_->CreateOperation<tim::vx::ops::Reshape>(idx_flattened_shape);
|
||||||
|
(*flatten_upd).BindInput(grad_tensor).BindOutput(upd_flattened_tensor);
|
||||||
|
|
||||||
scatternd_ = graph_->CreateOperation<tim::vx::ops::ScatterND>(out_flattened_shape);
|
auto scatternd =
|
||||||
(*scatternd_).BindInputs({idx_flattened_tensor, upd_flattened_tensor})
|
graph_->CreateOperation<tim::vx::ops::ScatterND>(out_flattened_shape);
|
||||||
.BindOutput(out_flattened_tensor);
|
(*scatternd).BindInputs({idx_flattened_tensor, upd_flattened_tensor})
|
||||||
|
.BindOutput(out_flattened_tensor);
|
||||||
|
|
||||||
reshape_like_input_ = graph_->CreateOperation<tim::vx::ops::Reshape>(in_shape);
|
reshape_like_input_ =
|
||||||
|
graph_->CreateOperation<tim::vx::ops::Reshape>(in_shape);
|
||||||
(*reshape_like_input_).BindInput(out_flattened_tensor);
|
(*reshape_like_input_).BindInput(out_flattened_tensor);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -150,14 +163,7 @@ class MaxpoolGradImpl : public OpImpl {
|
||||||
const RoundType round_type_;
|
const RoundType round_type_;
|
||||||
|
|
||||||
std::shared_ptr<tim::vx::Operation> maxpoolwithargmax2_;
|
std::shared_ptr<tim::vx::Operation> maxpoolwithargmax2_;
|
||||||
std::shared_ptr<tim::vx::Operation> slice_one_;
|
|
||||||
std::shared_ptr<tim::vx::Operation> self_sub_;
|
|
||||||
std::shared_ptr<tim::vx::Operation> add_zeros_;
|
|
||||||
std::shared_ptr<tim::vx::Operation> flatten_idx_;
|
|
||||||
std::shared_ptr<tim::vx::Operation> flatten_upd_;
|
|
||||||
std::shared_ptr<tim::vx::Operation> scatternd_;
|
|
||||||
std::shared_ptr<tim::vx::Operation> reshape_like_input_;
|
std::shared_ptr<tim::vx::Operation> reshape_like_input_;
|
||||||
std::shared_ptr<tim::vx::Operation> reshape_pool_output_;
|
|
||||||
std::array<std::shared_ptr<tim::vx::Tensor>, INPUT_CNT> in_tensors_;
|
std::array<std::shared_ptr<tim::vx::Tensor>, INPUT_CNT> in_tensors_;
|
||||||
std::array<std::shared_ptr<tim::vx::Tensor>, OUTPUT_CNT> out_tensors_;
|
std::array<std::shared_ptr<tim::vx::Tensor>, OUTPUT_CNT> out_tensors_;
|
||||||
uint32_t CalFlattenedShape(const tim::vx::ShapeType& shape) {
|
uint32_t CalFlattenedShape(const tim::vx::ShapeType& shape) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue