14 #include <arm_compute/runtime/Allocator.h> 17 #include <boost/test/unit_test.hpp> 21 using namespace armnn;
25 std::shared_ptr<NeonMemoryManager> memoryManager = std::make_shared<NeonMemoryManager>();
42 std::vector<Capability> capabilities = handleFactory.GetCapabilities(input,
45 BOOST_TEST(capabilities.empty());
49 BOOST_TEST(capabilities.empty());
53 BOOST_TEST(capabilities.empty());
58 std::shared_ptr<NeonMemoryManager> memoryManager = std::make_shared<NeonMemoryManager>();
74 std::vector<Capability> capabilities = handleFactory.GetCapabilities(input,
77 BOOST_TEST(capabilities.empty());
81 BOOST_TEST(capabilities.empty());
85 BOOST_TEST(capabilities.size() == 1);
87 BOOST_TEST(capabilities[0].m_Value);
114 std::array<armnn::TensorShape, 2> concatInputShapes = { intermediateInfo.GetShape(), intermediateInfo.GetShape() };
116 concatInputShapes.begin(), concatInputShapes.end(), 2),
"concatenation");
134 runtime->LoadNetwork(networkIdentifier, std::move(optimizedNet));
139 if (subTensorHandle && subTensorHandle->GetParent())
146 for (
auto&& layer : theGraph)
150 unsigned int numberOfSubTensors = 0;
151 for (
unsigned int i = 0; i < layer->GetNumInputSlots(); ++i)
156 ++numberOfSubTensors;
176 descriptor.m_PoolWidth = descriptor.m_PoolHeight = 3;
177 descriptor.m_StrideX = descriptor.m_StrideY = 1;
178 descriptor.m_PadLeft = 1;
179 descriptor.m_PadRight = 1;
180 descriptor.m_PadTop = 1;
181 descriptor.m_PadBottom = 1;
197 std::array<armnn::TensorShape, 2> concatInputShapes = { intermediateInfo.GetShape(), intermediateInfo.GetShape() };
199 concatInputShapes.begin(), concatInputShapes.end(), 2),
"concatenation");
217 runtime->LoadNetwork(networkIdentifier, std::move(optimizedNet));
222 if (subTensorHandle && subTensorHandle->GetParent())
229 unsigned int numberOfSubTensors = 0;
230 for (
auto&& layer : theGraph)
234 for (
unsigned int i = 0; i < layer->GetNumInputSlots(); ++i)
239 ++numberOfSubTensors;
250 using namespace armnn;
252 unsigned int splitAxis = 2;
253 unsigned int numSplit = 2;
257 const std::vector<TensorShape> outputShapes{{ 2, 3, 2, 2 },
259 const float qScale = 1.0f;
260 const int32_t qOffset = 0;
263 std::vector<float> inputData{
290 std::vector<float> expectedOutput0{
305 std::vector<float> expectedOutput1{
333 splitterDimSizes[i] = inputTensorInfo.
GetShape()[i];
336 if (splitterDimSizes[splitAxis] % numSplit != 0)
338 throw ParseException(
"Number of splits must evenly divide the dimension");
341 splitterDimSizes[splitAxis] /= numSplit;
345 for (
unsigned int g = 0; g < numSplit; ++g)
348 for (
unsigned int dimIdx = 0; dimIdx < splitterDimSizes.size(); ++dimIdx)
350 splitDesc.
SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]);
352 splitDesc.SetViewOriginCoord(g, splitAxis, splitterDimSizes[splitAxis] * g);
355 IConnectableLayer* elementWiseUnary0 = net->AddElementwiseUnaryLayer(descriptor,
"elementwiseunary_0");
356 IConnectableLayer* elementWiseUnary1 = net->AddElementwiseUnaryLayer(descriptor,
"elementwiseunary_0");
360 Connect(input, splitter, inputTensorInfo, 0, 0);
361 Connect(splitter, elementWiseUnary0, intermediateInfo, 0, 0);
362 Connect(splitter, elementWiseUnary1, intermediateInfo, 1, 0);
364 std::vector<IConnectableLayer*> pooling2dLayers{elementWiseUnary0, elementWiseUnary1};
366 for (
unsigned int i = 0; i < outputShapes.size(); ++i)
369 IConnectableLayer* output = net->AddOutputLayer(boost::numeric_cast<LayerBindingId>(i));
370 Connect(pooling2dLayers[i], output, outputTensorInfo, 0, 0);
373 std::map<int, std::vector<float>> inputTensorData = {{ 0,inputData }};
374 std::map<int, std::vector<float>> expectedOutputData = {{ 0, expectedOutput0 }, { 1, expectedOutput1 }};
386 runtime->LoadNetwork(networkIdentifier, std::move(optimizedNet));
391 if (subTensorHandle && subTensorHandle->GetParent())
398 for (
auto&& layer : theGraph)
402 unsigned int numberOfSubTensors = 0;
403 for (
unsigned int i = 0; i < layer->GetNumInputSlots(); ++i)
408 ++numberOfSubTensors;
417 inputTensors.reserve(inputTensorData.size());
418 for (
auto&& it : inputTensorData)
420 inputTensors.push_back({it.first,
421 ConstTensor(runtime->GetInputTensorInfo(networkIdentifier, it.first), it.second.data())});
424 outputTensors.reserve(expectedOutputData.size());
425 std::map<int, std::vector<float>> outputStorage;
426 for (
auto&& it : expectedOutputData)
428 std::vector<float> out(it.second.size());
429 outputStorage.emplace(it.first, out);
430 outputTensors.push_back({it.first,
431 Tensor(runtime->GetOutputTensorInfo(networkIdentifier, it.first),
432 outputStorage.at(it.first).data())});
436 runtime->EnqueueWorkload(networkIdentifier, inputTensors, outputTensors);
439 float tolerance = 0.000001f;
440 for (
auto&& it : expectedOutputData)
442 std::vector<float> out = outputStorage.at(it.first);
443 for (
unsigned int i = 0; i < out.size(); ++i)
445 BOOST_CHECK_MESSAGE(Compare<armnn::DataType::Float32>(it.second[i], out[i], tolerance) ==
true,
446 "Actual output: " << out[i] <<
". Expected output:" << it.second[i]);
454 using namespace armnn;
456 unsigned int splitAxis = 2;
457 unsigned int numSplit = 2;
461 const std::vector<TensorShape> outputShapes{{ 1, 1, 2, 4 },
464 const float qScale = 1.0f;
465 const int32_t qOffset = 0;
468 std::vector<float> inputData{
469 9.0f, 27.0f, 18.0f, 36.0f,
470 18.0f, 9.0f, 18.0f, 9.0f,
471 27.0f, 18.0f, 9.0f, 27.0f,
472 9.0f, 27.0f, 9.0f, 18.0f,
475 std::vector<float> expectedOutput0{
476 7.0f, 11.0f, 13.0f, 9.0f,
477 7.0f, 11.0f, 13.0f, 9.0f
480 std::vector<float> expectedOutput1{
481 9.0f, 11.0f, 12.0f, 7.0f,
482 9.0f, 11.0f, 12.0f, 7.0f
507 splitterDimSizes[i] = inputTensorInfo.
GetShape()[i];
510 if (splitterDimSizes[splitAxis] % numSplit != 0)
512 throw ParseException(
"Number of splits must evenly divide the dimension");
515 splitterDimSizes[splitAxis] /= numSplit;
519 for (
unsigned int g = 0; g < numSplit; ++g)
522 for (
unsigned int dimIdx = 0; dimIdx < splitterDimSizes.size(); ++dimIdx)
524 splitDesc.
SetViewSize(g, dimIdx, splitterDimSizes[dimIdx]);
526 splitDesc.SetViewOriginCoord(g, splitAxis, splitterDimSizes[splitAxis] * g);
530 IConnectableLayer* pooling2d0 = net->AddPooling2dLayer(descriptor,
"pooling2d_0");
531 IConnectableLayer* pooling2d1 = net->AddPooling2dLayer(descriptor,
"pooling2d_1");
535 Connect(input, splitter, inputTensorInfo, 0, 0);
536 Connect(splitter, pooling2d0, intermediateInfo, 0, 0);
537 Connect(splitter, pooling2d1, intermediateInfo, 1, 0);
539 std::vector<IConnectableLayer*> pooling2dLayers{pooling2d0, pooling2d1};
541 for (
unsigned int i = 0; i < outputShapes.size(); ++i)
544 IConnectableLayer* output = net->AddOutputLayer(boost::numeric_cast<LayerBindingId>(i));
545 Connect(pooling2dLayers[i], output, outputTensorInfo, 0, 0);
548 std::map<int, std::vector<float>> inputTensorData = {{ 0,inputData }};
549 std::map<int, std::vector<float>> expectedOutputData = {{ 0, expectedOutput0 }, { 1, expectedOutput1 }};
561 runtime->LoadNetwork(networkIdentifier, std::move(optimizedNet));
566 if (subTensorHandle && subTensorHandle->GetParent())
573 for (
auto&& layer : theGraph)
577 unsigned int numberOfSubTensors = 0;
578 for (
unsigned int i = 0; i < layer->GetNumInputSlots(); ++i)
583 ++numberOfSubTensors;
592 inputTensors.reserve(inputTensorData.size());
593 for (
auto&& it : inputTensorData)
595 inputTensors.push_back({it.first,
596 ConstTensor(runtime->GetInputTensorInfo(networkIdentifier, it.first), it.second.data())});
599 outputTensors.reserve(expectedOutputData.size());
600 std::map<int, std::vector<float>> outputStorage;
601 for (
auto&& it : expectedOutputData)
603 std::vector<float> out(it.second.size());
604 outputStorage.emplace(it.first, out);
605 outputTensors.push_back({it.first,
606 Tensor(runtime->GetOutputTensorInfo(networkIdentifier, it.first),
607 outputStorage.at(it.first).data())});
611 runtime->EnqueueWorkload(networkIdentifier, inputTensors, outputTensors);
614 float tolerance = 0.000001f;
615 for (
auto&& it : expectedOutputData)
617 std::vector<float> out = outputStorage.at(it.first);
618 for (
unsigned int i = 0; i < out.size(); ++i)
620 BOOST_CHECK_MESSAGE(Compare<armnn::DataType::Float32>(it.second[i], out[i], tolerance) ==
true,
621 "Actual output: " << out[i] <<
". Expected output:" << it.second[i]);
629 std::shared_ptr<NeonMemoryManager> memoryManager = std::make_shared<NeonMemoryManager>(
630 std::make_unique<arm_compute::Allocator>(),
640 memoryManager->Acquire();
642 float* buffer =
reinterpret_cast<float*
>(handle->Map());
643 BOOST_CHECK(buffer !=
nullptr);
646 BOOST_CHECK(buffer[0] == 1.5f);
647 BOOST_CHECK(buffer[1] == 2.5f);
649 memoryManager->Release();
651 memoryManager->Acquire();
653 float* buffer =
reinterpret_cast<float*
>(handle->Map());
654 BOOST_CHECK(buffer !=
nullptr);
657 BOOST_CHECK(buffer[0] == 3.5f);
658 BOOST_CHECK(buffer[1] == 4.5f);
660 memoryManager->Release();
662 float testPtr[2] = { 2.5f, 5.5f };
669 std::shared_ptr<NeonMemoryManager> memoryManager = std::make_shared<NeonMemoryManager>(
670 std::make_unique<arm_compute::Allocator>(),
679 memoryManager->Acquire();
682 BOOST_CHECK((PolymorphicDowncast<NeonTensorHandle*>(handle.get()))->GetTensor().buffer() ==
nullptr);
684 float testPtr[2] = { 2.5f, 5.5f };
687 float* buffer =
reinterpret_cast<float*
>(handle->Map());
688 BOOST_CHECK(buffer !=
nullptr);
689 BOOST_CHECK(buffer == testPtr);
691 BOOST_CHECK(buffer[0] == 2.5f);
692 BOOST_CHECK(buffer[1] == 5.5f);
695 BOOST_CHECK(buffer[0] == 3.5f);
696 BOOST_CHECK(buffer[1] == 10.0f);
697 memoryManager->Release();
BOOST_AUTO_TEST_SUITE(TensorflowLiteParser)
static IRuntimePtr Create(const CreationOptions &options)
A ViewsDescriptor for the SplitterLayer.
Interface for a layer that is connectable to other layers via InputSlots and OutputSlots.
uint32_t m_PadBottom
Padding bottom value in the height dimension.
const TensorShape & GetShape() const
uint32_t m_PadLeft
Padding left value in the width dimension.
std::unique_ptr< ITensorHandle > CreateTensorHandle(const TensorInfo &tensorInfo) const override
uint32_t m_PoolWidth
Pooling width value.
float m_Beta
Exponentiation value.
std::unique_ptr< IRuntime, void(*)(IRuntime *runtime)> IRuntimePtr
PaddingMethod m_PaddingMethod
The padding method to be used. (Exclude, IgnoreValue).
uint32_t m_PadTop
Padding top value in the height dimension.
std::vector< std::pair< LayerBindingId, class ConstTensor > > InputTensors
Copyright (c) 2020 ARM Limited.
uint32_t m_StrideX
Stride value when proceeding through input for the width dimension.
virtual void SetTensorInfo(const TensorInfo &tensorInfo)=0
A tensor defined by a TensorInfo (shape and data type) and a mutable backing store.
uint32_t m_PoolHeight
Pooling height value.
uint32_t m_PadRight
Padding right value in the width dimension.
IOptimizedNetworkPtr Optimize(const INetwork &network, const std::vector< BackendId > &backendPreferences, const IDeviceSpec &deviceSpec, const OptimizerOptions &options=OptimizerOptions(), Optional< std::vector< std::string > &> messages=EmptyOptional())
Create an optimized version of the network.
Status SetViewSize(uint32_t view, uint32_t coord, uint32_t value)
Set the size of the views.
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
std::vector< std::pair< LayerBindingId, class Tensor > > OutputTensors
std::unique_ptr< IOptimizedNetwork, void(*)(IOptimizedNetwork *network)> IOptimizedNetworkPtr
#define ARMNN_ASSERT(COND)
BOOST_AUTO_TEST_CASE(CheckConvolution2dLayer)
ITensorHandle * GetData() const
Gets the allocated tensor memory.
BOOST_AUTO_TEST_SUITE_END()
A ElementwiseUnaryDescriptor for the ElementwiseUnaryLayer.
PoolingAlgorithm m_PoolType
The pooling algorithm to use (Max. Average, L2).
The padding fields count, but are ignored.
CPU Execution: NEON: ArmCompute.
unsigned int GetNumDimensions() const
Function that returns the tensor rank.
virtual const IInputSlot & GetInputSlot(unsigned int index) const =0
Get a const input slot handle by slot index.
const OutputHandler & GetOutputHandler() const
virtual const IOutputSlot & GetOutputSlot(unsigned int index) const =0
Get the const output slot handle by slot index.
void Connect(armnn::IConnectableLayer *from, armnn::IConnectableLayer *to, const armnn::TensorInfo &tensorInfo, unsigned int fromIndex, unsigned int toIndex)
OriginsDescriptor CreateDescriptorForConcatenation(TensorShapeIt first, TensorShapeIt last, unsigned int concatenationDimension)
Convenience template to create an OriginsDescriptor to use when creating a ConcatLayer for performing...
std::unique_ptr< INetwork, void(*)(INetwork *network)> INetworkPtr
virtual int Connect(IInputSlot &destination)=0
A Pooling2dDescriptor for the Pooling2dLayer.
static INetworkPtr Create(NetworkOptions networkOptions={})
A SoftmaxDescriptor for the SoftmaxLayer.
uint32_t m_StrideY
Stride value when proceeding through input for the height dimension.