btas.h
Go to the documentation of this file.
1 /*
2  * This file is a part of TiledArray.
3  * Copyright (C) 2018 Virginia Tech
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * btas.h
19  * January 19, 2018
20  *
21  */
22 
23 #ifndef TILEDARRAY_CONVERSIONS_BTAS_H__INCLUDED
24 #define TILEDARRAY_CONVERSIONS_BTAS_H__INCLUDED
25 
26 #include <limits>
27 
28 #include <TiledArray/block_range.h>
29 #include <TiledArray/dense_shape.h>
34 #include <TiledArray/shape.h>
36 #include <TiledArray/tensor.h>
38 
39 namespace TiledArray {
40 
41 // clang-format off
43 
58 // clang-format on
59 template <typename T, typename Range_, typename Storage_, typename Tensor_>
61  const btas::Tensor<T, Range_, Storage_>& src, Tensor_& dst) {
62  TA_ASSERT(dst.range().rank() == src.range().rank());
63 
64  const auto& src_range = src.range();
65  const auto& dst_range = dst.range();
66  auto src_blk_range =
68  dst_range.lobound(), dst_range.upbound());
69  using std::data;
70  auto src_view = TiledArray::make_const_map(data(src), src_blk_range);
71  auto dst_view = TiledArray::make_map(data(dst), dst_range);
72 
73  dst_view = src_view;
74 }
75 
76 // clang-format off
78 
94 // clang-format on
95 template <typename Tensor_, typename T, typename Range_, typename Storage_>
96 inline void tensor_to_btas_subtensor(const Tensor_& src,
97  btas::Tensor<T, Range_, Storage_>& dst) {
98  TA_ASSERT(dst.range().rank() == src.range().rank());
99 
100  const auto& src_range = src.range();
101  const auto& dst_range = dst.range();
102  auto dst_blk_range =
104  src_range.lobound(), src_range.upbound());
105  using std::data;
106  auto src_view = TiledArray::make_const_map(data(src), src_range);
107  auto dst_view = TiledArray::make_map(data(dst), dst_blk_range);
108 
109  dst_view = src_view;
110 }
111 
112 namespace detail {
113 
116 
125 template <typename DistArray_, typename BTAS_Tensor_>
126 void counted_btas_subtensor_to_tensor(const BTAS_Tensor_* src, DistArray_* dst,
127  const typename DistArray_::ordinal_type i,
128  madness::AtomicInt* counter) {
129  typename DistArray_::value_type tensor(dst->trange().make_tile_range(i));
130  btas_subtensor_to_tensor(*src, tensor);
131  dst->set(i, tensor);
132  (*counter)++;
133 }
134 
136 
142 template <typename TA_Tensor_, typename BTAS_Tensor_>
143 void counted_tensor_to_btas_subtensor(const TA_Tensor_& src, BTAS_Tensor_* dst,
144  madness::AtomicInt* counter) {
145  tensor_to_btas_subtensor(src, *dst);
146  (*counter)++;
147 }
148 
149 template <bool sparse>
150 auto make_shape(World& world, const TiledArray::TiledRange& trange);
151 
152 template <>
153 inline auto make_shape<true>(World& world,
154  const TiledArray::TiledRange& trange) {
155  TiledArray::Tensor<float> tile_norms(trange.tiles_range(),
157  return TiledArray::SparseShape<float>(world, tile_norms, trange);
158 }
159 
160 template <>
161 inline auto make_shape<false>(World&, const TiledArray::TiledRange&) {
162  return TiledArray::DenseShape{};
163 }
164 
165 } // namespace detail
166 
168 
211 template <typename DistArray_, typename T, typename Range, typename Storage>
212 DistArray_ btas_tensor_to_array(World& world,
213  const TiledArray::TiledRange& trange,
214  const btas::Tensor<T, Range, Storage>& src,
215  bool replicated = false) {
216  // Test preconditions
217  const auto rank = trange.tiles_range().rank();
218  TA_ASSERT(rank == src.range().rank() &&
219  "TiledArray::btas_tensor_to_array(): rank of destination "
220  "trange does not match the rank of source BTAS tensor.");
221  auto dst_range_extents = trange.elements_range().extent();
222  for (std::remove_const_t<decltype(rank)> d = 0; d != rank; ++d) {
223  TA_ASSERT(dst_range_extents[d] == src.range().extent(d) &&
224  "TiledArray::btas_tensor_to_array(): source dimension does "
225  "not match destination dimension.");
226  }
227 
228  using Tensor_ = btas::Tensor<T, Range, Storage>;
229  using Policy_ = typename DistArray_::policy_type;
230  const auto is_sparse = !is_dense_v<Policy_>;
231 
232  // Check that this is not a distributed computing environment
233  if (!replicated)
234  TA_ASSERT(
235  world.size() == 1 &&
236  "An array can be created from a btas::Tensor if the number of World "
237  "ranks is greater than 1 only when replicated=true.");
238 
239  // Make a shape, only used if making a sparse array
240  using Shape_ = typename DistArray_::shape_type;
241  Shape_ shape = detail::make_shape<is_sparse>(world, trange);
242 
243  // Create a new tensor
244  DistArray_ array =
245  (replicated && (world.size() > 1)
246  ? DistArray_(
247  world, trange, shape,
248  std::static_pointer_cast<typename DistArray_::pmap_interface>(
249  std::make_shared<detail::ReplicatedPmap>(
250  world, trange.tiles_range().volume())))
251  : DistArray_(world, trange, shape));
252 
253  // Spawn copy tasks
254  madness::AtomicInt counter;
255  counter = 0;
256  std::int64_t n = 0;
257  for (typename DistArray_::ordinal_type i = 0; i < array.size(); ++i) {
258  world.taskq.add(
259  &detail::counted_btas_subtensor_to_tensor<DistArray_, Tensor_>, &src,
260  &array, i, &counter);
261  ++n;
262  }
263 
264  // Wait until the write tasks are complete
265  array.world().await([&counter, n]() { return counter == n; });
266 
267  // Analyze tiles norms and truncate based on sparse policy
268  if (is_sparse) truncate(array);
269 
270  return array;
271 }
272 
274 
298 template <typename Tile, typename Policy,
299  typename Storage = std::vector<typename Tile::value_type>>
300 btas::Tensor<typename Tile::value_type, btas::DEFAULT::range, Storage>
302  int target_rank = -1) {
303  // Test preconditions
304  if (target_rank == -1 && !src.pmap()->is_replicated())
305  TA_ASSERT(
306  src.world().size() == 1 &&
307  "TiledArray::array_to_btas_tensor(): a non-replicated array can only "
308  "be converted to a btas::Tensor on every rank if the number of World "
309  "ranks is 1.");
310 
311  using result_type =
312  btas::Tensor<typename TiledArray::DistArray<Tile, Policy>::element_type,
313  btas::DEFAULT::range, Storage>;
314  using result_range_type = typename result_type::range_type;
315 
316  // Construct the result
317  if (target_rank == -1 || src.world().rank() == target_rank) {
318  // if array is sparse must initialize to zero
319  result_type result(
320  result_range_type(src.trange().elements_range().extent()), 0.0);
321 
322  // Spawn tasks to copy array tiles to btas::Tensor
323  madness::AtomicInt counter;
324  counter = 0;
325  int n = 0;
326  for (std::size_t i = 0; i < src.size(); ++i) {
327  if (!src.is_zero(i)) {
328  src.world().taskq.add(
329  &detail::counted_tensor_to_btas_subtensor<Tile, result_type>,
330  src.find(i), &result, &counter);
331  ++n;
332  }
333  }
334 
335  // Wait until the write tasks are complete
336  src.world().await([&counter, n]() { return counter == n; });
337 
338  return result;
339  } else // else
340  return result_type{};
341 }
342 
343 } // namespace TiledArray
344 
345 #endif // TILEDARRAY_CONVERSIONS_BTAS_H__INCLUDED
const range_type & tiles_range() const
Access the tile range.
Definition: tiled_range.h:147
void counted_tensor_to_btas_subtensor(const TA_Tensor_ &src, BTAS_Tensor_ *dst, madness::AtomicInt *counter)
Task function for assigning a tensor to an Eigen submatrix.
Definition: btas.h:143
void counted_btas_subtensor_to_tensor(const BTAS_Tensor_ *src, DistArray_ *dst, const typename DistArray_::ordinal_type i, madness::AtomicInt *counter)
Definition: btas.h:126
TensorConstMap< T, Range_, OpResult > make_const_map(const T *const data, const Index &lower_bound, const Index &upper_bound)
Definition: tensor_map.h:98
TensorMap< T, Range_, OpResult > make_map(T *const data, const Index &lower_bound, const Index &upper_bound)
Definition: tensor_map.h:53
Range that references a subblock of another range.
Definition: block_range.h:34
auto rank(const DistArray< Tile, Policy > &a)
Definition: dist_array.h:1617
const range_type & elements_range() const
Access the element range.
Definition: tiled_range.h:158
#define TA_ASSERT(EXPR,...)
Definition: error.h:39
index_view_type lobound() const
Range lower bound accessor.
Definition: range.h:692
index_view_type extent() const
Range extent accessor.
Definition: range.h:741
btas::Tensor< typename Tile::value_type, btas::DEFAULT::range, Storage > array_to_btas_tensor(const TiledArray::DistArray< Tile, Policy > &src, int target_rank=-1)
Convert a TiledArray::DistArray object into a btas::Tensor object.
Definition: btas.h:301
auto size() const
Returns the number of tiles in the tensor.
Definition: dist_array.h:972
Range data of a tiled array.
Definition: tiled_range.h:32
const trange_type & trange() const
Tiled range accessor.
Definition: dist_array.h:917
KroneckerDeltaTile< _N >::numeric_type max(const KroneckerDeltaTile< _N > &arg)
Future< value_type > find(const Index &i) const
Find local or remote tile by index.
Definition: dist_array.h:524
const TiledArray::Range & make_ta_range(const TiledArray::Range &range)
Definition: btas.h:58
Forward declarations.
Definition: dist_array.h:57
Dense shape of an array.
Definition: dense_shape.h:53
World & world() const
World accessor.
Definition: dist_array.h:1007
DistArray_ btas_tensor_to_array(World &world, const TiledArray::TiledRange &trange, const btas::Tensor< T, Range, Storage > &src, bool replicated=false)
Convert a btas::Tensor object into a TiledArray::DistArray object.
Definition: btas.h:212
void btas_subtensor_to_tensor(const btas::Tensor< T, Range_, Storage_ > &src, Tensor_ &dst)
Copy a block of a btas::Tensor into a TiledArray::Tensor.
Definition: btas.h:60
bool is_zero(const Index &i) const
Check for zero tiles.
Definition: dist_array.h:1137
ordinal_type volume() const
Range volume accessor.
Definition: range.h:783
void tensor_to_btas_subtensor(const Tensor_ &src, btas::Tensor< T, Range_, Storage_ > &dst)
Copy a block of a btas::Tensor into a TiledArray::Tensor.
Definition: btas.h:96
auto make_shape(World &world, const TiledArray::TiledRange &trange)
std::enable_if_t< is_dense_v< Policy >, void > truncate(DistArray< Tile, Policy > &array, typename Policy::shape_type::value_type=0)
Truncate a dense Array.
Definition: truncate.h:46
Frobenius-norm-based sparse shape.
Definition: sparse_shape.h:74
An N-dimensional tensor object.
Definition: tensor.h:50
auto make_shape< false >(World &, const TiledArray::TiledRange &)
Definition: btas.h:161
const std::shared_ptr< pmap_interface > & pmap() const
Process map accessor.
Definition: dist_array.h:1019
unsigned int rank() const
Rank accessor.
Definition: range.h:669
auto make_shape< true >(World &world, const TiledArray::TiledRange &trange)
Definition: btas.h:153