pool_op.cc 26.1 KB
Newer Older
1
/* Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.
2 3 4 5 6 7 8 9 10 11 12 13 14

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License. */

Y
Yi Wang 已提交
15
#include "paddle/fluid/operators/pool_op.h"
16

17
#include <unordered_map>
18 19 20 21 22 23
#ifdef PADDLE_WITH_CUDA
#include "paddle/fluid/platform/cudnn_helper.h"
#endif
#ifdef PADDLE_WITH_MKLDNN
#include "paddle/fluid/platform/mkldnn_helper.h"
#endif
24 25 26 27

namespace paddle {
namespace operators {

28 29
int PoolOutputSize(int input_size, int filter_size, int padding_1,
                   int padding_2, int stride, bool ceil_mode) {
30 31
  int output_size;
  if (!ceil_mode) {
32 33
    output_size =
        (input_size - filter_size + padding_1 + padding_2) / stride + 1;
34 35
  } else {
    output_size =
36 37 38
        (input_size - filter_size + padding_1 + padding_2 + stride - 1) /
            stride +
        1;
39
  }
40 41
  PADDLE_ENFORCE_GT(
      output_size, 0,
42 43 44 45 46 47
      platform::errors::InvalidArgument(
          "the output size must be greater than 0. But received: "
          "output_size = %d due to the settings of input_size(%d), "
          "padding(%d,%d), "
          "k_size(%d) and stride(%d). Please check again!",
          output_size, input_size, padding_1, padding_2, filter_size, stride));
48 49 50
  return output_size;
}

C
chengduo 已提交
51
void PoolOp::InferShape(framework::InferShapeContext* ctx) const {
52 53 54 55 56 57
  PADDLE_ENFORCE_EQ(
      ctx->HasInput("X"), true,
      platform::errors::NotFound("Input(X) of Pool operator is not found."));
  PADDLE_ENFORCE_EQ(
      ctx->HasOutput("Out"), true,
      platform::errors::NotFound("Output(Out) of Pool operator is not found."));
58

C
chengduoZH 已提交
59
  std::string pooling_type = ctx->Attrs().Get<std::string>("pooling_type");
60 61 62
  std::vector<int> ksize = ctx->Attrs().Get<std::vector<int>>("ksize");
  std::vector<int> strides = ctx->Attrs().Get<std::vector<int>>("strides");
  std::vector<int> paddings = ctx->Attrs().Get<std::vector<int>>("paddings");
63
  bool ceil_mode = ctx->Attrs().Get<bool>("ceil_mode");
64
  bool adaptive = ctx->Attrs().Get<bool>("adaptive");
65 66 67 68
  bool global_pooling = ctx->Attrs().Get<bool>("global_pooling");
  std::string data_format = ctx->Attrs().Get<std::string>("data_format");
  std::string padding_algorithm =
      ctx->Attrs().Get<std::string>("padding_algorithm");
69

70
  auto in_x_dims = ctx->GetInputDim("X");
71 72
  PADDLE_ENFORCE_EQ(
      in_x_dims.size() == 4 || in_x_dims.size() == 5, true,
73 74 75 76
      platform::errors::InvalidArgument(
          "the input of Op(pool) should be 4-D or 5-D Tensor. But "
          "received: %u-D Tensor and it's shape is [%s].",
          in_x_dims.size(), in_x_dims));
77 78 79

  PADDLE_ENFORCE_EQ(
      in_x_dims.size() - ksize.size(), 2U,
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
      platform::errors::InvalidArgument(
          "the dimension of input minus the size of "
          "Attr(ksize) must be euqal to 2 in Op(pool). "
          "But received: the dimension of input minus the size "
          "of Attr(ksize) is %d, the "
          "input's dimension is %d, the shape of input "
          "is [%s], the Attr(ksize)'s size is %d, the Attr(ksize) is [%s].",
          in_x_dims.size() - ksize.size(), in_x_dims.size(), in_x_dims,
          ksize.size(), framework::make_ddim(ksize)));

  PADDLE_ENFORCE_EQ(
      ksize.size(), strides.size(),
      platform::errors::InvalidArgument(
          "the size of Attr(ksize) and Attr(strides) in "
          "Op(pool) must be equal. "
          "But received: Attr(ksize)'s size is %d, Attr(strides)'s "
          "size is %d, Attr(ksize) is [%s], Attr(strides)is [%s].",
          ksize.size(), strides.size(), framework::make_ddim(ksize),
          framework::make_ddim(strides)));
99

100 101 102 103
  // MKL-DNN Kernels are using NCHW order of dims description
  // so we ignore data_format consideration for MKL-DNN kernel
  const bool channel_last = (this->IsMKLDNNType() == false) &&
                            (data_format == "NHWC" || data_format == "NDHWC");
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119

  // update paddings if "SAME" or global_pooling
  framework::DDim data_dims;
  if (channel_last) {
    data_dims = framework::slice_ddim(in_x_dims, 1, in_x_dims.size() - 1);
  } else {
    data_dims = framework::slice_ddim(in_x_dims, 2, in_x_dims.size());
  }
  UpdatePadding(&paddings, global_pooling, adaptive, padding_algorithm,
                data_dims, strides, ksize);

  if (global_pooling) {
    UpdateKsize(&ksize, data_dims);
  }

  std::vector<int64_t> output_shape;
120 121 122
  if (adaptive) {
    output_shape.insert(output_shape.end(), ksize.begin(), ksize.end());
  } else {
123
    for (int i = 0; i < data_dims.size(); ++i) {
124
      if ((!ctx->IsRuntime()) && (data_dims[i] < 0)) {
125
        output_shape.push_back(data_dims[i]);
K
Kaipeng Deng 已提交
126
      } else {
127 128 129
        output_shape.push_back(
            PoolOutputSize(data_dims[i], ksize[i], paddings[2 * i],
                           paddings[2 * i + 1], strides[i], ceil_mode));
K
Kaipeng Deng 已提交
130
      }
131
    }
132
  }
133 134 135 136 137 138 139 140 141 142

  // output_N = input_N
  output_shape.insert(output_shape.begin(), in_x_dims[0]);
  // output_C = input_C
  if (channel_last) {
    output_shape.push_back(in_x_dims[in_x_dims.size() - 1]);
  } else {
    output_shape.insert(output_shape.begin() + 1, in_x_dims[1]);
  }

143
  ctx->SetOutputDim("Out", framework::make_ddim(output_shape));
Y
Yang Yu 已提交
144
  ctx->ShareLoD("X", "Out");
145 146
}

147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
bool CanMKLDNNSupportPool(const framework::ExecutionContext& ctx) {
  if (ctx.Attr<bool>("adaptive") == false) return true;
  // (jczaja): oneDNN is supporting only unchangable in size pool window
  auto src_tz = paddle::framework::vectorize(ctx.Input<Tensor>("X")->dims());
  std::vector<int> ksize = ctx.Attr<std::vector<int>>("ksize");
  // Fast but not exhustive check
  if ((src_tz[src_tz.size() - 1] % ksize[1] == 0) &&
      (src_tz[src_tz.size() - 2] % ksize[0] == 0))
    return true;

  // Exhustive check
  auto IH = static_cast<double>(src_tz[src_tz.size() - 2]);
  auto IW = static_cast<double>(src_tz[src_tz.size() - 1]);
  auto OH = static_cast<double>(ksize[0]);
  auto OW = static_cast<double>(ksize[1]);

  auto SH = static_cast<int>(floor((IH * 2.0) / OH) - floor(IH / OH));
  auto SW = static_cast<int>(floor((IW * 2.0) / OW) - floor(IW / OW));
  auto KH = static_cast<int>(ceil((IH * 2.0) / OH) - floor(IH / OH));
  auto KW = static_cast<int>(ceil((IW * 2.0) / OW) - floor(IW / OW));

  auto PH = (SH * (static_cast<int>(OH) - 1) + KH - static_cast<int>(IH));
  auto PW = (SW * (static_cast<int>(OW) - 1) + KW - static_cast<int>(IW));
  // If there is additional padding needed then
  // this is situation that oneDNN cannot comply with
  // paddlepaddle reference implementation
  return (PH == 0) && (PW == 0);
}

176
framework::OpKernelType PoolOp::GetExpectedKernelType(
C
chengduo 已提交
177
    const framework::ExecutionContext& ctx) const {
178
  framework::LibraryType library_{framework::LibraryType::kPlain};
179
  std::string data_format = "AnyLayout";
M
mozga-intel 已提交
180
  framework::DataLayout layout_ = framework::StringToDataLayout(data_format);
181
  auto data_type = OperatorWithKernel::IndicateVarDataType(ctx, "X");
M
mozga-intel 已提交
182

C
chengduoZH 已提交
183
#ifdef PADDLE_WITH_CUDA
184 185
  if (platform::CanCUDNNBeUsed(ctx)) {
    library_ = framework::LibraryType::kCUDNN;
C
chengduoZH 已提交
186 187
  }
#endif
188 189
#ifdef PADDLE_WITH_MKLDNN
  if (library_ == framework::LibraryType::kPlain &&
190
      this->CanMKLDNNBeUsed(ctx, data_type) && CanMKLDNNSupportPool(ctx)) {
191
    library_ = framework::LibraryType::kMKLDNN;
M
mozga-intel 已提交
192
    layout_ = framework::DataLayout::kMKLDNN;
193
  }
194
#endif
195

196
  return framework::OpKernelType(data_type, ctx.GetPlace(), layout_, library_);
197 198
}

199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
framework::OpKernelType PoolOp::GetKernelTypeForVar(
    const std::string& var_name, const Tensor& tensor,
    const framework::OpKernelType& expected_kernel_type) const {
#ifdef PADDLE_WITH_MKLDNN
  if ((expected_kernel_type.data_layout_ == framework::DataLayout::kMKLDNN) &&
      (tensor.layout() != framework::DataLayout::kMKLDNN)) {
    auto attrs = Attrs();
    auto ar = paddle::framework::AttrReader(attrs);
    const std::string data_format = ar.Get<std::string>("data_format");
    auto dl = framework::StringToDataLayout(data_format);
    // Some models may have intentionally set "AnyLayout" for pool
    // op. Treat this as NCHW (default data_format value)
    if (dl != framework::DataLayout::kAnyLayout) {
      return framework::OpKernelType(expected_kernel_type.data_type_,
                                     tensor.place(), dl);
    }
  }
#endif
  return framework::OpKernelType(expected_kernel_type.data_type_,
                                 tensor.place(), tensor.layout());
}

C
chengduo 已提交
221
void PoolOpGrad::InferShape(framework::InferShapeContext* ctx) const {
222 223 224
  PADDLE_ENFORCE_EQ(ctx->HasInput("X"), true,
                    platform::errors::NotFound(
                        "Input(X) of Pool Gradoperator is not found."));
225
  PADDLE_ENFORCE_EQ(ctx->HasOutput(framework::GradVarName("X")), true,
226 227
                    platform::errors::NotFound(
                        "Input(X@GRAD) of Pool Gradoperator is not found."));
228 229 230
  ctx->SetOutputDim(framework::GradVarName("X"), ctx->GetInputDim("X"));
}

231
framework::OpKernelType PoolOpGrad::GetExpectedKernelType(
C
chengduo 已提交
232
    const framework::ExecutionContext& ctx) const {
233
  framework::LibraryType library_{framework::LibraryType::kPlain};
234
  std::string data_format = "AnyLayout";
M
mozga-intel 已提交
235
  framework::DataLayout layout_ = framework::StringToDataLayout(data_format);
236
  auto input_data_type = OperatorWithKernel::IndicateVarDataType(ctx, "X");
M
mozga-intel 已提交
237

C
chengduoZH 已提交
238
#ifdef PADDLE_WITH_CUDA
239 240
  if (platform::CanCUDNNBeUsed(ctx)) {
    library_ = framework::LibraryType::kCUDNN;
C
chengduoZH 已提交
241 242
  }
#endif
243 244
#ifdef PADDLE_WITH_MKLDNN
  if (library_ == framework::LibraryType::kPlain &&
245 246
      this->CanMKLDNNBeUsed(ctx, input_data_type) &&
      CanMKLDNNSupportPool(ctx)) {
247
    library_ = framework::LibraryType::kMKLDNN;
M
mozga-intel 已提交
248
    layout_ = framework::DataLayout::kMKLDNN;
249
  }
250
#endif
251

K
Kexin Zhao 已提交
252 253
  return framework::OpKernelType(input_data_type, ctx.GetPlace(), layout_,
                                 library_);
254 255
}

256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
framework::OpKernelType PoolOpGrad::GetKernelTypeForVar(
    const std::string& var_name, const Tensor& tensor,
    const framework::OpKernelType& expected_kernel_type) const {
#ifdef PADDLE_WITH_MKLDNN
  if ((expected_kernel_type.data_layout_ == framework::DataLayout::kMKLDNN) &&
      (tensor.layout() != framework::DataLayout::kMKLDNN)) {
    auto attrs = Attrs();
    auto ar = paddle::framework::AttrReader(attrs);
    const std::string data_format = ar.Get<std::string>("data_format");
    return framework::OpKernelType(expected_kernel_type.data_type_,
                                   tensor.place(),
                                   framework::StringToDataLayout(data_format));
  }
#endif
  return framework::OpKernelType(expected_kernel_type.data_type_,
                                 tensor.place(), tensor.layout());
}

Y
Yu Yang 已提交
274
void Pool2dOpMaker::Make() {
275 276
  AddInput(
      "X",
C
chengduoZH 已提交
277
      "(Tensor) The input tensor of pooling operator. "
K
kexinzhao 已提交
278 279 280
      "The format of input tensor is NCHW, where N is batch size, C is the "
      "number of channels, H is the height of the feature, "
      "and W is the width of the feature.");
281
  AddOutput("Out",
K
kexinzhao 已提交
282 283 284 285
            "(Tensor) The output tensor of pooling operator. "
            "The format of output tensor is also NCHW, "
            "where N is batch size, C is the number of channels, "
            "H is the height of the feature, "
286
            "and W is the width of the feature.");
287

C
chengduoZH 已提交
288
  AddAttr<std::string>("pooling_type",
C
chengduoZH 已提交
289 290
                       "(string), pooling type, can be \"max\" for max-pooling "
                       "and \"avg\" for average-pooling.")
291
      .InEnum({"max", "avg"});
C
fix bug  
chengduoZH 已提交
292
  AddAttr<std::vector<int>>("ksize",
K
kexinzhao 已提交
293 294
                            "(vector<int>) The pooling window "
                            "size(height, width) of the pooling operator. "
C
chengduoZH 已提交
295
                            "If global_pooling = true, ksize and paddings will "
C
fix bug  
chengduoZH 已提交
296 297
                            "be ignored.");  // TODO(Chengduo): Add checker.
                                             // (Currently,
C
fix doc  
chengduoZH 已提交
298
  // TypedAttrChecker don't support vector type.)
299 300
  AddAttr<bool>(
      "global_pooling",
K
Kaipeng Deng 已提交
301 302 303
      "(bool) Whether to use the global pooling. "
      "If global_pooling = true, kernel size and paddings will be ignored. "
      "Default False.")
304
      .SetDefault(false);
K
kexinzhao 已提交
305 306 307
  AddAttr<std::vector<int>>("strides",
                            "(vector<int>, default {1, 1}), strides(height, "
                            "width) of pooling operator.")
308 309
      .SetDefault({1, 1});
  // TODO(Chengduo): Add checker. (Currently,
C
fix doc  
chengduoZH 已提交
310 311 312
  // TypedAttrChecker don't support vector type.)
  AddAttr<std::vector<int>>(
      "paddings",
313 314
      "(vector<int>, default {0,0}), paddings(height_top, height_bottom, "
      "width_left, wifth_right) of pooling operator."
315
      "If global_pooling = true, paddings and kernel size will be ignored.")
316
      .SetDefault({0, 0});
317 318
  AddAttr<bool>(
      "exclusive",
K
Kaipeng Deng 已提交
319
      "(bool) When true, will exclude the zero-padding in the "
320
      "averaging calculating, otherwise, include the zero-padding. Note, it "
K
Kaipeng Deng 已提交
321 322
      "is only used when pooling_type is avg. The default is True. "
      "Default True.")
323
      .SetDefault(true);
324 325
  AddAttr<bool>(
      "adaptive",
K
Kaipeng Deng 已提交
326
      "(bool) When true, will perform adaptive pooling instead, "
327 328
      "output shape in H and W dimensions will be same as ksize, input data "
      "will be divided into grids specify by ksize averagely and perform "
K
Kaipeng Deng 已提交
329 330
      "pooling in each grid area to get output pooling value. "
      "Default False.")
331 332
      .SetDefault(false);

333 334
  AddAttr<bool>(
      "use_cudnn",
K
Kaipeng Deng 已提交
335
      "(bool) Only used in cudnn kernel, need install cudnn. Default False")
336
      .SetDefault(false);
337 338
  AddAttr<bool>(
      "ceil_mode",
K
Kaipeng Deng 已提交
339
      "(bool) Whether to use the ceil function to calculate "
W
wanghaoshuang 已提交
340
      "output height and width. False is the default. If it is set to False, "
K
Kaipeng Deng 已提交
341
      "the floor function will be used. Default False")
342
      .SetDefault(false);
343
  AddAttr<bool>("use_mkldnn",
K
Kaipeng Deng 已提交
344
                "(bool) Only used in mkldnn kernel. Default False")
345
      .SetDefault(false);
346 347 348 349
  AddAttr<bool>(
      "use_quantizer",
      "(bool, default false) "
      "This parameter is no longer used. Use 'mkldnn_data_type' instead.")
350
      .SetDefault(false);
351 352 353 354 355
  AddAttr<std::string>(
      "mkldnn_data_type",
      "(string, default \"float32\"). Data type of mkldnn kernel")
      .SetDefault("float32")
      .InEnum({"float32", "int8", "bfloat16"});
356 357 358 359 360 361
  AddAttr<std::string>(
      "data_format",
      "(string, default NCHW) Only used in "
      "An optional string from: \"NHWC\", \"NCHW\". "
      "Defaults to \"NHWC\". Specify the data format of the output data, "
      "the input will be transformed automatically. ")
362
      .SetDefault("NCHW");
363 364 365 366 367
  AddAttr<bool>("is_test",
                "(bool, default false) Set to true for inference only, false "
                "for training. Some layers may run faster when this is true.")
      .SetDefault(false);

368 369 370 371 372 373
  AddAttr<std::string>(
      "padding_algorithm",
      "(string, default \"EXPLICIT\") An optional string from: \"EXPLICIT\","
      "\"SAME\",\"VALID\". Set to \"EXPLICIT\" for explicit padding. "
      "Set to \"SAME\" or \"VALID\" for algorithm of padding. ")
      .SetDefault("EXPLICIT");
374
  // TODO(dzhwinter): need to registered layout transform function
375 376

  AddComment(R"DOC(
K
Kaipeng Deng 已提交
377 378 379
This operation calculates the pooling output based on
the input, pooling_type and pool_size, pool_stride, pool_padding parameters.
Input(X) and Output(Out) are in NCHW or NHWC format, where N is batch size, C is the
K
kexinzhao 已提交
380
number of channels, H is the height of the feature, and W is the width of the feature.
K
Kaipeng Deng 已提交
381
Parameters(pool_size, pool_stride, pool_padding) hold two integer elements.
C
fix doc  
chengduoZH 已提交
382
These two elements represent height and width, respectively.
C
chengduoZH 已提交
383 384
The input(X) size and output(Out) size may be different.

385
Example:
F
fengjiayi 已提交
386

C
chengduoZH 已提交
387
  Input:
F
fengjiayi 已提交
388

K
kexinzhao 已提交
389
       X shape: $(N, C, H_{in}, W_{in})$
F
fengjiayi 已提交
390

C
chengduoZH 已提交
391
  Output:
F
fengjiayi 已提交
392

K
kexinzhao 已提交
393
       Out shape: $(N, C, H_{out}, W_{out})$
F
fengjiayi 已提交
394

395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410
  For pool_padding = "SAME":
       $$
       H_{out} = \\frac{(H_{in} + strides[0] - 1)}{strides[0]}
       $$
       $$
       W_{out} = \\frac{(W_{in} + strides[1] - 1)}{strides[1]}
       $$

  For pool_padding = "VALID":
       $$
       H_{out} = \\frac{(H_{in} - ksize[0] + strides[0])}{strides[0]}
       $$
       $$
       W_{out} = \\frac{(W_{in} - ksize[1] + strides[1])}{strides[1]}
       $$

411 412
  For ceil_mode = false:
       $$
413
       H_{out} = \\frac{(H_{in} - ksize[0] + pad_height_top + pad_height_bottom}{strides[0]} + 1
F
fengjiayi 已提交
414 415
       $$
       $$
416
       W_{out} = \\frac{(W_{in} - ksize[1] + pad_width_left + pad_width_right}{strides[1]} + 1
K
kexinzhao 已提交
417
       $$
418

419 420
  For ceil_mode = true:
       $$
421
       H_{out} = \\frac{(H_{in} - ksize[0] + pad_height_top + pad_height_bottom + strides[0] - 1)}{strides[0]} + 1
F
fengjiayi 已提交
422 423
       $$
       $$
424
       W_{out} = \\frac{(W_{in} - ksize[1] + pad_width_left + pad_width_right + strides[1] - 1)}{strides[1]} + 1
425
       $$
K
kexinzhao 已提交
426

427
  For exclusive = false:
428
       $$
429
       hstart = i * strides[0] - pad_height_top
430 431 432 433 434
       $$
       $$
       hend = hstart + ksize[0]
       $$
       $$
435
       wstart = j * strides[1] - pad_width_left
436 437 438 439 440 441 442
       $$
       $$
       wend = wstart + ksize[1]
       $$
       $$
       Output(i ,j) = \\frac{sum(Input[hstart:hend, wstart:wend])}{ksize[0] * ksize[1]}
       $$
443

444
  For exclusive = true:
445
       $$
446
       hstart = max(0, i * strides[0] - pad_height_top)
447 448 449 450 451
       $$
       $$
       hend = min(H, hstart + ksize[0])
       $$
       $$
452
       wstart = max(0, j * strides[1] - pad_width_left)
453 454 455 456 457 458 459
       $$
       $$
       wend = min(W, wstart + ksize[1])
       $$
       $$
       Output(i ,j) = \\frac{sum(Input[hstart:hend, wstart:wend])}{(hend - hstart) * (wend - wstart)}
       $$
460

461
)DOC");
462 463
}

C
chengduo 已提交
464 465
class PoolOpInferVarType : public framework::PassInDtypeAndVarTypeToOutput {
 protected:
466
  std::unordered_map<std::string, std::string>& GetInputOutputWithSameType()
C
chengduo 已提交
467
      const override {
468 469
    static std::unordered_map<std::string, std::string> m{{"X", /*->*/ "Out"}};
    return m;
C
chengduo 已提交
470 471 472
  }
};

Y
Yu Yang 已提交
473
void Pool3dOpMaker::Make() {
K
kexinzhao 已提交
474 475
  AddInput("X",
           "(Tensor) The input tensor of pooling operator. "
476 477
           "The format of input tensor is NCDHW or NDHWC, where N is batch "
           "size, C is "
K
kexinzhao 已提交
478 479 480
           "the number of channels, and D, H and W is the depth, height and "
           "width of "
           "the feature, respectively.");
481
  AddOutput("Out",
C
chengduoZH 已提交
482
            "(Tensor) The output tensor of pooling operator."
483
            "The format of output tensor is also NCDHW or NDHWC, "
K
kexinzhao 已提交
484 485
            "where N is batch size, C is "
            "the number of channels, and D, H and W is the depth, height and "
486
            "width of the feature, respectively.");
487

C
chengduoZH 已提交
488
  AddAttr<std::string>("pooling_type",
K
kexinzhao 已提交
489
                       "(string) Pooling type, can be \"max\" for max-pooling "
C
chengduoZH 已提交
490
                       "and \"avg\" for average-pooling.")
491
      .InEnum({"max", "avg"});
K
kexinzhao 已提交
492 493 494 495
  AddAttr<std::vector<int>>(
      "ksize",
      "(vector<int>) The pooling window size(depth, height, "
      "width) of pooling operator. "
C
chengduoZH 已提交
496
      "If global_pooling = true, ksize and paddings will "
K
kexinzhao 已提交
497 498
      "be ignored.");  // TODO(Chengduo): Add checker.
                       // (Currently,
C
fix bug  
chengduoZH 已提交
499
  // TypedAttrChecker don't support vector type.)
C
chengduoZH 已提交
500 501
  AddAttr<bool>(
      "global_pooling",
K
Kaipeng Deng 已提交
502 503 504
      "(bool) Whether to use the global pooling. "
      "If global_pooling = true, kernel size and paddings will be ignored. "
      "Default False")
505
      .SetDefault(false);
K
kexinzhao 已提交
506 507 508 509
  AddAttr<std::vector<int>>(
      "strides",
      "(vector<int>, default {1,1,1}) Strides(depth, height, "
      "width) of the pooling operator.")
510 511
      .SetDefault({1, 1, 1});  // TODO(Chengduo): Add checker. (Currently,
                               // TypedAttrChecker don't support vector type.)
C
fix bug  
chengduoZH 已提交
512 513
  AddAttr<std::vector<int>>(
      "paddings",
514 515 516 517
      "(vector<int>, default {0,0,0}), paddings(pad_depth_front, "
      "pad_depth_back, "
      "pad_height_top, pad_height_bottom, pad_width_left, pad_width_right"
      ") of pooling operator. "
C
chengduoZH 已提交
518
      "If global_pooling = true, ksize and paddings will be ignored.")
519 520
      .SetDefault({0, 0, 0});  // TODO(Chengduo): Add checker. (Currently,
                               // TypedAttrChecker don't support vector type.)
521 522
  AddAttr<bool>(
      "exclusive",
K
Kaipeng Deng 已提交
523
      "(bool) When true, will exclude the zero-padding in the "
524
      "averaging calculating, otherwise, include the zero-padding. Note, it "
K
Kaipeng Deng 已提交
525 526
      "is only used when pooling_type is avg. The default is True. "
      "Default True")
527
      .SetDefault(true);
528 529
  AddAttr<bool>(
      "adaptive",
K
Kaipeng Deng 已提交
530
      "(bool) When true, will perform adaptive pooling instead, "
531 532
      "output shape in H and W dimensions will be same as ksize, input data "
      "will be divided into grids specify by ksize averagely and perform "
K
Kaipeng Deng 已提交
533 534
      "pooling in each grid area to get output pooling value. "
      "Default False")
535
      .SetDefault(false);
536

537 538
  AddAttr<bool>(
      "use_cudnn",
K
Kaipeng Deng 已提交
539
      "(bool) Only used in cudnn kernel, need install cudnn. Default False")
540
      .SetDefault(false);
541 542
  AddAttr<bool>(
      "ceil_mode",
K
Kaipeng Deng 已提交
543
      "(bool) Whether to use the ceil function to calculate "
W
wanghaoshuang 已提交
544
      "output height and width. False is the default. If it is set to False, "
K
Kaipeng Deng 已提交
545
      "the floor function will be used. Default False")
546
      .SetDefault(false);
547
  AddAttr<bool>("use_mkldnn",
K
Kaipeng Deng 已提交
548
                "(bool) Only used in mkldnn kernel. Default False")
549
      .SetDefault(false);
550 551
  AddAttr<std::string>(
      "data_format",
552 553 554
      "(string, default NCDHW) Only used in "
      "An optional string from: \"NDHWC\", \"NCDHW\". "
      "Defaults to \"NDHWC\". Specify the data format of the output data, "
555
      "the input will be transformed automatically. ")
556 557 558 559 560 561 562
      .SetDefault("NCDHW");
  AddAttr<std::string>(
      "padding_algorithm",
      "(string, default \"EXPLICIT\") An optional string from: \"EXPLICIT\","
      "\"SAME\",\"VALID\". Set to \"EXPLICIT\" for explicit padding. "
      "Set to \"SAME\" or \"VALID\" for algorithm of padding. ")
      .SetDefault("EXPLICIT");
563 564
  // TODO(dzhwinter): need to registered layout transform function

565
  AddComment(R"DOC(
K
Kaipeng Deng 已提交
566 567
This operation calculates the output based on
the input, pooling_type, pool_size, pool_stride, and pool_padding parameters.
568
Input(X) and output(Out) are in NCDHW or NDHWC format, where N is batch
K
kexinzhao 已提交
569
size, C is the number of channels, and D, H and W are the depth, height and
K
Kaipeng Deng 已提交
570 571
width of the feature, respectively. Parameters(pool_size, pool_stride, pool_padding)
hold three integer elements. These three elements represent depth, height and
K
kexinzhao 已提交
572
width, respectively. The input(X) size and output(Out) size may be different.
C
chengduoZH 已提交
573 574 575

Example:
  Input:
K
kexinzhao 已提交
576
       X shape: $(N, C, D_{in}, H_{in}, W_{in})$
C
chengduoZH 已提交
577
  Output:
K
kexinzhao 已提交
578
       Out shape: $(N, C, D_{out}, H_{out}, W_{out})$
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601

  For pool_padding = "SAME":
       $$
       D_{out} = \\frac{(D_{in} + strides[0] - 1)}{strides[0]}
       $$
       $$
       H_{out} = \\frac{(H_{in} + strides[1] - 1)}{strides[1]}
       $$
       $$
       W_{out} = \\frac{(W_{in} + strides[2] - 1)}{strides[2]}
       $$

  For pool_padding = "VALID":
       $$
       D_{out} = \\frac{(D_{in} - ksize[0] + strides[0])}{strides[0]}
       $$
       $$
       H_{out} = \\frac{(H_{in} - ksize[1] + strides[1])}{strides[1]}
       $$
       $$
       W_{out} = \\frac{(W_{in} - ksize[2] + strides[2])}{strides[2]}
       $$

602
  For ceil_mode = false:
603
       $$
604
       D_{out} = \\frac{(D_{in} - ksize[0] + pad_depth_front + pad_depth_back)}{strides[0]} + 1
605 606
       $$
       $$
607
       H_{out} = \\frac{(H_{in} - ksize[1] + pad_height_top + pad_height_bottom)}{strides[1]} + 1
608 609
       $$
       $$
610
       W_{out} = \\frac{(W_{in} - ksize[2] + pad_width_left + pad_width_right)}{strides[2]} + 1
611
       $$
612
  For ceil_mode = true:
613
       $$
614
       D_{out} = \\frac{(D_{in} - ksize[0] + pad_depth_front + pad_depth_back + strides[0] -1)}{strides[0]} + 1
615 616
       $$
       $$
617
       H_{out} = \\frac{(H_{in} - ksize[1] + pad_height_top + pad_height_bottom + strides[1] -1)}{strides[1]} + 1
618 619
       $$
       $$
620
       W_{out} = \\frac{(W_{in} - ksize[2] + pad_width_left + pad_width_right + strides[2] -1)}{strides[2]} + 1
621
       $$
D
dengkaipeng 已提交
622

623
  For exclusive = false:
624
       $$
625
       dstart = i * strides[0] - pad_depth_front
626 627 628 629 630
       $$
       $$
       dend = dstart + ksize[0]
       $$
       $$
631
       hstart = j * strides[1] - pad_height_top
632 633 634 635 636
       $$
       $$
       hend = hstart + ksize[1]
       $$
       $$
637
       wstart = k * strides[2] -  pad_width_left
638 639 640 641 642 643 644
       $$
       $$
       wend = wstart + ksize[2]
       $$
       $$
       Output(i ,j, k) = \\frac{sum(Input[dstart:dend, hstart:hend, wstart:wend])}{ksize[0] * ksize[1] * ksize[2]}
       $$
645

646
  For exclusive = true:
647
       $$
648
       dstart = max(0, i * strides[0] - pad_depth_front)
649 650 651 652 653
       $$
       $$
       dend = min(D, dstart + ksize[0])
       $$
       $$
654 655 656
       hstart = max(0, j * strides[1] - pad_height_top)
       $$
       $$
657 658 659
       hend = min(H, hstart + ksize[1])
       $$
       $$
660
       wstart = max(0, k * strides[2] - pad_width_left)
661 662 663 664 665 666 667
       $$
       $$
       wend = min(W, wstart + ksize[2])
       $$
       $$
       Output(i ,j, k) = \\frac{sum(Input[dstart:dend, hstart:hend, wstart:wend])}{(dend - dstart) * (hend - hstart) * (wend - wstart)}
       $$
K
kexinzhao 已提交
668

669
)DOC");
670
}
671 672 673 674 675
}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;

H
hong 已提交
676 677 678 679
REGISTER_OPERATOR(
    pool2d, ops::PoolOp, ops::Pool2dOpMaker, ops::PoolOpInferVarType,
    paddle::framework::DefaultGradOpMaker<paddle::framework::OpDesc, true>,
    paddle::framework::DefaultGradOpMaker<paddle::imperative::OpBase, true>);
680
REGISTER_OPERATOR(pool2d_grad, ops::PoolOpGrad);
681

Q
QI JUN 已提交
682 683 684 685 686
REGISTER_OP_CPU_KERNEL(
    pool2d, ops::PoolKernel<paddle::platform::CPUDeviceContext, float>,
    ops::PoolKernel<paddle::platform::CPUDeviceContext, double>);
REGISTER_OP_CPU_KERNEL(
    pool2d_grad, ops::PoolGradKernel<paddle::platform::CPUDeviceContext, float>,
687
    ops::PoolGradKernel<paddle::platform::CPUDeviceContext, double>);
688

H
hong 已提交
689 690 691 692
REGISTER_OPERATOR(
    pool3d, ops::PoolOp, ops::Pool3dOpMaker, ops::PoolOpInferVarType,
    paddle::framework::DefaultGradOpMaker<paddle::framework::OpDesc, true>,
    paddle::framework::DefaultGradOpMaker<paddle::imperative::OpBase, true>);
693
REGISTER_OPERATOR(pool3d_grad, ops::PoolOpGrad);
694

Q
QI JUN 已提交
695 696 697 698 699 700
REGISTER_OP_CPU_KERNEL(
    pool3d, ops::PoolKernel<paddle::platform::CPUDeviceContext, float>,
    ops::PoolKernel<paddle::platform::CPUDeviceContext, double>);
REGISTER_OP_CPU_KERNEL(
    pool3d_grad, ops::PoolGradKernel<paddle::platform::CPUDeviceContext, float>,
    ops::PoolGradKernel<paddle::platform::CPUDeviceContext, double>);