| 251 | } |
| 252 | |
| 253 | void Compute(OpKernelContext* context) override { |
| 254 | const Tensor& tensor_in_shape = context->input(0); |
| 255 | const Tensor& out_backprop = context->input(1); |
| 256 | // For avgpooling, tensor_in_shape should have 1 dimension, and 4 elements. |
| 257 | OP_REQUIRES( |
| 258 | context, |
| 259 | tensor_in_shape.dims() == 1 && tensor_in_shape.NumElements() == 4, |
| 260 | errors::InvalidArgument("out_backprop must be 1-dimensional and 4 " |
| 261 | "elements")); |
| 262 | // For avgpooling, out_backprop should have 4 dimensions. |
| 263 | OP_REQUIRES(context, out_backprop.dims() == 4, |
| 264 | errors::InvalidArgument("out_backprop must be 4-dimensional")); |
| 265 | const int64 out_backprop_batch = out_backprop.dim_size(0); |
| 266 | const int64 out_backprop_rows = out_backprop.dim_size(1); |
| 267 | const int64 out_backprop_cols = out_backprop.dim_size(2); |
| 268 | const int64 out_backprop_depth = out_backprop.dim_size(3); |
| 269 | |
| 270 | TensorShape output_shape; |
| 271 | auto shape_vec = tensor_in_shape.vec<int32>(); |
| 272 | for (int64 i = 0; i < tensor_in_shape.NumElements(); ++i) { |
| 273 | output_shape.AddDim(shape_vec(i)); |
| 274 | } |
| 275 | const int64 in_rows = output_shape.dim_size(1); |
| 276 | const int64 in_cols = output_shape.dim_size(2); |
| 277 | |
| 278 | Tensor* output = nullptr; |
| 279 | OP_REQUIRES_OK(context, context->allocate_output(0, output_shape, &output)); |
| 280 | output->flat<T>().setZero(); |
| 281 | |
| 282 | const int window_rows = ksize_[1]; |
| 283 | const int window_cols = ksize_[2]; |
| 284 | const int depth_window = ksize_[3]; |
| 285 | |
| 286 | const int row_stride = stride_[1]; |
| 287 | const int col_stride = stride_[2]; |
| 288 | |
| 289 | // We (will) use different code for spatial pooling and |
| 290 | // non-spatial pooling. |
| 291 | // |
| 292 | // Spatial pooling is when depth_window = 1 |
| 293 | OP_REQUIRES(context, depth_window == 1, |
| 294 | errors::Unimplemented("Non-spatial pooling is not " |
| 295 | "yet supported. Volunteers? :)")); |
| 296 | |
| 297 | int64 out_height, out_width, pad_rows, pad_cols; |
| 298 | OP_REQUIRES_OK(context, |
| 299 | GetWindowedOutputSize(in_rows, window_rows, row_stride, |
| 300 | padding_, &out_height, &pad_rows)); |
| 301 | OP_REQUIRES_OK(context, |
| 302 | GetWindowedOutputSize(in_cols, window_cols, col_stride, |
| 303 | padding_, &out_width, &pad_cols)); |
| 304 | |
| 305 | const T* out_backprop_ptr = out_backprop.flat<T>().data(); |
| 306 | T* input_backprop_ptr = output->flat<T>().data(); |
| 307 | |
| 308 | auto shard = [context, out_backprop_ptr, input_backprop_ptr, |
| 309 | out_backprop_rows, out_backprop_cols, out_backprop_depth, |
| 310 | in_rows, in_cols, window_rows, window_cols, row_stride, |
nothing calls this directly
no test coverage detected