binary_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  */
19 
20 #ifndef TILEDARRAY_DIST_EVAL_BINARY_EVAL_H__INCLUDED
21 #define TILEDARRAY_DIST_EVAL_BINARY_EVAL_H__INCLUDED
22 
24 #include <TiledArray/zero_tensor.h>
25 
27 
28 namespace TiledArray {
29 namespace detail {
30 
32 
39 template <typename Left, typename Right, typename Op, typename Policy>
40 class BinaryEvalImpl : public DistEvalImpl<typename Op::result_type, Policy>,
41  public std::enable_shared_from_this<
42  BinaryEvalImpl<Left, Right, Op, Policy>> {
43  public:
48  typedef typename DistEvalImpl_::TensorImpl_
50  typedef Left left_type;
51  typedef Right right_type;
55  typedef typename DistEvalImpl_::pmap_interface
57  typedef
60  typedef
62  typedef Op op_type;
63 
64  using std::enable_shared_from_this<BinaryEvalImpl_>::shared_from_this;
65 
66  private:
67  left_type left_;
68  right_type right_;
69  op_type op_;
70 
71  public:
73 
82  template <typename Perm, typename = std::enable_if_t<
83  TiledArray::detail::is_permutation_v<Perm>>>
84  BinaryEvalImpl(const left_type& left, const right_type& right, World& world,
85  const trange_type& trange, const shape_type& shape,
86  const std::shared_ptr<pmap_interface>& pmap, const Perm& perm,
87  const op_type& op)
89  left_(left),
90  right_(right),
91  op_(op) {
92  TA_ASSERT(left.trange() == right.trange());
93  }
94 
95  virtual ~BinaryEvalImpl() {}
96 
98 
106 
107  const auto source_index = DistEvalImpl_::perm_index_to_source(i);
108  const ProcessID source =
109  left_.owner(source_index); // Left and right
110  // should have the same owner
111 
112  const madness::DistributedID key(DistEvalImpl_::id(), i);
113  return TensorImpl_::world().gop.template recv<value_type>(source, key);
114  }
115 
117 
121  virtual void discard_tile(ordinal_type i) const { get_tile(i); }
122 
123  private:
125 
126 #ifdef TILEDARRAY_HAS_CUDA
127  template <typename L, typename R, typename U = value_type>
131  std::enable_if_t<!detail::is_cuda_tile_v<U>, void> eval_tile(
132  const ordinal_type i, L left, R right) {
133  DistEvalImpl_::set_tile(i, op_(left, right));
134  }
135 
139  template <typename L, typename R, typename U = value_type>
140  std::enable_if_t<detail::is_cuda_tile_v<U>, void> eval_tile(
141  const ordinal_type i, L left, R right) {
142  // TODO avoid copy the Op object
143  auto result_tile =
144  madness::add_cuda_task(DistEvalImpl_::world(), op_, left, right);
145  DistEvalImpl_::set_tile(i, result_tile);
146  }
147 #else
148  template <typename L, typename R>
152  void eval_tile(const ordinal_type i, L left, R right) {
153  DistEvalImpl_::set_tile(i, op_(left, right));
154  }
155 #endif
156 
163  virtual int internal_eval() {
164  // Evaluate child tensors
165  left_.eval();
166  right_.eval();
167 
168  // Task function argument types
169  typedef typename std::conditional<
170  op_type::left_is_consumable, typename left_type::value_type,
171  const typename left_type::value_type>::type& left_argument_type;
172  typedef typename std::conditional<
173  op_type::right_is_consumable, typename right_type::value_type,
174  const typename right_type::value_type>::type& right_argument_type;
175 
176  ordinal_type task_count = 0ul;
177 
178  // Construct local iterator
179  TA_ASSERT(left_.pmap() == right_.pmap());
180  std::shared_ptr<BinaryEvalImpl_> self = shared_from_this();
181  typename pmap_interface::const_iterator it = left_.pmap()->begin();
182  const typename pmap_interface::const_iterator end = left_.pmap()->end();
183 
184  if (left_.is_dense() && right_.is_dense() && TensorImpl_::is_dense()) {
185  // Evaluate tiles where both arguments and the result are dense
186  for (; it != end; ++it) {
187  // Get tile indices
188  const auto source_index = *it;
189  const auto target_index =
191 
192  // Schedule tile evaluation task
193  TensorImpl_::world().taskq.add(
194  self,
195  &BinaryEvalImpl_::template eval_tile<left_argument_type,
196  right_argument_type>,
197  target_index, left_.get(source_index), right_.get(source_index));
198 
199  ++task_count;
200  }
201  } else {
202  // Evaluate tiles where the result or one of the arguments is sparse
203  for (; it != end; ++it) {
204  // Get tile indices
205  const auto index = *it;
206  const auto target_index = DistEvalImpl_::perm_index_to_target(index);
207 
208  if (!TensorImpl_::is_zero(target_index)) {
209  // Schedule tile evaluation task
210  if (left_.is_zero(index)) {
211  TensorImpl_::world().taskq.add(
212  self,
213  &BinaryEvalImpl_::template eval_tile<const ZeroTensor,
214  right_argument_type>,
215  target_index, ZeroTensor(), right_.get(index));
216  } else if (right_.is_zero(index)) {
217  TensorImpl_::world().taskq.add(
218  self,
219  &BinaryEvalImpl_::template eval_tile<left_argument_type,
220  const ZeroTensor>,
221  target_index, left_.get(index), ZeroTensor());
222  } else {
223  TensorImpl_::world().taskq.add(
224  self,
225  &BinaryEvalImpl_::template eval_tile<left_argument_type,
226  right_argument_type>,
227  target_index, left_.get(index), right_.get(index));
228  }
229 
230  ++task_count;
231  } else {
232  // Cleanup unused tiles
233  if (!left_.is_zero(index)) left_.discard(index);
234  if (!right_.is_zero(index)) right_.discard(index);
235  }
236  }
237  }
238 
239  // Wait for child tensors to be evaluated, and process tasks while waiting.
240  left_.wait();
241  right_.wait();
242 
243  return task_count;
244  }
245 
246 }; // class BinaryEvalImpl
247 
248 } // namespace detail
249 } // namespace TiledArray
250 
251 #endif // TILEDARRAY_DIST_EVAL_BINARY_EVAL_H__INCLUDED
BinaryEvalImpl(const left_type &left, const right_type &right, 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 a binary evaluator.
Definition: binary_eval.h:84
::blas::Op Op
Definition: blas.h:46
World & world() const
World accessor.
Definition: tensor_impl.h:175
DistEvalImpl_::shape_type shape_type
Shape type.
Definition: binary_eval.h:54
BinaryEvalImpl< Left, Right, Op, Policy > BinaryEvalImpl_
This object type.
Definition: binary_eval.h:45
bool is_zero(const Index &i) const
Query for a zero tile.
Definition: tensor_impl.h:147
ordinal_type perm_index_to_target(ordinal_type index) const
Permute index from a source index to a target index.
Definition: dist_eval.h:85
bool is_dense() const
Query the density of the tensor.
Definition: tensor_impl.h:156
Left left_type
The left-hand argument type.
Definition: binary_eval.h:50
DistEvalImpl_::TensorImpl_ TensorImpl_
The base, base class type.
Definition: binary_eval.h:49
void set_tile(ordinal_type i, const value_type &value)
Set tensor value.
Definition: dist_eval.h:154
eval_trait< value_type >::type eval_type
Tile evaluation type.
Definition: dist_eval.h:62
const std::shared_ptr< pmap_interface > & pmap() const
Tensor process map accessor.
Definition: tensor_impl.h:89
DistEvalImpl_::pmap_interface pmap_interface
Process map interface type.
Definition: binary_eval.h:56
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
DistEvalImpl_::value_type value_type
Tile type.
Definition: binary_eval.h:59
DistEvalImpl_::range_type range_type
Range type.
Definition: binary_eval.h:53
DistEvalImpl< typename Op::result_type, Policy > DistEvalImpl_
The base class type.
Definition: binary_eval.h:47
DistEvalImpl_::ordinal_type ordinal_type
Ordinal type.
Definition: binary_eval.h:52
Op op_type
Tile evaluation operator type.
Definition: binary_eval.h:62
Tensor implementation and base for other tensor implementation objects.
Definition: tensor_impl.h:39
#define TA_ASSERT(EXPR,...)
Definition: error.h:39
DistEvalImpl_::eval_type eval_type
Tile evaluation type.
Definition: binary_eval.h:61
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_::trange_type trange_type
Tiled range type.
Definition: binary_eval.h:58
virtual void discard_tile(ordinal_type i) const
Discard a tile that is not needed.
Definition: binary_eval.h:121
TensorImpl_::ordinal_type ordinal_type
Ordinal type.
Definition: dist_eval.h:52
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
TensorImpl_::pmap_interface pmap_interface
process map interface type
Definition: dist_eval.h:59
Binary, distributed tensor evaluator.
Definition: binary_eval.h:42
const trange_type & trange() const
Tiled range accessor.
Definition: tensor_impl.h:167
Right right_type
The right-hand argument type.
Definition: binary_eval.h:51
const shape_type & shape() const
Tensor shape accessor.
Definition: tensor_impl.h:162
const madness::uniqueidT & id() const
Unique object id accessor.
Definition: dist_eval.h:133
virtual Future< value_type > get_tile(ordinal_type i) const
Get tile at index i.
Definition: binary_eval.h:103
TensorImpl_::trange_type trange_type
Tiled range type for this object.
Definition: dist_eval.h:54
An N-dimensional shallow copy wrapper for tile objects.
Definition: tile.h:82
bool is_local(const Index &i) const
Query for a locally owned tile.
Definition: tensor_impl.h:134