_paddings.at(1) = 0;
// FALLTHROUGH
case ops::PaddingType::Custom:
- output_shape.dim(1) = (input_shape.dim(1) + 2 * getPadding(0) - window_shape.dim(0)) / strides.dim(0) + 1;
- output_shape.dim(2) = (input_shape.dim(2) + 2 * getPadding(1) - window_shape.dim(1)) / strides.dim(0) + 1;
+ switch (_roundMode) {
+ case PoolOp::RoundMode::ceil:
+ output_shape.dim(1) = static_cast<int>(ceil(static_cast<double>(
+ input_shape.dim(1) + 2 * getPadding(0) - window_shape.dim(0)) / strides.dim(0))) + 1;
+ output_shape.dim(2) = static_cast<int>(ceil(static_cast<double>(
+ input_shape.dim(2) + 2 * getPadding(1) - window_shape.dim(1)) / strides.dim(1))) + 1;
+ break;
+ case PoolOp::RoundMode::floor:
+ output_shape.dim(1) = (input_shape.dim(1) + 2 * getPadding(0) - window_shape.dim(0)) / strides.dim(0) + 1;
+ output_shape.dim(2) = (input_shape.dim(2) + 2 * getPadding(1) - window_shape.dim(1)) / strides.dim(1) + 1;
+ break;
+ }
break;
default:
assert(false && "invalid padding type");
#include "core/modelIR/Operation.h"
#include "core/modelIR/operations/common.h"
#include <vector>
+#include <cmath>
namespace nnc {
namespace mir {
EMPTY // Consider that there are no elements outside of input shape
};
+ enum class RoundMode {
+ ceil, // used in caffe
+ floor // used in tflite
+ };
+
PoolOp(const IODescriptor& arg,
const Shape& window_shape,
const Shape& strides,
PoolingType pooling_type,
const std::vector<int32_t>& paddings,
- BorderType border_type)
+ BorderType border_type,
+ RoundMode round_mode)
: Operation(Type::pool, {arg}),
_windowShape(window_shape),
_strides(strides),
_poolingType(pooling_type),
_paddingType(PaddingType::Custom),
_paddings(paddings),
- _borderType(border_type) {
+ _borderType(border_type),
+ _roundMode(round_mode) {
inferOutputShapes();
}
const Shape& strides,
PoolingType pooling_type,
PaddingType padding_type,
- BorderType border_type)
+ BorderType border_type,
+ RoundMode round_mode)
: Operation(Type::pool, {arg}),
_windowShape(window_shape),
_strides(strides),
_poolingType(pooling_type),
_paddingType(padding_type),
_paddings(window_shape.rank()),
- _borderType(border_type) {
+ _borderType(border_type),
+ _roundMode(round_mode) {
assert(_paddingType != PaddingType::Custom);
inferOutputShapes();
}
PaddingType _paddingType;
PoolingType _poolingType;
BorderType _borderType;
+ RoundMode _roundMode;
Shape _windowShape;
Shape _strides;
std::vector<int32_t> _paddings;
}
auto pooling = createOp<ops::PoolOp>(layer.name(), inputs[0], window_shape, strides, pool_type,
- paddings, border_type);
+ paddings, border_type, ops::PoolOp::RoundMode::ceil);
return {pooling->getOutput(0)};
}
Shape strides{opts->stride_h(), opts->stride_w(), 1};
return createOp<ops::PoolOp>(opts->fused_activation_function(), inputs[0]->getOutput(0),
window_shape, strides, ops::PoolOp::PoolingType::MAX,
- paddingMap[opts->padding()], ops::PoolOp::BorderType::EMPTY);
+ paddingMap[opts->padding()], ops::PoolOp::BorderType::EMPTY,
+ ops::PoolOp::RoundMode::floor);
}
std::vector<mir::Operation*> TFLiteOpCreator::convertAveragePool2D(InputOps inputs,
Shape strides{opts->stride_h(), opts->stride_w(), 1};
return createOp<ops::PoolOp>(opts->fused_activation_function(), inputs[0]->getOutput(0),
window_shape, strides, ops::PoolOp::PoolingType::AVG,
- paddingMap[opts->padding()], ops::PoolOp::BorderType::EMPTY);
+ paddingMap[opts->padding()], ops::PoolOp::BorderType::EMPTY,
+ ops::PoolOp::RoundMode::floor);
}
std::vector<mir::Operation*> TFLiteOpCreator::createSoftmax(InputOps inputs, InputParams params,
paddings.reserve(static_cast<size_t>(num_dims));
// create strucuture with paddings
- for (int i = 1; i < num_dims; i++)
+ for (int i = 0; i < num_dims; i++)
paddings.emplace_back(paddings_tensor.at(Index({i, 0})), paddings_tensor.at(Index({i, 1})));
// create const value, it's float because we can't see input type
float const_value = 0.0; // not support different constant value
Scalar constant_value(reinterpret_cast<char*>(&const_value), DTYPE::FLOAT32, sizeof(float));
return createOp<ops::PadOp>(ActivationFunctionType_NONE, inputs[0]->getOutput(0),
- num_dims - 1, paddings, constant_value);
+ num_dims, paddings, constant_value);
}
std::vector<mir::Operation*>
const opinfo::OperatorInfo* opInfo) {
return g->create<ops::PoolOp>("y", inputs[0], getShapeParam(opInfo, 0), getShapeParam(opInfo, 1),
getPoolingType(opInfo), getPaddingType(opInfo),
- ops::PoolOp::BorderType::ZEROFILLED);
+ ops::PoolOp::BorderType::ZEROFILLED,
+ ops::PoolOp::RoundMode::floor);
}
static Operation* createConcatenation(std::unique_ptr<Graph>& g,
auto opGenerator = [windowShape, strides, padT, border](mir::Graph& g,
const std::vector<mir::IODescriptor>& inputs) {
return g.create<mir::ops::PoolOp>("y", inputs[0], windowShape, strides, poolT, padT,
- border);
+ border, irOps::PoolOp::RoundMode::floor);
};
createAndRunTestGraph(opGenerator, testFunc, inputNTensors, aInputTensor);