• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "NeuralNetworksWrapper.h"
18 
19 //#include <android-base/logging.h>
20 #include <gtest/gtest.h>
21 
22 using namespace android::nn::wrapper;
23 
24 namespace {
25 
26 typedef float Matrix3x4[3][4];
27 typedef float Matrix4[4];
28 
29 class TrivialTest : public ::testing::Test {
30 protected:
SetUp()31     virtual void SetUp() {}
32 
33     const Matrix3x4 matrix1 = {{1.f, 2.f, 3.f, 4.f}, {5.f, 6.f, 7.f, 8.f}, {9.f, 10.f, 11.f, 12.f}};
34     const Matrix3x4 matrix2 = {{100.f, 200.f, 300.f, 400.f},
35                                {500.f, 600.f, 700.f, 800.f},
36                                {900.f, 1000.f, 1100.f, 1200.f}};
37     const Matrix4 matrix2b = {100.f, 200.f, 300.f, 400.f};
38     const Matrix3x4 matrix3 = {{20.f, 30.f, 40.f, 50.f},
39                                {21.f, 22.f, 23.f, 24.f},
40                                {31.f, 32.f, 33.f, 34.f}};
41     const Matrix3x4 expected2 = {{101.f, 202.f, 303.f, 404.f},
42                                  {505.f, 606.f, 707.f, 808.f},
43                                  {909.f, 1010.f, 1111.f, 1212.f}};
44     const Matrix3x4 expected2b = {{101.f, 202.f, 303.f, 404.f},
45                                   {105.f, 206.f, 307.f, 408.f},
46                                   {109.f, 210.f, 311.f, 412.f}};
47     const Matrix3x4 expected2c = {{100.f, 400.f, 900.f, 1600.f},
48                                   {500.f, 1200.f, 2100.f, 3200.f},
49                                   {900.f, 2000.f, 3300.f, 4800.f}};
50 
51     const Matrix3x4 expected3 = {{121.f, 232.f, 343.f, 454.f},
52                                  {526.f, 628.f, 730.f, 832.f},
53                                  {940.f, 1042.f, 1144.f, 1246.f}};
54     const Matrix3x4 expected3b = {{22.f, 34.f, 46.f, 58.f},
55                                   {31.f, 34.f, 37.f, 40.f},
56                                   {49.f, 52.f, 55.f, 58.f}};
57 };
58 
59 // Create a model that can add two tensors using a one node graph.
CreateAddTwoTensorModel(Model * model)60 void CreateAddTwoTensorModel(Model* model) {
61     OperandType matrixType(Type::TENSOR_FLOAT32, {3, 4});
62     OperandType scalarType(Type::INT32, {});
63     int32_t activation(ANEURALNETWORKS_FUSED_NONE);
64     auto a = model->addOperand(&matrixType);
65     auto b = model->addOperand(&matrixType);
66     auto c = model->addOperand(&matrixType);
67     auto d = model->addOperand(&scalarType);
68     model->setOperandValue(d, &activation, sizeof(activation));
69     model->addOperation(ANEURALNETWORKS_ADD, {a, b, d}, {c});
70     model->identifyInputsAndOutputs({a, b}, {c});
71     ASSERT_TRUE(model->isValid());
72     model->finish();
73 }
74 
75 // Create a model that can add three tensors using a two node graph,
76 // with one tensor set as part of the model.
CreateAddThreeTensorModel(Model * model,const Matrix3x4 bias)77 void CreateAddThreeTensorModel(Model* model, const Matrix3x4 bias) {
78     OperandType matrixType(Type::TENSOR_FLOAT32, {3, 4});
79     OperandType scalarType(Type::INT32, {});
80     int32_t activation(ANEURALNETWORKS_FUSED_NONE);
81     auto a = model->addOperand(&matrixType);
82     auto b = model->addOperand(&matrixType);
83     auto c = model->addOperand(&matrixType);
84     auto d = model->addOperand(&matrixType);
85     auto e = model->addOperand(&matrixType);
86     auto f = model->addOperand(&scalarType);
87     model->setOperandValue(e, bias, sizeof(Matrix3x4));
88     model->setOperandValue(f, &activation, sizeof(activation));
89     model->addOperation(ANEURALNETWORKS_ADD, {a, c, f}, {b});
90     model->addOperation(ANEURALNETWORKS_ADD, {b, e, f}, {d});
91     model->identifyInputsAndOutputs({c, a}, {d});
92     ASSERT_TRUE(model->isValid());
93     model->finish();
94 }
95 
96 // Check that the values are the same. This works only if dealing with integer
97 // value, otherwise we should accept values that are similar if not exact.
CompareMatrices(const Matrix3x4 & expected,const Matrix3x4 & actual)98 int CompareMatrices(const Matrix3x4& expected, const Matrix3x4& actual) {
99     int errors = 0;
100     for (int i = 0; i < 3; i++) {
101         for (int j = 0; j < 4; j++) {
102             if (expected[i][j] != actual[i][j]) {
103                 printf("expected[%d][%d] != actual[%d][%d], %f != %f\n", i, j, i, j,
104                        static_cast<double>(expected[i][j]), static_cast<double>(actual[i][j]));
105                 errors++;
106             }
107         }
108     }
109     return errors;
110 }
111 
TEST_F(TrivialTest,AddTwo)112 TEST_F(TrivialTest, AddTwo) {
113     Model modelAdd2;
114     CreateAddTwoTensorModel(&modelAdd2);
115 
116     // Test the one node model.
117     Matrix3x4 actual;
118     memset(&actual, 0, sizeof(actual));
119     Compilation compilation(&modelAdd2);
120     compilation.finish();
121     Execution execution(&compilation);
122     ASSERT_EQ(execution.setInput(0, matrix1, sizeof(Matrix3x4)), Result::NO_ERROR);
123     ASSERT_EQ(execution.setInput(1, matrix2, sizeof(Matrix3x4)), Result::NO_ERROR);
124     ASSERT_EQ(execution.setOutput(0, actual, sizeof(Matrix3x4)), Result::NO_ERROR);
125     ASSERT_EQ(execution.compute(), Result::NO_ERROR);
126     ASSERT_EQ(CompareMatrices(expected2, actual), 0);
127 }
128 
TEST_F(TrivialTest,AddThree)129 TEST_F(TrivialTest, AddThree) {
130     Model modelAdd3;
131     CreateAddThreeTensorModel(&modelAdd3, matrix3);
132 
133     // Test the three node model.
134     Matrix3x4 actual;
135     memset(&actual, 0, sizeof(actual));
136     Compilation compilation2(&modelAdd3);
137     compilation2.finish();
138     Execution execution2(&compilation2);
139     ASSERT_EQ(execution2.setInput(0, matrix1, sizeof(Matrix3x4)), Result::NO_ERROR);
140     ASSERT_EQ(execution2.setInput(1, matrix2, sizeof(Matrix3x4)), Result::NO_ERROR);
141     ASSERT_EQ(execution2.setOutput(0, actual, sizeof(Matrix3x4)), Result::NO_ERROR);
142     ASSERT_EQ(execution2.compute(), Result::NO_ERROR);
143     ASSERT_EQ(CompareMatrices(expected3, actual), 0);
144 
145     // Test it a second time to make sure the model is reusable.
146     memset(&actual, 0, sizeof(actual));
147     Compilation compilation3(&modelAdd3);
148     compilation3.finish();
149     Execution execution3(&compilation3);
150     ASSERT_EQ(execution3.setInput(0, matrix1, sizeof(Matrix3x4)), Result::NO_ERROR);
151     ASSERT_EQ(execution3.setInput(1, matrix1, sizeof(Matrix3x4)), Result::NO_ERROR);
152     ASSERT_EQ(execution3.setOutput(0, actual, sizeof(Matrix3x4)), Result::NO_ERROR);
153     ASSERT_EQ(execution3.compute(), Result::NO_ERROR);
154     ASSERT_EQ(CompareMatrices(expected3b, actual), 0);
155 }
156 
TEST_F(TrivialTest,BroadcastAddTwo)157 TEST_F(TrivialTest, BroadcastAddTwo) {
158     Model modelBroadcastAdd2;
159     // activation: NONE.
160     int32_t activation_init[] = {ANEURALNETWORKS_FUSED_NONE};
161     OperandType scalarType(Type::INT32, {1});
162     auto activation = modelBroadcastAdd2.addOperand(&scalarType);
163     modelBroadcastAdd2.setOperandValue(activation, activation_init, sizeof(int32_t) * 1);
164 
165     OperandType matrixType(Type::TENSOR_FLOAT32, {1, 1, 3, 4});
166     OperandType matrixType2(Type::TENSOR_FLOAT32, {4});
167 
168     auto a = modelBroadcastAdd2.addOperand(&matrixType);
169     auto b = modelBroadcastAdd2.addOperand(&matrixType2);
170     auto c = modelBroadcastAdd2.addOperand(&matrixType);
171     modelBroadcastAdd2.addOperation(ANEURALNETWORKS_ADD, {a, b, activation}, {c});
172     modelBroadcastAdd2.identifyInputsAndOutputs({a, b}, {c});
173     ASSERT_TRUE(modelBroadcastAdd2.isValid());
174     modelBroadcastAdd2.finish();
175 
176     // Test the one node model.
177     Matrix3x4 actual;
178     memset(&actual, 0, sizeof(actual));
179     Compilation compilation(&modelBroadcastAdd2);
180     compilation.finish();
181     Execution execution(&compilation);
182     ASSERT_EQ(execution.setInput(0, matrix1, sizeof(Matrix3x4)), Result::NO_ERROR);
183     ASSERT_EQ(execution.setInput(1, matrix2b, sizeof(Matrix4)), Result::NO_ERROR);
184     ASSERT_EQ(execution.setOutput(0, actual, sizeof(Matrix3x4)), Result::NO_ERROR);
185     ASSERT_EQ(execution.compute(), Result::NO_ERROR);
186     ASSERT_EQ(CompareMatrices(expected2b, actual), 0);
187 }
188 
TEST_F(TrivialTest,BroadcastMulTwo)189 TEST_F(TrivialTest, BroadcastMulTwo) {
190     Model modelBroadcastMul2;
191     // activation: NONE.
192     int32_t activation_init[] = {ANEURALNETWORKS_FUSED_NONE};
193     OperandType scalarType(Type::INT32, {1});
194     auto activation = modelBroadcastMul2.addOperand(&scalarType);
195     modelBroadcastMul2.setOperandValue(activation, activation_init, sizeof(int32_t) * 1);
196 
197     OperandType matrixType(Type::TENSOR_FLOAT32, {1, 1, 3, 4});
198     OperandType matrixType2(Type::TENSOR_FLOAT32, {4});
199 
200     auto a = modelBroadcastMul2.addOperand(&matrixType);
201     auto b = modelBroadcastMul2.addOperand(&matrixType2);
202     auto c = modelBroadcastMul2.addOperand(&matrixType);
203     modelBroadcastMul2.addOperation(ANEURALNETWORKS_MUL, {a, b, activation}, {c});
204     modelBroadcastMul2.identifyInputsAndOutputs({a, b}, {c});
205     ASSERT_TRUE(modelBroadcastMul2.isValid());
206     modelBroadcastMul2.finish();
207 
208     // Test the one node model.
209     Matrix3x4 actual;
210     memset(&actual, 0, sizeof(actual));
211     Compilation compilation(&modelBroadcastMul2);
212     compilation.finish();
213     Execution execution(&compilation);
214     ASSERT_EQ(execution.setInput(0, matrix1, sizeof(Matrix3x4)), Result::NO_ERROR);
215     ASSERT_EQ(execution.setInput(1, matrix2b, sizeof(Matrix4)), Result::NO_ERROR);
216     ASSERT_EQ(execution.setOutput(0, actual, sizeof(Matrix3x4)), Result::NO_ERROR);
217     ASSERT_EQ(execution.compute(), Result::NO_ERROR);
218     ASSERT_EQ(CompareMatrices(expected2c, actual), 0);
219 }
220 
221 }  // end namespace
222