ONE - On-device Neural Engine
Loading...
Searching...
No Matches
mir_caffe2::Caffe2OpCreator Class Reference

#include <caffe2_op_creator.h>

Public Member Functions

 Caffe2OpCreator (mir::Graph *g)
 
std::vector< mir::Operation::Output * > convertConstant (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 * > convertAveragePool (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)
 
std::vector< mir::Operation::Output * > convertConcat (const std::vector< mir::Operation::Output * > &inputs, const ::caffe2::OperatorDef &op)
 
std::vector< mir::Operation::Output * > convertDropout (const std::vector< mir::Operation::Output * > &inputs, const ::caffe2::OperatorDef &op)
 
std::vector< mir::Operation::Output * > convertFC (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 * > convertMul (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 * > convertResizeNearest (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 * > convertSoftmax (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 * > convertSum (const std::vector< mir::Operation::Output * > &inputs)
 
std::vector< mir::Operation::Output * > convertClip (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)
 

Detailed Description

Definition at line 38 of file caffe2_op_creator.h.

Constructor & Destructor Documentation

◆ Caffe2OpCreator()

mir_caffe2::Caffe2OpCreator::Caffe2OpCreator ( mir::Graph g)
inlineexplicit

Definition at line 41 of file caffe2_op_creator.h.

41: _graph(g) {}

Member Function Documentation

◆ convertAdd()

std::vector< mir::Operation::Output * > mir_caffe2::Caffe2OpCreator::convertAdd ( const std::vector< mir::Operation::Output * > &  inputs,
const ::caffe2::OperatorDef &  op 
)

Definition at line 261 of file caffe2_op_creator.cpp.

263{
264 assert(inputs.size() == 2);
265 auto lhs = inputs[0];
266 auto rhs = inputs[1];
267
268 if (getSingleArgument(op, "broadcast", 0) != 0)
269 {
270 // FIXME This only works when 'axis' == 1 and the second input is 1-D.
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);
273 return {result};
274 }
275
276 auto result = createOp<ops::AddOp>(lhs, rhs)->getOutput(0);
277 return {result};
278}
result
Definition infer.py:103
int getSingleArgument(const ::caffe2::OperatorDef &op, const std::string &argument_name, const int default_value)
Definition Shape.h:28

References mir_caffe2::getSingleArgument().

◆ convertAveragePool()

std::vector< mir::Operation::Output * > mir_caffe2::Caffe2OpCreator::convertAveragePool ( const std::vector< mir::Operation::Output * > &  inputs,
const ::caffe2::OperatorDef &  op 
)

Definition at line 281 of file caffe2_op_creator.cpp.

283{
284 checkConvLikeOp(op);
285
286 assert(inputs.size() == 1);
287 auto input = inputs[0];
288
289 AvgPool2DOpAttributes attributes;
290 std::tie(attributes.padding_before, attributes.padding_after) = getPadding(op);
291 attributes.window = getWindowSize(op, inputs);
292 attributes.strides = getStrides(op);
293 attributes.include_pad = false;
294 attributes.data_format = DataFormat::NCHW;
295 auto result = createOp<ops::AvgPool2DOp>(input, attributes)->getOutput(0);
296 return {result};
297}

References mir::AvgPool2DOpAttributes::data_format, mir::AvgPool2DOpAttributes::include_pad, mir::AvgPool2DOpAttributes::padding_after, mir::AvgPool2DOpAttributes::padding_before, mir::AvgPool2DOpAttributes::strides, and mir::AvgPool2DOpAttributes::window.

◆ convertClip()

std::vector< mir::Operation::Output * > mir_caffe2::Caffe2OpCreator::convertClip ( const std::vector< mir::Operation::Output * > &  inputs,
const ::caffe2::OperatorDef &  op 
)

Definition at line 509 of file caffe2_op_creator.cpp.

511{
512
513 float max = getSingleArgument(op, "max", float(0));
514 float min = getSingleArgument(op, "min", float(0));
515
516 if (min != 0.0f)
517 throw std::runtime_error("Clip: min != 0 is not supported.");
518 if (max <= min)
519 throw std::runtime_error("Clip: max <= min is not supported.");
520 auto cap_relu = createOp<ops::CappedReluOp>(inputs[0], max);
521
522 return {cap_relu->getOutput(0)};
523}

References mir_caffe2::getSingleArgument().

◆ convertConcat()

std::vector< mir::Operation::Output * > mir_caffe2::Caffe2OpCreator::convertConcat ( const std::vector< mir::Operation::Output * > &  inputs,
const ::caffe2::OperatorDef &  op 
)

Definition at line 325 of file caffe2_op_creator.cpp.

327{
328 checkLayout(op);
329
330 // `1` corresponds to the default (channels) axis.
331 int axis = getSingleArgument(op, "axis", 1);
332 auto result = createOp<ops::ConcatOp>(inputs, axis);
333 return {result->getOutput(0)};
334}

References mir_caffe2::getSingleArgument().

◆ convertConstant()

std::vector< mir::Operation::Output * > mir_caffe2::Caffe2OpCreator::convertConstant ( const std::vector< mir::Operation::Output * > &  inputs,
const ::caffe2::OperatorDef &  op 
)

Definition at line 250 of file caffe2_op_creator.cpp.

252{
253 // Constant may not contain any data if it is a fake input.
254 if (!hasArgument(op.arg(), "values"))
255 return {};
256
257 return {createOp<ops::ConstantOp>(createTensor(op))->getOutput(0)};
258}
bool hasArgument(RepArgument args, const std::string &name)

References mir_caffe2::hasArgument().

◆ convertConv()

std::vector< mir::Operation::Output * > mir_caffe2::Caffe2OpCreator::convertConv ( const std::vector< mir::Operation::Output * > &  inputs,
const ::caffe2::OperatorDef &  op 
)

Definition at line 300 of file caffe2_op_creator.cpp.

302{
303 // dilation order: h w (not used)
304 mir::Conv2DOpAttributes attributes;
305 attributes.strides = getStrides(op);
306 std::tie(attributes.padding_before, attributes.padding_after) = getPadding(op);
307 attributes.num_groups = getSingleArgument(op, "group", 1);
308 attributes.data_format = DataFormat::NCHW;
309
310 std::vector<std::size_t> perm{0, 2, 3, 1}; // OIHW -> OHWI
311 auto kernel = createOp<ops::TransposeOp>(inputs[1], perm)->getOutput(0);
312 auto result = createOp<ops::Conv2DOp>(inputs[0], kernel, attributes)->getOutput(0);
313
314 if (op.input_size() > 2)
315 {
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);
319 }
320
321 return {result};
322}
std::vector< std::int32_t > padding_after
Definition Attributes.h:33
std::vector< std::int32_t > strides
Definition Attributes.h:31
std::int32_t num_groups
Definition Attributes.h:34
std::vector< std::int32_t > padding_before
Definition Attributes.h:32

References mir::Conv2DOpAttributes::data_format, mir_caffe2::getSingleArgument(), mir::Conv2DOpAttributes::num_groups, mir::Conv2DOpAttributes::padding_after, mir::Conv2DOpAttributes::padding_before, and mir::Conv2DOpAttributes::strides.

◆ convertDropout()

std::vector< mir::Operation::Output * > mir_caffe2::Caffe2OpCreator::convertDropout ( const std::vector< mir::Operation::Output * > &  inputs,
const ::caffe2::OperatorDef &  op 
)

Definition at line 337 of file caffe2_op_creator.cpp.

339{
340 // This is a no-op in inference mode.
341 return {inputs[0]};
342}

◆ convertFC()

std::vector< mir::Operation::Output * > mir_caffe2::Caffe2OpCreator::convertFC ( const std::vector< mir::Operation::Output * > &  inputs,
const ::caffe2::OperatorDef &  op 
)

Definition at line 345 of file caffe2_op_creator.cpp.

347{
348 for (auto &s : {"axis", "axis_w", "float16_compute"})
349 if (hasArgument(op.arg(), s))
350 throw std::runtime_error(std::string("FC: only default '") + s + "' value is supported");
351
352 const auto &input_shape = inputs[0]->getShape();
353 // Transform input into 2-D tensor by flattening axes
354 Shape shape{input_shape.dim(0), input_shape.numElements() / input_shape.dim(0)};
355
356 auto reshape = createOp<ops::ReshapeOp>(inputs[0], shape)->getOutput(0);
357 auto weights =
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);
361
362 return {result};
363}

References mir::Shape::dim(), mir_caffe2::hasArgument(), and mir_caffe2::reshape.

◆ convertMaxPool()

std::vector< mir::Operation::Output * > mir_caffe2::Caffe2OpCreator::convertMaxPool ( const std::vector< mir::Operation::Output * > &  inputs,
const ::caffe2::OperatorDef &  op 
)

Definition at line 366 of file caffe2_op_creator.cpp.

368{
369 checkConvLikeOp(op);
370
371 assert(inputs.size() == 1);
372 auto input = inputs[0];
373
374 MaxPool2DOpAttributes attributes;
375 std::tie(attributes.padding_before, attributes.padding_after) = getPadding(op);
376 attributes.window = getWindowSize(op, inputs);
377 attributes.strides = getStrides(op);
378 attributes.data_format = DataFormat::NCHW;
379 auto result = createOp<ops::MaxPool2DOp>(input, attributes)->getOutput(0);
380 return {result};
381}

References mir::MaxPool2DOpAttributes::data_format, mir::MaxPool2DOpAttributes::padding_after, mir::MaxPool2DOpAttributes::padding_before, mir::MaxPool2DOpAttributes::strides, and mir::MaxPool2DOpAttributes::window.

◆ convertMul()

std::vector< mir::Operation::Output * > mir_caffe2::Caffe2OpCreator::convertMul ( const std::vector< mir::Operation::Output * > &  inputs,
const ::caffe2::OperatorDef &  op 
)

Definition at line 384 of file caffe2_op_creator.cpp.

386{
387 assert(inputs.size() == 2);
388 auto lhs = inputs[0];
389 auto rhs = inputs[1];
390
391 if (getSingleArgument(op, "broadcast", 0) != 0)
392 {
393 // FIXME This only works when `axis` == 1 and the second input is 1-D.
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);
396 return {result};
397 }
398
399 auto result = createOp<ops::MulOp>(lhs, rhs)->getOutput(0);
400 return {result};
401}

References mir_caffe2::getSingleArgument().

◆ convertRelu()

std::vector< mir::Operation::Output * > mir_caffe2::Caffe2OpCreator::convertRelu ( const std::vector< mir::Operation::Output * > &  inputs)

Definition at line 404 of file caffe2_op_creator.cpp.

405{
406 auto relu = createOp<ops::ReluOp>(inputs[0]);
407 return {relu->getOutput(0)};
408}

References mir_caffe2::relu.

◆ convertReshape()

std::vector< mir::Operation::Output * > mir_caffe2::Caffe2OpCreator::convertReshape ( const std::vector< mir::Operation::Output * > &  inputs,
const ::caffe2::OperatorDef &  op 
)

Definition at line 526 of file caffe2_op_creator.cpp.

528{
529 auto shape_op = dynamic_cast<mir::ops::ConstantOp *>(inputs[1]->getNode());
530 if (shape_op == nullptr)
531 throw std::runtime_error("Reshape: non-constant shape is not supported yet.");
532
533 const auto &shape_tensor = shape_op->getValue();
534
535 Tensor<int64_t> out_shape_tensor(shape_tensor);
536
537 ShapeRange range(out_shape_tensor.getShape());
538 std::vector<int32_t> shape_vec;
539 for (const auto &index : range)
540 {
541 shape_vec.push_back(static_cast<int32_t>(out_shape_tensor.at(index)));
542 }
543 Shape out_shape(shape_vec);
544
545 auto reshape = createOp<ops::ReshapeOp>(inputs[0], out_shape);
546
547 return {reshape->getOutput(0)};
548}

References mir::Tensor< T >::at(), mir::Tensor< T >::getShape(), and mir_caffe2::reshape.

◆ convertResizeNearest()

std::vector< mir::Operation::Output * > mir_caffe2::Caffe2OpCreator::convertResizeNearest ( const std::vector< mir::Operation::Output * > &  inputs,
const ::caffe2::OperatorDef &  op 
)

Definition at line 411 of file caffe2_op_creator.cpp.

413{
414 std::vector<float> scales(4);
415 assert(inputs[0]->getShape().rank() == 4 && "only 4d tensors is supported");
416 // Assuming NCHW format.
417 scales[0] = 1.0f;
418 scales[1] = 1.0f;
419 scales[2] = getSingleArgument(op, "height_scale", 1.0f);
420 scales[3] = getSingleArgument(op, "width_scale", 1.0f);
421 auto result =
422 createOp<ops::ResizeOp>(inputs[0], ops::ResizeOp::ResizeMethod::nearestNeighbor, scales)
423 ->getOutput(0);
424 return {result};
425}
nnfw::cker::Shape getShape(const IPortableTensor *tensor)

References mir_caffe2::getSingleArgument().

◆ convertSigmoid()

std::vector< mir::Operation::Output * > mir_caffe2::Caffe2OpCreator::convertSigmoid ( const std::vector< mir::Operation::Output * > &  inputs)

Definition at line 428 of file caffe2_op_creator.cpp.

429{
430 auto result = createOp<ops::SigmoidOp>(inputs[0]);
431 return {result->getOutput(0)};
432}

◆ convertSoftmax()

std::vector< mir::Operation::Output * > mir_caffe2::Caffe2OpCreator::convertSoftmax ( const std::vector< mir::Operation::Output * > &  inputs,
const ::caffe2::OperatorDef &  op 
)

Definition at line 435 of file caffe2_op_creator.cpp.

437{
438 int axis = getSingleArgument(op, "axis", 1);
439 auto softmax = createOp<ops::SoftmaxOp>(inputs[0], axis);
440 return {softmax->getOutput(0)};
441}

References mir_caffe2::getSingleArgument(), and mir_caffe2::softmax.

◆ convertSpatialBN()

std::vector< mir::Operation::Output * > mir_caffe2::Caffe2OpCreator::convertSpatialBN ( const std::vector< mir::Operation::Output * > &  inputs,
const ::caffe2::OperatorDef &  op 
)

Definition at line 444 of file caffe2_op_creator.cpp.

446{
447 checkLayout(op);
448
449 // Sanity checks
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)");
453 if (getSingleArgument(op, "is_test", 1) != 1)
454 throw std::runtime_error("SpatialBN: only test mode supported");
455
456 // overall_res = (X - mean) / sqrt(var + epsilon) * scale + bias
457
458 auto scale_op = dynamic_cast<mir::ops::ConstantOp *>(inputs[1]->getNode());
459 auto bias_op = dynamic_cast<mir::ops::ConstantOp *>(inputs[2]->getNode());
460 auto mean_op = dynamic_cast<mir::ops::ConstantOp *>(inputs[3]->getNode());
461 auto var_op = dynamic_cast<mir::ops::ConstantOp *>(inputs[4]->getNode());
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.");
465
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();
470 float eps = getSingleArgument(op, "epsilon", 1e-5f);
471
472 // res1 = X - mean
473 Tensor<float> bias_data(mean_tensor);
474 for (auto &idx : ShapeRange(bias_data.getShape()))
475 bias_data.at(idx) *= -1;
476
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);
480
481 // res2 = res1 * scale / (var + epsilon)
482 Tensor<float> multiplier(scale_tensor);
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);
488
489 // overall_res = res2 + bias
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);
493
494 return {result};
495}

References mir::Tensor< T >::at(), mir::Tensor< T >::getShape(), and mir_caffe2::getSingleArgument().

◆ convertSum()

std::vector< mir::Operation::Output * > mir_caffe2::Caffe2OpCreator::convertSum ( const std::vector< mir::Operation::Output * > &  inputs)

Definition at line 498 of file caffe2_op_creator.cpp.

499{
500 auto result = createOp<ops::AddOp>(inputs[0], inputs[1])->getOutput(0);
501 for (int i = 2; i < static_cast<int>(inputs.size()); ++i)
502 {
503 result = createOp<ops::AddOp>(result, inputs[i])->getOutput(0);
504 }
505 return {result};
506}

The documentation for this class was generated from the following files: