pool_op.cc 25.0 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
#include <unordered_map>
17 18 19 20 21 22
#ifdef PADDLE_WITH_CUDA
#include "paddle/fluid/platform/cudnn_helper.h"
#endif
#ifdef PADDLE_WITH_MKLDNN
#include "paddle/fluid/platform/mkldnn_helper.h"
#endif
23 24 25 26

namespace paddle {
namespace operators {

27 28
int PoolOutputSize(int input_size, int filter_size, int padding_1,
                   int padding_2, int stride, bool ceil_mode) {
29 30
  int output_size;
  if (!ceil_mode) {
31 32
    output_size =
        (input_size - filter_size + padding_1 + padding_2) / stride + 1;
33 34
  } else {
    output_size =
35 36 37
        (input_size - filter_size + padding_1 + padding_2 + stride - 1) /
            stride +
        1;
38
  }
39 40
  PADDLE_ENFORCE_GT(
      output_size, 0,
41 42 43 44 45 46
      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));
47 48 49
  return output_size;
}

C
chengduo 已提交
50
void PoolOp::InferShape(framework::InferShapeContext* ctx) const {
51 52 53 54 55 56
  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."));
57

C
chengduoZH 已提交
58
  std::string pooling_type = ctx->Attrs().Get<std::string>("pooling_type");
59 60 61
  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");
62
  bool ceil_mode = ctx->Attrs().Get<bool>("ceil_mode");
63
  bool adaptive = ctx->Attrs().Get<bool>("adaptive");
64 65 66 67
  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");
68

69
  auto in_x_dims = ctx->GetInputDim("X");
70 71
  PADDLE_ENFORCE_EQ(
      in_x_dims.size() == 4 || in_x_dims.size() == 5, true,
72 73 74 75
      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));
76 77 78

  PADDLE_ENFORCE_EQ(
      in_x_dims.size() - ksize.size(), 2U,
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
      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)));
98

99 100 101 102
  // 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");
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118

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

  // 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]);
  }

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

146
framework::OpKernelType PoolOp::GetExpectedKernelType(
C
chengduo 已提交
147
    const framework::ExecutionContext& ctx) const {
148
  framework::LibraryType library_{framework::LibraryType::kPlain};
149
  std::string data_format = "AnyLayout";
M
mozga-intel 已提交
150 151
  framework::DataLayout layout_ = framework::StringToDataLayout(data_format);

C
chengduoZH 已提交
152
#ifdef PADDLE_WITH_CUDA
153 154
  if (platform::CanCUDNNBeUsed(ctx)) {
    library_ = framework::LibraryType::kCUDNN;
C
chengduoZH 已提交
155 156
  }
#endif
157 158 159 160
#ifdef PADDLE_WITH_MKLDNN
  if (library_ == framework::LibraryType::kPlain &&
      platform::CanMKLDNNBeUsed(ctx)) {
    library_ = framework::LibraryType::kMKLDNN;
M
mozga-intel 已提交
161
    layout_ = framework::DataLayout::kMKLDNN;
162
  }
163
#endif
164

165 166 167
  return framework::OpKernelType(
      OperatorWithKernel::IndicateVarDataType(ctx, "X"), ctx.GetPlace(),
      layout_, library_);
168 169
}

170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
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 已提交
192
void PoolOpGrad::InferShape(framework::InferShapeContext* ctx) const {
193 194 195
  PADDLE_ENFORCE_EQ(ctx->HasInput("X"), true,
                    platform::errors::NotFound(
                        "Input(X) of Pool Gradoperator is not found."));
196
  PADDLE_ENFORCE_EQ(ctx->HasOutput(framework::GradVarName("X")), true,
197 198
                    platform::errors::NotFound(
                        "Input(X@GRAD) of Pool Gradoperator is not found."));
199 200 201
  ctx->SetOutputDim(framework::GradVarName("X"), ctx->GetInputDim("X"));
}

202
framework::OpKernelType PoolOpGrad::GetExpectedKernelType(
C
chengduo 已提交
203
    const framework::ExecutionContext& ctx) const {
204
  framework::LibraryType library_{framework::LibraryType::kPlain};
205
  std::string data_format = "AnyLayout";
M
mozga-intel 已提交
206 207
  framework::DataLayout layout_ = framework::StringToDataLayout(data_format);

C
chengduoZH 已提交
208
#ifdef PADDLE_WITH_CUDA
209 210
  if (platform::CanCUDNNBeUsed(ctx)) {
    library_ = framework::LibraryType::kCUDNN;
C
chengduoZH 已提交
211 212
  }
#endif
213 214 215 216
#ifdef PADDLE_WITH_MKLDNN
  if (library_ == framework::LibraryType::kPlain &&
      platform::CanMKLDNNBeUsed(ctx)) {
    library_ = framework::LibraryType::kMKLDNN;
M
mozga-intel 已提交
217
    layout_ = framework::DataLayout::kMKLDNN;
218
  }
219
#endif
220

221
  auto input_data_type = OperatorWithKernel::IndicateVarDataType(ctx, "X");
K
Kexin Zhao 已提交
222 223
  if (input_data_type == framework::proto::VarType::FP16) {
    PADDLE_ENFORCE_EQ(library_, framework::LibraryType::kCUDNN,
224 225
                      platform::errors::InvalidArgument(
                          "Float16 can only be used when CUDNN is used"));
K
Kexin Zhao 已提交
226 227 228
  }
  return framework::OpKernelType(input_data_type, ctx.GetPlace(), layout_,
                                 library_);
229 230
}

231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
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 已提交
249
void Pool2dOpMaker::Make() {
250 251
  AddInput(
      "X",
C
chengduoZH 已提交
252
      "(Tensor) The input tensor of pooling operator. "
K
kexinzhao 已提交
253 254 255
      "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.");
256
  AddOutput("Out",
K
kexinzhao 已提交
257 258 259 260
            "(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, "
261
            "and W is the width of the feature.");
262

C
chengduoZH 已提交
263
  AddAttr<std::string>("pooling_type",
C
chengduoZH 已提交
264 265
                       "(string), pooling type, can be \"max\" for max-pooling "
                       "and \"avg\" for average-pooling.")
266
      .InEnum({"max", "avg"});
C
fix bug  
chengduoZH 已提交
267
  AddAttr<std::vector<int>>("ksize",
K
kexinzhao 已提交
268 269
                            "(vector<int>) The pooling window "
                            "size(height, width) of the pooling operator. "
C
chengduoZH 已提交
270
                            "If global_pooling = true, ksize and paddings will "
C
fix bug  
chengduoZH 已提交
271 272
                            "be ignored.");  // TODO(Chengduo): Add checker.
                                             // (Currently,
C
fix doc  
chengduoZH 已提交
273
  // TypedAttrChecker don't support vector type.)
274 275
  AddAttr<bool>(
      "global_pooling",
K
Kaipeng Deng 已提交
276 277 278
      "(bool) Whether to use the global pooling. "
      "If global_pooling = true, kernel size and paddings will be ignored. "
      "Default False.")
279
      .SetDefault(false);
K
kexinzhao 已提交
280 281 282
  AddAttr<std::vector<int>>("strides",
                            "(vector<int>, default {1, 1}), strides(height, "
                            "width) of pooling operator.")
283 284
      .SetDefault({1, 1});
  // TODO(Chengduo): Add checker. (Currently,
C
fix doc  
chengduoZH 已提交
285 286 287
  // TypedAttrChecker don't support vector type.)
  AddAttr<std::vector<int>>(
      "paddings",
288 289
      "(vector<int>, default {0,0}), paddings(height_top, height_bottom, "
      "width_left, wifth_right) of pooling operator."
290
      "If global_pooling = true, paddings and kernel size will be ignored.")
291
      .SetDefault({0, 0});
292 293
  AddAttr<bool>(
      "exclusive",
K
Kaipeng Deng 已提交
294
      "(bool) When true, will exclude the zero-padding in the "
295
      "averaging calculating, otherwise, include the zero-padding. Note, it "
K
Kaipeng Deng 已提交
296 297
      "is only used when pooling_type is avg. The default is True. "
      "Default True.")
298
      .SetDefault(true);
299 300
  AddAttr<bool>(
      "adaptive",
K
Kaipeng Deng 已提交
301
      "(bool) When true, will perform adaptive pooling instead, "
302 303
      "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 已提交
304 305
      "pooling in each grid area to get output pooling value. "
      "Default False.")
306 307
      .SetDefault(false);

308 309
  AddAttr<bool>(
      "use_cudnn",
K
Kaipeng Deng 已提交
310
      "(bool) Only used in cudnn kernel, need install cudnn. Default False")
311
      .SetDefault(false);
312 313
  AddAttr<bool>(
      "ceil_mode",
K
Kaipeng Deng 已提交
314
      "(bool) Whether to use the ceil function to calculate "
W
wanghaoshuang 已提交
315
      "output height and width. False is the default. If it is set to False, "
K
Kaipeng Deng 已提交
316
      "the floor function will be used. Default False")
317
      .SetDefault(false);
318
  AddAttr<bool>("use_mkldnn",
K
Kaipeng Deng 已提交
319
                "(bool) Only used in mkldnn kernel. Default False")
320
      .SetDefault(false);
321 322 323 324
  AddAttr<bool>(
      "use_quantizer",
      "(bool, default false) "
      "This parameter is no longer used. Use 'mkldnn_data_type' instead.")
325
      .SetDefault(false);
326 327 328 329 330
  AddAttr<std::string>(
      "mkldnn_data_type",
      "(string, default \"float32\"). Data type of mkldnn kernel")
      .SetDefault("float32")
      .InEnum({"float32", "int8", "bfloat16"});
331 332 333 334 335 336
  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. ")
337
      .SetDefault("NCHW");
338 339 340 341 342
  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);

343 344 345 346 347 348
  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");
349
  // TODO(dzhwinter): need to registered layout transform function
350 351

  AddComment(R"DOC(
K
Kaipeng Deng 已提交
352 353 354
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 已提交
355
number of channels, H is the height of the feature, and W is the width of the feature.
K
Kaipeng Deng 已提交
356
Parameters(pool_size, pool_stride, pool_padding) hold two integer elements.
C
fix doc  
chengduoZH 已提交
357
These two elements represent height and width, respectively.
C
chengduoZH 已提交
358 359
The input(X) size and output(Out) size may be different.

360
Example:
F
fengjiayi 已提交
361

C
chengduoZH 已提交
362
  Input:
F
fengjiayi 已提交
363

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

C
chengduoZH 已提交
366
  Output:
F
fengjiayi 已提交
367

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

370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
  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]}
       $$

386 387
  For ceil_mode = false:
       $$
388
       H_{out} = \\frac{(H_{in} - ksize[0] + pad_height_top + pad_height_bottom}{strides[0]} + 1
F
fengjiayi 已提交
389 390
       $$
       $$
391
       W_{out} = \\frac{(W_{in} - ksize[1] + pad_width_left + pad_width_right}{strides[1]} + 1
K
kexinzhao 已提交
392
       $$
393

394 395
  For ceil_mode = true:
       $$
396
       H_{out} = \\frac{(H_{in} - ksize[0] + pad_height_top + pad_height_bottom + strides[0] - 1)}{strides[0]} + 1
F
fengjiayi 已提交
397 398
       $$
       $$
399
       W_{out} = \\frac{(W_{in} - ksize[1] + pad_width_left + pad_width_right + strides[1] - 1)}{strides[1]} + 1
400
       $$
K
kexinzhao 已提交
401

402
  For exclusive = false:
403
       $$
404
       hstart = i * strides[0] - pad_height_top
405 406 407 408 409
       $$
       $$
       hend = hstart + ksize[0]
       $$
       $$
410
       wstart = j * strides[1] - pad_width_left
411 412 413 414 415 416 417
       $$
       $$
       wend = wstart + ksize[1]
       $$
       $$
       Output(i ,j) = \\frac{sum(Input[hstart:hend, wstart:wend])}{ksize[0] * ksize[1]}
       $$
418

419
  For exclusive = true:
420
       $$
421
       hstart = max(0, i * strides[0] - pad_height_top)
422 423 424 425 426
       $$
       $$
       hend = min(H, hstart + ksize[0])
       $$
       $$
427
       wstart = max(0, j * strides[1] - pad_width_left)
428 429 430 431 432 433 434
       $$
       $$
       wend = min(W, wstart + ksize[1])
       $$
       $$
       Output(i ,j) = \\frac{sum(Input[hstart:hend, wstart:wend])}{(hend - hstart) * (wend - wstart)}
       $$
435

436
)DOC");
437 438
}

C
chengduo 已提交
439 440
class PoolOpInferVarType : public framework::PassInDtypeAndVarTypeToOutput {
 protected:
441
  std::unordered_map<std::string, std::string>& GetInputOutputWithSameType()
C
chengduo 已提交
442
      const override {
443 444
    static std::unordered_map<std::string, std::string> m{{"X", /*->*/ "Out"}};
    return m;
C
chengduo 已提交
445 446 447
  }
};

Y
Yu Yang 已提交
448
void Pool3dOpMaker::Make() {
K
kexinzhao 已提交
449 450
  AddInput("X",
           "(Tensor) The input tensor of pooling operator. "
451 452
           "The format of input tensor is NCDHW or NDHWC, where N is batch "
           "size, C is "
K
kexinzhao 已提交
453 454 455
           "the number of channels, and D, H and W is the depth, height and "
           "width of "
           "the feature, respectively.");
456
  AddOutput("Out",
C
chengduoZH 已提交
457
            "(Tensor) The output tensor of pooling operator."
458
            "The format of output tensor is also NCDHW or NDHWC, "
K
kexinzhao 已提交
459 460
            "where N is batch size, C is "
            "the number of channels, and D, H and W is the depth, height and "
461
            "width of the feature, respectively.");
462

C
chengduoZH 已提交
463
  AddAttr<std::string>("pooling_type",
K
kexinzhao 已提交
464
                       "(string) Pooling type, can be \"max\" for max-pooling "
C
chengduoZH 已提交
465
                       "and \"avg\" for average-pooling.")
466
      .InEnum({"max", "avg"});
K
kexinzhao 已提交
467 468 469 470
  AddAttr<std::vector<int>>(
      "ksize",
      "(vector<int>) The pooling window size(depth, height, "
      "width) of pooling operator. "
C
chengduoZH 已提交
471
      "If global_pooling = true, ksize and paddings will "
K
kexinzhao 已提交
472 473
      "be ignored.");  // TODO(Chengduo): Add checker.
                       // (Currently,
C
fix bug  
chengduoZH 已提交
474
  // TypedAttrChecker don't support vector type.)
C
chengduoZH 已提交
475 476
  AddAttr<bool>(
      "global_pooling",
K
Kaipeng Deng 已提交
477 478 479
      "(bool) Whether to use the global pooling. "
      "If global_pooling = true, kernel size and paddings will be ignored. "
      "Default False")
480
      .SetDefault(false);
K
kexinzhao 已提交
481 482 483 484
  AddAttr<std::vector<int>>(
      "strides",
      "(vector<int>, default {1,1,1}) Strides(depth, height, "
      "width) of the pooling operator.")
485 486
      .SetDefault({1, 1, 1});  // TODO(Chengduo): Add checker. (Currently,
                               // TypedAttrChecker don't support vector type.)
C
fix bug  
chengduoZH 已提交
487 488
  AddAttr<std::vector<int>>(
      "paddings",
489 490 491 492
      "(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 已提交
493
      "If global_pooling = true, ksize and paddings will be ignored.")
494 495
      .SetDefault({0, 0, 0});  // TODO(Chengduo): Add checker. (Currently,
                               // TypedAttrChecker don't support vector type.)
496 497
  AddAttr<bool>(
      "exclusive",
K
Kaipeng Deng 已提交
498
      "(bool) When true, will exclude the zero-padding in the "
499
      "averaging calculating, otherwise, include the zero-padding. Note, it "
K
Kaipeng Deng 已提交
500 501
      "is only used when pooling_type is avg. The default is True. "
      "Default True")
502
      .SetDefault(true);
503 504
  AddAttr<bool>(
      "adaptive",
K
Kaipeng Deng 已提交
505
      "(bool) When true, will perform adaptive pooling instead, "
506 507
      "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 已提交
508 509
      "pooling in each grid area to get output pooling value. "
      "Default False")
510
      .SetDefault(false);
511

512 513
  AddAttr<bool>(
      "use_cudnn",
K
Kaipeng Deng 已提交
514
      "(bool) Only used in cudnn kernel, need install cudnn. Default False")
515
      .SetDefault(false);
516 517
  AddAttr<bool>(
      "ceil_mode",
K
Kaipeng Deng 已提交
518
      "(bool) Whether to use the ceil function to calculate "
W
wanghaoshuang 已提交
519
      "output height and width. False is the default. If it is set to False, "
K
Kaipeng Deng 已提交
520
      "the floor function will be used. Default False")
521
      .SetDefault(false);
522
  AddAttr<bool>("use_mkldnn",
K
Kaipeng Deng 已提交
523
                "(bool) Only used in mkldnn kernel. Default False")
524
      .SetDefault(false);
525 526
  AddAttr<std::string>(
      "data_format",
527 528 529
      "(string, default NCDHW) Only used in "
      "An optional string from: \"NDHWC\", \"NCDHW\". "
      "Defaults to \"NDHWC\". Specify the data format of the output data, "
530
      "the input will be transformed automatically. ")
531 532 533 534 535 536 537
      .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");
538 539
  // TODO(dzhwinter): need to registered layout transform function

540
  AddComment(R"DOC(
K
Kaipeng Deng 已提交
541 542
This operation calculates the output based on
the input, pooling_type, pool_size, pool_stride, and pool_padding parameters.
543
Input(X) and output(Out) are in NCDHW or NDHWC format, where N is batch
K
kexinzhao 已提交
544
size, C is the number of channels, and D, H and W are the depth, height and
K
Kaipeng Deng 已提交
545 546
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 已提交
547
width, respectively. The input(X) size and output(Out) size may be different.
C
chengduoZH 已提交
548 549 550

Example:
  Input:
K
kexinzhao 已提交
551
       X shape: $(N, C, D_{in}, H_{in}, W_{in})$
C
chengduoZH 已提交
552
  Output:
K
kexinzhao 已提交
553
       Out shape: $(N, C, D_{out}, H_{out}, W_{out})$
554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576

  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]}
       $$

577
  For ceil_mode = false:
578
       $$
579
       D_{out} = \\frac{(D_{in} - ksize[0] + pad_depth_front + pad_depth_back)}{strides[0]} + 1
580 581
       $$
       $$
582
       H_{out} = \\frac{(H_{in} - ksize[1] + pad_height_top + pad_height_bottom)}{strides[1]} + 1
583 584
       $$
       $$
585
       W_{out} = \\frac{(W_{in} - ksize[2] + pad_width_left + pad_width_right)}{strides[2]} + 1
586
       $$
587
  For ceil_mode = true:
588
       $$
589
       D_{out} = \\frac{(D_{in} - ksize[0] + pad_depth_front + pad_depth_back + strides[0] -1)}{strides[0]} + 1
590 591
       $$
       $$
592
       H_{out} = \\frac{(H_{in} - ksize[1] + pad_height_top + pad_height_bottom + strides[1] -1)}{strides[1]} + 1
593 594
       $$
       $$
595
       W_{out} = \\frac{(W_{in} - ksize[2] + pad_width_left + pad_width_right + strides[2] -1)}{strides[2]} + 1
596
       $$
D
dengkaipeng 已提交
597

598
  For exclusive = false:
599
       $$
600
       dstart = i * strides[0] - pad_depth_front
601 602 603 604 605
       $$
       $$
       dend = dstart + ksize[0]
       $$
       $$
606
       hstart = j * strides[1] - pad_height_top
607 608 609 610 611
       $$
       $$
       hend = hstart + ksize[1]
       $$
       $$
612
       wstart = k * strides[2] -  pad_width_left
613 614 615 616 617 618 619
       $$
       $$
       wend = wstart + ksize[2]
       $$
       $$
       Output(i ,j, k) = \\frac{sum(Input[dstart:dend, hstart:hend, wstart:wend])}{ksize[0] * ksize[1] * ksize[2]}
       $$
620

621
  For exclusive = true:
622
       $$
623
       dstart = max(0, i * strides[0] - pad_depth_front)
624 625 626 627 628
       $$
       $$
       dend = min(D, dstart + ksize[0])
       $$
       $$
629 630 631
       hstart = max(0, j * strides[1] - pad_height_top)
       $$
       $$
632 633 634
       hend = min(H, hstart + ksize[1])
       $$
       $$
635
       wstart = max(0, k * strides[2] - pad_width_left)
636 637 638 639 640 641 642
       $$
       $$
       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 已提交
643

644
)DOC");
645
}
646 647 648 649 650
}  // namespace operators
}  // namespace paddle

namespace ops = paddle::operators;

H
hong 已提交
651 652 653 654
REGISTER_OPERATOR(
    pool2d, ops::PoolOp, ops::Pool2dOpMaker, ops::PoolOpInferVarType,
    paddle::framework::DefaultGradOpMaker<paddle::framework::OpDesc, true>,
    paddle::framework::DefaultGradOpMaker<paddle::imperative::OpBase, true>);
655
REGISTER_OPERATOR(pool2d_grad, ops::PoolOpGrad);
656

Q
QI JUN 已提交
657 658 659 660 661
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>,
662
    ops::PoolGradKernel<paddle::platform::CPUDeviceContext, double>);
663

H
hong 已提交
664 665 666 667
REGISTER_OPERATOR(
    pool3d, ops::PoolOp, ops::Pool3dOpMaker, ops::PoolOpInferVarType,
    paddle::framework::DefaultGradOpMaker<paddle::framework::OpDesc, true>,
    paddle::framework::DefaultGradOpMaker<paddle::imperative::OpBase, true>);
668
REGISTER_OPERATOR(pool3d_grad, ops::PoolOpGrad);
669

Q
QI JUN 已提交
670 671 672 673 674 675
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>);