From 9d44b4477b71748220334f031fffeeb878eba69e Mon Sep 17 00:00:00 2001 From: "xiang.zhang" Date: Fri, 19 Feb 2021 17:53:24 +0800 Subject: [PATCH] Added NBG support Signed-off-by: xiang.zhang --- BUILD.bazel | 13 ++++ WORKSPACE | 17 +++++ include/tim/vx/context.h | 6 +- include/tim/vx/graph.h | 9 ++- include/tim/vx/ops/l2normalization.h | 2 +- include/tim/vx/ops/nbg.h | 41 +++++++++++++ include/tim/vx/tensor.h | 9 ++- src/tim/vx/context.cc | 1 - src/tim/vx/context_private.h | 4 +- src/tim/vx/context_test.cc | 32 ++++++++++ src/tim/vx/graph.cc | 44 +++++++++---- src/tim/vx/graph_private.h | 30 +++++---- src/tim/vx/graph_test.cc | 92 ++++++++++++++++++++++++++++ src/tim/vx/ops/nbg.cc | 38 ++++++++++++ 14 files changed, 305 insertions(+), 33 deletions(-) create mode 100644 include/tim/vx/ops/nbg.h create mode 100644 src/tim/vx/context_test.cc create mode 100644 src/tim/vx/graph_test.cc create mode 100644 src/tim/vx/ops/nbg.cc diff --git a/BUILD.bazel b/BUILD.bazel index 17f39de..726002a 100644 --- a/BUILD.bazel +++ b/BUILD.bazel @@ -49,3 +49,16 @@ cc_binary( ], ) +############################################################################## +# unit test +############################################################################## +cc_test ( + name = "unit_test", + copts = ["-std=c++14", "-Werror"], + srcs = glob(["src/tim/vx/*_test.cc"]), + deps = [ + "@gtest//:gtest", + "@gtest//:gtest_main", + ":tim-vx_interface", + ] +) diff --git a/WORKSPACE b/WORKSPACE index 20478de..d34a04c 100644 --- a/WORKSPACE +++ b/WORKSPACE @@ -2,6 +2,9 @@ workspace(name = "TIM_VX") load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") +############################################################################## +# Toolchains +############################################################################## http_archive( name = "aarch64_A311D", build_file = "@//prebuilt-sdk/x86_64_linux:BUILD", @@ -19,3 +22,17 @@ local_repository( load("@TOOLCHAINS//:toolchains.bzl", "init_toolchains") init_toolchains() + +############################################################################## +#Third party repositories +############################################################################## +http_archive( + name = "gtest", + sha256 = "ff7a82736e158c077e76188232eac77913a15dac0b22508c390ab3f88e6d6d86", + strip_prefix = "googletest-b6cd405286ed8635ece71c72f118e659f4ade3fb", + urls = [ + "https://storage.googleapis.com/mirror.tensorflow.org/github.com/google/googletest/archive/b6cd405286ed8635ece71c72f118e659f4ade3fb.zip", + "https://github.com/google/googletest/archive/b6cd405286ed8635ece71c72f118e659f4ade3fb.zip", + ], +) + diff --git a/include/tim/vx/context.h b/include/tim/vx/context.h index 897bfc8..578f7ce 100644 --- a/include/tim/vx/context.h +++ b/include/tim/vx/context.h @@ -26,11 +26,11 @@ #include -#include "tim/vx/graph.h" - namespace tim { namespace vx { +class Graph; + class Context { public: virtual ~Context() {} @@ -41,4 +41,4 @@ class Context { } // namespace vx } // namespace tim -#endif /* TIM_VX_CONTEXT_H_ */ \ No newline at end of file +#endif /* TIM_VX_CONTEXT_H_ */ diff --git a/include/tim/vx/graph.h b/include/tim/vx/graph.h index 8ff8e5e..cd17ef0 100644 --- a/include/tim/vx/graph.h +++ b/include/tim/vx/graph.h @@ -27,11 +27,12 @@ #include #include -#include "tim/vx/tensor.h" - namespace tim { namespace vx { +class Tensor; +class TensorSpec; + class Graph { public: virtual ~Graph() {} @@ -46,7 +47,9 @@ class Graph { /// Freeze graph virtual bool Compile() = 0; - /// Process the compiled graph + /// Compile to BinaryGraph + virtual bool CompileToBinary(void* buf, size_t* size) = 0; + virtual bool Run() = 0; template diff --git a/include/tim/vx/ops/l2normalization.h b/include/tim/vx/ops/l2normalization.h index 8455f91..33fa792 100644 --- a/include/tim/vx/ops/l2normalization.h +++ b/include/tim/vx/ops/l2normalization.h @@ -39,4 +39,4 @@ class L2Normalization : public Operation { } // namespace ops } // namespace vx } // namespace tim -#endif \ No newline at end of file +#endif diff --git a/include/tim/vx/ops/nbg.h b/include/tim/vx/ops/nbg.h new file mode 100644 index 0000000..63805a6 --- /dev/null +++ b/include/tim/vx/ops/nbg.h @@ -0,0 +1,41 @@ +/**************************************************************************** +* +* Copyright (c) 2020 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_VX_OPS_NBG_H_ +#define TIM_VX_OPS_NBG_H_ +#include "tim/vx/operation.h" + +namespace tim { +namespace vx { +namespace ops { + +class NBG : public Operation { + public: + NBG(Graph* graph, const char* binary, size_t input_count, size_t output_count); + +}; + +} // namespace ops +} // namespace vx +} // namespace tim +#endif diff --git a/include/tim/vx/tensor.h b/include/tim/vx/tensor.h index a27802e..26fc04b 100644 --- a/include/tim/vx/tensor.h +++ b/include/tim/vx/tensor.h @@ -90,6 +90,13 @@ struct TensorSpec { this->quantization_ = quantization; } + TensorSpec(const TensorSpec& other) { + this->datatype_ = other.datatype_; + this->shape_ = other.shape_; + this->attr_ = other.attr_; + this->quantization_ = other.quantization_; + } + TensorSpec& SetDataType(DataType datatype) { this->datatype_ = datatype; return *this; @@ -138,4 +145,4 @@ class Tensor { } // namespace vx } // namespace tim -#endif /* TIM_VX_TENSOR_H_ */ \ No newline at end of file +#endif /* TIM_VX_TENSOR_H_ */ diff --git a/src/tim/vx/context.cc b/src/tim/vx/context.cc index df8b694..a030083 100644 --- a/src/tim/vx/context.cc +++ b/src/tim/vx/context.cc @@ -48,6 +48,5 @@ std::shared_ptr Context::Create() { std::shared_ptr ContextImpl::CreateGraph() { return std::make_shared(this); } - } // namespace vx } // namespace tim \ No newline at end of file diff --git a/src/tim/vx/context_private.h b/src/tim/vx/context_private.h index 23b2807..ea6644c 100644 --- a/src/tim/vx/context_private.h +++ b/src/tim/vx/context_private.h @@ -34,8 +34,8 @@ class ContextImpl : public Context { ContextImpl(); ~ContextImpl(); vsi_nn_context_t context(); - std::shared_ptr CreateGraph(); - + std::shared_ptr CreateGraph() override; + protected: vsi_nn_context_t context_; }; diff --git a/src/tim/vx/context_test.cc b/src/tim/vx/context_test.cc new file mode 100644 index 0000000..75fcd48 --- /dev/null +++ b/src/tim/vx/context_test.cc @@ -0,0 +1,32 @@ +/**************************************************************************** +* +* Copyright (c) 2020 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. +* +*****************************************************************************/ +#include "tim/vx/context.h" +#include "gtest/gtest.h" + +TEST(Context, create) { + auto ctx0 = tim::vx::Context::Create(); + {auto ctx0 = tim::vx::Context::Create();} + auto ctx1 = tim::vx::Context::Create(); + // EXPECT_TRUE(0); +} \ No newline at end of file diff --git a/src/tim/vx/graph.cc b/src/tim/vx/graph.cc index c9852f7..72986ab 100644 --- a/src/tim/vx/graph.cc +++ b/src/tim/vx/graph.cc @@ -28,7 +28,10 @@ #include "context_private.h" #include "graph_private.h" #include "tensor_private.h" +#include "operation_private.h" + #include "tim/vx/context.h" +#include "tim/vx/ops/nbg.h" #include "vsi_nn_pub.h" namespace tim { @@ -37,8 +40,7 @@ namespace vx { GraphImpl::GraphImpl(ContextImpl* context) : context_(context), graph_(vsi_nn_CreateGraph(context_->context(), 0, 0)), - tensor_placeholder_(nullptr), - compiled_(false) {} + tensor_placeholder_(nullptr) {} GraphImpl::~GraphImpl() { vsi_nn_ReleaseGraph(&graph_); } @@ -70,20 +72,40 @@ std::shared_ptr GraphImpl::CreateTensorPlaceHolder() { } bool GraphImpl::Compile() { - compiled_ = true; + bool status = true; - vsi_nn_SetGraphInputs(graph_, inputs_.data(), inputs_.size()); - vsi_nn_SetGraphOutputs(graph_, outputs_.data(), outputs_.size()); + std::call_once(setio_once_, [&status, this]() { + status = (vsi_nn_SetGraphInputs(this->graph_, this->inputs_.data(), this->inputs_.size()) && + vsi_nn_SetGraphOutputs(this->graph_, this->outputs_.data(), this->outputs_.size())); + }); - return (VSI_SUCCESS == vsi_nn_SetupGraph(graph_, true) && - VSI_SUCCESS == vsi_nn_VerifyGraph(graph_)); + std::call_once(setup_once_, [&status, this](){ + status = (VSI_SUCCESS == vsi_nn_SetupGraph(this->graph_, true)); + }); + + std::call_once(verify_graph_once_, [&status, this]() { + status = (VSI_SUCCESS == vsi_nn_VerifyGraph(this->graph_)); + }); + + return status; +} + +bool GraphImpl::CompileToBinary(void* buf, size_t* size) { + bool status = true; + std::call_once(setio_once_, [&status, this]() { + status = (vsi_nn_SetGraphInputs(this->graph_, this->inputs_.data(), this->inputs_.size()) && + vsi_nn_SetGraphOutputs(this->graph_,this->outputs_.data(), this->outputs_.size())); + }); + + std::call_once(setup_once_, [&status, this](){ + status = (VSI_SUCCESS == vsi_nn_SetupGraph(this->graph_, true)); + }); + + return ((status) && (VSI_SUCCESS == vsi_nn_GenerateNBG(graph_, buf, size))); } bool GraphImpl::Run() { - if (!compiled_ && !Compile()) { - return false; - } - return (VSI_SUCCESS == vsi_nn_RunGraph(graph_)); + return ((Compile()) && (VSI_SUCCESS == vsi_nn_RunGraph(graph_))); } } // namespace vx diff --git a/src/tim/vx/graph_private.h b/src/tim/vx/graph_private.h index e4e2820..1ef0871 100644 --- a/src/tim/vx/graph_private.h +++ b/src/tim/vx/graph_private.h @@ -23,10 +23,15 @@ *****************************************************************************/ #ifndef TIM_VX_GRAPH_PRIVATE_H_ #define TIM_VX_GRAPH_PRIVATE_H_ -#include - -#include "context_private.h" #include "tim/vx/graph.h" + +#include +#include +#include + +#include "tim/vx/tensor.h" +#include "context_private.h" + #include "vsi_nn_pub.h" namespace tim { @@ -39,22 +44,25 @@ class GraphImpl : public Graph { /// Return the low-level graph object vsi_nn_graph_t* graph(); - void AddInput(vsi_nn_tensor_id_t id); void AddOutput(vsi_nn_tensor_id_t id); - + /// Implement parents' virtual functions - std::shared_ptr CreateTensor(const TensorSpec& spec, - const void* data = nullptr); - std::shared_ptr CreateTensorPlaceHolder(); - bool Compile(); - bool Run(); + std::shared_ptr CreateTensor(const TensorSpec& spec, + const void* data = nullptr) override; + std::shared_ptr CreateTensorPlaceHolder() override; + bool Compile() override; + + bool CompileToBinary(void* buf, size_t* size) override; + bool Run() override; protected: ContextImpl* context_; vsi_nn_graph_t* graph_; std::shared_ptr tensor_placeholder_; - bool compiled_; + std::once_flag setio_once_; + std::once_flag setup_once_; + std::once_flag verify_graph_once_; std::vector inputs_; std::vector outputs_; }; diff --git a/src/tim/vx/graph_test.cc b/src/tim/vx/graph_test.cc new file mode 100644 index 0000000..b56280d --- /dev/null +++ b/src/tim/vx/graph_test.cc @@ -0,0 +1,92 @@ +/**************************************************************************** +* +* Copyright (c) 2020 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. +* +*****************************************************************************/ +#include "tim/vx/context.h" +#include "tim/vx/graph.h" +#include "tim/vx/ops/elementwise.h" +#include "tim/vx/ops/nbg.h" + +#include "gtest/gtest.h" + +#include + +TEST(graph, gen_binary_graph_with_empty_graph) { + auto ctx = tim::vx::Context::Create(); + auto graph = ctx->CreateGraph(); + + size_t bin_size = -1; + EXPECT_FALSE(graph->CompileToBinary(nullptr, &bin_size)) << "Can not generate binary graph if it is empty"; +} + +TEST(graph, gen_binary_graph_with_simple_add) { + auto ctx = tim::vx::Context::Create(); + auto graph = ctx->CreateGraph(); + + tim::vx::ShapeType io_shape({1,1,1,1}); + tim::vx::TensorSpec input_spec(tim::vx::DataType::FLOAT32, io_shape, tim::vx::TensorAttribute::INPUT); + tim::vx::TensorSpec output_spec(tim::vx::DataType::FLOAT32, io_shape, tim::vx::TensorAttribute::OUTPUT); + auto input_t0 = graph->CreateTensor(input_spec); + auto input_t1 = graph->CreateTensor(input_spec); + auto output_t = graph->CreateTensor(output_spec); + + float in = 1.0f; + float expected_out = 2.0f; + + EXPECT_TRUE(input_t0->CopyDataToTensor(&in, sizeof(in))); + EXPECT_TRUE(input_t1->CopyDataToTensor(&in, sizeof(in))); + + auto add = graph->CreateOperation(); + (*add).BindInputs({input_t0, input_t1}).BindOutputs({output_t}); + + size_t bin_size = -1; + EXPECT_TRUE(graph->CompileToBinary(nullptr, &bin_size)); + EXPECT_NE(bin_size, -1); + std::vector nbg_buf(bin_size); + + EXPECT_TRUE(graph->CompileToBinary(nbg_buf.data(), &bin_size)); + + // binary graph compilation doesn't impact current graph's execution + EXPECT_TRUE(graph->Run()); + float output = 0.0f; + EXPECT_TRUE(output_t->CopyDataFromTensor(&output)); + EXPECT_EQ(output, expected_out); + + auto nbg_graph = ctx->CreateGraph(); + auto nbg_in0 = nbg_graph->CreateTensor(input_spec); + auto nbg_in1 = nbg_graph->CreateTensor(input_spec); + auto nbg_out = nbg_graph->CreateTensor(output_spec); + + EXPECT_TRUE(nbg_in0->CopyDataToTensor(&in, sizeof(in))); + EXPECT_TRUE(nbg_in1->CopyDataToTensor(&in, sizeof(in))); + + auto nbg_node = nbg_graph->CreateOperation( + (nbg_buf.data()), /*num_of_input*/ 2, + /*num_of_output*/ 1); + (*nbg_node).BindInputs({nbg_in0, nbg_in1}).BindOutputs({output_t}); + EXPECT_TRUE(nbg_graph->Compile()); + EXPECT_TRUE(nbg_graph->Run()); + + output=0.0f; + EXPECT_TRUE(nbg_out->CopyDataFromTensor(&output)); + EXPECT_EQ(output, expected_out); +} \ No newline at end of file diff --git a/src/tim/vx/ops/nbg.cc b/src/tim/vx/ops/nbg.cc new file mode 100644 index 0000000..1e60359 --- /dev/null +++ b/src/tim/vx/ops/nbg.cc @@ -0,0 +1,38 @@ +/**************************************************************************** +* +* Copyright (c) 2020 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. +* +*****************************************************************************/ +#include "tim/vx/ops/nbg.h" + +#include "operation_private.h" +#include "vsi_nn_pub.h" + +namespace tim { +namespace vx { +namespace ops { + NBG::NBG(Graph* graph, const char* binary, size_t input_count, size_t output_count) : Operation(graph, VSI_NN_OP_NBG, input_count, output_count) { + this->impl()->node()->nn_param.nbg.url = binary; + this->impl()->node()->nn_param.nbg.type = VSI_NN_NBG_POINTER; + } +} // namespace ops +} // namespace vx +} // namespace tim \ No newline at end of file