diff --git a/include/tim/vx/ops/broadcast.h b/include/tim/vx/ops/broadcast.h index 404ba71c3..48b4ed238 100644 --- a/include/tim/vx/ops/broadcast.h +++ b/include/tim/vx/ops/broadcast.h @@ -24,7 +24,7 @@ #ifndef OVXLIBXX_OPERATIONS_BROADCAST_H_ #define OVXLIBXX_OPERATIONS_BROADCAST_H_ #include "tim/vx/builtin_op.h" - +#define BROADCAST_OPVERSION 1 namespace tim { namespace vx { namespace ops { @@ -45,12 +45,12 @@ namespace ops { class Broadcast : public BuiltinOp { public: - Broadcast(Graph* graph, const std::vector& shape, const std::vector& dimensions = {}); + Broadcast(Graph* graph, const std::vector& shape, const std::vector& dimensions = {}); std::shared_ptr Clone(std::shared_ptr& graph) const override; - protected: - const std::vector shape_; + protected: + std::vector shape_; std::vector dimensions_; }; diff --git a/src/tim/vx/ops/broadcast.cc b/src/tim/vx/ops/broadcast.cc index 98d739734..0592bf947 100644 --- a/src/tim/vx/ops/broadcast.cc +++ b/src/tim/vx/ops/broadcast.cc @@ -30,23 +30,24 @@ namespace tim { namespace vx { namespace ops { -Broadcast::Broadcast(Graph* graph, const std::vector& shape, +Broadcast::Broadcast(Graph* graph, const std::vector & shape, const std::vector& dimensions) : BuiltinOp(graph, VSI_NN_OP_EXPAND_BROADCAST), shape_(shape), dimensions_(dimensions) { this->impl()->node()->nn_param.expand_broadcast.dim_num = shape_.size(); - this->impl()->node()->nn_param.expand_broadcast.shape = (uint32_t*)shape_.data(); + this->impl()->node()->nn_param.expand_broadcast.shape = shape_.data(); #ifdef VSI_EXPAND_BROADCAST_ENABLE_DIMENSIONS this->impl()->node()->nn_param.expand_broadcast.dimensions_num = dimensions_.size(); if (dimensions.size() > 0) { - int dim_num = shape.size(); - for (uint32_t i = 0; i < dimensions.size(); ++i) { - dimensions_[i] += (dimensions[i] < 0 ? dim_num : 0U); + for (uint32_t i = 0; i < dimensions.size(); i++) + { + dimensions_[i] += (dimensions[i] < 0 ? shape_.size() : 0U ); } this->impl()->node()->nn_param.expand_broadcast.dimensions = (uint32_t*)dimensions_.data(); - } else { + } else + { this->impl()->node()->nn_param.expand_broadcast.dimensions = nullptr; } #endif diff --git a/src/tim/vx/ops/broadcast_test.cc b/src/tim/vx/ops/broadcast_test.cc index 759a32807..6668edd1d 100644 --- a/src/tim/vx/ops/broadcast_test.cc +++ b/src/tim/vx/ops/broadcast_test.cc @@ -62,7 +62,7 @@ TEST(Broadcast, ScalarTo2D_2x3) { std::vector golden = { 2.25f, 2.25f, 2.25f, 2.25f, 2.25f, 2.25f, }; - std::vector shape = {3, 2}; + std::vector shape = {3, 2}; EXPECT_TRUE(input_tensor->CopyDataToTensor(in_data.data(), in_data.size() * sizeof(float))); @@ -93,7 +93,7 @@ TEST(Broadcast, 1DTo2D) { std::vector golden = { 1.f, 2.f, 3.f, 1.f, 2.f, 3.f, }; - std::vector shape = {3, 2}; + std::vector shape = {3, 2}; EXPECT_TRUE(input_tensor->CopyDataToTensor(in_data.data(), in_data.size() * sizeof(float))); @@ -125,7 +125,7 @@ TEST(Broadcast, 1DTo2D_WithDims0) { 1.f, 2.f, 1.f, 2.f, }; - std::vector shape = {2, 2}; + std::vector shape = {2, 2}; std::vector dimensions = {0}; EXPECT_TRUE(input_tensor->CopyDataToTensor(in_data.data(), @@ -158,7 +158,7 @@ TEST(Broadcast, 1DTo2D_WithDims1) { 1.f, 1.f, 2.f, 2.f, }; - std::vector shape = {2, 2}; + std::vector shape = {2, 2}; std::vector dimensions = {1}; EXPECT_TRUE(input_tensor->CopyDataToTensor(in_data.data(), @@ -170,6 +170,44 @@ TEST(Broadcast, 1DTo2D_WithDims1) { CheckResult(graph, golden, output_tensor); } +TEST(Broadcast, 1DTo2D_WithDimsMinus2) { + auto ctx = tim::vx::Context::Create(); + auto graph = ctx->CreateGraph(); + + tim::vx::ShapeType input_shape({3}); + tim::vx::ShapeType output_shape({3, 2}); + tim::vx::TensorSpec input_spec(tim::vx::DataType::FLOAT32, input_shape, + tim::vx::TensorAttribute::INPUT); + tim::vx::TensorSpec output_spec(tim::vx::DataType::FLOAT32, output_shape, + tim::vx::TensorAttribute::OUTPUT); + + auto input_tensor = graph->CreateTensor(input_spec); + auto output_tensor = graph->CreateTensor(output_spec); + + std::vector in_data = { + 1.f, 2.f, 3.f + }; + std::vector golden = { + 1.f, 2.f, 3.f, + 1.f, 2.f, 3.f + }; + std::vector shape = {3, 2}; + std::vector dimensions = {-2}; + EXPECT_TRUE(input_tensor->CopyDataToTensor(in_data.data(), + in_data.size() * sizeof(float))); + + auto op = graph->CreateOperation(shape, dimensions); + (*op).BindInputs({input_tensor}).BindOutputs({output_tensor}); + + + EXPECT_TRUE(graph->Compile()); + EXPECT_TRUE(graph->Run()); + + std::vector output(golden.size()); + EXPECT_TRUE(output_tensor->CopyDataFromTensor(output.data())); + EXPECT_EQ(golden, output); +} + TEST(Broadcast, 1DTo3D_WithDims0) { auto ctx = tim::vx::Context::Create(); auto graph = ctx->CreateGraph(); @@ -190,7 +228,7 @@ TEST(Broadcast, 1DTo3D_WithDims0) { std::vector golden = { 1.f, 2.f, 1.f, 2.f, 1.f, 2.f, 1.f, 2.f, }; - std::vector shape = {2, 2, 2}; + std::vector shape = {2, 2, 2}; std::vector dimensions = {0}; EXPECT_TRUE(input_tensor->CopyDataToTensor(in_data.data(), @@ -222,7 +260,7 @@ TEST(Broadcast, 1DTo3D_WithDims1) { std::vector golden = { 1.f, 1.f, 2.f, 2.f, 1.f, 1.f, 2.f, 2.f, }; - std::vector shape = {2, 2, 2}; + std::vector shape = {2, 2, 2}; std::vector dimensions = {1}; EXPECT_TRUE(input_tensor->CopyDataToTensor(in_data.data(), @@ -254,7 +292,7 @@ TEST(Broadcast, 1DTo3D_WithDims2) { std::vector golden = { 1.f, 1.f, 1.f, 1.f, 2.f, 2.f, 2.f, 2.f, }; - std::vector shape = {2, 2, 2}; + std::vector shape = {2, 2, 2}; std::vector dimensions = {2}; EXPECT_TRUE(input_tensor->CopyDataToTensor(in_data.data(), @@ -286,7 +324,7 @@ TEST(Broadcast, 2DTo3D_WithDims02) { std::vector golden = { 1.f, 5.f, 1.f, 5.f, 2.f, 6.f, 2.f, 6.f, }; - std::vector shape = {2, 2, 2}; + std::vector shape = {2, 2, 2}; std::vector dimensions = {0, 2}; EXPECT_TRUE(input_tensor->CopyDataToTensor(in_data.data(), @@ -318,7 +356,7 @@ TEST(Broadcast, 2DTo3D_WithDims12) { std::vector golden = { 1.f, 1.f, 5.f, 5.f, 2.f, 2.f, 6.f, 6.f, }; - std::vector shape = {2, 2, 2}; + std::vector shape = {2, 2, 2}; std::vector dimensions = {1, 2}; EXPECT_TRUE(input_tensor->CopyDataToTensor(in_data.data(),