array_eval.h
Go to the documentation of this file.
1 /*
2  * This file is a part of TiledArray.
3  * Copyright (C) 2013 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  * Justus Calvin
19  * Department of Chemistry, Virginia Tech
20  *
21  * array_eval.h
22  * Aug 9, 2013
23  *
24  */
25 
26 #ifndef TILEDARRAY_DIST_EVAL_ARRAY_EVAL_H__INCLUDED
27 #define TILEDARRAY_DIST_EVAL_ARRAY_EVAL_H__INCLUDED
28 
29 #include <TiledArray/block_range.h>
31 
32 namespace TiledArray {
33 namespace detail {
34 
36 
41 template <typename Tile, typename Op>
43  public:
45  typedef Op op_type;
46  typedef typename op_type::result_type eval_type;
47  typedef Tile tile_type;
48  private:
49  mutable tile_type tile_;
50  std::shared_ptr<op_type>
51  op_;
52  bool consume_;
53 
54  template <typename T>
55  using eval_t = typename eval_trait<typename std::decay<T>::type>::type;
56 
57  public:
58  using conversion_result_type = decltype(
59  ((!Op::is_consumable) && consume_ ? op_->consume(tile_)
60  : (*op_)(tile_)));
61 
62 #ifdef TILEDARRAY_HAS_CUDA
63  // TODO need a better design on how to manage the lifetime of converted Tile
64  mutable conversion_result_type conversion_tile_;
65 #endif
66  public:
69  : tile_(),
70  op_(),
71  consume_(false)
72 #ifdef TILEDARRAY_HAS_CUDA
73  ,
74  conversion_tile_()
75 #endif
76  {
77  }
78 
80 
83  : tile_(other.tile_),
84  op_(other.op_),
85  consume_(other.consume_)
86 #ifdef TILEDARRAY_HAS_CUDA
87  ,
88  conversion_tile_()
89 #endif
90  {
91  }
92 
94 
98  LazyArrayTile(const tile_type& tile, const std::shared_ptr<op_type>& op,
99  const bool consume)
100  : tile_(tile),
101  op_(op),
102  consume_(consume)
103 #ifdef TILEDARRAY_HAS_CUDA
104  ,
105  conversion_tile_()
106 #endif
107  {
108  }
109 
111 
114  tile_ = other.tile_;
115  op_ = other.op_;
116  consume_ = other.consume_;
117 #ifdef TILEDARRAY_HAS_CUDA
118  conversion_tile_ = other.conversion_tile_;
119 #endif
120  return *this;
121  }
122 
124 
126  bool is_consumable() const { return consume_ || op_->permutation(); }
127 
129 #ifdef TILEDARRAY_HAS_CUDA
130 
131  explicit operator conversion_result_type&() const {
132  conversion_tile_ =
133  std::move(((!Op::is_consumable) && consume_ ? op_->consume(tile_)
134  : (*op_)(tile_)));
135  return conversion_tile_;
136  }
137 
138 #else
139  explicit operator conversion_result_type() const {
140  return ((!Op::is_consumable) && consume_ ? op_->consume(tile_)
141  : (*op_)(tile_));
142  }
143 #endif
144 
146  const tile_type& tile() const { return tile_; }
147 
149 
151  template <typename Archive>
152  void serialize(const Archive&) {
153  TA_ASSERT(false);
154  }
155 
156 }; // LazyArrayTile
157 
159 
169 template <typename Array, typename Op, typename Policy>
171  : public DistEvalImpl<LazyArrayTile<typename Array::value_type, Op>,
172  Policy>,
173  public std::enable_shared_from_this<ArrayEvalImpl<Array, Op, Policy>> {
174  public:
179  typedef typename DistEvalImpl_::TensorImpl_
181  typedef Array array_type;
185  typedef typename DistEvalImpl_::pmap_interface
187  typedef
189  typedef typename DistEvalImpl_::value_type
191  typedef Op op_type;
192 
193  using std::enable_shared_from_this<
194  ArrayEvalImpl<Array, Op, Policy>>::shared_from_this;
195 
196  private:
197  array_type array_;
198  std::shared_ptr<op_type> op_;
199  BlockRange block_range_;
200 
201  public:
203 
211  template <typename Perm, typename = std::enable_if_t<
212  TiledArray::detail::is_permutation_v<Perm>>>
213  ArrayEvalImpl(const array_type& array, World& world,
214  const trange_type& trange, const shape_type& shape,
215  const std::shared_ptr<pmap_interface>& pmap, const Perm& perm,
216  const op_type& op)
217  : DistEvalImpl_(world, trange, shape, pmap, outer(perm)),
218  array_(array),
219  op_(std::make_shared<op_type>(op)),
220  block_range_() {}
221 
223 
235  template <typename Index1, typename Index2, typename Perm,
236  typename = std::enable_if_t<
237  TiledArray::detail::is_integral_range_v<Index1> &&
238  TiledArray::detail::is_integral_range_v<Index2> &&
239  TiledArray::detail::is_permutation_v<Perm>>>
240  ArrayEvalImpl(const array_type& array, World& world,
241  const trange_type& trange, const shape_type& shape,
242  const std::shared_ptr<pmap_interface>& pmap, const Perm& perm,
243  const op_type& op, const Index1& lower_bound,
244  const Index2& upper_bound)
245  : DistEvalImpl_(world, trange, shape, pmap, outer(perm)),
246  array_(array),
247  op_(std::make_shared<op_type>(op)),
248  block_range_(array.trange().tiles_range(), lower_bound, upper_bound) {}
249 
251  virtual ~ArrayEvalImpl() {}
252 
254  // Get the array index that corresponds to the target index
255  auto array_index = DistEvalImpl_::perm_index_to_source(i);
256 
257  // If this object only uses a sub-block of the array, shift the tile
258  // index to the correct location.
259  if (block_range_.rank()) array_index = block_range_.ordinal(array_index);
260 
261  // Get the tile from array_, which may be located on a remote node.
262  Future<typename array_type::value_type> tile = array_.find(array_index);
263 
264  const bool consumable_tile = !array_.is_local(array_index);
265 
266  return eval_tile(tile, consumable_tile);
267  }
268 
270 
273  virtual void discard_tile(ordinal_type) const {
274  const_cast<ArrayEvalImpl_*>(this)->notify();
275  }
276 
277  private:
278  value_type make_tile(const typename array_type::value_type& tile,
279  const bool consume) const {
280  return value_type(tile, op_, consume);
281  }
282 
284  madness::Future<value_type> eval_tile(
286  const bool consumable_tile) const {
287  // Insert the tile into this evaluator for subsequent processing
288  if (tile.probe()) {
289  // Skip the task since the tile is ready
290  Future<value_type> result;
291  result.set(make_tile(tile, consumable_tile));
292  const_cast<ArrayEvalImpl_*>(this)->notify();
293  return result;
294  } else {
295  // Spawn a task to set the tile when the input tile is not ready.
296  Future<value_type> result = TensorImpl_::world().taskq.add(
297  shared_from_this(), &ArrayEvalImpl_::make_tile, tile, consumable_tile,
298  madness::TaskAttributes::hipri());
299  result.register_callback(const_cast<ArrayEvalImpl_*>(this));
300  return result;
301  }
302  }
304 
308  virtual int internal_eval() {
309  // Counter for the number of tasks submitted by this object
310  int task_count = 0;
311 
312  // Get a count of the number of local tiles.
313  if (TensorImpl_::shape().is_dense()) {
314  task_count = TensorImpl_::pmap()->local_size();
315  } else {
316  // Create iterator to tiles that are local for this evaluator.
317  typename array_type::pmap_interface::const_iterator it =
318  TensorImpl_::pmap()->begin();
319  const typename array_type::pmap_interface::const_iterator end =
320  TensorImpl_::pmap()->end();
321 
322  for (; it != end; ++it) {
323  if (!TensorImpl_::is_zero(*it)) ++task_count;
324  }
325  }
326 
327  return task_count;
328  }
329 
330 }; // class ArrayEvalImpl
331 
332 } // namespace detail
333 } // namespace TiledArray
334 
335 #endif // TILEDARRAY_DIST_EVAL_ARRAY_EVAL_H__INCLUDED
impl_type::value_type value_type
Tile type.
Definition: dist_array.h:86
::blas::Op Op
Definition: blas.h:46
World & world() const
World accessor.
Definition: tensor_impl.h:175
DistEvalImpl_::range_type range_type
Range type.
Definition: array_eval.h:183
LazyArrayTile()
Default constructor.
Definition: array_eval.h:68
ArrayEvalImpl(const array_type &array, World &world, const trange_type &trange, const shape_type &shape, const std::shared_ptr< pmap_interface > &pmap, const Perm &perm, const op_type &op)
Construct with full array range.
Definition: array_eval.h:213
DistEvalImpl_::TensorImpl_ TensorImpl_
The base, base class type.
Definition: array_eval.h:180
bool is_zero(const Index &i) const
Query for a zero tile.
Definition: tensor_impl.h:147
bool is_dense() const
Query the density of the tensor.
Definition: tensor_impl.h:156
LazyArrayTile_ & operator=(const LazyArrayTile_ &other)
Assignment operator.
Definition: array_eval.h:113
Distributed evaluator for TiledArray::Array objects.
Definition: array_eval.h:173
ArrayEvalImpl(const array_type &array, World &world, const trange_type &trange, const shape_type &shape, const std::shared_ptr< pmap_interface > &pmap, const Perm &perm, const op_type &op, const Index1 &lower_bound, const Index2 &upper_bound)
Constructor with sub-block range.
Definition: array_eval.h:240
LazyArrayTile< Tile, Op > LazyArrayTile_
This class type.
Definition: array_eval.h:44
const range_type & tiles_range() const
Tiles range accessor.
Definition: tensor_impl.h:95
Lazy tile for on-the-fly evaluation of array tiles.
Definition: array_eval.h:42
decltype(((!Op::is_consumable) &&consume_ ? op_->consume(tile_) :(*op_)(tile_))) conversion_result_type
conversion_type
Definition: array_eval.h:60
const std::shared_ptr< pmap_interface > & pmap() const
Tensor process map accessor.
Definition: tensor_impl.h:89
Range that references a subblock of another range.
Definition: block_range.h:34
ArrayEvalImpl< Array, Op, Policy > ArrayEvalImpl_
This object type.
Definition: array_eval.h:176
virtual void discard_tile(ordinal_type) const
Discard a tile that is not needed.
Definition: array_eval.h:273
Distributed evaluator implementation object.
Definition: dist_eval.h:46
constexpr auto end(Eigen::Matrix< _Scalar, _Rows, 1, _Options, _MaxRows, 1 > &m)
Definition: eigen.h:51
auto outer(const Permutation &p)
Definition: permutation.h:820
LazyArrayTile(const LazyArrayTile_ &other)
Copy constructor.
Definition: array_eval.h:82
DistEvalImpl_::trange_type trange_type
tiled range type
Definition: array_eval.h:188
Op op_type
Tile evaluation operator type.
Definition: array_eval.h:191
virtual ~ArrayEvalImpl()
Virtual destructor.
Definition: array_eval.h:251
Tensor implementation and base for other tensor implementation objects.
Definition: tensor_impl.h:39
#define TA_ASSERT(EXPR,...)
Definition: error.h:39
Op op_type
The operation that will modify this tile.
Definition: array_eval.h:45
DistEvalImpl_::pmap_interface pmap_interface
Process map interface type.
Definition: array_eval.h:186
DistEvalImpl_::ordinal_type ordinal_type
Ordinal type.
Definition: array_eval.h:182
ordinal_type perm_index_to_source(ordinal_type index) const
Permute index from a target index to a source index.
Definition: dist_eval.h:94
DistEvalImpl_::value_type value_type
value type = LazyArrayTile
Definition: array_eval.h:190
ordinal_type ordinal(const Index &index) const
calculate the ordinal index of i
Definition: block_range.h:312
Future< value_type > find(const Index &i) const
Find local or remote tile by index.
Definition: dist_array.h:524
bool is_consumable() const
Query runtime consumable status.
Definition: array_eval.h:126
LazyArrayTile(const tile_type &tile, const std::shared_ptr< op_type > &op, const bool consume)
Construct from tile and operation.
Definition: array_eval.h:98
TensorImpl_::ordinal_type ordinal_type
Ordinal type.
Definition: dist_eval.h:52
Tile tile_type
The input tile type.
Definition: array_eval.h:47
Forward declarations.
Definition: dist_array.h:57
const tile_type & tile() const
return ref to input tile
Definition: array_eval.h:146
bool is_local(const Index &i) const
Check if the tile at index i is stored locally.
Definition: dist_array.h:1098
TensorImpl_::range_type range_type
Range type this tensor.
Definition: dist_eval.h:56
TensorImpl_::shape_type shape_type
Shape type.
Definition: dist_eval.h:57
void serialize(const Archive &)
Serialization (not implemented)
Definition: array_eval.h:152
TensorImpl_::pmap_interface pmap_interface
process map interface type
Definition: dist_eval.h:59
op_type::result_type eval_type
Definition: array_eval.h:46
DistEvalImpl_::shape_type shape_type
Shape type.
Definition: array_eval.h:184
DistEvalImpl< LazyArrayTile< typename Array::value_type, Op >, Policy > DistEvalImpl_
The base class type.
Definition: array_eval.h:178
Determine the object type used in the evaluation of tensor expressions.
Definition: type_traits.h:580
virtual Future< value_type > get_tile(ordinal_type i) const
Get tile at index i.
Definition: array_eval.h:253
const trange_type & trange() const
Tiled range accessor.
Definition: tensor_impl.h:167
const shape_type & shape() const
Tensor shape accessor.
Definition: tensor_impl.h:162
Array array_type
The array type.
Definition: array_eval.h:181
TensorImpl_::trange_type trange_type
Tiled range type for this object.
Definition: dist_eval.h:54
unsigned int rank() const
Rank accessor.
Definition: range.h:669
An N-dimensional shallow copy wrapper for tile objects.
Definition: tile.h:82