27 #ifndef LBANN_LAYER_POOLING_HPP_INCLUDED 28 #define LBANN_LAYER_POOLING_HPP_INCLUDED 34 #ifdef LBANN_HAS_DNN_LIB 37 #endif // LBANN_HAS_DNN_LIB 44 #ifdef LBANN_HAS_DISTCONV 45 #include "distconv/dnn_backend/pooling.hpp" 47 #endif // LBANN_HAS_DISTCONV 53 #ifdef LBANN_DETERMINISTIC 59 #endif // LBANN_DETERMINISTIC 62 if (m ==
"average_no_pad")
69 #ifdef LBANN_HAS_DISTCONV 73 using Backend = ::distconv::BackendDNNLib;
74 template <
typename TensorDataType>
75 using Pooling = ::distconv::Pooling<Backend, TensorDataType>;
78 template <
typename TensorDataType,
81 class pooling_distconv_adapter
87 pooling_distconv_adapter(
Layer& layer)
90 virtual ~pooling_distconv_adapter() =
default;
92 dc::Shape get_activations_local_shape(
int index = 0)
const override;
93 void setup_layer(
size_t workspace_capacity)
override;
97 std::unique_ptr<dc::Pooling<TensorDataType>> m_pooling;
99 #endif // LBANN_HAS_DISTCONV 102 template <
typename TensorDataType, data_layout T_layout, El::Device Dev>
105 template <
typename TensorDataType,
111 "pooling only supports DATA_PARALLEL");
133 #ifdef LBANN_HAS_DNN_LIB 135 dnn_lib::PoolingDescriptor m_pooling_dnn_desc;
139 #endif // LBANN_HAS_DNN_LIB 152 std::vector<int>(num_data_dims, pool_dim),
153 std::vector<int>(num_data_dims, pad),
154 std::vector<int>(num_data_dims, stride),
160 std::vector<int> pool_dims,
161 std::vector<int> pads,
162 std::vector<int> strides,
166 m_pool_dims(pool_dims),
169 #ifdef LBANN_HAS_DNN_LIB
171 m_tensors_dnn_desc(this)
180 m_pool_mode(other.m_pool_mode),
181 m_pool_dims(other.m_pool_dims),
182 m_pool_size(other.m_pool_size),
183 m_pads(other.m_pads),
184 m_strides(other.m_strides),
185 m_max_pool_indices(other.m_max_pool_indices)
186 #ifdef LBANN_HAS_DNN_LIB
188 m_pooling_dnn_desc(other.m_pooling_dnn_desc),
189 m_tensors_dnn_desc(other.m_tensors_dnn_desc)
192 #ifdef LBANN_HAS_DNN_LIB 193 m_tensors_dnn_desc.set_layer(
this);
194 #endif // LBANN_HAS_DNN_LIB 206 #ifdef LBANN_HAS_DNN_LIB 207 m_pooling_dnn_desc = other.m_pooling_dnn_desc;
208 m_tensors_dnn_desc = other.m_tensors_dnn_desc;
209 m_tensors_dnn_desc.set_layer(
this);
210 #endif // LBANN_HAS_DNN_LIB 221 template <
typename ArchiveT>
226 std::string
get_type()
const override {
return "pooling"; }
235 #ifdef LBANN_HAS_ONNX 236 void fill_onnx_node(onnx::GraphProto& graph)
const override;
237 #endif // LBANN_HAS_ONNX 242 std::stringstream ss;
245 ss.str(std::string{});
247 switch (m_pool_mode) {
252 ss <<
"max (deterministic)";
258 ss <<
"average (no pad)";
263 desc.add(
"Pool mode", ss.str());
266 ss.str(std::string{});
268 for (
size_t i = 0; i < m_pool_dims.size(); ++i) {
269 ss << (i > 0 ?
", " :
"") << m_pool_dims[i];
271 desc.add(
"Pool dimensions", ss.str());
274 ss.str(std::string{});
276 for (
size_t i = 0; i < m_strides.size(); ++i) {
277 ss << (i > 0 ?
", " :
"") << m_strides[i];
279 desc.add(
"Strides", ss.str());
282 ss.str(std::string{});
284 for (
size_t i = 0; i < m_pads.size(); ++i) {
285 ss << (i > 0 ?
", " :
"") << m_pads[i];
287 desc.add(
"Pads", ss.str());
295 void write_specific_proto(lbann_data::Layer& proto)
const final;
297 friend class cereal::access;
303 const auto& input_dims = this->get_input_dims();
304 auto output_dims = input_dims;
305 for (
size_t i = 0; i < output_dims.size() - 1; ++i) {
306 const int effective_dim =
307 (input_dims[i + 1] + 2 * m_pads[i] - m_pool_dims[i] + 1);
308 output_dims[i + 1] = (effective_dim + m_strides[i] - 1) / m_strides[i];
310 this->set_output_dims(output_dims);
317 #ifndef LBANN_HAS_DNN_LIB 322 m_pooling_dnn_desc.set(m_pool_mode,
323 dnn_lib::DNN_PROPAGATE_NAN,
329 #endif // #ifndef LBANN_HAS_DNN_LIB 332 void fp_compute()
override;
334 void bp_compute()
override;
338 void fp_compute_dnn();
341 void bp_compute_dnn();
344 void fp_compute_im2col();
347 void bp_compute_im2col();
349 #ifdef LBANN_HAS_DISTCONV 350 friend class pooling_distconv_adapter<TensorDataType, T_layout, Dev>;
353 bool is_distconv_supported()
const override;
354 void setup_distconv_adapter()
override 356 this->get_distconv_adapter_ptr() =
357 std::make_unique<pooling_distconv_adapter<TensorDataType, T_layout, Dev>>(
360 pooling_distconv_adapter<TensorDataType, T_layout, Dev>&
361 get_distconv_adapter()
override;
362 const pooling_distconv_adapter<TensorDataType, T_layout, Dev>&
363 get_distconv_adapter()
const override;
364 #endif // LBANN_HAS_DISTCONV 367 #ifdef LBANN_HAS_ONNX 368 template <
typename T, data_layout L, El::Device D>
371 auto* pool = graph.add_node();
375 auto* kernel_shape = pool->add_attribute();
376 kernel_shape->
set_name(
"kernel_shape");
377 kernel_shape->set_type(onnx::AttributeProto::INTS);
378 for (
auto const& k : this->m_pool_dims)
379 kernel_shape->add_ints(k);
381 if (!this->m_strides.empty()) {
382 auto* strides = pool->add_attribute();
383 strides->set_name(
"strides");
384 strides->set_type(onnx::AttributeProto::INTS);
385 for (
auto const& s : this->m_strides)
386 strides->add_ints(s);
388 if (!this->m_pads.empty()) {
389 auto* pads = pool->add_attribute();
390 pads->set_name(
"pads");
391 pads->set_type(onnx::AttributeProto::INTS);
392 for (
auto const& p : this->m_pads) {
400 for (
auto const* parent : this->get_parent_layers()) {
401 size_t idx = parent->find_child_layer_index(*
this);
404 for (
size_t ii = 0; ii < this->num_weights(); ii++)
405 pool->add_input(this->get_weights(ii).get_name());
406 for (
auto const* child : this->get_child_layers()) {
407 size_t idx = this->find_child_layer_index(*child);
410 pool->set_name(this->get_name());
412 switch (m_pool_mode) {
414 pool->set_op_type(
"MaxPool");
417 pool->set_op_type(
"MaxPool");
420 pool->set_op_type(
"AveragePool");
423 pool->set_op_type(
"AveragePool");
426 LBANN_ERROR(
"pooling_layer: no ONNX implementation for pooling mode");
429 pool->set_domain(
"");
430 pool->set_doc_string(this->get_type());
434 #ifndef LBANN_POOLING_LAYER_INSTANTIATE 435 #define PROTO_DEVICE(T, Device) \ 436 extern template class pooling_layer<T, data_layout::DATA_PARALLEL, Device> 440 #endif // LBANN_POOLING_LAYER_INSTANTIATE 444 #endif // LBANN_LAYER_POOLING_HPP_INCLUDED
int get_backprop_requirements() const override
Returns the necessary tensors for computing backpropagation.
El::Device get_device_allocation() const override
Get the device allocation for the data tensors. We assume that the decice allocation of the previous ...
virtual void setup_dims()
Setup tensor dimensions Called by the 'setup' function. If there are any input tensors, the base method sets all uninitialized output tensor dimensions equal to the first input tensor dimensions.
std::basic_string< T > pad(const std::basic_string< T > &s, typename std::basic_string< T >::size_type n, T c)
auto get_linear_size(std::vector< T > const &dims)
void setup_gpu() override
Initialize GPU objects.
pooling_layer(lbann_comm *comm, int num_data_dims, std::vector< int > pool_dims, std::vector< int > pads, std::vector< int > strides, pooling_mode mode)
void serialize(std::ostream &os, google::protobuf::Message const &msg)
Serialize the protobuf message to a stream.
Neural network tensor operation.
Generates nicely formatted description messages.
pooling_mode to_pool_mode(std::string m)
std::vector< int > m_pool_dims
virtual description get_description() const
Human-readable description.
constexpr El::Device Device
std::string to_string(El::Device const &d)
bool can_run_inplace() const override
If True, the computation can run in-place (feeding each input activations tensor as the corresponding...
pooling_layer(const pooling_layer &other)
virtual void setup_gpu()
Setup GPU objects. Called by the 'setup' function if the layer is on GPUs.
pooling_mode
Which pooling mode to use.
data_layout get_data_layout() const override
Get data layout of the data tensors. We assume that the data layouts of the previous activations...
::distconv::tensor::Shape Shape
std::vector< int > m_pads
void setup_dims() override
Setup tensor dimensions Called by the 'setup' function. If there are any input tensors, the base method sets all uninitialized output tensor dimensions equal to the first input tensor dimensions.
std::vector< int > m_max_pool_indices
data_layout
Data layout that is optimized for different modes of parallelism.
pooling_layer & operator=(const pooling_layer &other)
std::vector< int > m_strides
Transpose of pooling layer.
description get_description() const override
Human-readable description.
pooling_layer * copy() const override
Copy function. This function dynamically allocates memory for a layer instance and instantiates a cop...
std::string get_type() const override
Get the layer type's name.
void set_name(const std::string name)
Set the layer instance's name. Each layer in a model should have a unique, preferably human-readable...
data_type_layer & operator=(data_type_layer &&other)=default
dc::TensorDev< OutputTensorDataType > TensorDevType
pooling_layer(lbann_comm *comm, int num_data_dims, int pool_dim, int pad, int stride, pooling_mode mode)