Add SVDF support - only FLOAT32 supported

Signed-off-by: Chen Xin <jack.chen@verisilicon.com>
This commit is contained in:
chxin66 2021-10-29 16:19:15 +08:00 committed by GitHub
parent f5881c6fa5
commit e4cc133d36
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 561 additions and 0 deletions

57
include/tim/vx/ops/svdf.h Normal file
View File

@ -0,0 +1,57 @@
/****************************************************************************
*
* Copyright (c) 2021 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_SVDF_H_
#define TIM_VX_OPS_SVDF_H_
#include <array>
#include "tim/vx/operation.h"
#include "tim/vx/types.h"
namespace tim {
namespace vx {
namespace ops {
/**
* ## Svdf
*
* Performs an 2-D pooling operation.
*
* - rank : The rank of the SVD approximation.
* - num_units : corresponds to the number of units.
* - spectrogram_length : corresponds to the fixed-size of the memory.
*/
class Svdf : public Operation {
public:
Svdf(Graph* graph, int32_t rank, int32_t num_units, int32_t spectrogram_length);
std::shared_ptr<Operation> Clone(std::shared_ptr<Graph>& graph) const override;
};
} // namespace ops
} // namespace vx
} // namespace tim
#endif /* TIM_VX_OPS_SVDF_H_ */

View File

@ -99,6 +99,7 @@ GroupedConv2d|GROUPED_CONV2D|Mapped|[ANEURALNETWORKS_GROUPED_CONV_2D](https://de
SpatialTransformer|SPATIAL_TRANSFORMER|Mapped|[SpatialTransformer](https://github.com/daerduoCarey/SpatialTransformerLayer)
shuffle_channel|SHUFFLECHANNEL|Mapped|[ANEURALNETWORKS_CHANNEL_SHUFFLE](https://developer.android.com/ndk/reference/group/neural-networks#group___neural_networks_1ggaabbe492c60331b13038e39d4207940e0a5b993c1211c4b1bc52fb595a3025251d)
Gelu|GELU|Mapped|[tf.nn.gelu](https://tensorflow.google.cn/api_docs/python/tf/nn/gelu)
Svdf|SVDF|Mapped|[ANEURALNETWORKS_SVDF](https://developer.android.com/ndk/reference/group/neural-networks#group___neural_networks_1ggaabbe492c60331b13038e39d4207940e0a7096de21038c1ce49d354a00cba7b552)
||PROPOSAL|Planned 21Q3|[Faster-RCNN Proposal Layer](https://github.com/intel/caffe/blob/master/examples/faster-rcnn/lib/rpn/proposal_layer.py)
||ROI_POOL|Planned 21Q3|[ANEURALNETWORKS_ROI_POOLING](https://developer.android.com/ndk/reference/group/neural-networks#group___neural_networks_1ggaabbe492c60331b13038e39d4207940e0a6736198af337b2efbdb0b6b64dee7fe4)
||ROI_ALIGN|Planned 21Q3|[ANEURALNETWORKS_ROI_ALIGN](https://developer.android.com/ndk/reference/group/neural-networks#group___neural_networks_1ggaabbe492c60331b13038e39d4207940e0a2848b39dd4bfba78f2438fda0d9397a4)

49
src/tim/vx/ops/svdf.cc Normal file
View File

@ -0,0 +1,49 @@
/****************************************************************************
*
* Copyright (c) 2021 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/svdf.h"
#include "operation_private.h"
#include "type_utils.h"
#include "vsi_nn_pub.h"
namespace tim {
namespace vx {
namespace ops {
Svdf::Svdf(Graph* graph, int32_t rank, int32_t num_units, int32_t spectrogram_length)
: Operation(graph, VSI_NN_OP_SVDF) {
this->impl()->node()->nn_param.svdf.rank = rank;
this->impl()->node()->nn_param.svdf.num_units = num_units;
this->impl()->node()->nn_param.svdf.spectrogram_length = spectrogram_length;
}
std::shared_ptr<Operation> Svdf::Clone(std::shared_ptr<Graph>& graph) const {
return graph->CreateOperation<Svdf>(this->impl()->node()->nn_param.svdf.rank,
this->impl()->node()->nn_param.svdf.num_units,
this->impl()->node()->nn_param.svdf.spectrogram_length);
}
} // namespace ops
} // namespace vx
} // namespace tim

454
src/tim/vx/ops/svdf_test.cc Normal file
View File

@ -0,0 +1,454 @@
/****************************************************************************
*
* Copyright (c) 2021 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/svdf.h"
#include "test_utils.h"
#include "gtest/gtest.h"
TEST(Svdf, shape_3_2_10_1_4_float) {
auto ctx = tim::vx::Context::Create();
auto graph = ctx->CreateGraph();
uint32_t input_size = 3, batches = 2, memory_size = 10, rank = 1, num_units = 4, spectrogram_length = num_units;
tim::vx::ShapeType input_shape({input_size, batches});
tim::vx::ShapeType state_in_shape({rank * num_units * memory_size, batches});
tim::vx::ShapeType weights_feature_shape({input_size, rank * num_units});
tim::vx::ShapeType weights_time_shape({memory_size, rank * num_units});
tim::vx::ShapeType output_shape({num_units, batches});
tim::vx::ShapeType state_out_shape({rank * num_units * memory_size, batches});
tim::vx::TensorSpec input_spec(tim::vx::DataType::FLOAT32,
input_shape, tim::vx::TensorAttribute::INPUT);
tim::vx::TensorSpec state_in_spec(tim::vx::DataType::FLOAT32,
state_in_shape, tim::vx::TensorAttribute::INPUT);
tim::vx::TensorSpec weights_feature_spec(tim::vx::DataType::FLOAT32,
weights_feature_shape, tim::vx::TensorAttribute::INPUT);
tim::vx::TensorSpec weights_time_spec(tim::vx::DataType::FLOAT32,
weights_time_shape, tim::vx::TensorAttribute::INPUT);
tim::vx::TensorSpec output_spec(tim::vx::DataType::FLOAT32,
output_shape, tim::vx::TensorAttribute::OUTPUT);
tim::vx::TensorSpec state_out_spec(tim::vx::DataType::FLOAT32,
state_out_shape, tim::vx::TensorAttribute::OUTPUT);
auto input_tensor = graph->CreateTensor(input_spec);
auto state_in_tensor = graph->CreateTensor(state_in_spec);
auto weights_feature_tensor = graph->CreateTensor(weights_feature_spec);
auto weights_time_tensor = graph->CreateTensor(weights_time_spec);
auto output_tensor = graph->CreateTensor(output_spec);
auto state_out_tensor = graph->CreateTensor(state_out_spec);
std::vector<float> in_data = {
0.12609188, -0.46347019, -0.89598465,
0.35867718, 0.36897406, 0.73463392,
};
std::vector<float> state_in;
for(uint32_t m = 0; m < rank * num_units * memory_size * batches; m++)
state_in.push_back(0);
std::vector<float> weights_feature = {
-0.31930989, -0.36118156, 0.0079667,
0.37613347, 0.22197971, 0.12416199,
0.27901134, 0.27557442, 0.3905206,
-0.36137494, -0.06634006, -0.10640851};
std::vector<float> weights_time = {
-0.31930989, 0.37613347, 0.27901134, -0.36137494, -0.36118156,
0.22197971, 0.27557442, -0.06634006, 0.0079667, 0.12416199,
0.3905206, -0.10640851, -0.0976817, 0.15294972, 0.39635518,
-0.02702999, 0.39296314, 0.15785322, 0.21931258, 0.31053296,
-0.36916667, 0.38031587, -0.21580373, 0.27072677, 0.23622236,
0.34936687, 0.18174365, 0.35907319, -0.17493086, 0.324846,
-0.10781813, 0.27201805, 0.14324132, -0.23681851, -0.27115166,
-0.01580888, -0.14943552, 0.15465137, 0.09784451, -0.0337657};
std::vector<float> golden = {
0.014899, -0.0517661, -0.143725, -0.00271883,
-0.03004015, 0.09565311, 0.1587342, 0.00784263,
};
EXPECT_TRUE(input_tensor->CopyDataToTensor(
in_data.data(), in_data.size() * sizeof(float)));
EXPECT_TRUE(state_in_tensor->CopyDataToTensor(
state_in.data(), state_in.size() * sizeof(float)));
EXPECT_TRUE(weights_feature_tensor->CopyDataToTensor(
weights_feature.data(), in_data.size() * sizeof(float)));
EXPECT_TRUE(weights_time_tensor->CopyDataToTensor(
weights_time.data(), in_data.size() * sizeof(float)));
auto op = graph->CreateOperation<tim::vx::ops::Svdf>(rank, num_units, spectrogram_length);
(*op).BindInputs({input_tensor, state_in_tensor, weights_feature_tensor, weights_time_tensor})
.BindOutputs({output_tensor, state_out_tensor});
EXPECT_TRUE(graph->Compile());
EXPECT_TRUE(graph->Run());
std::vector<float> output(golden.size());
EXPECT_TRUE(output_tensor->CopyDataFromTensor(output.data()));
// EXPECT_EQ(golden, output);
EXPECT_TRUE(ArraysMatch(golden, output,1e-5f));
}
TEST(Svdf, shape_3_2_10_2_4_float) {
auto ctx = tim::vx::Context::Create();
auto graph = ctx->CreateGraph();
uint32_t input_size = 3, batches = 2, memory_size = 10, rank = 2, num_units = 4, spectrogram_length = num_units;
tim::vx::ShapeType input_shape({input_size, batches});
tim::vx::ShapeType state_in_shape({rank * num_units * memory_size, batches});
tim::vx::ShapeType weights_feature_shape({input_size, rank * num_units});
tim::vx::ShapeType weights_time_shape({memory_size, rank * num_units});
tim::vx::ShapeType output_shape({num_units, batches});
tim::vx::ShapeType state_out_shape({rank * num_units * memory_size, batches});
tim::vx::TensorSpec input_spec(tim::vx::DataType::FLOAT32,
input_shape, tim::vx::TensorAttribute::INPUT);
tim::vx::TensorSpec state_in_spec(tim::vx::DataType::FLOAT32,
state_in_shape, tim::vx::TensorAttribute::INPUT);
tim::vx::TensorSpec weights_feature_spec(tim::vx::DataType::FLOAT32,
weights_feature_shape, tim::vx::TensorAttribute::INPUT);
tim::vx::TensorSpec weights_time_spec(tim::vx::DataType::FLOAT32,
weights_time_shape, tim::vx::TensorAttribute::INPUT);
tim::vx::TensorSpec output_spec(tim::vx::DataType::FLOAT32,
output_shape, tim::vx::TensorAttribute::OUTPUT);
tim::vx::TensorSpec state_out_spec(tim::vx::DataType::FLOAT32,
state_out_shape, tim::vx::TensorAttribute::OUTPUT);
auto input_tensor = graph->CreateTensor(input_spec);
auto state_in_tensor = graph->CreateTensor(state_in_spec);
auto weights_feature_tensor = graph->CreateTensor(weights_feature_spec);
auto weights_time_tensor = graph->CreateTensor(weights_time_spec);
auto output_tensor = graph->CreateTensor(output_spec);
auto state_out_tensor = graph->CreateTensor(state_out_spec);
std::vector<float> in_data = {
0.12609188, -0.46347019, -0.89598465,
0.35867718, 0.36897406, 0.73463392,};
std::vector<float> state_in;
for(uint32_t m = 0; m < rank * num_units * memory_size * batches; m++)
state_in.push_back(0);
std::vector<float> weights_feature = {
-0.31930989, 0.0079667, 0.39296314,
0.37613347, 0.12416199, 0.15785322,
0.27901134, 0.3905206, 0.21931258,
-0.36137494, -0.10640851, 0.31053296,
-0.36118156, -0.0976817, -0.36916667,
0.22197971, 0.15294972, 0.38031587,
0.27557442, 0.39635518, -0.21580373,
-0.06634006, -0.02702999, 0.27072677
};
std::vector<float> weights_time = {
-0.31930989, 0.37613347, 0.27901134, -0.36137494, -0.36118156,
0.22197971, 0.27557442, -0.06634006, 0.0079667, 0.12416199,
0.3905206, -0.10640851, -0.0976817, 0.15294972, 0.39635518,
-0.02702999, 0.39296314, 0.15785322, 0.21931258, 0.31053296,
-0.36916667, 0.38031587, -0.21580373, 0.27072677, 0.23622236,
0.34936687, 0.18174365, 0.35907319, -0.17493086, 0.324846,
-0.10781813, 0.27201805, 0.14324132, -0.23681851, -0.27115166,
-0.01580888, -0.14943552, 0.15465137, 0.09784451, -0.0337657,
-0.14884081, 0.19931212, -0.36002168, 0.34663299, -0.11405486,
0.12672701, 0.39463779, -0.07886535, -0.06384811, 0.08249187,
-0.26816407, -0.19905911, 0.29211238, 0.31264046, -0.28664589,
0.05698794, 0.11613581, 0.14078894, 0.02187902, -0.21781836,
-0.15567942, 0.08693647, -0.38256618, 0.36580828, -0.22922277,
-0.0226903, 0.12878349, -0.28122205, -0.10850525, -0.11955214,
0.27179423, -0.04710215, 0.31069002, 0.22672787, 0.09580326,
0.08682203, 0.1258215, 0.1851041, 0.29228821, 0.12366763,
};
std::vector<float> golden = {
-0.09623547, -0.10193135, 0.11083051, -0.0347917,
0.1141196, 0.12965347, -0.12652366, 0.01007236,
};
EXPECT_TRUE(input_tensor->CopyDataToTensor(
in_data.data(), in_data.size() * sizeof(float)));
EXPECT_TRUE(state_in_tensor->CopyDataToTensor(
state_in.data(), state_in.size() * sizeof(float)));
EXPECT_TRUE(weights_feature_tensor->CopyDataToTensor(
weights_feature.data(), in_data.size() * sizeof(float)));
EXPECT_TRUE(weights_time_tensor->CopyDataToTensor(
weights_time.data(), in_data.size() * sizeof(float)));
auto op = graph->CreateOperation<tim::vx::ops::Svdf>(rank, num_units, spectrogram_length);
(*op).BindInputs({input_tensor, state_in_tensor, weights_feature_tensor, weights_time_tensor})
.BindOutputs({output_tensor, state_out_tensor});
EXPECT_TRUE(graph->Compile());
EXPECT_TRUE(graph->Run());
std::vector<float> output(golden.size());
EXPECT_TRUE(output_tensor->CopyDataFromTensor(output.data()));
// EXPECT_EQ(golden, output);
EXPECT_TRUE(ArraysMatch(golden, output,1e-5f));
}
TEST(Svdf, shape_3_2_10_3_4_float) {
auto ctx = tim::vx::Context::Create();
auto graph = ctx->CreateGraph();
uint32_t input_size = 3, batches = 2, memory_size = 10, rank = 3, num_units = 4, spectrogram_length = num_units;
tim::vx::ShapeType input_shape({input_size, batches});
tim::vx::ShapeType state_in_shape({rank * num_units * memory_size, batches});
tim::vx::ShapeType weights_feature_shape({input_size, rank * num_units});
tim::vx::ShapeType weights_time_shape({memory_size, rank * num_units});
tim::vx::ShapeType output_shape({num_units, batches});
tim::vx::ShapeType state_out_shape({rank * num_units * memory_size, batches});
tim::vx::TensorSpec input_spec(tim::vx::DataType::FLOAT32,
input_shape, tim::vx::TensorAttribute::INPUT);
tim::vx::TensorSpec state_in_spec(tim::vx::DataType::FLOAT32,
state_in_shape, tim::vx::TensorAttribute::INPUT);
tim::vx::TensorSpec weights_feature_spec(tim::vx::DataType::FLOAT32,
weights_feature_shape, tim::vx::TensorAttribute::INPUT);
tim::vx::TensorSpec weights_time_spec(tim::vx::DataType::FLOAT32,
weights_time_shape, tim::vx::TensorAttribute::INPUT);
tim::vx::TensorSpec output_spec(tim::vx::DataType::FLOAT32,
output_shape, tim::vx::TensorAttribute::OUTPUT);
tim::vx::TensorSpec state_out_spec(tim::vx::DataType::FLOAT32,
state_out_shape, tim::vx::TensorAttribute::OUTPUT);
auto input_tensor = graph->CreateTensor(input_spec);
auto state_in_tensor = graph->CreateTensor(state_in_spec);
auto weights_feature_tensor = graph->CreateTensor(weights_feature_spec);
auto weights_time_tensor = graph->CreateTensor(weights_time_spec);
auto output_tensor = graph->CreateTensor(output_spec);
auto state_out_tensor = graph->CreateTensor(state_out_spec);
std::vector<float> in_data = {
0.12609188, -0.46347019, -0.89598465,
0.35867718, 0.36897406, 0.73463392,};
std::vector<float> state_in;
for(uint32_t m = 0; m < rank * num_units * memory_size * batches; m++)
state_in.push_back(0);
std::vector<float> weights_feature = {
-0.31930989, 0.0079667, 0.39296314,
0.37613347, 0.12416199, 0.15785322,
0.27901134, 0.3905206, 0.21931258,
-0.36137494, -0.10640851, 0.31053296,
-0.36118156, -0.0976817, -0.36916667,
0.22197971, 0.15294972, 0.38031587,
0.27557442, 0.39635518, -0.21580373,
-0.06634006, -0.02702999, 0.27072677,
-0.31930989, -0.36118156, 0.0079667,
0.37613347, 0.22197971, 0.12416199,
0.27901134, 0.27557442, 0.3905206,
-0.36137494, -0.06634006, -0.10640851
};
std::vector<float> weights_time = {
-0.31930989, 0.37613347, 0.27901134, -0.36137494, -0.36118156,
0.22197971, 0.27557442, -0.06634006, 0.0079667, 0.12416199,
0.3905206, -0.10640851, -0.0976817, 0.15294972, 0.39635518,
-0.02702999, 0.39296314, 0.15785322, 0.21931258, 0.31053296,
-0.36916667, 0.38031587, -0.21580373, 0.27072677, 0.23622236,
0.34936687, 0.18174365, 0.35907319, -0.17493086, 0.324846,
-0.10781813, 0.27201805, 0.14324132, -0.23681851, -0.27115166,
-0.01580888, -0.14943552, 0.15465137, 0.09784451, -0.0337657,
-0.14884081, 0.19931212, -0.36002168, 0.34663299, -0.11405486,
0.12672701, 0.39463779, -0.07886535, -0.06384811, 0.08249187,
-0.26816407, -0.19905911, 0.29211238, 0.31264046, -0.28664589,
0.05698794, 0.11613581, 0.14078894, 0.02187902, -0.21781836,
-0.15567942, 0.08693647, -0.38256618, 0.36580828, -0.22922277,
-0.0226903, 0.12878349, -0.28122205, -0.10850525, -0.11955214,
0.27179423, -0.04710215, 0.31069002, 0.22672787, 0.09580326,
0.08682203, 0.1258215, 0.1851041, 0.29228821, 0.12366763,
0.3905206, -0.10640851, -0.0976817, 0.15294972, 0.39635518,
-0.02702999, 0.39296314, 0.15785322, 0.21931258, 0.31053296,
-0.36916667, 0.38031587, -0.21580373, 0.27072677, 0.23622236,
0.34936687, 0.18174365, 0.35907319, -0.17493086, 0.324846,
-0.10781813, 0.27201805, 0.14324132, -0.23681851, -0.27115166,
-0.01580888, -0.14943552, 0.15465137, 0.09784451, -0.0337657,
-0.14884081, 0.19931212, -0.36002168, 0.34663299, -0.11405486,
0.12672701, 0.39463779, -0.07886535, -0.06384811, 0.08249187,
};
std::vector<float> golden = {
-0.207435, 0.120099, 0.00247115, -0.0325705,
0.245774, -0.128524, -0.065059, 0.0644025,
};
EXPECT_TRUE(input_tensor->CopyDataToTensor(
in_data.data(), in_data.size() * sizeof(float)));
EXPECT_TRUE(state_in_tensor->CopyDataToTensor(
state_in.data(), state_in.size() * sizeof(float)));
EXPECT_TRUE(weights_feature_tensor->CopyDataToTensor(
weights_feature.data(), in_data.size() * sizeof(float)));
EXPECT_TRUE(weights_time_tensor->CopyDataToTensor(
weights_time.data(), in_data.size() * sizeof(float)));
auto op = graph->CreateOperation<tim::vx::ops::Svdf>(rank, num_units, spectrogram_length);
(*op).BindInputs({input_tensor, state_in_tensor, weights_feature_tensor, weights_time_tensor})
.BindOutputs({output_tensor, state_out_tensor});
EXPECT_TRUE(graph->Compile());
EXPECT_TRUE(graph->Run());
std::vector<float> output(golden.size());
EXPECT_TRUE(output_tensor->CopyDataFromTensor(output.data()));
// EXPECT_EQ(golden, output);
EXPECT_TRUE(ArraysMatch(golden, output,1e-5f));
}
// TEST(Svdf, shape_3_2_10_1_4_uint8) {
// auto ctx = tim::vx::Context::Create();
// auto graph = ctx->CreateGraph();
// const float InputMin = -127, InputMax = 128, OutputMin = -127, OutputMax = 128;
// uint32_t input_size = 3, batches = 2, memory_size = 10, rank = 1, num_units = 4, spectrogram_length = num_units;
// std::pair<float, int32_t> scalesAndZp;
// scalesAndZp = QuantizationParams<uint8_t>(InputMin, InputMax);
// std::vector<float> scalesInput = {scalesAndZp.first}; //scale
// std::vector<int32_t> zeroPointsInput = {scalesAndZp.second}; //zero point
// scalesAndZp = QuantizationParams<uint8_t>(OutputMin, OutputMax);
// std::vector<float> scalesOutput = {scalesAndZp.first};
// std::vector<int32_t> zeroPointsOutput = {scalesAndZp.second};
// tim::vx::ShapeType input_shape({input_size, batches});
// tim::vx::ShapeType state_in_shape({rank * num_units * memory_size, batches});
// tim::vx::ShapeType weights_feature_shape({input_size, rank * num_units});
// tim::vx::ShapeType weights_time_shape({memory_size, rank * num_units});
// tim::vx::ShapeType output_shape({num_units, batches});
// tim::vx::ShapeType state_out_shape({rank * num_units * memory_size, batches});
// tim::vx::Quantization quantInput(tim::vx::QuantType::ASYMMETRIC, 1,
// scalesInput, zeroPointsInput);
// tim::vx::Quantization quantOutput(tim::vx::QuantType::ASYMMETRIC, 1,
// scalesOutput, zeroPointsOutput);
// tim::vx::TensorSpec input_spec(tim::vx::DataType::UINT8,
// input_shape, tim::vx::TensorAttribute::INPUT, quantInput);
// tim::vx::TensorSpec state_in_spec(tim::vx::DataType::UINT8,
// state_in_shape, tim::vx::TensorAttribute::INPUT, quantInput);
// tim::vx::TensorSpec weights_feature_spec(tim::vx::DataType::UINT8,
// weights_feature_shape, tim::vx::TensorAttribute::INPUT, quantInput);
// tim::vx::TensorSpec weights_time_spec(tim::vx::DataType::UINT8,
// weights_time_shape, tim::vx::TensorAttribute::INPUT, quantInput);
// tim::vx::TensorSpec output_spec(tim::vx::DataType::UINT8,
// output_shape, tim::vx::TensorAttribute::OUTPUT, quantOutput);
// tim::vx::TensorSpec state_out_spec(tim::vx::DataType::UINT8,
// state_out_shape, tim::vx::TensorAttribute::OUTPUT, quantOutput);
// auto input_tensor = graph->CreateTensor(input_spec);
// auto state_in_tensor = graph->CreateTensor(state_in_spec);
// auto weights_feature_tensor = graph->CreateTensor(weights_feature_spec);
// auto weights_time_tensor = graph->CreateTensor(weights_time_spec);
// auto output_tensor = graph->CreateTensor(output_spec);
// auto state_out_tensor = graph->CreateTensor(state_out_spec);
// std::vector<float> in_data_float = {
// 0.12609188, -0.46347019, -0.89598465,
// 0.35867718, 0.36897406, 0.73463392,
// };
// std::vector<uint8_t> state_in_uint8;
// for(uint32_t m = 0; m < rank * num_units * memory_size * batches; m++)
// state_in_uint8.push_back(0);
// std::vector<float> weights_feature_float = {
// -0.31930989, -0.36118156, 0.0079667,
// 0.37613347, 0.22197971, 0.12416199,
// 0.27901134, 0.27557442, 0.3905206,
// -0.36137494, -0.06634006, -0.10640851};
// std::vector<float> weights_time_float = {
// -0.31930989, 0.37613347, 0.27901134, -0.36137494, -0.36118156,
// 0.22197971, 0.27557442, -0.06634006, 0.0079667, 0.12416199,
// 0.3905206, -0.10640851, -0.0976817, 0.15294972, 0.39635518,
// -0.02702999, 0.39296314, 0.15785322, 0.21931258, 0.31053296,
// -0.36916667, 0.38031587, -0.21580373, 0.27072677, 0.23622236,
// 0.34936687, 0.18174365, 0.35907319, -0.17493086, 0.324846,
// -0.10781813, 0.27201805, 0.14324132, -0.23681851, -0.27115166,
// -0.01580888, -0.14943552, 0.15465137, 0.09784451, -0.0337657};
// std::vector<float> golden_float = {
// 0.014899, -0.0517661, -0.143725, -0.00271883,
// -0.03004015, 0.09565311, 0.1587342, 0.00784263,
// };
// std::vector<uint8_t> in_data_uint8 =
// Quantize<uint8_t>(in_data_float, scalesInput[0], zeroPointsInput[0]); //Quantification process
// std::vector<uint8_t> weights_feature_uint8 =
// Quantize<uint8_t>(weights_feature_float, scalesInput[0], zeroPointsInput[0]);
// std::vector<uint8_t> weights_time_uint8 =
// Quantize<uint8_t>(weights_time_float, scalesInput[0], zeroPointsInput[0]);
// std::vector<uint8_t> golden_uint8 =
// Quantize<uint8_t>(golden_float, scalesInput[0], zeroPointsInput[0]);
// EXPECT_TRUE(input_tensor->CopyDataToTensor(
// in_data_uint8.data(), in_data_uint8.size() * sizeof(uint8_t)));
// EXPECT_TRUE(state_in_tensor->CopyDataToTensor(
// state_in_uint8.data(), state_in_uint8.size() * sizeof(uint8_t)));
// EXPECT_TRUE(weights_feature_tensor->CopyDataToTensor(
// weights_feature_uint8.data(), weights_feature_uint8.size() * sizeof(uint8_t)));
// EXPECT_TRUE(weights_time_tensor->CopyDataToTensor(
// weights_time_uint8.data(), weights_time_uint8.size() * sizeof(uint8_t)));
// auto op = graph->CreateOperation<tim::vx::ops::Svdf>(rank, num_units, spectrogram_length);
// (*op).BindInputs({input_tensor, state_in_tensor, weights_feature_tensor, weights_time_tensor})
// .BindOutputs({output_tensor, state_out_tensor});
// EXPECT_TRUE(graph->Compile());
// EXPECT_TRUE(graph->Run());
// std::vector<uint8_t> output_uint8(golden_uint8.size());
// EXPECT_TRUE(output_tensor->CopyDataFromTensor(output_uint8.data()));
// EXPECT_EQ(golden_uint8, output_uint8);
// // EXPECT_TRUE(ArraysMatch(golden, output,1e-5f));
// }