LBANN  0.103.0
LivermoreBigArtificialNeuralNetworkToolkit
tessellate.hpp
Go to the documentation of this file.
1 // Copyright (c) 2014-2023, Lawrence Livermore National Security, LLC.
3 // Produced at the Lawrence Livermore National Laboratory.
4 // Written by the LBANN Research Team (B. Van Essen, et al.) listed in
5 // the CONTRIBUTORS file. <lbann-dev@llnl.gov>
6 //
7 // LLNL-CODE-697807.
8 // All rights reserved.
9 //
10 // This file is part of LBANN: Livermore Big Artificial Neural Network
11 // Toolkit. For details, see http://software.llnl.gov/LBANN or
12 // https://github.com/LLNL/LBANN.
13 //
14 // Licensed under the Apache License, Version 2.0 (the "Licensee"); you
15 // may not use this file except in compliance with the License. You may
16 // obtain a copy of the License at:
17 //
18 // http://www.apache.org/licenses/LICENSE-2.0
19 //
20 // Unless required by applicable law or agreed to in writing, software
21 // distributed under the License is distributed on an "AS IS" BASIS,
22 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
23 // implied. See the License for the specific language governing
24 // permissions and limitations under the license.
26 
27 #ifndef LBANN_LAYERS_TRANSFORM_TESSELLATE_HPP_INCLUDED
28 #define LBANN_LAYERS_TRANSFORM_TESSELLATE_HPP_INCLUDED
29 
31 #include "lbann/layers/layer.hpp"
33 #include "lbann/proto/layers.pb.h"
34 #include "lbann/utils/protobuf.hpp"
35 
36 namespace lbann {
37 
58 template <typename TensorDataType,
60  El::Device Device = El::Device::CPU>
61 class tessellate_layer : public data_type_layer<TensorDataType>
62 {
63 public:
65 
68  using AbsDistMatrixType = El::AbstractDistMatrix<TensorDataType>;
69 
71  using AbsMatrixType = El::AbstractMatrix<TensorDataType>;
72 
74 
75 public:
76  tessellate_layer(lbann_comm* comm, std::vector<int> dims = {})
78  {
79  this->set_output_dims(dims);
80  }
81 
83  : data_type_layer<TensorDataType>(other),
84  m_input_v(other.m_input_v ? other.m_input_v->Copy() : nullptr)
85  {}
87  {
89  m_input_v.reset(other.m_input_v ? other.m_input_v->Copy() : nullptr);
90  return *this;
91  }
92 
93  tessellate_layer* copy() const override
94  {
95  return new tessellate_layer(*this);
96  }
97 
99 
101  template <typename ArchiveT>
102  void serialize(ArchiveT& ar);
103 
105 
106  std::string get_type() const override { return "tessellate"; }
107  data_layout get_data_layout() const override { return Layout; }
108  El::Device get_device_allocation() const override { return Device; }
109  bool can_run_inplace() const override { return false; }
110  int get_backprop_requirements() const override { return ERROR_SIGNALS; }
111 
112  void setup_dims() override
113  {
115  std::stringstream err;
116 
117  // Check input and output dimensions
118  const auto input_dims = this->get_input_dims();
119  const auto& output_dims = this->get_output_dims();
120  if (input_dims.size() != output_dims.size()) {
121  err << get_type() << " layer \"" << this->get_name() << "\" "
122  << "attempted to tessellate a ";
123  for (size_t i = 0; i < input_dims.size(); ++i) {
124  err << (i > 0 ? "x" : "") << input_dims[i];
125  }
126  err << " tensor into a ";
127  for (size_t i = 0; i < output_dims.size(); ++i) {
128  err << (i > 0 ? "x" : "") << output_dims[i];
129  }
130  err << " tensor";
131  LBANN_ERROR(err.str());
132  }
133 
135  if (input_dims.size() > 3) {
136  err << get_type() << " layer \"" << this->get_name() << "\" "
137  << "attempted to tessellate a ";
138  for (size_t i = 0; i < input_dims.size(); ++i) {
139  err << (i > 0 ? "x" : "") << input_dims[i];
140  }
141  err << " tensor, but tessellation is currently only supported "
142  << "with 3 dimensions or less";
143  }
144  }
145 
146  void setup_data(size_t max_mini_batch_size) override
147  {
148  data_type_layer<TensorDataType>::setup_data(max_mini_batch_size);
149  auto dist_data = this->get_prev_activations().DistData();
150  dist_data.colDist = El::STAR;
151  m_input_v.reset(AbsDistMatrixType::Instantiate(dist_data));
152  }
153 
154 protected:
156  void write_specific_proto(lbann_data::Layer& proto) const final;
157 
158  friend class cereal::access;
160 
161  void fp_compute() override
162  {
163 
164  // Get input and output dimensions
165  auto input_dims = this->get_input_dims();
166  auto output_dims = this->get_output_dims();
167  while (input_dims.size() < 3) {
168  input_dims.insert(input_dims.begin(), 1);
169  }
170  while (output_dims.size() < 3) {
171  output_dims.insert(output_dims.begin(), 1);
172  }
173 
174  // Get input and output data
175  auto& output = this->get_activations();
176  const auto& input = this->get_prev_activations();
177  m_input_v->Empty(false);
178  m_input_v->AlignWith(output);
179  if (m_input_v->DistData() == input.DistData()) {
180  El::LockedView(*m_input_v, input);
181  }
182  else {
183  El::Copy(input, *m_input_v);
184  }
185  const auto& local_input = m_input_v->LockedMatrix();
186 
187  // Apply tessellation
189  if (input_dims.size() > 3) {
190  LBANN_ERROR("tessellate layer currently only supports 3D tensors");
191  }
192  fp_compute_3d(input_dims, output_dims, local_input, output);
193  }
194 
195  void bp_compute() override
196  {
197 
198  // Get input and output dimensions
199  auto input_dims = this->get_input_dims();
200  auto output_dims = this->get_output_dims();
201  while (input_dims.size() < 3) {
202  input_dims.insert(input_dims.begin(), 1);
203  }
204  while (output_dims.size() < 3) {
205  output_dims.insert(output_dims.begin(), 1);
206  }
207 
208  // Get input and output data
209  const auto& gradient_wrt_output = this->get_prev_error_signals();
210  auto& gradient_wrt_input = this->get_error_signals();
211  m_input_v->Empty(false);
212  m_input_v->AlignWith(gradient_wrt_output);
213  if (m_input_v->DistData() == gradient_wrt_input.DistData()) {
214  El::View(*m_input_v, gradient_wrt_input);
215  }
216  else {
217  m_input_v->Resize(gradient_wrt_input.Height(),
218  gradient_wrt_input.Width());
219  }
220  auto& local_gradient_wrt_input = m_input_v->Matrix();
221 
222  // Apply back prop with local data
224  bp_compute_3d(input_dims,
225  output_dims,
226  gradient_wrt_output,
227  local_gradient_wrt_input);
228 
229  // Accumulate local error signals, if needed
230  if (m_input_v->DistData() != gradient_wrt_input.DistData()) {
231  this->get_comm()->allreduce(*m_input_v, m_input_v->RedundantComm());
232  El::Copy(*m_input_v, gradient_wrt_input);
233  }
234  }
235 
236 private:
238  std::unique_ptr<AbsDistMatrixType> m_input_v;
239 
245  void fp_compute_3d(const std::vector<int>& input_dims,
246  const std::vector<int>& output_dims,
247  const AbsMatrixType& input,
248  AbsDistMatrixType& output);
253  void bp_compute_3d(const std::vector<int>& input_dims,
254  const std::vector<int>& output_dims,
255  const AbsDistMatrixType& gradient_wrt_output,
256  AbsMatrixType& gradient_wrt_input);
257 };
258 
259 template <typename T, data_layout L, El::Device D>
261  lbann_data::Layer& proto) const
262 {
263  proto.set_datatype(proto::ProtoDataType<T>);
264  auto* msg = proto.mutable_tessellate();
265  protobuf::assign_to_repeated(*msg->mutable_dims(), this->get_output_dims());
266 }
267 
268 #ifndef LBANN_TESSELLATE_LAYER_INSTANTIATE
269 #define PROTO_DEVICE(T, Device) \
270  extern template class tessellate_layer<T, \
271  data_layout::DATA_PARALLEL, \
272  Device>; \
273  extern template class tessellate_layer<T, data_layout::MODEL_PARALLEL, Device>
274 
276 #undef PROTO_DEVICE
277 #endif // LBANN_TESSELLATE_LAYER_INSTANTIATE
278 
279 } // namespace lbann
280 
281 #endif // LBANN_LAYERS_TRANSFORM_TESSELLATE_HPP_INCLUDED
tessellate_layer * copy() const override
Copy function. This function dynamically allocates memory for a layer instance and instantiates a cop...
Definition: tessellate.hpp:93
void serialize(ArchiveT &ar)
virtual void setup_dims()
Setup tensor dimensions Called by the &#39;setup&#39; function. If there are any input tensors, the base method sets all uninitialized output tensor dimensions equal to the first input tensor dimensions.
void setup_data(size_t max_mini_batch_size) override
Setup layer data. Called by the &#39;setup&#39; function. Memory is allocated for distributed matrices...
Definition: tessellate.hpp:146
tessellate_layer & operator=(const tessellate_layer &other)
Definition: tessellate.hpp:86
void write_specific_proto(lbann_data::Layer &proto) const final
Definition: tessellate.hpp:260
El::AbstractDistMatrix< TensorDataType > AbsDistMatrixType
The tensor type expected in this object.
Definition: tessellate.hpp:68
Repeat a tensor until it matches specified dimensions.
Definition: tessellate.hpp:61
lbann_comm * get_comm() const
std::string get_type() const override
Get the layer type&#39;s name.
Definition: tessellate.hpp:106
void bp_compute_3d(const std::vector< int > &input_dims, const std::vector< int > &output_dims, const AbsDistMatrixType &gradient_wrt_output, AbsMatrixType &gradient_wrt_input)
std::unique_ptr< AbsDistMatrixType > m_input_v
Definition: tessellate.hpp:238
#define LBANN_ERROR(...)
Definition: exception.hpp:37
El::AbstractMatrix< TensorDataType > AbsMatrixType
The local tensor type expected in this object.
Definition: tessellate.hpp:71
std::vector< int > get_input_dims(size_t input_index=0) const
Get input tensor dimensions.
El::Device get_device_allocation() const override
Get the device allocation for the data tensors. We assume that the decice allocation of the previous ...
Definition: tessellate.hpp:108
constexpr El::Device Device
OutputAbsDistMatrixType & get_prev_error_signals(int child_index=0)
InputAbsDistMatrixType & get_prev_activations(int parent_index=0)
const OutputAbsDistMatrixType & get_activations(const Layer &child) const override
bool can_run_inplace() const override
If True, the computation can run in-place (feeding each input activations tensor as the corresponding...
Definition: tessellate.hpp:109
void set_output_dims(std::vector< int > dims, size_t output_index=0)
Set output tensor dimensions.
void assign_to_repeated(google::protobuf::RepeatedField< T > &field, ContainerT const &values)
Assign a range of values to a repeated protobuf field.
Definition: impl.hpp:125
tessellate_layer(lbann_comm *comm, std::vector< int > dims={})
Definition: tessellate.hpp:76
void setup_dims() override
Setup tensor dimensions Called by the &#39;setup&#39; function. If there are any input tensors, the base method sets all uninitialized output tensor dimensions equal to the first input tensor dimensions.
Definition: tessellate.hpp:112
friend class cereal::access
Definition: tessellate.hpp:158
int get_backprop_requirements() const override
Returns the necessary tensors for computing backpropagation.
Definition: tessellate.hpp:110
tessellate_layer(const tessellate_layer &other)
Definition: tessellate.hpp:82
T allreduce(T snd, const El::mpi::Comm &c, El::mpi::Op op=El::mpi::SUM) const
Definition: comm_impl.hpp:643
std::string get_name() const
Get the layer instance&#39;s name.
Definition: layer.hpp:332
data_layout get_data_layout() const override
Get data layout of the data tensors. We assume that the data layouts of the previous activations...
Definition: tessellate.hpp:107
data_layout
Data layout that is optimized for different modes of parallelism.
Definition: base.hpp:218
void fp_compute_3d(const std::vector< int > &input_dims, const std::vector< int > &output_dims, const AbsMatrixType &input, AbsDistMatrixType &output)
void fp_compute() override
Apply layer operation. Called by the &#39;forward_prop&#39; function. Given the input tensors, the output tensors are populated with computed values.
Definition: tessellate.hpp:161
void setup_data(size_t max_mini_batch_size) override
void bp_compute() override
Compute objective funciton gradients. Called by the &#39;back_prop&#39; function. Given the input...
Definition: tessellate.hpp:195
std::vector< int > get_output_dims(size_t output_index=0) const
Get output tensor dimensions.
data_type_layer & operator=(data_type_layer &&other)=default
const InputAbsDistMatrixType & get_error_signals(const Layer &parent) const override