49using namespace ::caffe2;
56static std::pair<std::vector<int32_t>, std::vector<int32_t>>
57getPadding(const ::caffe2::OperatorDef &op)
65 std::vector<int32_t> paddings;
66 for (
const auto &pad : pads_arg.ints())
67 paddings.push_back(static_cast<int32_t>(pad));
69 assert(paddings.size() == 4);
71 int32_t pad_t = paddings[0];
72 int32_t pad_l = paddings[1];
73 int32_t pad_b = paddings[2];
74 int32_t pad_r = paddings[3];
76 std::vector<int32_t> padding_before{pad_t, pad_l};
77 std::vector<int32_t> padding_after{pad_b, pad_r};
78 return {padding_before, padding_after};
91 std::vector<int32_t> padding_before{pad_t, pad_l};
92 std::vector<int32_t> padding_after{pad_b, pad_r};
93 return {padding_before, padding_after};
97 return {{pad, pad}, {pad, pad}};
100static std::vector<std::int32_t> getStrides(const ::caffe2::OperatorDef &op)
102 std::vector<std::int32_t> strides;
107 strides = {stride, stride};
114 for (
const auto &s : strides_arg.ints())
115 strides.push_back(
s);
118 assert(!strides.empty() &&
"Strides not found");
123static std::vector<std::int32_t> getWindowSize(const ::caffe2::OperatorDef &op,
124 const std::vector<mir::Operation::Output *> &inputs)
127 bool has_custom_kernel_size =
129 bool has_custom_kernels_size =
hasArgument(op.arg(),
"kernels");
131 int kernel_h(0), kernel_w(0);
132 if (is_global_pooling)
134 const auto &input_shape =
inputs[0]->getShape();
135 assert(input_shape.rank() == 4 &&
"getWindowSize() inputs must be of rank 4");
136 kernel_h = input_shape.dim(2);
137 kernel_w = input_shape.dim(3);
141 if (has_custom_kernel_size)
148 if (has_custom_kernels_size)
151 std::vector<int32_t> kernels;
153 for (
const auto &ker : kernels_arg.ints())
154 kernels.push_back(static_cast<int32_t>(ker));
155 assert(kernels.size() == 2);
156 kernel_h = kernels[0];
157 kernel_w = kernels[1];
165 return {kernel_h, kernel_w};
172static void checkLayout(
const OperatorDef &op)
175 throw std::runtime_error(op.type() +
": only 'NCHW' axis order is supported");
178static void checkConvLikeOp(const ::caffe2::OperatorDef &op)
186 if (has_custom_pad &&
hasArgument(op.arg(),
"pad"))
187 throw std::runtime_error(
"Custom pad can't be combined with overall pad");
191 throw std::runtime_error(
"If one custom pad specified - all custom pads must be specified");
194 bool has_custom_kernel_size =
197 if (has_custom_kernel_size &&
hasArgument(op.arg(),
"kernel"))
198 throw std::runtime_error(
"Custom kernel size can't be combined with overall kernel size");
200 if (has_custom_kernel_size &&
202 throw std::runtime_error(
203 "If one custom kernel size specified - all custom kernel sizes must be specified");
214 const void *src_data;
216 if (!values.floats().empty())
218 element_type = mir::DataType::FLOAT32;
219 src_data = values.floats().data();
223 assert(!values.ints().empty());
224 if (op.type() ==
"GivenTensorInt64Fill")
226 element_type = mir::DataType::INT64;
230 element_type = mir::DataType::INT32;
232 src_data = values.ints().data();
237 for (
int i = 0; i < shape.ints_size(); ++i)
239 tensor_shape.
dim(i) = shape.ints(i);
249std::vector<mir::Operation::Output *>
251 const ::caffe2::OperatorDef &op)
257 return {createOp<ops::ConstantOp>(createTensor(op))->getOutput(0)};
260std::vector<mir::Operation::Output *>
262 const ::caffe2::OperatorDef &op)
264 assert(inputs.size() == 2);
265 auto lhs = inputs[0];
266 auto rhs = inputs[1];
271 rhs = createOp<ops::ReshapeOp>(rhs,
Shape{1, rhs->getShape().dim(0), 1, 1})->getOutput(0);
272 auto result = createOp<ops::AddOp>(lhs, rhs)->getOutput(0);
276 auto result = createOp<ops::AddOp>(lhs, rhs)->getOutput(0);
280std::vector<mir::Operation::Output *>
282 const OperatorDef &op)
286 assert(inputs.size() == 1);
287 auto input = inputs[0];
291 attributes.
window = getWindowSize(op, inputs);
292 attributes.
strides = getStrides(op);
295 auto result = createOp<ops::AvgPool2DOp>(input, attributes)->getOutput(0);
299std::vector<mir::Operation::Output *>
301 const ::caffe2::OperatorDef &op)
305 attributes.
strides = getStrides(op);
310 std::vector<std::size_t> perm{0, 2, 3, 1};
311 auto kernel = createOp<ops::TransposeOp>(inputs[1], perm)->getOutput(0);
312 auto result = createOp<ops::Conv2DOp>(inputs[0], kernel, attributes)->getOutput(0);
314 if (op.input_size() > 2)
316 auto bias = inputs[2];
317 bias = createOp<ops::ReshapeOp>(bias,
Shape{1, bias->getShape().dim(0), 1, 1})->getOutput(0);
318 result = createOp<ops::AddOp>(result, bias)->getOutput(0);
324std::vector<mir::Operation::Output *>
326 const ::caffe2::OperatorDef &op)
332 auto result = createOp<ops::ConcatOp>(inputs, axis);
333 return {result->getOutput(0)};
336std::vector<mir::Operation::Output *>
338 const ::caffe2::OperatorDef &)
344std::vector<mir::Operation::Output *>
346 const ::caffe2::OperatorDef &op)
348 for (
auto &s : {
"axis",
"axis_w",
"float16_compute"})
350 throw std::runtime_error(std::string(
"FC: only default '") + s +
"' value is supported");
352 const auto &input_shape = inputs[0]->getShape();
354 Shape shape{input_shape.
dim(0), input_shape.numElements() / input_shape.dim(0)};
356 auto reshape = createOp<ops::ReshapeOp>(inputs[0], shape)->getOutput(0);
358 createOp<ops::TransposeOp>(inputs[1], std::vector<std::size_t>{1, 0})->getOutput(0);
359 auto result = createOp<ops::FullyConnectedOp>(
reshape, weights)->getOutput(0);
360 result = createOp<ops::AddOp>(result, inputs[2])->getOutput(0);
365std::vector<mir::Operation::Output *>
367 const OperatorDef &op)
371 assert(inputs.size() == 1);
372 auto input = inputs[0];
376 attributes.
window = getWindowSize(op, inputs);
377 attributes.
strides = getStrides(op);
379 auto result = createOp<ops::MaxPool2DOp>(input, attributes)->getOutput(0);
383std::vector<mir::Operation::Output *>
385 const ::caffe2::OperatorDef &op)
387 assert(inputs.size() == 2);
388 auto lhs = inputs[0];
389 auto rhs = inputs[1];
394 rhs = createOp<ops::ReshapeOp>(rhs,
Shape{1, rhs->getShape().dim(0), 1, 1})->getOutput(0);
395 auto result = createOp<ops::MulOp>(lhs, rhs)->getOutput(0);
399 auto result = createOp<ops::MulOp>(lhs, rhs)->getOutput(0);
403std::vector<mir::Operation::Output *>
406 auto relu = createOp<ops::ReluOp>(inputs[0]);
407 return {
relu->getOutput(0)};
410std::vector<mir::Operation::Output *>
412 const ::caffe2::OperatorDef &op)
414 std::vector<float> scales(4);
415 assert(inputs[0]->getShape().rank() == 4 &&
"only 4d tensors is supported");
422 createOp<ops::ResizeOp>(inputs[0], ops::ResizeOp::ResizeMethod::nearestNeighbor, scales)
427std::vector<mir::Operation::Output *>
430 auto result = createOp<ops::SigmoidOp>(inputs[0]);
431 return {result->getOutput(0)};
434std::vector<mir::Operation::Output *>
436 const ::caffe2::OperatorDef &op)
439 auto softmax = createOp<ops::SoftmaxOp>(inputs[0], axis);
440 return {
softmax->getOutput(0)};
443std::vector<mir::Operation::Output *>
445 const ::caffe2::OperatorDef &op)
450 if (op.input_size() != 5)
451 throw std::runtime_error(
452 "SpatialBN must have exactly 5 inputs ('sums' and 'sumsq' are not supported yet)");
454 throw std::runtime_error(
"SpatialBN: only test mode supported");
462 if (scale_op ==
nullptr || bias_op ==
nullptr || mean_op ==
nullptr || var_op ==
nullptr)
463 throw std::runtime_error(
464 "SpatialBN: non-constant 'scale', 'bias', 'mean' and 'var' inputs are not supported yet.");
466 const auto &scale_tensor = scale_op->getValue();
467 const auto &bias_tensor = bias_op->getValue();
468 const auto &mean_tensor = mean_op->getValue();
469 const auto &var_tensor = var_op->getValue();
475 bias_data.
at(idx) *= -1;
477 auto mean = createOp<ops::ConstantOp>(mean_tensor)->getOutput(0);
478 mean = createOp<ops::ReshapeOp>(mean,
Shape{1, mean->getShape().dim(0), 1, 1})->getOutput(0);
479 auto result = createOp<ops::AddOp>(inputs[0], mean)->getOutput(0);
483 for (
auto &idx :
ShapeRange(scale_tensor.getShape()))
484 multiplier.
at(idx) /= std::sqrt(*
reinterpret_cast<float *
>(var_tensor.at(idx)) + eps);
485 auto scale = createOp<ops::ConstantOp>(scale_tensor)->getOutput(0);
486 scale = createOp<ops::ReshapeOp>(scale,
Shape{1, scale->getShape().dim(0), 1, 1})->getOutput(0);
487 result = createOp<ops::MulOp>(result, scale)->getOutput(0);
490 auto bias = createOp<ops::ConstantOp>(bias_tensor)->getOutput(0);
491 bias = createOp<ops::ReshapeOp>(bias,
Shape{1, bias->getShape().dim(0), 1, 1})->getOutput(0);
492 result = createOp<ops::AddOp>(result, bias)->getOutput(0);
497std::vector<mir::Operation::Output *>
500 auto result = createOp<ops::AddOp>(inputs[0], inputs[1])->getOutput(0);
501 for (
int i = 2; i < static_cast<int>(inputs.size()); ++i)
503 result = createOp<ops::AddOp>(result, inputs[i])->getOutput(0);
508std::vector<mir::Operation::Output *>
510 const ::caffe2::OperatorDef &op)
517 throw std::runtime_error(
"Clip: min != 0 is not supported.");
519 throw std::runtime_error(
"Clip: max <= min is not supported.");
520 auto cap_relu = createOp<ops::CappedReluOp>(inputs[0], max);
522 return {cap_relu->getOutput(0)};
525std::vector<mir::Operation::Output *>
527 const ::caffe2::OperatorDef &)
530 if (shape_op ==
nullptr)
531 throw std::runtime_error(
"Reshape: non-constant shape is not supported yet.");
533 const auto &shape_tensor = shape_op->getValue();
538 std::vector<int32_t> shape_vec;
539 for (
const auto &index : range)
541 shape_vec.push_back(
static_cast<int32_t
>(out_shape_tensor.
at(index)));
543 Shape out_shape(shape_vec);
545 auto reshape = createOp<ops::ReshapeOp>(inputs[0], out_shape);
547 return {
reshape->getOutput(0)};
const Dimension & dim(uint32_t axis) const
int32_t & dim(int32_t axis) noexcept
const Shape & getShape() const
T at(const Index &id) const
std::vector< mir::Operation::Output * > convertMul(const std::vector< mir::Operation::Output * > &inputs, const ::caffe2::OperatorDef &op)
std::vector< mir::Operation::Output * > convertConstant(const std::vector< mir::Operation::Output * > &inputs, const ::caffe2::OperatorDef &op)
std::vector< mir::Operation::Output * > convertSpatialBN(const std::vector< mir::Operation::Output * > &inputs, const ::caffe2::OperatorDef &op)
std::vector< mir::Operation::Output * > convertAveragePool(const std::vector< mir::Operation::Output * > &inputs, const ::caffe2::OperatorDef &op)
std::vector< mir::Operation::Output * > convertMaxPool(const std::vector< mir::Operation::Output * > &inputs, const ::caffe2::OperatorDef &op)
std::vector< mir::Operation::Output * > convertClip(const std::vector< mir::Operation::Output * > &inputs, const ::caffe2::OperatorDef &op)
std::vector< mir::Operation::Output * > convertResizeNearest(const std::vector< mir::Operation::Output * > &inputs, const ::caffe2::OperatorDef &op)
std::vector< mir::Operation::Output * > convertSoftmax(const std::vector< mir::Operation::Output * > &inputs, const ::caffe2::OperatorDef &op)
std::vector< mir::Operation::Output * > convertRelu(const std::vector< mir::Operation::Output * > &inputs)
std::vector< mir::Operation::Output * > convertConcat(const std::vector< mir::Operation::Output * > &inputs, const ::caffe2::OperatorDef &op)
std::vector< mir::Operation::Output * > convertAdd(const std::vector< mir::Operation::Output * > &inputs, const ::caffe2::OperatorDef &op)
std::vector< mir::Operation::Output * > convertReshape(const std::vector< mir::Operation::Output * > &inputs, const ::caffe2::OperatorDef &op)
std::vector< mir::Operation::Output * > convertSigmoid(const std::vector< mir::Operation::Output * > &inputs)
std::vector< mir::Operation::Output * > convertFC(const std::vector< mir::Operation::Output * > &inputs, const ::caffe2::OperatorDef &op)
std::vector< mir::Operation::Output * > convertSum(const std::vector< mir::Operation::Output * > &inputs)
std::vector< mir::Operation::Output * > convertDropout(const std::vector< mir::Operation::Output * > &inputs, const ::caffe2::OperatorDef &op)
std::vector< mir::Operation::Output * > convertConv(const std::vector< mir::Operation::Output * > &inputs, const ::caffe2::OperatorDef &op)
const ::caffe2::Argument & findArgumentByName(RepArgument args, const std::string &name)
int getSingleArgument(const ::caffe2::OperatorDef &op, const std::string &argument_name, const int default_value)
bool hasArgument(RepArgument args, const std::string &name)
std::vector< std::int32_t > window
std::vector< std::int32_t > padding_before
std::vector< std::int32_t > padding_after
std::vector< std::int32_t > strides
std::vector< std::int32_t > padding_after
std::vector< std::int32_t > strides
std::vector< std::int32_t > padding_before
std::vector< std::int32_t > window
std::vector< std::int32_t > padding_after
std::vector< std::int32_t > strides
std::vector< std::int32_t > padding_before