LBANN  0.103.0
LivermoreBigArtificialNeuralNetworkToolkit
onednn.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_UTILS_DNN_LIB_ONEDNN_HPP
28 #define LBANN_UTILS_DNN_LIB_ONEDNN_HPP
29 
33 
34 #include <h2/meta/Core.hpp>
35 #include <h2/meta/TypeList.hpp>
36 
37 #ifdef LBANN_HAS_ONEDNN
38 
39 #include <dnnl.hpp>
40 
41 namespace lbann {
42 namespace onednn {
43 namespace details {
44 
48 template <typename T>
49 struct TypeMapT;
50 
54 template <typename T>
55 struct IsSupportedTypeT : std::false_type
56 {
57 };
58 
59 #define ADD_ONEDNN_TYPE_MAP(CPPTYPE, EVAL) \
60  template <> \
61  struct TypeMapT<CPPTYPE> \
62  : std::integral_constant<dnnl::memory::data_type, \
63  dnnl::memory::data_type::EVAL> \
64  { \
65  }; \
66  template <> \
67  struct IsSupportedTypeT<CPPTYPE> : std::true_type \
68  { \
69  }
70 
71 // Basic types
72 ADD_ONEDNN_TYPE_MAP(float, f32);
73 ADD_ONEDNN_TYPE_MAP(int32_t, s32);
74 ADD_ONEDNN_TYPE_MAP(int8_t, s8);
75 ADD_ONEDNN_TYPE_MAP(uint8_t, u8);
76 
77 // 16-bit floating point
78 // TODO: bfloat16 types (not yet supported in Hydrogen)
79 #if defined LBANN_HAS_HALF
80 ADD_ONEDNN_TYPE_MAP(cpu_fp16, f16);
81 #endif
82 #if defined LBANN_HAS_GPU_FP16
83 ADD_ONEDNN_TYPE_MAP(fp16, f16);
84 #endif
85 
86 } // namespace details
87 
88 template <typename T>
89 using TypeMap = typename details::TypeMapT<T>;
90 
91 template <typename T>
92 inline constexpr auto DataTypeValue = TypeMap<T>::value;
93 
94 template <typename T>
95 inline constexpr bool IsSupportedType = details::IsSupportedTypeT<T>::value;
96 
97 template <typename T, ::h2::meta::EnableWhen<IsSupportedType<T>, int> = 0>
98 inline constexpr dnnl::memory::data_type get_data_type()
99 {
100  return DataTypeValue<T>;
101 }
102 
103 template <typename T, ::h2::meta::EnableUnless<IsSupportedType<T>, int> = 0>
104 inline dnnl::memory::data_type get_data_type()
105 {
106  LBANN_ERROR("Type \"",
107  El::TypeName<T>(),
108  "\" is not supported "
109  "by the oneDNN runtime.");
110 }
111 
112 template <El::Device D>
113 dnnl::engine& get_device_engine();
114 
115 template <El::Device D>
116 dnnl::stream get_stream(dnnl::engine const& e, El::SyncInfo<D> const&);
117 
118 } // namespace onednn
119 
120 template <El::Device D>
121 struct onednn_backend
122 {
123  static constexpr auto device = D;
124 
125  template <typename T>
126  static auto data_type()
127  {
128  return onednn::get_data_type<T>();
129  }
130 
131  class TensorDescriptor
132  {
133  public:
135  static constexpr auto device = D;
136 
138  using backend_type = onednn_backend<D>;
139 
141  using dnnTensorDescriptor_t = dnnl::memory;
142 
144  using dnnDataType_t = dnnl::memory::data_type;
145 
147  using dnnTensorFormat_t = dnnl::memory::format_tag;
148 
150  using internal_descriptor_type = dnnl::memory::desc;
151 
152  public:
154 
156  TensorDescriptor() = default;
157 
159  explicit TensorDescriptor(dnnTensorDescriptor_t desc)
160  : desc_{std::move(desc)}
161  {}
162 
164  ~TensorDescriptor() noexcept = default;
165 
167  TensorDescriptor(TensorDescriptor const&) = default;
169  TensorDescriptor(TensorDescriptor&&) = default;
171  TensorDescriptor& operator=(TensorDescriptor const&) = default;
173  TensorDescriptor& operator=(TensorDescriptor&&) = default;
174 
176  void swap(TensorDescriptor& other) { std::swap(desc_, other.desc_); }
177 
179  void reset(dnnTensorDescriptor_t desc = dnnTensorDescriptor_t{})
180  {
181  desc_ = dnnl::memory{std::move(desc)};
182  }
183 
185  dnnTensorDescriptor_t release() noexcept
186  {
187  dnnTensorDescriptor_t tmp = desc_;
188  desc_ = dnnl::memory{};
189  return tmp;
190  }
191 
193  dnnTensorDescriptor_t get() const noexcept { return desc_; }
194 
196  operator dnnTensorDescriptor_t() const noexcept { return desc_; }
197 
202  void create() noexcept {}
203 
204  void set(dnnDataType_t data_type,
205  dnnl::memory::dims dims,
206  dnnl::memory::dims strides = {})
207  {
208  if (strides.empty())
209  strides = get_packed_strides(dims);
210 
211  auto md = dnnl::memory::desc(dims, data_type, strides);
212  desc_ =
213  dnnl::memory(md, onednn::get_device_engine<D>(), DNNL_MEMORY_NONE);
214  }
215 
220  template <typename DimT>
221  void set(dnnDataType_t data_type,
222  std::vector<DimT> const& dims_in,
223  std::vector<DimT> const& strides_in = {})
224  {
225  dnnl::memory::dims dims{cbegin(dims_in), cend(dims_in)};
226  dnnl::memory::dims strides{cbegin(strides_in), cend(strides_in)};
227  this->set(data_type, dims, strides);
228  }
229 
234  template <typename... IntTs>
235  void set(dnnDataType_t data_type, IntTs... dims)
236  {
237  set(data_type, {static_cast<dnnl::memory::dim>(dims)...});
238  }
239  // This function is required for API compatibility.
240  void set(dnnDataType_t data_type,
241  dnnTensorFormat_t /*format*/,
242  const std::vector<int>& dims)
243  {
244  this->set(data_type, dims);
245  }
246 
247  private:
255  dnnl::memory desc_;
256 
257  }; // class TensorDescriptor
258 
259  template <typename DataT, typename ScalarT>
260  static void softmax_forward(ScalarT const& alpha_in,
261  TensorDescriptor const& xDesc,
262  El::Matrix<DataT, D> const& x,
263  ScalarT const& beta_in,
264  TensorDescriptor const& yDesc,
265  El::Matrix<DataT, D>& y,
266  El::SyncInfo<D> const& si,
267  softmax_mode mode,
269 
270  template <typename DataT, typename ScalarT>
271  static void logsoftmax_forward(ScalarT const& alpha_in,
272  TensorDescriptor const& xDesc,
273  El::Matrix<DataT, D> const& x,
274  ScalarT const& beta_in,
275  TensorDescriptor const& yDesc,
276  El::Matrix<DataT, D>& y,
277  El::SyncInfo<D> const& si,
278  softmax_mode mode)
279  {
280  LBANN_ERROR("Not yet implemented.");
281  }
282 
283  template <typename DataT, typename ScalarT>
284  static void softmax_backward(ScalarT const& alpha_in,
285  TensorDescriptor const& yDesc,
286  El::Matrix<DataT, D> const& y,
287  TensorDescriptor const& dyDesc,
288  El::Matrix<DataT, D> const& dy,
289  ScalarT const& beta_in,
290  TensorDescriptor const& dxDesc,
291  El::Matrix<DataT, D>& dx,
292  El::SyncInfo<D> const& si,
293  softmax_mode mode,
295 
296  template <typename DataT, typename ScalarT>
297  static void logsoftmax_backward(ScalarT const& alpha_in,
298  TensorDescriptor const& yDesc,
299  El::Matrix<DataT, D> const& y,
300  TensorDescriptor const& dyDesc,
301  El::Matrix<DataT, D> const& dy,
302  ScalarT const& beta_in,
303  TensorDescriptor const& dxDesc,
304  El::Matrix<DataT, D>& dx,
305  El::SyncInfo<D> const& si,
306  softmax_mode mode,
308  {
309  LBANN_ERROR("Not yet implemented.");
310  }
311 
312 }; // struct onednn_backend
313 
314 } // namespace lbann
315 #endif // LBANN_HAS_ONEDNN
316 #endif // LBANN_UTILS_DNN_LIB_ONEDNN_HPP
void softmax_backward(ScalarT const &alpha_in, TensorDescT const &yDesc, El::Matrix< DataT, D > const &y, TensorDescT const &dyDesc, El::Matrix< DataT, D > const &dy, ScalarT const &beta_in, TensorDescT const &dxDesc, El::Matrix< DataT, D > &dx, El::SyncInfo< D > const &si, softmax_mode mode, softmax_alg alg=softmax_alg::ACCURATE)
void softmax_forward(ScalarT const &alpha_in, TensorDescT const &xDesc, El::Matrix< DataT, D > const &x, ScalarT const &beta_in, TensorDescT const &yDesc, El::Matrix< DataT, D > &y, El::SyncInfo< D > const &si, softmax_mode mode, softmax_alg alg=softmax_alg::ACCURATE)
#define LBANN_ERROR(...)
Definition: exception.hpp:37
softmax_alg
Internal LBANN names for supported softmax algorithms.
Definition: dnn_enums.hpp:110
softmax_mode
Which tensor dimensions to apply softmax over.
Definition: dnn_enums.hpp:87
auto get_packed_strides(size_t ndims, T const *dims)
Definition: dim_helpers.hpp:91