• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright © 2022 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 
6 #include <TestUtils.hpp>
7 
8 #include <Half.hpp>
9 #include <Optimizer.hpp>
10 
11 #include <doctest/doctest.h>
12 
13 using namespace armnn;
14 
15 TEST_SUITE("Optimizer")
16 {
17 using namespace armnn::optimizations;
18 
19 TEST_CASE("ConvertConstantsFloatToHalfTest")
20 {
21     armnn::Graph graph;
22 
23     const armnn::TensorInfo info({ 1, 1, 1, 2 }, armnn::DataType::Float16);
24 
25     // Create const tensor from fp32 data
26     unsigned int dims[] = { 4, 1, 1, 1 };
27     std::vector<float> floatWeights{ 1.0f, 2.0f, 3.0f, 4.0f };
28     armnn::TensorInfo weightsInfo = armnn::TensorInfo(4, dims, armnn::DataType::Float32, 0.0f, 0, true);
29     armnn::ConstTensor weights(weightsInfo, floatWeights);
30 
31     // Create simple test network
32     auto input = graph.AddLayer<armnn::InputLayer>(0, "input");
33     input->GetOutputSlot().SetTensorInfo(info);
34 
35     auto fc      = graph.AddLayer<armnn::FullyConnectedLayer>(armnn::FullyConnectedDescriptor(), "fc");
36     fc->GetOutputSlot().SetTensorInfo(info);
37 
38     auto weightsLayer = graph.AddLayer<armnn::ConstantLayer>("weights");
39     weightsLayer->m_LayerOutput = std::make_unique<armnn::ScopedTensorHandle>(weights);
40     weightsLayer->GetOutputSlot().SetTensorInfo(weightsInfo);
41 
42     auto output = graph.AddLayer<armnn::OutputLayer>(1, "output");
43 
44     // Connect up the layers
45     input->GetOutputSlot().Connect(fc->GetInputSlot(0));
46     weightsLayer->GetOutputSlot().Connect(fc->GetInputSlot(1));
47     fc->GetOutputSlot().Connect(output->GetInputSlot(0));
48 
49     // Check tensor data type before conversion
50     CHECK(weightsLayer->m_LayerOutput->GetTensorInfo().GetDataType() == armnn::DataType::Float32);
51 
52     // Run the optimizer
53     armnn::Optimizer::Pass(graph, armnn::MakeOptimizations(ConvertConstantsFloatToHalf()));
54 
55     // Check tensor data type after conversion
56     CHECK(weightsLayer->m_LayerOutput->GetTensorInfo().GetDataType() == armnn::DataType::Float16);
57 
58     // Check whether data matches expected fp16 data
59     const Half* data = weightsLayer->m_LayerOutput->GetConstTensor<Half>();
60     CHECK(data[0] == Half(1.0f));
61     CHECK(data[1] == Half(2.0f));
62     CHECK(data[2] == Half(3.0f));
63     CHECK(data[3] == Half(4.0f));
64 }
65 
66 
67 TEST_CASE("ConvertConstantsFloatToHalfTest_constant")
68 {
69     armnn::Graph graph;
70 
71     // Create the simple test network with Weights and Biases as inputs to a FullyConnected layer.
72     auto input   = graph.AddLayer<armnn::InputLayer>(0, "Input");
73     auto weights = graph.AddLayer<armnn::ConstantLayer>("Weights");
74     auto biases  = graph.AddLayer<armnn::ConstantLayer>("Biases");
75 
76     armnn::FullyConnectedDescriptor desc;
77     desc.m_BiasEnabled = true;
78     desc.m_ConstantWeights = true;
79     auto fcLayer = graph.AddLayer<armnn::FullyConnectedLayer>(desc, "FullyConnected");
80     auto output  = graph.AddLayer<armnn::OutputLayer>(1, "Output");
81 
82     float expectedWeightsData[] = { 1.0f, 2.0f, 3.0f, 4.0f };
83     float expectedBiasesData[]  = { 2.0f, 2.0f };
84 
85     const armnn::TensorInfo inputInfo  ({ 1, 2, 2, 3 }, armnn::DataType::Float16);
86     const armnn::TensorInfo outputInfo ({ 1, 2, 2, 3 }, armnn::DataType::Float16);
87     const armnn::TensorInfo weightsInfo({ 4 }, armnn::DataType::Float32, 0.0f, 0, true);
88     const armnn::TensorInfo biasesInfo ({ 2 }, armnn::DataType::Float32, 0.0f, 0, true);
89 
90     // Set the m_LayerOutput for the optimizer to point to.
91     armnn::ConstTensor weightsTensor(weightsInfo, &expectedWeightsData);
92     armnn::ConstTensor biasesTensor(biasesInfo, &expectedBiasesData);
93     weights->m_LayerOutput = std::make_unique<armnn::ScopedTensorHandle>(weightsTensor);
94     biases->m_LayerOutput  = std::make_unique<armnn::ScopedTensorHandle>(biasesTensor);
95 
96     input->GetOutputSlot().SetTensorInfo(inputInfo);
97     weights->GetOutputSlot().SetTensorInfo(weightsInfo);
98     biases->GetOutputSlot().SetTensorInfo(biasesInfo);
99     fcLayer->GetOutputSlot().SetTensorInfo(outputInfo);
100 
101     // Connect up the layers
102     input->GetOutputSlot(0).Connect(fcLayer->GetInputSlot(0));
103     weights->GetOutputSlot(0).Connect(fcLayer->GetInputSlot(1));
104     biases->GetOutputSlot(0).Connect(fcLayer->GetInputSlot(2));
105     fcLayer->GetOutputSlot(0).Connect(output->GetInputSlot(0));
106 
107     // Check tensor data type before conversion
108     CHECK(5 == graph.GetNumLayers());
109     CHECK(weights->m_LayerOutput->GetTensorInfo().GetDataType() == armnn::DataType::Float32);
110 
111     // Run the optimizer
112     armnn::Optimizer::Pass(graph, armnn::MakeOptimizations(ConvertConstantsFloatToHalf()));
113 
114     // Check tensor data type after conversion
115     CHECK(5 == graph.GetNumLayers());
116     CHECK(weights->m_LayerOutput->GetTensorInfo().GetDataType() == armnn::DataType::Float16);
117 
118     // Check whether weights data matches expected fp16 data
119     const Half* data = weights->m_LayerOutput->GetConstTensor<Half>();
120     CHECK(data[0] == Half(1.0f));
121     CHECK(data[1] == Half(2.0f));
122     CHECK(data[2] == Half(3.0f));
123     CHECK(data[3] == Half(4.0f));
124 
125     // Check whether bias data matches expected fp16 data
126     const Half* biasData = biases->m_LayerOutput->GetConstTensor<Half>();
127     CHECK(biasData[0] == Half(2.0f));
128     CHECK(biasData[1] == Half(2.0f));
129 }
130 
131 
132 }