diff --git a/include/tim/vx/ops/simple_operations.h b/include/tim/vx/ops/simple_operations.h index 7e11324..514ae3a 100644 --- a/include/tim/vx/ops/simple_operations.h +++ b/include/tim/vx/ops/simple_operations.h @@ -90,6 +90,9 @@ namespace ops { * * Change the format from input tensor to output tensor. This operation ignores * the scale and zeroPoint of quanized tensors. + * + * ## Rcp + * Computes the reciprocal of input element-wise. */ DECLARE_SIMPLE_OP(DataConvert) @@ -108,6 +111,7 @@ DECLARE_SIMPLE_OP(Floor) DECLARE_SIMPLE_OP(Ceil) DECLARE_SIMPLE_OP(Round) DECLARE_SIMPLE_OP(Cast) +DECLARE_SIMPLE_OP(Rcp) #undef DECLARE_SIMPLE_OP diff --git a/src/tim/vx/ops/README.md b/src/tim/vx/ops/README.md index dc29cb5..295b214 100644 --- a/src/tim/vx/ops/README.md +++ b/src/tim/vx/ops/README.md @@ -116,6 +116,7 @@ GroupedConv1d|GROUPED_CONV1D|Mapped|[tf.keras.layers.Conv1D](https://tensorflow. Mod|MOD|Mapped|[Onnx.mod](https://github.com/onnx/onnx/blob/main/docs/Operators.md#Mod) Selu|SELU|Mapped|[tf.keras.activations.selu](https://www.tensorflow.org/api_docs/python/tf/keras/activations/selu) Celu|CELU|Mapped|[Onnx.celu](https://github.com/onnx/onnx/blob/main/docs/Operators.md#Celu) +Rcp|RCP|Mapped|[tf.math.reciprocal](https://www.tensorflow.org/api_docs/python/tf/math/reciprocal) |UnidirectionalSequenceRNN|UNIDIRECTIONAL_SEQUENCE_RNN|Planned 22Q3|[ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_RNN](https://developer.android.com/ndk/reference/group/neural-networks#group___neural_networks_1ggaabbe492c60331b13038e39d4207940e0ae11aa1d461d2abaa117f6ee2cb503dd8) |BidirectionalSequenceRNN|BIDIRECTIONAL_SEQUENCE_RNN|Planned 22Q3|[ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_RNN](https://developer.android.com/ndk/reference/group/neural-networks#group___neural_networks_1ggaabbe492c60331b13038e39d4207940e0a487fc5ae247de828f13e62b99f259f3c) |BidirectionalSequenceLSTM|BIDIRECTIONAL_SEQUENCE_LSTM|Mapped|[ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_LSTM](https://developer.android.com/ndk/reference/group/neural-networks#group___neural_networks_1ggaabbe492c60331b13038e39d4207940e0a492a71cb7aa50b9a1a834a3cb269d778) diff --git a/src/tim/vx/ops/simple_operations.cc b/src/tim/vx/ops/simple_operations.cc index 4a3b8ba..08636cf 100644 --- a/src/tim/vx/ops/simple_operations.cc +++ b/src/tim/vx/ops/simple_operations.cc @@ -52,6 +52,7 @@ DEFINE_SIMPLE_OP(Floor, VSI_NN_OP_FLOOR) DEFINE_SIMPLE_OP(Ceil, VSI_NN_OP_CEIL) DEFINE_SIMPLE_OP(Round, VSI_NN_OP_ROUND) DEFINE_SIMPLE_OP(Cast, VSI_NN_OP_CAST) +DEFINE_SIMPLE_OP(Rcp, VSI_NN_OP_RCP) #undef DEFINE_SIMPLE_OP diff --git a/src/tim/vx/ops/simple_operations_test.cc b/src/tim/vx/ops/simple_operations_test.cc index 6c4828c..efadec6 100644 --- a/src/tim/vx/ops/simple_operations_test.cc +++ b/src/tim/vx/ops/simple_operations_test.cc @@ -24,6 +24,7 @@ #include "tim/vx/context.h" #include "tim/vx/graph.h" #include "tim/vx/ops/simple_operations.h" +#include "test_utils.h" #include "gtest/gtest.h" #include @@ -232,4 +233,32 @@ TEST(DataConvert, requantize_shape_2_3_asym_u8) { std::vector output(6, 0); EXPECT_TRUE(output_tensor->CopyDataFromTensor(output.data())); EXPECT_EQ(golden, output); +} + +TEST(Rcp, shape_5_1_fp32) { + auto ctx = tim::vx::Context::Create(); + auto graph = ctx->CreateGraph(); + + tim::vx::ShapeType io_shape({5, 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_tensor = graph->CreateTensor(input_spec); + auto output_tensor = graph->CreateTensor(output_spec); + + std::vector in_data = { -2.5, -0.1, 0, 0.55, std::numeric_limits::infinity() }; + std::vector golden = {-0.4, -10, std::numeric_limits::infinity(), 1.81818, 0.}; + + EXPECT_TRUE(input_tensor->CopyDataToTensor(in_data.data(), in_data.size()*4)); + + auto add = graph->CreateOperation(); + (*add).BindInputs({input_tensor}).BindOutputs({output_tensor}); + + EXPECT_TRUE(graph->Compile()); + EXPECT_TRUE(graph->Run()); + std::vector output(5, 0); + EXPECT_TRUE(output_tensor->CopyDataFromTensor(output.data())); + EXPECT_TRUE(ArraysMatch(golden, output, 1e-5f)); } \ No newline at end of file diff --git a/src/tim/vx/test_utils.h b/src/tim/vx/test_utils.h index f2493eb..a06d312 100644 --- a/src/tim/vx/test_utils.h +++ b/src/tim/vx/test_utils.h @@ -115,7 +115,11 @@ template const std::vector& actual, T abs_error){ for (size_t i = 0; i < expected.size(); ++i){ - EXPECT_NEAR(expected[i], actual[i], abs_error) << "at index:" << i; + // If expected and actual are INF, "==" operation will return true while EXPEC_NEAR return false + if (expected[i] == actual[i]) continue; + else { + EXPECT_NEAR(expected[i], actual[i], abs_error) << "at index:" << i; + } } return ::testing::AssertionSuccess();