output_shape.dim(0) = input_shape.dim(0);
output_shape.dim(3) = input_shape.dim(3);
- // Height and width.
- switch (_roundMode) {
- case RoundMode::ceil:
- for (int i = 0; i < 2; i++) {
- auto padded_input = input_shape.dim(1 + i) + _paddingBefore.at(i) + _paddingAfter.at(i);
- // Incorrect formula taken from Caffe leading to out-of-bound accesses.
- // out_size = ceil((in_size - window_size) / stride) + 1 =
- // = (in_size - window_size + stride - 1) / stride + 1 =
- // = ceil((in_size - window_size + stride) / stride)
- output_shape.dim(1 + i) =
- (padded_input - _windowShape.dim(i) + _strides.dim(i) - 1) / _strides.dim(i) + 1;
- }
- break;
- case RoundMode::floor:
- for (int i = 0; i < 2; i++) {
- auto padded_input = input_shape.dim(1 + i) + _paddingBefore.at(i) + _paddingAfter.at(i);
- // out_size = ceil((in_size - window_size + 1) / stride) =
- // (in_size - window_size + 1 + stride - 1) / stride =
- // (in_size - window_size) / stride + 1
- output_shape.dim(1 + i) = (padded_input - _windowShape.dim(i)) / _strides.dim(i) + 1;
- }
- break;
- default:
- assert(false);
+ for (int i = 0; i < 2; i++) {
+ auto padded_input = input_shape.dim(1 + i) + _paddingBefore.at(i) + _paddingAfter.at(i);
+ // out_size = ceil((in_size - window_size + 1) / stride) =
+ // (in_size - window_size + 1 + stride - 1) / stride =
+ // (in_size - window_size) / stride + 1
+ output_shape.dim(1 + i) = (padded_input - _windowShape.dim(i)) / _strides.dim(i) + 1;
}
for (int i = 0; i < output_shape.rank(); i++) {
EMPTY // Consider that there are no elements outside of input shape
};
- // Rounding mode to use when calculating the output size.
- enum class RoundMode {
- ceil,
- floor
- };
-
PoolOp(const IODescriptor& arg,
PoolingType pooling_type,
const Shape& window_shape,
const Shape& strides,
const std::vector<int32_t>& padding_before,
const std::vector<int32_t>& padding_after,
- BorderType border_type,
- RoundMode round_mode)
+ BorderType border_type)
: Operation(Type::pool, {arg}),
_poolingType(pooling_type),
_windowShape(window_shape),
_strides(strides),
_paddingBefore(padding_before),
_paddingAfter(padding_after),
- _borderType(border_type),
- _roundMode(round_mode) {
+ _borderType(border_type) {
inferOutputShapes();
}
std::vector<int32_t> _paddingBefore;
std::vector<int32_t> _paddingAfter;
BorderType _borderType;
- RoundMode _roundMode;
};
} // namespace ops
auto arithmetic_add_layer = arithmetic_add_layer_var->use();
// Generate the call: arithmetic_add_layer.configure(&in1, &in2, &out);
- _constrBlock->call("configure", {AF::ref(in1), AF::ref(in2), AF::ref(out)}, arithmetic_add_layer);
+ _constrBlock->call("configure", {AF::ref(in1), AF::ref(in2), AF::ref(out),
+ AF::lit("arm_compute::ConvertPolicy::WRAP")},
+ arithmetic_add_layer);
// Generate the call: arithmetic_add_layer.run();
_infBlock->call("run", {}, arithmetic_add_layer);
void Caffe2OpCreator::commonCheck(const ::caffe2::OperatorDef& op,
std::set<std::string>& problemsOpSet) {
if (getSingleArgument(op, "order", "NCHW") != "NCHW")
- problemsOpSet.insert("Only 'NCHW' oreder is supported");
+ problemsOpSet.insert("Only 'NCHW' axis order is supported");
}
//
std::vector<int32_t> pad_before, pad_after;
std::tie(pad_before, pad_after) = getPadding(op);
- auto pooling = createOp<ops::PoolOp>("Average_Pool", convertCaffeToMIR(inputs[0]), pool_type, window_shape,
- strides, pad_before, pad_after, border_type,
- ops::PoolOp::RoundMode::floor);
+ auto pooling = createOp<ops::PoolOp>("Average_Pool", convertCaffeToMIR(inputs[0]), pool_type,
+ window_shape, strides, pad_before, pad_after, border_type);
return {convertMIRToCaffe(pooling->getOutput(0))};
}
std::tie(pad_before, pad_after) = getPadding(op);
auto pooling = createOp<ops::PoolOp>("Pool", convertCaffeToMIR(inputs[0]), pool_type, window_shape,
- strides, pad_before, pad_after, border_type,
- ops::PoolOp::RoundMode::floor);
+ strides, pad_before, pad_after, border_type);
return {convertMIRToCaffe(pooling->getOutput(0))};
}
}
static void convertPoolingParam(const caffe::PoolingParameter& pool_param,
+ const mir::Shape& input_shape,
Shape& window_shape, Shape& strides,
- std::vector<int32_t>& padding) {
+ std::vector<int32_t>& padding_before,
+ std::vector<int32_t>& padding_after) {
int32_t kernel_h, kernel_w;
assert(!pool_param.global_pooling());
if (pool_param.has_kernel_size()) {
} else {
pad_h = pad_w = pool_param.pad();
}
- padding = {pad_h, pad_w};
+
+ padding_before = padding_after = {pad_h, pad_w};
+ // Since Caffe has incorrect pooling output shape formula,
+ // which leading to out-of-bound accesses - increase padding if needed
+ if ((input_shape.dim(2) + pad_h * 2 - window_shape.dim(0)) % stride_h != 0)
+ ++padding_after[0];
+ if ((input_shape.dim(3) + pad_w * 2 - window_shape.dim(1)) % stride_w != 0)
+ ++padding_after[1];
}
void CaffeOpCreator::checkPooling(const PoolingParameter& opts,
auto& opts = layer.pooling_param();
Shape window_shape;
Shape strides;
- std::vector<int32_t> padding;
+ std::vector<int32_t> padding_before, padding_after;
- convertPoolingParam(opts, window_shape, strides, padding);
+ const auto& input_shape = inputs[0].op->getOutputShape(inputs[0].index);
+ convertPoolingParam(opts, input_shape, window_shape, strides, padding_before, padding_after);
ops::PoolOp::PoolingType pool_type = getPoolingType(opts);
ops::PoolOp::BorderType border_type;
}
auto pooling = createOp<ops::PoolOp>(layer.name(), convertCaffeToMIR(inputs[0]), pool_type,
- window_shape, strides, padding, padding, border_type,
- ops::PoolOp::RoundMode::ceil);
+ window_shape, strides, padding_before, padding_after,
+ border_type);
return {convertMIRToCaffe(pooling->getOutput(0))};
}
default:
assert(false);
}
- auto result = createOp<ops::PoolOp>(t_input, pool_type,
- cdata.kernel_shape, cdata.strides_shape,
- cdata.padding_before, cdata.padding_after,
- border_type, ops::PoolOp::RoundMode::floor);
+ auto result = createOp<ops::PoolOp>(t_input, pool_type, cdata.kernel_shape, cdata.strides_shape,
+ cdata.padding_before, cdata.padding_after, border_type);
return {convertMIRToONNX(result->getOutput(0))};
}
auto result = createOp<ops::PoolOp>(input, ops::PoolOp::PoolingType::MAX,
window_shape, strides, padding_before, padding_after,
- ops::PoolOp::BorderType::EMPTY,
- ops::PoolOp::RoundMode::floor);
+ ops::PoolOp::BorderType::EMPTY);
return {addFusedActivation(result->getOutput(0), opts->fused_activation_function())};
}
auto result = createOp<ops::PoolOp>(input, ops::PoolOp::PoolingType::AVG,
window_shape, strides, padding_before, padding_after,
- ops::PoolOp::BorderType::EMPTY,
- ops::PoolOp::RoundMode::floor);
+ ops::PoolOp::BorderType::EMPTY);
return {addFusedActivation(result->getOutput(0), opts->fused_activation_function())};
}
return g->create<ops::PoolOp>("y", inputs[0], getPoolingType(opInfo),
getShapeParam(opInfo, 0), getShapeParam(opInfo, 1),
std::vector<int32_t>{0, 0}, std::vector<int32_t>{0, 0},
- ops::PoolOp::BorderType::ZEROFILLED,
- ops::PoolOp::RoundMode::floor);
+ ops::PoolOp::BorderType::ZEROFILLED);
}
static Operation* createConcatenation(std::unique_ptr<Graph>& g,
std::vector<int32_t> padding{0, 0};
return g.create<mir::ops::PoolOp>("maxPool", inputs[0], ops::PoolOp::PoolingType::MAX,
window_shape, strides, padding, padding,
- mir::ops::PoolOp::BorderType::EMPTY,
- ops::PoolOp::RoundMode::floor);
+ mir::ops::PoolOp::BorderType::EMPTY);
};
vector<Shape> input_shapes{{1, 10, 10, 3}};
irOps::PoolOp::BorderType border) {
std::vector<int32_t> padding{0, 0};
return g.create<mir::ops::PoolOp>("pool", inputs[0], poolT, window_shape, strides,
- padding, padding, border,
- irOps::PoolOp::RoundMode::floor);
+ padding, padding, border);
};
template <irOps::PoolOp::PoolingType poolT, class Func>