diff --git a/include/tim/vx/ops/activations.h b/include/tim/vx/ops/activations.h index 8b0366a..b5b2ba7 100644 --- a/include/tim/vx/ops/activations.h +++ b/include/tim/vx/ops/activations.h @@ -48,7 +48,7 @@ namespace ops { * Sigmoid(x) : 1/(1 + e^{-x}) * * Swish(x) : x * sigmoid(x) - * + * * HardSwish(x) : 0 if x <= -3; x(x + 3)/6 if -3 < x < 3; x if x >= 3 * * Mish(x) : x if x >= 0 else alpha * x @@ -122,9 +122,13 @@ class Linear : public Operation { }; class Gelu : public Operation { - public: - explicit Gelu(Graph* graph, bool approximate = false); - std::shared_ptr Clone( + public: + /**************************************************************************** + *Non-approximate calculations will also have errors when the data type is + *fp32, it is recommended to use the approximate option. + ****************************************************************************/ + explicit Gelu(Graph* graph, bool approximate = true); + std::shared_ptr Clone( std::shared_ptr& graph) const override; }; diff --git a/src/tim/vx/ops/activations_test.cc b/src/tim/vx/ops/activations_test.cc index a920db3..5cde1e7 100644 --- a/src/tim/vx/ops/activations_test.cc +++ b/src/tim/vx/ops/activations_test.cc @@ -29,181 +29,152 @@ #include "src/tim/vx/test_utils.h" TEST(Linear, shape_5_1_fp32) { - auto ctx = tim::vx::Context::Create(); - auto graph = ctx->CreateGraph(); + 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); + 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); + 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.5, 1.9, 2, 2.55, std::numeric_limits::infinity() }; + std::vector in_data = {-2.5, -0.1, 0, 0.55, + std::numeric_limits::infinity()}; + std::vector golden = {-0.5, 1.9, 2, 2.55, + std::numeric_limits::infinity()}; - EXPECT_TRUE(input_tensor->CopyDataToTensor(in_data.data(), in_data.size()*4)); + EXPECT_TRUE( + input_tensor->CopyDataToTensor(in_data.data(), in_data.size() * 4)); - auto op = graph->CreateOperation(1, 2); - (*op).BindInputs({input_tensor}).BindOutputs({output_tensor}); + auto op = graph->CreateOperation(1, 2); + (*op).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_EQ(golden, output); + EXPECT_TRUE(graph->Compile()); + EXPECT_TRUE(graph->Run()); + std::vector output(5, 0); + EXPECT_TRUE(output_tensor->CopyDataFromTensor(output.data())); + EXPECT_EQ(golden, output); } TEST(Linear, shape_5_1_fp32_omit_b) { - auto ctx = tim::vx::Context::Create(); - auto graph = ctx->CreateGraph(); + 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); + 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); + 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 = {-5.0, -0.2, 0, 1.1, std::numeric_limits::infinity() }; + std::vector in_data = {-2.5, -0.1, 0, 0.55, + std::numeric_limits::infinity()}; + std::vector golden = {-5.0, -0.2, 0, 1.1, + std::numeric_limits::infinity()}; - EXPECT_TRUE(input_tensor->CopyDataToTensor(in_data.data(), in_data.size()*4)); + EXPECT_TRUE( + input_tensor->CopyDataToTensor(in_data.data(), in_data.size() * 4)); - auto op = graph->CreateOperation(2); - (*op).BindInputs({input_tensor}).BindOutputs({output_tensor}); + auto op = graph->CreateOperation(2); + (*op).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_EQ(golden, output); -} - -TEST(Gelu, shape_5_1_fp32) { - auto ctx = tim::vx::Context::Create(); - auto graph = ctx->CreateGraph(); - - tim::vx::ShapeType in_shape({5, 1}); - tim::vx::ShapeType out_shape({5, 1}); - tim::vx::TensorSpec in_spec(tim::vx::DataType::FLOAT32, - in_shape, tim::vx::TensorAttribute::INPUT); - tim::vx::TensorSpec out_spec(tim::vx::DataType::FLOAT32, - out_shape, tim::vx::TensorAttribute::OUTPUT); - - auto in_tensor = graph->CreateTensor(in_spec); - auto out_tensor = graph->CreateTensor(out_spec); - - std::vector in_data = { - -3, -1, 0, 1, 3 - }; - std::vector golden = { - -0.00404951, -0.15865529, 0, 0.8413447, 2.9959507 - }; - - EXPECT_TRUE(in_tensor->CopyDataToTensor(in_data.data(), in_data.size() * sizeof(float))); - auto op = graph->CreateOperation(false); - (*op).BindInput(in_tensor).BindOutput(out_tensor); - - EXPECT_TRUE(graph->Compile()); - EXPECT_TRUE(graph->Run()); - - std::vector output(golden.size()); - EXPECT_TRUE(out_tensor->CopyDataFromTensor(output.data())); - EXPECT_TRUE(ArraysMatch(golden, output, 1e-5f)); + EXPECT_TRUE(graph->Compile()); + EXPECT_TRUE(graph->Run()); + std::vector output(5, 0); + EXPECT_TRUE(output_tensor->CopyDataFromTensor(output.data())); + EXPECT_EQ(golden, output); } TEST(Gelu, shape_5_1_fp32_approximate) { - auto ctx = tim::vx::Context::Create(); - auto graph = ctx->CreateGraph(); + auto ctx = tim::vx::Context::Create(); + auto graph = ctx->CreateGraph(); - tim::vx::ShapeType in_shape({5, 1}); - tim::vx::ShapeType out_shape({5, 1}); - tim::vx::TensorSpec in_spec(tim::vx::DataType::FLOAT32, - in_shape, tim::vx::TensorAttribute::INPUT); - tim::vx::TensorSpec out_spec(tim::vx::DataType::FLOAT32, - out_shape, tim::vx::TensorAttribute::OUTPUT); + tim::vx::ShapeType in_shape({5, 1}); + tim::vx::ShapeType out_shape({5, 1}); + tim::vx::TensorSpec in_spec(tim::vx::DataType::FLOAT32, in_shape, + tim::vx::TensorAttribute::INPUT); + tim::vx::TensorSpec out_spec(tim::vx::DataType::FLOAT32, out_shape, + tim::vx::TensorAttribute::OUTPUT); - auto in_tensor = graph->CreateTensor(in_spec); - auto out_tensor = graph->CreateTensor(out_spec); + auto in_tensor = graph->CreateTensor(in_spec); + auto out_tensor = graph->CreateTensor(out_spec); - std::vector in_data = { - -3, -1, 0, 1, 3 - }; - std::vector golden = { - -0.00363752, -0.15880796, 0, 0.841192, 2.9963627 - }; + std::vector in_data = {-3, -1, 0, 1, 3}; + std::vector golden = {-0.00363752, -0.15880796, 0, 0.841192, + 2.9963627}; - EXPECT_TRUE(in_tensor->CopyDataToTensor(in_data.data(), in_data.size() * sizeof(float))); - auto op = graph->CreateOperation(true); - (*op).BindInput(in_tensor).BindOutput(out_tensor); + EXPECT_TRUE(in_tensor->CopyDataToTensor(in_data.data(), + in_data.size() * sizeof(float))); + auto op = graph->CreateOperation(true); + (*op).BindInput(in_tensor).BindOutput(out_tensor); - EXPECT_TRUE(graph->Compile()); - EXPECT_TRUE(graph->Run()); + EXPECT_TRUE(graph->Compile()); + EXPECT_TRUE(graph->Run()); - std::vector output(golden.size()); - EXPECT_TRUE(out_tensor->CopyDataFromTensor(output.data())); - EXPECT_TRUE(ArraysMatch(golden, output, 1e-5f)); + std::vector output(golden.size()); + EXPECT_TRUE(out_tensor->CopyDataFromTensor(output.data())); + EXPECT_TRUE(ArraysMatch(golden, output, 1e-5f)); } TEST(Gelu, shape_5_1_uint8_Quantized) { - auto ctx = tim::vx::Context::Create(); - auto graph = ctx->CreateGraph(); + auto ctx = tim::vx::Context::Create(); + auto graph = ctx->CreateGraph(); - tim::vx::ShapeType in_shape({5, 1}); - tim::vx::ShapeType out_shape({5, 1}); + tim::vx::ShapeType in_shape({5, 1}); + tim::vx::ShapeType out_shape({5, 1}); - const float InputMin = -127, InputMax = 128, OutputMin = -127, OutputMax = 128; + const float InputMin = -127, InputMax = 128, OutputMin = -127, + OutputMax = 128; - std::pair scalesAndZp; + std::pair scalesAndZp; - scalesAndZp = QuantizationParams(InputMin, InputMax); - std::vector scalesInput = {scalesAndZp.first}; //scale - std::vector zeroPointsInput = {scalesAndZp.second}; //zero point + scalesAndZp = QuantizationParams(InputMin, InputMax); + std::vector scalesInput = {scalesAndZp.first}; //scale + std::vector zeroPointsInput = {scalesAndZp.second}; //zero point - scalesAndZp = QuantizationParams(OutputMin, OutputMax); - std::vector scalesOutput = {scalesAndZp.first}; - std::vector zeroPointsOutput = {scalesAndZp.second}; + scalesAndZp = QuantizationParams(OutputMin, OutputMax); + std::vector scalesOutput = {scalesAndZp.first}; + std::vector zeroPointsOutput = {scalesAndZp.second}; - - tim::vx::Quantization quantInput(tim::vx::QuantType::ASYMMETRIC, 1, + tim::vx::Quantization quantInput(tim::vx::QuantType::ASYMMETRIC, 1, scalesInput, zeroPointsInput); - tim::vx::Quantization quantOutput(tim::vx::QuantType::ASYMMETRIC, 1, + tim::vx::Quantization quantOutput(tim::vx::QuantType::ASYMMETRIC, 1, scalesOutput, zeroPointsOutput); - tim::vx::TensorSpec input_spec(tim::vx::DataType::UINT8, in_shape, + tim::vx::TensorSpec input_spec(tim::vx::DataType::UINT8, in_shape, tim::vx::TensorAttribute::INPUT, quantInput); - tim::vx::TensorSpec output_spec(tim::vx::DataType::UINT8, out_shape, - tim::vx::TensorAttribute::OUTPUT, quantOutput); + tim::vx::TensorSpec output_spec(tim::vx::DataType::UINT8, out_shape, + tim::vx::TensorAttribute::OUTPUT, + quantOutput); - auto input_tensor = graph->CreateTensor(input_spec); - auto output_tensor = graph->CreateTensor(output_spec); + auto input_tensor = graph->CreateTensor(input_spec); + auto output_tensor = graph->CreateTensor(output_spec); - std::vector in_float_data = { - -3, -1, 0, 1, 3 - }; - std::vector golden_float = { - -0.00404951, -0.15865529, 0, 0.8413447, 2.9959507 - }; + std::vector in_float_data = {-3, -1, 0, 1, 3}; + std::vector golden_float = {-0.00404951, -0.15865529, 0, 0.8413447, + 2.9959507}; - std::vector input_data = - Quantize(in_float_data, scalesInput[0], zeroPointsInput[0]); //Quantification process - std::vector golden = + std::vector input_data = + Quantize(in_float_data, scalesInput[0], + zeroPointsInput[0]); //Quantification process + std::vector golden = Quantize(golden_float, scalesOutput[0], zeroPointsOutput[0]); - EXPECT_TRUE(input_tensor->CopyDataToTensor(input_data.data(), input_data.size()*4)); - auto op = graph->CreateOperation(false); - (*op).BindInput(input_tensor).BindOutput(output_tensor); + EXPECT_TRUE( + input_tensor->CopyDataToTensor(input_data.data(), input_data.size() * 4)); + auto op = graph->CreateOperation(false); + (*op).BindInput(input_tensor).BindOutput(output_tensor); - EXPECT_TRUE(graph->Compile()); - EXPECT_TRUE(graph->Run()); - std::vector output(golden.size()); + EXPECT_TRUE(graph->Compile()); + EXPECT_TRUE(graph->Run()); + std::vector output(golden.size()); - EXPECT_TRUE(output_tensor->CopyDataFromTensor(output.data())); - EXPECT_TRUE(ArraysMatch(golden, output, (uint8_t)1)); + EXPECT_TRUE(output_tensor->CopyDataFromTensor(output.data())); + EXPECT_TRUE(ArraysMatch(golden, output, (uint8_t)1)); } \ No newline at end of file