// // Copyright © 2017 Arm Ltd. All rights reserved. // See LICENSE file in the project root for full license information. // #include "DriverTestHelpers.hpp" #include "TestTensor.hpp" #include #include BOOST_AUTO_TEST_SUITE(MergerTests) using ArmnnDriver = armnn_driver::ArmnnDriver; using DriverOptions = armnn_driver::DriverOptions; using namespace driverTestHelpers; namespace { void MergerTestImpl(const std::vector & inputs, int32_t concatAxis, const TestTensor & expectedOutputTensor, ErrorStatus expectedPrepareStatus=ErrorStatus::NONE, ErrorStatus expectedExecStatus=ErrorStatus::NONE) { std::unique_ptr driver = std::make_unique(DriverOptions(armnn::Compute::CpuRef)); Model model{}; hidl_vec modelInputIds; modelInputIds.resize(inputs.size()+1); for (uint32_t i = 0; iGetDimensions()); } modelInputIds[inputs.size()] = inputs.size(); // add an id for the axis too AddIntOperand(model, concatAxis); AddOutputOperand(model, expectedOutputTensor.GetDimensions()); // make the concat operation model.operations.resize(1); model.operations[0].type = OperationType::CONCATENATION; model.operations[0].inputs = modelInputIds; model.operations[0].outputs = hidl_vec{static_cast(inputs.size()+1)}; // make the prepared model ErrorStatus prepareStatus=ErrorStatus::NONE; android::sp preparedModel = PrepareModelWithStatus(model, *driver, prepareStatus, expectedPrepareStatus); BOOST_TEST(prepareStatus == expectedPrepareStatus); if (prepareStatus != ErrorStatus::NONE) { // prepare failed, we cannot continue return; } BOOST_TEST(preparedModel.get() != nullptr); if (preparedModel.get() == nullptr) { // don't spoil other tests if prepare failed return; } // construct the request hidl_vec inputArguments; hidl_vec outputArguments; inputArguments.resize(inputs.size()); outputArguments.resize(1); // the request's memory pools will follow the same order as // the inputs for (uint32_t i = 0; iGetNumElements() * sizeof(float); RequestArgument input = {}; input.location = inloc; input.dimensions = inputs[i]->GetDimensions(); inputArguments[i] = input; } // and an additional memory pool is needed for the output { DataLocation outloc = {}; outloc.poolIndex = inputs.size(); outloc.offset = 0; outloc.length = expectedOutputTensor.GetNumElements() * sizeof(float); RequestArgument output = {}; output.location = outloc; output.dimensions = expectedOutputTensor.GetDimensions(); outputArguments[0] = output; } // make the request based on the arguments Request request = {}; request.inputs = inputArguments; request.outputs = outputArguments; // set the input data for (uint32_t i = 0; iGetNumElements(), request, inputs[i]->GetData()); } // add memory for the output android::sp outMemory = AddPoolAndGetData(expectedOutputTensor.GetNumElements(), request); float* outdata = static_cast(static_cast(outMemory->getPointer())); // run the execution auto execStatus = Execute(preparedModel, request, expectedExecStatus); BOOST_TEST(execStatus == expectedExecStatus); if (execStatus == ErrorStatus::NONE) { // check the result if there was no error const float * expectedOutput = expectedOutputTensor.GetData(); for (unsigned int i=0; i BOOST_AUTO_TEST_CASE(SimpleConcatAxis0) { int32_t axis = 0; TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}}; TestTensor bIn{armnn::TensorShape{1,1,1,1},{1}}; TestTensor cIn{armnn::TensorShape{1,1,1,1},{2}}; TestTensor expected{armnn::TensorShape{3,1,1,1},{0,1,2}}; MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected); } BOOST_AUTO_TEST_CASE(ConcatAxis0_NoInterleave) { int32_t axis = 0; TestTensor aIn{armnn::TensorShape{2,1,2,1},{0, 1, 2, 3}}; TestTensor bIn{armnn::TensorShape{3,1,2,1},{4, 5, 6, 7, 8, 9}}; TestTensor cIn{armnn::TensorShape{1,1,2,1},{10, 11}}; TestTensor expected{armnn::TensorShape{6,1,2,1},{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}; MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected); } BOOST_AUTO_TEST_CASE(SimpleConcatAxis1) { int32_t axis = 1; TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}}; TestTensor bIn{armnn::TensorShape{1,1,1,1},{1}}; TestTensor cIn{armnn::TensorShape{1,1,1,1},{2}}; TestTensor expected{armnn::TensorShape{1,3,1,1},{0,1,2}}; MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected); } BOOST_AUTO_TEST_CASE(ConcatAxis1_NoInterleave) { int32_t axis = 1; TestTensor aIn{armnn::TensorShape{1,2,2,1},{0, 1, 2, 3}}; TestTensor bIn{armnn::TensorShape{1,3,2,1},{4, 5, 6, 7, 8, 9}}; TestTensor cIn{armnn::TensorShape{1,1,2,1},{10, 11}}; TestTensor expected{armnn::TensorShape{1,6,2,1},{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}; MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected); } BOOST_AUTO_TEST_CASE(SimpleConcatAxis1_DoInterleave) { int32_t axis = 1; TestTensor aIn{armnn::TensorShape{2,2,1,1},{0, 1, 2, 3}}; TestTensor bIn{armnn::TensorShape{2,3,1,1},{4, 5, 6, 7, 8, 9}}; TestTensor cIn{armnn::TensorShape{2,1,1,1},{10, 11}}; TestTensor expected{armnn::TensorShape{2,6,1,1},{0, 1, 4, 5, 6, 10, 2, 3, 7, 8, 9, 11}}; MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected); } BOOST_AUTO_TEST_CASE(SimpleConcatAxis2) { int32_t axis = 2; TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}}; TestTensor bIn{armnn::TensorShape{1,1,1,1},{1}}; TestTensor cIn{armnn::TensorShape{1,1,1,1},{2}}; TestTensor expected{armnn::TensorShape{1,1,3,1},{0,1,2}}; MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected); } BOOST_AUTO_TEST_CASE(ConcatAxis2_NoInterleave) { int32_t axis = 2; TestTensor aIn{armnn::TensorShape{1,1,2,2},{0, 1, 2, 3}}; TestTensor bIn{armnn::TensorShape{1,1,3,2},{4, 5, 6, 7, 8, 9}}; TestTensor cIn{armnn::TensorShape{1,1,1,2},{10, 11}}; TestTensor expected{armnn::TensorShape{1,1,6,2},{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11}}; MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected); } BOOST_AUTO_TEST_CASE(SimpleConcatAxis2_DoInterleave) { int32_t axis = 2; TestTensor aIn{armnn::TensorShape{1,2,2,1},{0, 1, 2, 3}}; TestTensor bIn{armnn::TensorShape{1,2,3,1},{4, 5, 6, 7, 8, 9}}; TestTensor cIn{armnn::TensorShape{1,2,1,1},{10, 11}}; TestTensor expected{armnn::TensorShape{1,2,6,1},{0, 1, 4, 5, 6, 10, 2, 3, 7, 8, 9, 11}}; MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected); } BOOST_AUTO_TEST_CASE(SimpleConcatAxis3) { int32_t axis = 3; TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}}; TestTensor bIn{armnn::TensorShape{1,1,1,1},{1}}; TestTensor cIn{armnn::TensorShape{1,1,1,1},{2}}; TestTensor expected{armnn::TensorShape{1,1,1,3},{0,1,2}}; MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected); } BOOST_AUTO_TEST_CASE(SimpleConcatAxis3_DoInterleave) { int32_t axis = 3; TestTensor aIn{armnn::TensorShape{1,1,2,2},{0, 1, 2, 3}}; TestTensor bIn{armnn::TensorShape{1,1,2,3},{4, 5, 6, 7, 8, 9}}; TestTensor cIn{armnn::TensorShape{1,1,2,1},{10, 11}}; TestTensor expected{armnn::TensorShape{1,1,2,6},{0, 1, 4, 5, 6, 10, 2, 3, 7, 8, 9, 11}}; MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected); } BOOST_AUTO_TEST_CASE(AxisTooBig) { int32_t axis = 4; TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}}; TestTensor bIn{armnn::TensorShape{1,1,1,1},{0}}; // The axis must be within the range of [-rank(values), rank(values)) // see: https://www.tensorflow.org/api_docs/python/tf/concat TestTensor uncheckedOutput{armnn::TensorShape{1,1,1,1},{0}}; ErrorStatus expectedParserStatus = ErrorStatus::GENERAL_FAILURE; MergerTestImpl({&aIn, &bIn}, axis, uncheckedOutput, expectedParserStatus); } BOOST_AUTO_TEST_CASE(AxisTooSmall) { int32_t axis = -5; TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}}; TestTensor bIn{armnn::TensorShape{1,1,1,1},{0}}; // The axis must be within the range of [-rank(values), rank(values)) // see: https://www.tensorflow.org/api_docs/python/tf/concat TestTensor uncheckedOutput{armnn::TensorShape{1,1,1,1},{0}}; ErrorStatus expectedParserStatus = ErrorStatus::GENERAL_FAILURE; MergerTestImpl({&aIn, &bIn}, axis, uncheckedOutput, expectedParserStatus); } BOOST_AUTO_TEST_CASE(TooFewInputs) { int32_t axis = 0; TestTensor aIn{armnn::TensorShape{1,1,1,1},{0}}; // We need at least two tensors to concatenate ErrorStatus expectedParserStatus = ErrorStatus::GENERAL_FAILURE; MergerTestImpl({&aIn}, axis, aIn, expectedParserStatus); } BOOST_AUTO_TEST_CASE(MismatchedInputDimensions) { int32_t axis = 3; TestTensor aIn{armnn::TensorShape{1,1,2,2},{0, 1, 2, 3}}; TestTensor bIn{armnn::TensorShape{1,1,2,3},{4, 5, 6, 7, 8, 9}}; TestTensor mismatched{armnn::TensorShape{1,1,1,1},{10}}; TestTensor expected{armnn::TensorShape{1,1,2,6},{0, 1, 4, 5, 6, 10, 2, 3, 7, 8, 9, 11}}; // The input dimensions must be compatible ErrorStatus expectedParserStatus = ErrorStatus::GENERAL_FAILURE; MergerTestImpl({&aIn, &bIn, &mismatched}, axis, expected, expectedParserStatus); } BOOST_AUTO_TEST_CASE(MismatchedInputRanks) { int32_t axis = 2; TestTensor aIn{armnn::TensorShape{1,1,2},{0,1}}; TestTensor bIn{armnn::TensorShape{1,1},{4}}; TestTensor expected{armnn::TensorShape{1,1,3},{0,1,4}}; // The input dimensions must be compatible ErrorStatus expectedParserStatus = ErrorStatus::GENERAL_FAILURE; MergerTestImpl({&aIn, &bIn}, axis, expected, expectedParserStatus); } BOOST_AUTO_TEST_CASE(MismatchedOutputDimensions) { int32_t axis = 3; TestTensor aIn{armnn::TensorShape{1,1,2,2},{0, 1, 2, 3}}; TestTensor bIn{armnn::TensorShape{1,1,2,3},{4, 5, 6, 7, 8, 9}}; TestTensor cIn{armnn::TensorShape{1,1,2,1},{10, 11}}; TestTensor mismatched{armnn::TensorShape{1,1,6,2},{0, 1, 4, 5, 6, 10, 2, 3, 7, 8, 9, 11}}; // The input and output dimensions must be compatible ErrorStatus expectedParserStatus = ErrorStatus::GENERAL_FAILURE; MergerTestImpl({&aIn, &bIn, &cIn}, axis, mismatched, expectedParserStatus); } BOOST_AUTO_TEST_CASE(MismatchedOutputRank) { int32_t axis = 3; TestTensor aIn{armnn::TensorShape{1,1,2,2},{0, 1, 2, 3}}; TestTensor bIn{armnn::TensorShape{1,1,2,3},{4, 5, 6, 7, 8, 9}}; TestTensor cIn{armnn::TensorShape{1,1,2,1},{10, 11}}; TestTensor mismatched{armnn::TensorShape{6,2},{0, 1, 4, 5, 6, 10, 2, 3, 7, 8, 9, 11}}; // The input and output ranks must match ErrorStatus expectedParserStatus = ErrorStatus::GENERAL_FAILURE; MergerTestImpl({&aIn, &bIn, &cIn}, axis, mismatched, expectedParserStatus); } BOOST_AUTO_TEST_CASE(ValidNegativeAxis) { // this is the same as 3 // see: https://www.tensorflow.org/api_docs/python/tf/concat int32_t axis = -1; TestTensor aIn{armnn::TensorShape{1,1,2,2},{0, 1, 2, 3}}; TestTensor bIn{armnn::TensorShape{1,1,2,3},{4, 5, 6, 7, 8, 9}}; TestTensor cIn{armnn::TensorShape{1,1,2,1},{10, 11}}; TestTensor expected{armnn::TensorShape{1,1,2,6},{0, 1, 4, 5, 6, 10, 2, 3, 7, 8, 9, 11}}; MergerTestImpl({&aIn, &bIn, &cIn}, axis, expected); } BOOST_AUTO_TEST_SUITE_END()