extract pooling attributes into a separate class (#1906)

Refactor cpu provider's pool ops by extracting pooling attributes
into a separate helper class PoolAttributes. With this change,
other providers such as Nuphar can re-use the same routines
for processing pooling attributes. This refactorying doesn't
have any functional changes.
This commit is contained in:
Yang Chen 2019-09-24 22:11:02 -07:00 committed by Scott McKay
parent 0317e825f1
commit e769617f75
8 changed files with 253 additions and 226 deletions

View file

@ -29,10 +29,10 @@ class MaxpoolWithMask : public OpKernel, public PoolBase {
//TODO: fix this checker later
//ONNXRUNTIME_RETURN_IF_NOT((x_shape[2] == m_shape[2]) && (x_shape[3] == m_shape[3]), " Input shape and mask shape mismatch: ", x_shape, " vs ", m_shape);
std::vector<int64_t> pads = pads_;
std::vector<int64_t> kernel_shape = kernel_shape_;
std::vector<int64_t> pads = pool_attrs_.pads;
std::vector<int64_t> kernel_shape = pool_attrs_.kernel_shape;
std::vector<int64_t> output_dims = PoolBase::SetOutputSize(x_shape, x_shape[1], &pads, dilations_, ceil_mode_);
std::vector<int64_t> output_dims = pool_attrs_.SetOutputSize(x_shape, x_shape[1], &pads);
Tensor* Y = context->Output(0, TensorShape(output_dims));
const float* X_data = X->template Data<float>();

View file

@ -171,17 +171,17 @@ Status NchwcPoolBase::NchwcPool(OpKernelContext* context, MLAS_POOLING_KIND kind
ORT_ENFORCE((X_shape[1] % MlasNchwcGetBlockSize()) == 0);
std::vector<int64_t> pads = pads_;
std::vector<int64_t> output_dims = PoolBase::SetOutputSize(X_shape, X_shape[1], &pads, dilations_, ceil_mode_);
std::vector<int64_t> pads = pool_attrs_.pads;
std::vector<int64_t> output_dims = pool_attrs_.SetOutputSize(X_shape, X_shape[1], &pads);
auto* Y = context->Output(0, output_dims);
MlasNchwcPool(kind,
2,
X_shape.GetDims().data(),
global_pooling_ ? nullptr : kernel_shape_.data(),
global_pooling_ ? nullptr : dilations_.data(),
global_pooling_ ? nullptr : pads.data(),
global_pooling_ ? nullptr : strides_.data(),
pool_attrs_.global_pooling ? nullptr : pool_attrs_.kernel_shape.data(),
pool_attrs_.global_pooling ? nullptr : pool_attrs_.dilations.data(),
pool_attrs_.global_pooling ? nullptr : pads.data(),
pool_attrs_.global_pooling ? nullptr : pool_attrs_.strides.data(),
output_dims.data(),
X->template Data<float>(),
Y->template MutableData<float>(),
@ -195,7 +195,8 @@ Status NchwcMaxPool::Compute(OpKernelContext* context) const {
}
Status NchwcAveragePool::Compute(OpKernelContext* context) const {
return NchwcPoolBase::NchwcPool(context, count_include_pad_ ? MlasAveragePoolingIncludePad : MlasAveragePoolingExcludePad);
return NchwcPoolBase::NchwcPool(context, pool_attrs_.count_include_pad ? MlasAveragePoolingIncludePad :
MlasAveragePoolingExcludePad);
}
} // namespace contrib

View file

@ -50,8 +50,8 @@ class NchwcConv : public OpKernel, public ConvBase {
class NchwcPoolBase : public PoolBase {
public:
NchwcPoolBase(const OpKernelInfo& info) : PoolBase(info) {
if (!global_pooling_)
ORT_ENFORCE(kernel_shape_.size() == 2, "kernel_shape num_dims is not compatible with X num_dims.");
if (!pool_attrs_.global_pooling)
ORT_ENFORCE(pool_attrs_.kernel_shape.size() == 2, "kernel_shape num_dims is not compatible with X num_dims.");
}
Status NchwcPool(OpKernelContext* context, MLAS_POOLING_KIND kind) const;

View file

@ -15,16 +15,16 @@ Status Pool<T, PoolType>::Compute(OpKernelContext* context) const {
ORT_RETURN_IF_NOT(x_shape.NumDimensions() >= 3, "Input dimension cannot be less than 3.");
std::vector<int64_t> pads = pads_;
std::vector<int64_t> kernel_shape = kernel_shape_;
std::vector<int64_t> pads = pool_attrs_.pads;
std::vector<int64_t> kernel_shape = pool_attrs_.kernel_shape;
if (global_pooling_) {
if (pool_attrs_.global_pooling) {
const auto& input_dims = x_shape.GetDims();
kernel_shape.assign(input_dims.begin() + 2, input_dims.end());
pads.assign(kernel_shape.size(), 0);
}
std::vector<int64_t> output_dims = PoolBase::SetOutputSize(x_shape, x_shape[1], &pads, dilations_, ceil_mode_);
std::vector<int64_t> output_dims = pool_attrs_.SetOutputSize(x_shape, x_shape[1], &pads);
Tensor* Y = context->Output(0, output_dims);
const auto* X_data = X->template Data<float>();
@ -60,7 +60,7 @@ Status Pool<T, PoolType>::Compute(OpKernelContext* context) const {
for (int64_t h = hstart; h < hend; ++h) {
PoolType::Process(x_d[h], Yh, pool_context_);
}
if (count_include_pad_) {
if (pool_attrs_.count_include_pad) {
PoolType::Finalize(kernel_shape[0], Yh, pool_context_);
} else {
PoolType::Finalize(hend - hstart, Yh, pool_context_);
@ -100,7 +100,7 @@ Status Pool<T, PoolType>::Compute(OpKernelContext* context) const {
PoolType::Process(x_d[input_index], Yh, pool_context_);
}
}
if (count_include_pad_) {
if (pool_attrs_.count_include_pad) {
PoolType::Finalize(kernel_shape[0] * kernel_shape[1], Yh, pool_context_);
} else {
PoolType::Finalize((hend - hstart) * (wend - wstart), Yh, pool_context_);
@ -147,7 +147,7 @@ Status Pool<T, PoolType>::Compute(OpKernelContext* context) const {
}
}
}
if (count_include_pad_) {
if (pool_attrs_.count_include_pad) {
PoolType::Finalize(kernel_shape[0] * kernel_shape[1] * kernel_shape[2], Yh, pool_context_);
} else {
PoolType::Finalize(
@ -179,12 +179,13 @@ Status PoolBase::Compute(OpKernelContext* context, MLAS_POOLING_KIND kind) const
if (pooling_dims > 3) {
return Status(ONNXRUNTIME, INVALID_ARGUMENT, "Unsupported pooling size.");
}
if (!global_pooling_) {
ORT_RETURN_IF_NOT(pooling_dims == kernel_shape_.size(), "kernel_shape num_dims is not compatible with X num_dims.");
if (!pool_attrs_.global_pooling) {
ORT_RETURN_IF_NOT(pooling_dims == pool_attrs_.kernel_shape.size(),
"kernel_shape num_dims is not compatible with X num_dims.");
}
std::vector<int64_t> pads = pads_;
std::vector<int64_t> output_dims = PoolBase::SetOutputSize(x_shape, x_shape[1], &pads, dilations_, ceil_mode_);
std::vector<int64_t> pads = pool_attrs_.pads;
std::vector<int64_t> output_dims = pool_attrs_.SetOutputSize(x_shape, x_shape[1], &pads);
Tensor* Y = context->Output(0, output_dims);
// Get access to the internal threadpool
@ -195,9 +196,9 @@ Status PoolBase::Compute(OpKernelContext* context, MLAS_POOLING_KIND kind) const
MlasPool(kind,
pooling_dims,
X->Shape().GetDims().data(),
global_pooling_ ? nullptr : kernel_shape_.data(),
global_pooling_ ? nullptr : pads.data(),
global_pooling_ ? nullptr : strides_.data(),
pool_attrs_.global_pooling ? nullptr : pool_attrs_.kernel_shape.data(),
pool_attrs_.global_pooling ? nullptr : pads.data(),
pool_attrs_.global_pooling ? nullptr : pool_attrs_.strides.data(),
output_dims.data(),
X->template Data<float>(),
Y->template MutableData<float>(),
@ -213,7 +214,8 @@ Status Pool<float, MaxPool<1 /*VERSION*/>>::Compute(OpKernelContext* context) co
template <>
Status Pool<float, AveragePool>::Compute(OpKernelContext* context) const {
return PoolBase::Compute(context, count_include_pad_ ? MlasAveragePoolingIncludePad : MlasAveragePoolingExcludePad);
return PoolBase::Compute(context, pool_attrs_.count_include_pad ? MlasAveragePoolingIncludePad
: MlasAveragePoolingExcludePad);
}
template <>
@ -222,7 +224,7 @@ Status Pool<float, MaxPool<8 /*VERSION*/>>::Compute(OpKernelContext* context) co
// and also if dilation is not required
bool need_dilation = false;
for (auto n : dilations_) {
for (auto n : pool_attrs_.dilations) {
need_dilation |= n > 1;
}
@ -235,10 +237,10 @@ Status Pool<float, MaxPool<8 /*VERSION*/>>::Compute(OpKernelContext* context) co
ORT_RETURN_IF_NOT(x_shape.NumDimensions() >= 3, "Input dimension cannot be less than 3.");
std::vector<int64_t> pads = pads_;
std::vector<int64_t> kernel_shape = kernel_shape_;
std::vector<int64_t> pads = pool_attrs_.pads;
std::vector<int64_t> kernel_shape = pool_attrs_.kernel_shape;
std::vector<int64_t> output_dims = PoolBase::SetOutputSize(x_shape, x_shape[1], &pads, dilations_, ceil_mode_);
std::vector<int64_t> output_dims = pool_attrs_.SetOutputSize(x_shape, x_shape[1], &pads);
Tensor* Y = context->Output(0, output_dims);
Tensor* I = context->Output(1, output_dims);
@ -260,7 +262,7 @@ Status Pool<float, MaxPool<8 /*VERSION*/>>::Compute(OpKernelContext* context) co
int64_t x_step = height;
int64_t y_step = pooled_height;
const int64_t total_channels = x_shape[0] * channels;
const int64_t dilation_h = dilations_[0];
const int64_t dilation_h = pool_attrs_.dilations[0];
#ifdef USE_OPENMP
#pragma omp parallel for
@ -294,8 +296,8 @@ Status Pool<float, MaxPool<8 /*VERSION*/>>::Compute(OpKernelContext* context) co
int64_t x_step = height * width;
int64_t y_step = pooled_height * pooled_width;
const int64_t total_channels = x_shape[0] * channels;
const int64_t dilation_h = dilations_[0];
const int64_t dilation_w = dilations_[1];
const int64_t dilation_h = pool_attrs_.dilations[0];
const int64_t dilation_w = pool_attrs_.dilations[1];
#ifdef USE_OPENMP
#pragma omp parallel for
@ -331,8 +333,8 @@ Status Pool<float, MaxPool<8 /*VERSION*/>>::Compute(OpKernelContext* context) co
}
y_d[pool_index] = Yh;
if (i_d != nullptr)
i_d[pool_index] = storage_order_ == 0 ? c * x_step + h_index * width + w_index
: c * x_step + h_index + w_index * height;
i_d[pool_index] = pool_attrs_.storage_order == 0 ? c * x_step + h_index * width + w_index
: c * x_step + h_index + w_index * height;
}
}
}
@ -343,9 +345,9 @@ Status Pool<float, MaxPool<8 /*VERSION*/>>::Compute(OpKernelContext* context) co
int64_t x_step = height * width * depth;
int64_t y_step = pooled_height * pooled_width * pooled_depth;
const int64_t total_channels = x_shape[0] * channels;
const int64_t dilation_h = dilations_[0];
const int64_t dilation_w = dilations_[1];
const int64_t dilation_d = dilations_[2];
const int64_t dilation_h = pool_attrs_.dilations[0];
const int64_t dilation_w = pool_attrs_.dilations[1];
const int64_t dilation_d = pool_attrs_.dilations[2];
#ifdef USE_OPENMP
#pragma omp parallel for
@ -391,8 +393,8 @@ Status Pool<float, MaxPool<8 /*VERSION*/>>::Compute(OpKernelContext* context) co
}
y_d[pool_index] = Yh;
if (i_d != nullptr)
i_d[pool_index] = storage_order_ == 0 ? c * x_step + h_index * width * depth + w_index * depth + d_index
: c * x_step + h_index + w_index * height + d_index * height * width;
i_d[pool_index] = pool_attrs_.storage_order == 0 ? c * x_step + h_index * width * depth + w_index * depth + d_index
: c * x_step + h_index + w_index * height + d_index * height * width;
}
}
}

View file

@ -0,0 +1,176 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
#pragma once
#include "core/common/common.h"
#include "core/framework/op_node_proto_helper.h"
#include "core/framework/tensor_shape.h"
#include "core/providers/cpu/nn/autopad_type.h"
namespace onnxruntime {
// A helper struct holding attributes for Pool-family ops
struct PoolAttributes {
static bool IsGlobalPooling(const std::string& op_name) {
return op_name == "GlobalAveragePool" || op_name == "GlobalMaxPool" || op_name == "GlobalLpPool";
}
PoolAttributes(const OpNodeProtoHelper<ProtoHelperNodeContext> &info,
const std::string& op_name, int start_ver_p)
: global_pooling(IsGlobalPooling(op_name)), start_version(start_ver_p) {
if (global_pooling) {
return;
}
ORT_ENFORCE(info.GetAttrs<int64_t>("kernel_shape", kernel_shape).IsOK(),
"No kernel shape is set.");
std::string auto_padding;
ORT_ENFORCE(info.GetAttr<std::string>("auto_pad", &auto_padding).IsOK());
auto_pad = StringToAutoPadType(auto_padding);
if (!info.GetAttrs<int64_t>("pads", pads).IsOK() || pads.empty()) {
pads.resize(kernel_shape.size() * 2, 0);
}
if (!info.GetAttrs<int64_t>("strides", strides).IsOK() || strides.empty()) {
strides.resize(kernel_shape.size(), 1);
}
if (!info.GetAttr<int64_t>("ceil_mode", &ceil_mode).IsOK()) {
ceil_mode = 0;
}
default_dilations = false;
if (!info.GetAttrs<int64_t>("dilations", dilations).IsOK() || dilations.empty()) {
dilations.resize(kernel_shape.size(), 1);
default_dilations = true;
} else {
default_dilations = std::all_of(dilations.begin(), dilations.end(), [](int64_t i) { return i == 1; });
}
if (op_name == "AveragePool") {
int64_t temp;
ORT_ENFORCE(info.GetAttr<int64_t>("count_include_pad", &temp).IsOK());
count_include_pad = (temp != 0);
}
if (op_name == "MaxPool") {
if (start_version == 8) {
storage_order = info.GetAttrOrDefault<int64_t>("storage_order", 0 /*default_value*/);
}
}
for (size_t dim = 0; dim < kernel_shape.size(); ++dim) {
ORT_ENFORCE(kernel_shape[dim] > 0);
ORT_ENFORCE(pads[dim] < kernel_shape[dim] && pads[dim + kernel_shape.size()] < kernel_shape[dim],
"Pad should be smaller than kernel.");
}
ORT_ENFORCE(strides.size() == kernel_shape.size());
ORT_ENFORCE(dilations.size() == kernel_shape.size(),
"Dilations dimensions should match kernel shape");
}
const bool global_pooling;
const int start_version;
bool count_include_pad{};
int64_t storage_order{0}; // MaxPool_8 only. 0 is row major, and 1 is column major. Default is 0.
int64_t ceil_mode{0}; // Introduced in MaxPool_10
std::vector<int64_t> kernel_shape;
std::vector<int64_t> pads;
std::vector<int64_t> strides;
std::vector<int64_t> dilations; // Introduced in MaxPool_10
// default_dilations is true if dilations is not set or all dilations are 1
bool default_dilations;
AutoPadType auto_pad;
std::vector<int64_t> SetOutputSize(const TensorShape& input_shape,
int64_t output_channel,
std::vector<int64_t>* actual_pads) const {
ORT_ENFORCE(input_shape.Size() > 0);
std::vector<int64_t> output_dims;
int64_t N = input_shape[0];
InferOutputSize(input_shape.GetDims(), &output_dims, actual_pads);
output_dims.insert(output_dims.begin(), {N, output_channel});
return output_dims;
}
void InferOutputSize(const std::vector<int64_t>& input_dims,
std::vector<int64_t>* output_dims,
std::vector<int64_t>* actual_pads) const {
ORT_ENFORCE(input_dims.size() >= 2);
if (global_pooling) {
output_dims->assign(input_dims.size() - 2, 1);
} else {
for (size_t dim = 0; dim < input_dims.size() - 2; ++dim) {
int64_t dim_size = 0;
ComputeSizePadDilations(static_cast<int>(input_dims[dim + 2]),
strides[dim],
kernel_shape[dim],
&actual_pads->at(dim),
&actual_pads->at(input_dims.size() + dim - 2),
dilations[dim],
&dim_size);
output_dims->push_back(dim_size);
}
}
}
void ComputeSizePadDilations(const int64_t in_size,
const int64_t stride,
const int64_t kernel,
int64_t* pad_head,
int64_t* pad_tail,
int64_t dilation,
int64_t* out_size) const {
if (auto_pad != AutoPadType::NOTSET) {
switch (auto_pad) {
case AutoPadType::VALID:
*pad_head = 0;
*pad_tail = 0;
*out_size = ComputeOutputSize(in_size, stride, kernel, 0, dilation);
break;
case AutoPadType::SAME_LOWER: {
int64_t legacy_target_size = (in_size + stride - 1) / stride;
int64_t pad_needed = (legacy_target_size - 1) * stride + kernel - in_size;
*pad_head = (pad_needed + 1) / 2;
*pad_tail = pad_needed - *pad_head;
*out_size = ComputeOutputSize(in_size, stride, kernel, pad_needed, dilation);
break;
}
case AutoPadType::SAME_UPPER: {
int64_t legacy_target_size = (in_size + stride - 1) / stride;
int64_t pad_needed = (legacy_target_size - 1) * stride + kernel - in_size;
*pad_head = pad_needed / 2;
*pad_tail = pad_needed - *pad_head;
*out_size = ComputeOutputSize(in_size, stride, kernel, pad_needed, dilation);
break;
}
default: {
ORT_THROW("Unsupported AutoPad Type.");
}
}
} else {
*out_size = ComputeOutputSize(in_size, stride, kernel, *pad_head + *pad_tail, dilation);
}
}
int64_t ComputeOutputSize(int64_t in_size,
int64_t stride,
int64_t kernel,
int64_t pad_needed,
int64_t dilation) const {
if (ceil_mode == 0) {
return static_cast<int64_t>(static_cast<float>(in_size + pad_needed - dilation * (kernel - 1) - 1) / stride + 1);
}
return static_cast<int64_t>(
std::ceil(static_cast<float>(in_size + pad_needed - dilation * (kernel - 1) - 1) / stride + 1));
}
};
} // namespace onnxruntime

View file

@ -6,7 +6,7 @@
#include <cmath>
#include "core/common/common.h"
#include "core/framework/op_kernel.h"
#include "core/providers/cpu/nn/autopad_type.h"
#include "core/providers/cpu/nn/pool_attributes.h"
#include "core/util/math.h"
#include "core/mlas/inc/mlas.h"
@ -100,190 +100,37 @@ class LpPool {
class PoolBase {
private:
static bool IsGlobalPooling(const std::string& op_name) {
return op_name == "GlobalAveragePool" || op_name == "GlobalMaxPool" || op_name == "GlobalLpPool";
static int GetStartVersion(const OpKernelInfo& info) {
int start, end;
info.GetKernelDef().SinceVersion(&start, &end);
return start;
}
protected:
PoolBase(const OpKernelInfo& info) : op_name_(info.GetKernelDef().OpName()), global_pooling_(IsGlobalPooling(op_name_)) {
int end;
info.GetKernelDef().SinceVersion(&start_version_, &end);
if (!global_pooling_) {
ORT_ENFORCE(info.GetAttrs<int64_t>("kernel_shape", kernel_shape_).IsOK(),
"No kernel shape is set.");
std::string auto_padding;
ORT_ENFORCE(info.GetAttr<std::string>("auto_pad", &auto_padding).IsOK());
auto_pad_ = StringToAutoPadType(auto_padding);
if (!info.GetAttrs<int64_t>("pads", pads_).IsOK() || pads_.empty()) {
pads_.resize(kernel_shape_.size() * 2, 0);
}
if (!info.GetAttrs<int64_t>("strides", strides_).IsOK() || strides_.empty()) {
strides_.resize(kernel_shape_.size(), 1);
}
if (!info.GetAttr<int64_t>("ceil_mode", &ceil_mode_).IsOK()) {
ceil_mode_ = 0;
}
default_dilations_ = false;
if (!info.GetAttrs<int64_t>("dilations", dilations_).IsOK() || dilations_.empty()) {
dilations_.resize(kernel_shape_.size(), 1);
default_dilations_ = true;
} else {
default_dilations_ = std::all_of(dilations_.begin(), dilations_.end(), [](int64_t i) { return i == 1; });
}
if (op_name_ == "AveragePool") {
int64_t temp;
ORT_ENFORCE(info.GetAttr<int64_t>("count_include_pad", &temp).IsOK());
count_include_pad_ = (temp != 0);
}
if (op_name_ == "MaxPool") {
if (start_version_ == 8) {
storage_order_ = info.GetAttrOrDefault<int64_t>("storage_order", 0 /*default_value*/);
}
}
for (size_t dim = 0; dim < kernel_shape_.size(); ++dim) {
ORT_ENFORCE(kernel_shape_[dim] > 0);
ORT_ENFORCE(pads_[dim] < kernel_shape_[dim] && pads_[dim + kernel_shape_.size()] < kernel_shape_[dim],
"Pad should be smaller than kernel.");
}
ORT_ENFORCE(strides_.size() == kernel_shape_.size());
ORT_ENFORCE(dilations_.size() == kernel_shape_.size(),
"Dilations dimensions should match kernel shape");
}
PoolBase(const OpKernelInfo& info)
: op_name_(info.GetKernelDef().OpName()),
pool_attrs_(info, op_name_, GetStartVersion(info)) {
}
~PoolBase() = default;
;
std::vector<int64_t> SetOutputSize(const TensorShape& input_shape,
int64_t output_channel,
std::vector<int64_t>* pads,
const std::vector<int64_t>& dilations,
int64_t ceil_mode) const {
ORT_ENFORCE(input_shape.Size() > 0);
std::vector<int64_t> output_dims;
int64_t N = input_shape[0];
InferOutputSize(input_shape.GetDims(), &output_dims, pads, dilations, ceil_mode);
output_dims.insert(output_dims.begin(), {N, output_channel});
return output_dims;
}
inline void InferOutputSize(const std::vector<int64_t>& input_dims,
std::vector<int64_t>* output_dims,
std::vector<int64_t>* pads,
const std::vector<int64_t>& dilations,
int64_t ceil_mode) const {
ORT_ENFORCE(input_dims.size() >= 2);
if (global_pooling_) {
output_dims->assign(input_dims.size() - 2, 1);
} else {
for (size_t dim = 0; dim < input_dims.size() - 2; ++dim) {
int64_t dim_size = 0;
ComputeSizePadDilations(static_cast<int>(input_dims[dim + 2]),
strides_[dim],
kernel_shape_[dim],
&pads->at(dim),
&pads->at(input_dims.size() + dim - 2),
dilations[dim],
ceil_mode,
&dim_size);
output_dims->push_back(dim_size);
}
}
}
inline void ComputeSizePadDilations(const int64_t in_size,
const int64_t stride,
const int64_t kernel,
int64_t* pad_head,
int64_t* pad_tail,
int64_t dilation,
int64_t ceil_mode,
int64_t* out_size) const {
if (auto_pad_ != AutoPadType::NOTSET) {
switch (auto_pad_) {
case AutoPadType::VALID:
*pad_head = 0;
*pad_tail = 0;
*out_size = ComputeOutputSize(in_size, stride, kernel, 0, dilation, ceil_mode);
break;
case AutoPadType::SAME_LOWER: {
int64_t legacy_target_size = (in_size + stride - 1) / stride;
int64_t pad_needed = (legacy_target_size - 1) * stride + kernel - in_size;
*pad_head = (pad_needed + 1) / 2;
*pad_tail = pad_needed - *pad_head;
*out_size = ComputeOutputSize(in_size, stride, kernel, pad_needed, dilation, ceil_mode);
break;
}
case AutoPadType::SAME_UPPER: {
int64_t legacy_target_size = (in_size + stride - 1) / stride;
int64_t pad_needed = (legacy_target_size - 1) * stride + kernel - in_size;
*pad_head = pad_needed / 2;
*pad_tail = pad_needed - *pad_head;
*out_size = ComputeOutputSize(in_size, stride, kernel, pad_needed, dilation, ceil_mode);
break;
}
default: {
ORT_THROW("Unsupported AutoPad Type.");
}
}
} else {
*out_size = ComputeOutputSize(in_size, stride, kernel, *pad_head + *pad_tail, dilation, ceil_mode);
}
}
inline int64_t ComputeOutputSize(int64_t in_size,
int64_t stride,
int64_t kernel,
int64_t pad_needed,
int64_t dilation,
int64_t ceil_mode) const {
if (ceil_mode == 0) {
return static_cast<int64_t>(static_cast<float>(in_size + pad_needed - dilation * (kernel - 1) - 1) / stride + 1);
}
return static_cast<int64_t>(
std::ceil(static_cast<float>(in_size + pad_needed - dilation * (kernel - 1) - 1) / stride + 1));
}
Status Compute(OpKernelContext* context, MLAS_POOLING_KIND kind) const;
protected:
const std::string op_name_;
const bool global_pooling_;
bool count_include_pad_{};
int64_t storage_order_{0}; // MaxPool_8 only. 0 is row major, and 1 is column major. Default is 0.
int64_t ceil_mode_{0}; // Introduced in MaxPool_10
std::vector<int64_t> kernel_shape_;
std::vector<int64_t> pads_;
std::vector<int64_t> strides_;
std::vector<int64_t> dilations_; // Introduced in MaxPool_10
int start_version_;
// default_dilations_ is true if dilations_ is not set or all dilations_ are 1
bool default_dilations_;
AutoPadType auto_pad_;
PoolAttributes pool_attrs_;
inline int64_t stride_h() const {
return global_pooling_ ? 1 : strides_[0];
return pool_attrs_.global_pooling ? 1 : pool_attrs_.strides[0];
}
inline int64_t stride_w() const {
return global_pooling_ ? 1 : strides_[1];
return pool_attrs_.global_pooling ? 1 : pool_attrs_.strides[1];
}
inline int64_t stride_d() const {
return global_pooling_ ? 1 : strides_[2];
return pool_attrs_.global_pooling ? 1 : pool_attrs_.strides[2];
}
};

View file

@ -113,17 +113,17 @@ Status Pool<T, PoolType>::ComputeInternal(OpKernelContext* context) const {
return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Input dimension cannot be less than 3.");
}
std::vector<int64_t> kernel_shape = kernel_shape_;
std::vector<int64_t> pads = pads_;
std::vector<int64_t> strides = strides_;
std::vector<int64_t> kernel_shape = pool_attrs_.kernel_shape;
std::vector<int64_t> pads = pool_attrs_.pads;
std::vector<int64_t> strides = pool_attrs_.strides;
if (global_pooling_) {
if (pool_attrs_.global_pooling) {
kernel_shape.assign(x_dims.begin() + 2, x_dims.end());
pads.assign(kernel_shape.size(), 0);
strides.assign(kernel_shape.size(), 1);
}
std::vector<int64_t> y_dims = PoolBase::SetOutputSize(x_shape, x_shape[1], &pads, dilations_, ceil_mode_);
std::vector<int64_t> y_dims = pool_attrs_.SetOutputSize(x_shape, x_shape[1], &pads);
Tensor* Y = context->Output(0, TensorShape(y_dims));
auto x_data = reinterpret_cast<const CudaT*>(X->template Data<T>());
@ -150,7 +150,8 @@ Status Pool<T, PoolType>::ComputeInternal(OpKernelContext* context) const {
cudnnPoolingMode_t mode = CUDNN_POOLING_MAX;
if (PoolType::type == onnxruntime::PoolType::kAveragePool) {
mode = count_include_pad_ ? CUDNN_POOLING_AVERAGE_COUNT_INCLUDE_PADDING : CUDNN_POOLING_AVERAGE_COUNT_EXCLUDE_PADDING;
mode = pool_attrs_.count_include_pad ? CUDNN_POOLING_AVERAGE_COUNT_INCLUDE_PADDING :
CUDNN_POOLING_AVERAGE_COUNT_EXCLUDE_PADDING;
}
CudnnPoolingDescriptor pooling_desc;
ORT_RETURN_IF_ERROR(pooling_desc.Set(mode, kernel_shape, pads, strides));
@ -171,24 +172,24 @@ Status Pool<T, MaxPool<8>>::ComputeInternal(OpKernelContext* context) const {
return ORT_MAKE_STATUS(ONNXRUNTIME, FAIL, "Input dimension cannot be less than 3.");
}
std::vector<int64_t> kernel_shape = this->kernel_shape_;
std::vector<int64_t> pads = this->pads_;
std::vector<int64_t> strides = this->strides_;
std::vector<int64_t> kernel_shape = this->pool_attrs_.kernel_shape;
std::vector<int64_t> pads = this->pool_attrs_.pads;
std::vector<int64_t> strides = this->pool_attrs_.strides;
if (this->global_pooling_) {
if (this->pool_attrs_.global_pooling) {
kernel_shape.assign(x_dims.begin() + 2, x_dims.end());
pads.assign(kernel_shape.size(), 0);
strides.assign(kernel_shape.size(), 1);
}
std::vector<int64_t> y_dims = PoolBase::SetOutputSize(x_shape, x_shape[1], &pads, this->dilations_, this->ceil_mode_);
std::vector<int64_t> y_dims = this->pool_attrs_.SetOutputSize(x_shape, x_shape[1], &pads);
Tensor* Y = context->Output(0, TensorShape(y_dims));
auto x_data = reinterpret_cast<const CudaT*>(X->template Data<T>());
auto y_data = reinterpret_cast<CudaT*>(Y->template MutableData<T>());
Tensor* I = context->Output(1, TensorShape(y_dims));
if (nullptr != I || !this->default_dilations_) {
if (nullptr != I || !this->pool_attrs_.default_dilations) {
auto i_data = nullptr == I ? nullptr : I->template MutableData<int64_t>();
MaxPoolWithIndex<CudaT>(
x_shape,
@ -196,8 +197,8 @@ Status Pool<T, MaxPool<8>>::ComputeInternal(OpKernelContext* context) const {
kernel_shape,
strides,
pads,
this->dilations_,
this->storage_order_,
this->pool_attrs_.dilations,
this->pool_attrs_.storage_order,
x_data,
y_data,
i_data);

View file

@ -244,17 +244,17 @@ Status Pool<T, PoolType>::Compute(OpKernelContext* context) const {
return onnxruntime::Pool<T, PoolType>::Compute(context);
}
std::vector<int64_t> kernel_shape = this->kernel_shape_;
std::vector<int64_t> pads = this->pads_;
std::vector<int64_t> strides = this->strides_;
std::vector<int64_t> kernel_shape = this->pool_attrs_.kernel_shape;
std::vector<int64_t> pads = this->pool_attrs_.pads;
std::vector<int64_t> strides = this->pool_attrs_.strides;
if (this->global_pooling_) {
if (this->pool_attrs_.global_pooling) {
kernel_shape.assign(x_dims.begin() + 2, x_dims.end());
pads.assign(kernel_shape.size() * 2, 0);
strides.assign(kernel_shape.size(), 1);
}
std::vector<int64_t> y_dims = PoolBase::SetOutputSize(x_shape, x_shape[1], &pads, this->dilations_, this->ceil_mode_);
std::vector<int64_t> y_dims = this->pool_attrs_.SetOutputSize(x_shape, x_shape[1], &pads);
Tensor* Y = context->Output(0, TensorShape(y_dims));
size_t num_outputs = OpKernel::Node().OutputDefs().size();
@ -285,7 +285,7 @@ Status Pool<T, PoolType>::Compute(OpKernelContext* context) const {
src_dims_mkl, dst_dims_mkl,
kernel_mkl, strides_mkl,
padding_left_mkl, padding_right_mkl,
this->count_include_pad_);
this->pool_attrs_.count_include_pad);
PoolPrimitive<T, PoolType>* pool_primitive = PoolPrimitivePool<T, PoolType>::Get(pool_params);
auto fwd_primitive_desc = pool_primitive->GetPrimitiveDesc();