2 // Copyright (c) 2016-2019 Intel Corporation
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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.
17 ///////////////////////////////////////////////////////////////////////////////////////////////////
19 #include "../C/eltwise.h"
20 #include "primitive.hpp"
24 /// @addtogroup cpp_api C++ API
26 /// @addtogroup cpp_topology Network Topology
28 /// @addtogroup cpp_primitives Primitives
31 /// @brief Select mode for the @ref eltwise layer.
32 enum class eltwise_mode : int32_t {
33 /// @brief Eltwise sum.
34 sum = cldnn_eltwise_sum,
35 /// @brief Eltwise subtract.
36 sub = cldnn_eltwise_sub,
37 /// @brief Eltwise max.
38 max = cldnn_eltwise_max,
39 /// @brief Eltwise product (Hadamard).
40 prod = cldnn_eltwise_prod,
41 /// @brief Eltwise div.
42 div = cldnn_eltwise_div,
43 /// @brief Eltwise min.
44 min = cldnn_eltwise_min,
45 /// @brief Eltwise pow.
46 pow = cldnn_eltwise_pow,
47 /// @brief Eltwise squared diff.
48 squared_diff = cldnn_eltwise_squared_diff,
49 /// @brief Eltwise mod.
50 mod = cldnn_eltwise_mod,
51 /// @brief Eltwise equal.
52 eq = cldnn_eltwise_eq,
53 /// @brief Eltwise not equal.
54 ne = cldnn_eltwise_ne,
55 /// @brief Eltwise less.
56 lt = cldnn_eltwise_lt,
57 /// @brief Eltwise less of equal.
58 le = cldnn_eltwise_le,
59 /// @brief Eltwise greater.
60 gt = cldnn_eltwise_gt,
61 /// @brief Eltwise greater or equal.
62 ge = cldnn_eltwise_ge,
63 /// @brief Eltwise and.
64 logic_and = cldnn_eltwise_and,
65 /// @brief Eltwise or.
66 logic_or = cldnn_eltwise_or,
67 /// @brief Eltwise XOR.
68 logic_xor = cldnn_eltwise_xor,
69 /// @brief Eltwise floormod.
70 floor_mod = cldnn_eltwise_floor_mod
73 /// @brief Performs elementwise operations (sum, subtract, max or product) on two input primitives
74 /// Also supports built-in Relu @ref activation available by setting it in arguments.
76 /// - both inputs have to have equal sizes in all dimensions or the input tensors are broadcastable
77 /// to the same shape in which the size of each dimention is a max. of input sizes on this dimension)
78 /// - format of both inputs has to be the same
79 /// - when using integer types, only following eltwise modes are supported: sum, sub, prod, div
80 struct eltwise : public primitive_base<eltwise, CLDNN_PRIMITIVE_DESC(eltwise)> {
81 CLDNN_DECLARE_PRIMITIVE(eltwise)
83 /// @brief Constructs eltwise primitive.
84 /// @param id This primitive id.
85 /// @param input Input primitive id.
86 /// @param input2 Second input primitive id with values needed for eltwise computation.
87 /// @param mode Eltwise mode.
88 /// @param with_activation Enables Relu activation.
89 /// @param activation_slp Relu activation slope.
90 eltwise(const primitive_id& id,
91 const primitive_id& input,
92 const primitive_id& input2,
94 bool with_activation = false,
95 float activation_slp = 0.0f,
96 const padding& output_padding = padding())
97 : primitive_base(id, {input, input2}, output_padding),
98 output_calibration_factors(""),
99 output_quantization_factor(1.0f),
100 inputs_calibration_factors(_inputs_calibration_factors.cpp_ids),
101 input_quantization_factors(0),
103 coefficients(std::vector<float>(0)),
104 with_activation(with_activation),
105 activation_negative_slope(activation_slp),
106 stride(std::vector<tensor>(0)),
107 _inputs_calibration_factors(std::vector<primitive_id>(0)),
108 _stride(tensor_vector_to_cldnn_vector(stride)) {}
110 /// @brief Constructs eltwise primitive.
111 /// @param id This primitive id.
112 /// @param input Input primitive id.
113 /// @param input2 Second input primitive id with values needed for eltwise computation.
114 /// @param stride Defines shift in input buffers between adjacent calculations of output values.
115 /// @param mode Eltwise mode.
116 /// @param with_activation Enables Relu activation.
117 /// @param activation_slp Relu activation slope.
118 eltwise(const primitive_id& id,
119 const primitive_id& input,
120 const primitive_id& input2,
121 std::vector<tensor> stride,
123 bool with_activation = false,
124 float activation_slp = 0.0f,
125 const padding& output_padding = padding())
126 : primitive_base(id, {input, input2}, output_padding),
127 output_calibration_factors(""),
128 output_quantization_factor(1.0f),
129 inputs_calibration_factors(_inputs_calibration_factors.cpp_ids),
130 input_quantization_factors(0),
132 coefficients(std::vector<float>(0)),
133 with_activation(with_activation),
134 activation_negative_slope(activation_slp),
136 _inputs_calibration_factors(std::vector<primitive_id>(0)),
137 _stride(tensor_vector_to_cldnn_vector(stride)) {}
139 /// @brief Constructs eltwise primitive.
140 /// @param id This primitive id.
141 /// @param inputs Input primitives ids.
142 /// @param mode Eltwise mode.
143 /// @param with_activation Enables Relu activation.
144 /// @param activation_slp Relu activation slope.
145 eltwise(const primitive_id& id,
146 const std::vector<primitive_id>& inputs,
148 bool with_activation = false,
149 float activation_slp = 0.0f,
150 const padding& output_padding = padding())
151 : primitive_base(id, inputs, output_padding),
152 output_calibration_factors(""),
153 output_quantization_factor(1.0f),
154 inputs_calibration_factors(_inputs_calibration_factors.cpp_ids),
155 input_quantization_factors(0),
157 coefficients(std::vector<float>(0)),
158 with_activation(with_activation),
159 activation_negative_slope(activation_slp),
160 stride(std::vector<tensor>(0)),
161 _inputs_calibration_factors(std::vector<primitive_id>(0)),
162 _stride(tensor_vector_to_cldnn_vector(stride)) {}
164 /// @brief Constructs eltwise primitive.
165 /// @param id This primitive id.
166 /// @param input Input primitive id.
167 /// @param input2 Second input primitive id with values needed for eltwise computation.
168 /// @param output_calibration_factors Primitive id containing output calibration factors per output feature map.
169 /// @param mode Eltwise mode.
170 /// @param with_activation Enables Relu activation.
171 /// @param activation_slp Relu activation slope.
172 eltwise(const primitive_id& id,
173 const primitive_id& input,
174 const primitive_id& input2,
175 const primitive_id& output_calibration_factors,
177 bool with_activation = false,
178 float activation_slp = 0.0f,
179 const padding& output_padding = padding())
180 : primitive_base(id, {input, input2}, output_padding),
181 output_calibration_factors(output_calibration_factors),
182 output_quantization_factor(1.0f),
183 inputs_calibration_factors(_inputs_calibration_factors.cpp_ids),
184 input_quantization_factors(0),
186 coefficients(std::vector<float>(0)),
187 with_activation(with_activation),
188 activation_negative_slope(activation_slp),
189 stride(std::vector<tensor>(0)),
190 _inputs_calibration_factors(std::vector<primitive_id>(0)),
191 _stride(tensor_vector_to_cldnn_vector(stride)) {}
193 /// @brief Constructs eltwise primitive.
194 /// @param id This primitive id.
195 /// @param inputs Input primitives ids.
196 /// @param output_calibration_factors Primitive id containing output calibration factors per output feature map.
197 /// @param mode Eltwise mode.
198 /// @param with_activation Enables Relu activation.
199 /// @param activation_slp Relu activation slope.
200 eltwise(const primitive_id& id,
201 const std::vector<primitive_id>& inputs,
202 const primitive_id& output_calibration_factors,
204 bool with_activation = false,
205 float activation_slp = 0.0f,
206 const padding& output_padding = padding())
207 : primitive_base(id, inputs, output_padding),
208 output_calibration_factors(output_calibration_factors),
209 output_quantization_factor(1.0f),
210 inputs_calibration_factors(_inputs_calibration_factors.cpp_ids),
211 input_quantization_factors(0),
213 coefficients(std::vector<float>(0)),
214 with_activation(with_activation),
215 activation_negative_slope(activation_slp),
216 stride(std::vector<tensor>(0)),
217 _inputs_calibration_factors(std::vector<primitive_id>(0)),
218 _stride(tensor_vector_to_cldnn_vector(stride)) {}
220 /// @brief Constructs eltwise primitive.
221 /// @param id This primitive id.
222 /// @param input Input primitive id.
223 /// @param input2 Second input primitive id with values needed for eltwise computation.
224 /// @param o_quantization_factor Output quantization factor
225 /// @param mode Eltwise mode.
226 /// @param with_activation Enables Relu activation.
227 /// @param activation_slp Relu activation slope.
228 eltwise(const primitive_id& id,
229 const primitive_id& input,
230 const primitive_id& input2,
231 const float o_quantization_factor,
233 bool with_activation = false,
234 float activation_slp = 0.0f,
235 const padding& output_padding = padding())
236 : primitive_base(id, {input, input2}, output_padding),
237 output_calibration_factors(""),
238 output_quantization_factor(o_quantization_factor),
239 inputs_calibration_factors(_inputs_calibration_factors.cpp_ids),
240 input_quantization_factors(0),
242 coefficients(std::vector<float>(0)),
243 with_activation(with_activation),
244 activation_negative_slope(activation_slp),
245 stride(std::vector<tensor>(0)),
246 _inputs_calibration_factors(std::vector<primitive_id>(0)),
247 _stride(tensor_vector_to_cldnn_vector(stride)) {}
249 /// @brief Constructs eltwise primitive.
250 /// @param id This primitive id.
251 /// @param inputs Input primitives ids.
252 /// @param o_quantization_factor Output quantization factor
253 /// @param mode Eltwise mode.
254 /// @param with_activation Enables Relu activation.
255 /// @param activation_slp Relu activation slope.
256 eltwise(const primitive_id& id,
257 const std::vector<primitive_id>& inputs,
258 const float o_quantization_factor,
260 bool with_activation = false,
261 float activation_slp = 0.0f,
262 const padding& output_padding = padding())
263 : primitive_base(id, inputs, output_padding),
264 output_calibration_factors(""),
265 output_quantization_factor(o_quantization_factor),
266 inputs_calibration_factors(_inputs_calibration_factors.cpp_ids),
267 input_quantization_factors(0),
269 coefficients(std::vector<float>(0)),
270 with_activation(with_activation),
271 activation_negative_slope(activation_slp),
272 stride(std::vector<tensor>(0)),
273 _inputs_calibration_factors(std::vector<primitive_id>(0)),
274 _stride(tensor_vector_to_cldnn_vector(stride)) {}
276 /// @brief Constructs eltwise primitive.
277 /// @param id This primitive id.
278 /// @param inputs Input primitives ids.
279 /// @param coefficients Blob-wise coefficient for SUM operation
280 /// @param mode Eltwise mode.
281 /// @param with_activation Enables Relu activation.
282 /// @param activation_slp Relu activation slope.
283 eltwise(const primitive_id& id,
284 const std::vector<primitive_id>& inputs,
286 const std::vector<float>& coefficients,
287 bool with_activation = false,
288 float activation_slp = 0.0f,
289 const padding& output_padding = padding())
290 : primitive_base(id, inputs, output_padding),
291 output_calibration_factors(""),
292 output_quantization_factor(1.0f),
293 inputs_calibration_factors(_inputs_calibration_factors.cpp_ids),
294 input_quantization_factors(0),
296 coefficients(coefficients),
297 with_activation(with_activation),
298 activation_negative_slope(activation_slp),
299 stride(std::vector<tensor>(0)),
300 _inputs_calibration_factors(std::vector<primitive_id>(0)),
301 _stride(tensor_vector_to_cldnn_vector(stride)) {
302 if (mode == eltwise_mode::sum && !coefficients.empty() && coefficients.size() != inputs.size()) {
303 throw std::invalid_argument("Invalid eltwise sum coefficients count (should be equal to 0 or input.size)");
305 if (mode != eltwise_mode::sum && !coefficients.empty()) {
306 throw std::invalid_argument("Only eltwise sum operation supports blob-wise coefficients");
310 /// @brief Constructs a copy from C API @CLDNN_PRIMITIVE_DESC{eltwise}
311 eltwise(const dto* dto)
312 : primitive_base(dto),
313 output_calibration_factors(dto->output_calibration_factors),
314 output_quantization_factor(dto->output_quantization_factor),
315 inputs_calibration_factors(_inputs_calibration_factors.cpp_ids),
316 input_quantization_factors(float_arr_to_vector(dto->input_quantization_factors)),
317 mode(static_cast<eltwise_mode>(dto->mode)),
318 coefficients(float_arr_to_vector(dto->coefficients)),
319 with_activation(dto->with_activation != 0),
320 activation_negative_slope(dto->activation_negative_slope),
321 stride(tensor_arr_to_vector(dto->stride)),
322 _inputs_calibration_factors(dto->input_calibration_factors),
323 _stride(tensor_vector_to_cldnn_vector(stride)) {
324 if (dto->input.size < 2)
325 throw std::invalid_argument("eltiwise dto should containt at least two inputs");
326 if (dto->coefficients.size != 0 && dto->coefficients.size != dto->input.size)
327 throw std::invalid_argument(
328 "Invalid eltwise coefficients count in dto (should be equal to 0 or input.size)");
331 /// @brief Primitive id containing output quanitization factors per output feature map.
332 primitive_id output_calibration_factors;
333 /// @brief Output quantization factor
334 float output_quantization_factor;
335 /// @brief List of primitive ids containing input quantization factors per feature map, one primitive id for each input.
336 fixed_size_vector_ref inputs_calibration_factors;
337 /// @brief List of quantization factors per input.
338 std::vector<float> input_quantization_factors;
339 /// @param mode Eltwise mode.
341 /// @param coefficients Blob-wise coefficient for SUM operation.
342 std::vector<float> coefficients;
343 /// @brief Enables Relu activation.
344 bool with_activation;
345 /// @brief Relu activation slope.
346 float activation_negative_slope;
347 /// @brief Defines shift in input buffers between adjacent calculations of output values.
348 std::vector<tensor> stride;
351 primitive_id_arr _inputs_calibration_factors;
352 std::vector<cldnn_tensor> _stride;
353 std::vector<std::reference_wrapper<const primitive_id>> get_dependencies() const override {
354 std::vector<std::reference_wrapper<const primitive_id>> ret;
355 if (!output_calibration_factors.empty())
356 ret.push_back(output_calibration_factors);
358 for (auto& icf : inputs_calibration_factors) ret.push_back(icf);
363 void update_dto(dto& dto) const override {
364 dto.output_calibration_factors = output_calibration_factors.c_str();
365 dto.output_quantization_factor = output_quantization_factor;
366 dto.input_calibration_factors = _inputs_calibration_factors.ref();
367 dto.input_quantization_factors = float_vector_to_arr(input_quantization_factors);
368 dto.mode = static_cast<cldnn_eltwise_mode>(mode);
369 dto.coefficients = float_vector_to_arr(coefficients);
370 dto.with_activation = with_activation;
371 dto.activation_negative_slope = activation_negative_slope;
372 dto.stride = tensor_vector_to_arr(_stride);