dc6c7847833e31fc2bc6dfa78e581701fa951e3d
[platform/core/ml/nnfw.git] / compute / ARMComputeEx / src / runtime / NEON / functions / NEFullyConnectedReshapingLayer.cpp
1 /*
2  * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved
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 "arm_compute/runtime/NEON/functions/NEFullyConnectedReshapingLayer.h"
18
19 #include <arm_compute/runtime/NEON/functions/NEFullyConnectedLayer.h>
20 #include <arm_compute/runtime/NEON/functions/NEFullyConnectedHybridLayer.h>
21 #include <arm_compute/runtime/NEON/functions/NEFullyConnectedLayerEx.h>
22
23 using namespace arm_compute;
24
25 void NEFullyConnectedReshapingLayer::configure(const arm_compute::ITensor *input,
26                                                const arm_compute::ITensor *weights,
27                                                const arm_compute::ITensor *biases,
28                                                arm_compute::ITensor *output, bool needs_reshape,
29                                                const arm_compute::TensorShape &reshape,
30                                                KernelType kernel_type)
31 {
32   _input = input;
33   _weights = weights;
34   _biases = biases;
35   _output = output;
36   _needs_reshape = needs_reshape;
37
38   const ITensor *input_to_use = input;
39   if (_needs_reshape)
40   {
41     // reshape
42     auto_init_if_empty(*_neon_buffer.info(), _input->info()->clone()->set_tensor_shape(reshape));
43     _neon_reshape.configure(_input, &_neon_buffer);
44     input_to_use = &_neon_buffer;
45   }
46
47   _neon_fc = [&]() {
48     if (kernel_type == KernelType::GENERAL)
49     {
50       auto fc = new arm_compute::NEFullyConnectedLayerEx{_memory_manager};
51       fc->configure(input_to_use, _weights, _biases, _output);
52       return std::unique_ptr<arm_compute::IFunction>(fc);
53     }
54     else
55     {
56       assert(kernel_type == KernelType::PREPROCESSED_WEIGHTS);
57
58       bool is_hybrid = input->info()->data_type() == DataType::F32 &&
59                        (weights->info()->data_type() == DataType::S8 ||
60                         weights->info()->data_type() == DataType::QASYMM8_SIGNED);
61
62       if (is_hybrid)
63       {
64         auto fc = new arm_compute::NEFullyConnectedHybridLayer{_memory_manager};
65         ITensorInfo *weights_info = const_cast<ITensorInfo *>(_weights->info());
66         const auto orgin_weights_data_type = weights_info->data_type();
67         weights_info->set_data_type(DataType::QASYMM8_SIGNED);
68         fc->configure(input_to_use, _weights, _biases, _output);
69         weights_info->set_data_type(orgin_weights_data_type);
70         return std::unique_ptr<arm_compute::IFunction>(fc);
71       }
72       else
73       {
74         auto fc = new arm_compute::NEFullyConnectedLayer{_memory_manager};
75         fc->configure(input_to_use, _weights, _biases, _output);
76         return std::unique_ptr<arm_compute::IFunction>(fc);
77       }
78     }
79   }();
80
81   // NOTE _neon_buffer is inaccessible from outside, and thus it is safe to invoke allocate here.
82   if (_needs_reshape)
83   {
84     _neon_buffer.allocator()->allocate();
85   }
86 }
87
88 void NEFullyConnectedReshapingLayer::run(void)
89 {
90   if (_needs_reshape)
91     _neon_reshape.run();
92
93   _neon_fc->run();
94 }
95
96 void NEFullyConnectedReshapingLayer::prepare(void) { _neon_fc->prepare(); }