blob: 0d2574957f0a01a771c85b82df9180adb3d35d9c [file] [log] [blame]
SiCong Lif44bbc52022-08-29 18:25:51 +01001/*
2 * Copyright (c) 2022 Arm Limited.
3 *
4 * SPDX-License-Identifier: MIT
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24#include "GpuKernelComponentGroup.h"
25
26#include "arm_compute/core/ITensorInfo.h"
27#include "arm_compute/core/Validate.h"
28#include "src/dynamic_fusion/sketch/gpu/components/IGpuKernelComponent.h"
29
Viet-Hoa Do04f46202022-12-14 14:49:56 +000030#include <algorithm>
31
SiCong Lif44bbc52022-08-29 18:25:51 +010032namespace arm_compute
33{
34namespace experimental
35{
36namespace dynamic_fusion
37{
38bool GpuKernelComponentGroup::add_component(ComponentPtr component)
39{
Viet-Hoa Do04f46202022-12-14 14:49:56 +000040 ARM_COMPUTE_ERROR_ON_MSG(
41 _finalized, "The component group has been finalized and cannot be altered.");
42
SiCong Lif44bbc52022-08-29 18:25:51 +010043 // note: Constraint 1 is guaranteed as a precondition
44 // Constraint 2
45 if(component->type() != GpuComponentType::Output && _components.size() >= max_fused_components)
46 {
47 return false;
48 }
49 // Constraint 3.1: Pattern: (Unfusable + Output)
50 if(!_components.empty() && get_root_component()->type() == GpuComponentType::Unfusable && component->type() != GpuComponentType::Output)
51 {
52 return false;
53 }
54 // Constraint 3.2
55 if(!_components.empty() && (component->type() != GpuComponentType::Simple && component->type() != GpuComponentType::Output))
56 {
57 return false;
58 }
SiCong Lif44bbc52022-08-29 18:25:51 +010059 // Constraint 4
60 if(component->type() != GpuComponentType::Unfusable && component->tensors().get_const_dst_tensors().size() != 1U)
61 {
62 return false;
63 }
64 // Constraint 5
65 if(!_components.empty() && !(get_root_component()->properties() == component->properties()))
66 {
67 return false;
68 }
69 // Constraint 7
70 if(!_components.empty())
71 {
72 const auto root_dst_tensors = get_root_component()->tensors().get_const_dst_tensors();
73 ARM_COMPUTE_ERROR_ON(root_dst_tensors.empty());
74 const auto first_dst_tensor = root_dst_tensors[0];
75 const auto dst_tensors = component->tensors().get_const_dst_tensors();
76 for(const auto &t : root_dst_tensors)
77 {
78 if(detail::have_different_dimensions(t->tensor_shape(), first_dst_tensor->tensor_shape(), 0))
79 {
80 return false;
81 }
82 }
83 for(const auto &t : dst_tensors)
84 {
85 if(detail::have_different_dimensions(t->tensor_shape(), first_dst_tensor->tensor_shape(), 0))
86 {
87 return false;
88 }
89 }
90 }
91 // Constraint 8
92 if(!_components.empty())
93 {
94 const auto root_dst_tensors = get_root_component()->tensors().get_const_dst_tensors();
95 ARM_COMPUTE_ERROR_ON(root_dst_tensors.empty());
96 const auto first_dst_tensor_layout = root_dst_tensors[0]->data_layout();
97 const auto dst_tensors = component->tensors().get_const_dst_tensors();
98 for(const auto &t : root_dst_tensors)
99 {
100 if(t->data_layout() != first_dst_tensor_layout)
101 {
102 return false;
103 }
104 }
105 for(const auto &t : dst_tensors)
106 {
107 if(t->data_layout() != first_dst_tensor_layout)
108 {
109 return false;
110 }
111 }
112 }
113 // Constraint 9
114 if(component->tensors().get_const_dst_tensors().size() >= max_dst_tensors)
115 {
116 return false;
117 }
118 // Constraint 9 corollary
119 if(component->type() == GpuComponentType::Output && _components.size() >= max_fused_components + max_dst_tensors)
120 {
121 return false;
122 }
123 _components.push_back(component);
124 return true;
125}
126
Viet-Hoa Do04f46202022-12-14 14:49:56 +0000127void GpuKernelComponentGroup::finalize()
SiCong Lif44bbc52022-08-29 18:25:51 +0100128{
Viet-Hoa Do04f46202022-12-14 14:49:56 +0000129 if(_finalized)
SiCong Lif44bbc52022-08-29 18:25:51 +0100130 {
Viet-Hoa Do04f46202022-12-14 14:49:56 +0000131 return;
SiCong Lif44bbc52022-08-29 18:25:51 +0100132 }
133
Viet-Hoa Do04f46202022-12-14 14:49:56 +0000134 _finalized = true;
135
136 std::set<const ITensorInfo *> input_tensors;
137 std::set<const ITensorInfo *> output_tensors;
138
139 for(auto component : _components)
140 {
141 const auto tensors = component->tensors();
142 const auto src_tensors = tensors.get_const_src_tensors();
143 const auto dst_tensors = tensors.get_const_dst_tensors();
144
145 // Detect input, output and intermediate tensors.
146 for(auto tensor : src_tensors)
147 {
148 const auto output_tensors_it = output_tensors.find(tensor);
149
150 if(output_tensors_it != output_tensors.end())
151 {
152 // This tensor is the output of another operator.
153 // It must be marked as intermediate tensor.
154 output_tensors.erase(output_tensors_it);
155 _interm_tensors.insert(tensor);
156 }
157 else if(_interm_tensors.find(tensor) == _interm_tensors.end())
158 {
159 input_tensors.insert(tensor);
160 }
161 }
162
163 for(auto tensor : dst_tensors)
164 {
165 ARM_COMPUTE_ERROR_ON(input_tensors.find(tensor) != input_tensors.end());
166 ARM_COMPUTE_ERROR_ON(output_tensors.find(tensor) != output_tensors.end());
167 ARM_COMPUTE_ERROR_ON(_interm_tensors.find(tensor) != _interm_tensors.end());
168 output_tensors.insert(tensor);
169 }
170 }
171
172 std::set_union(
173 input_tensors.begin(), input_tensors.end(),
174 output_tensors.begin(), output_tensors.end(),
175 std::back_inserter(_argument_tensors));
176 _any_output_tensor = *output_tensors.begin();
SiCong Lif44bbc52022-08-29 18:25:51 +0100177}
178
Viet-Hoa Do04f46202022-12-14 14:49:56 +0000179const ITensorInfo *GpuKernelComponentGroup::get_any_dst_tensor() const
SiCong Lif44bbc52022-08-29 18:25:51 +0100180{
Viet-Hoa Do04f46202022-12-14 14:49:56 +0000181 ARM_COMPUTE_ERROR_ON_MSG(!_finalized, "The component group must have been finalized.");
182 return _any_output_tensor;
SiCong Lif44bbc52022-08-29 18:25:51 +0100183}
184
185std::vector<const ITensorInfo *> GpuKernelComponentGroup::get_argument_tensors() const
186{
Viet-Hoa Do04f46202022-12-14 14:49:56 +0000187 ARM_COMPUTE_ERROR_ON_MSG(!_finalized, "The component group must have been finalized.");
188 return _argument_tensors;
SiCong Lif44bbc52022-08-29 18:25:51 +0100189}
190
191GpuKernelComponentGroup::ComponentPtr GpuKernelComponentGroup::get_root_component() const
192{
193 if(empty())
194 {
195 return nullptr;
196 }
197 return _components[0];
198}
199
SiCong Lif44bbc52022-08-29 18:25:51 +0100200bool GpuKernelComponentGroup::is_intermediate_tensor(const ITensorInfo *tensor) const
201{
Viet-Hoa Do04f46202022-12-14 14:49:56 +0000202 ARM_COMPUTE_ERROR_ON_MSG(!_finalized, "The component group must have been finalized.");
203 return _interm_tensors.find(tensor) != _interm_tensors.end();
SiCong Lif44bbc52022-08-29 18:25:51 +0100204}
205
206size_t GpuKernelComponentGroup::size() const
207{
208 return _components.size();
209}
210bool GpuKernelComponentGroup::empty() const
211{
212 return _components.empty();
213}
214GpuKernelComponentGroup::ComponentPtr &GpuKernelComponentGroup::operator[](size_t index)
215{
216 return _components[index];
217}
218const GpuKernelComponentGroup::ComponentPtr &GpuKernelComponentGroup::operator[](size_t index) const
219{
220 return _components[index];
221}
222typename std::vector<GpuKernelComponentGroup::ComponentPtr>::iterator GpuKernelComponentGroup::begin()
223{
224 return _components.begin();
225}
226typename std::vector<GpuKernelComponentGroup::ComponentPtr>::iterator GpuKernelComponentGroup::end()
227{
228 return _components.end();
229}
230typename std::vector<GpuKernelComponentGroup::ComponentPtr>::const_iterator GpuKernelComponentGroup::begin() const
231{
232 return _components.cbegin();
233}
234typename std::vector<GpuKernelComponentGroup::ComponentPtr>::const_iterator GpuKernelComponentGroup::end() const
235{
236 return _components.cend();
237}
238typename std::vector<GpuKernelComponentGroup::ComponentPtr>::const_iterator GpuKernelComponentGroup::cbegin() const
239{
240 return _components.cbegin();
241}
242typename std::vector<GpuKernelComponentGroup::ComponentPtr>::const_iterator GpuKernelComponentGroup::cend() const
243{
244 return _components.cend();
245}
246
SiCong Lif44bbc52022-08-29 18:25:51 +0100247} // namespace dynamic_fusion
248} // namespace experimental
249} // namespace arm_compute