Ginkgo  Generated from tags/v1.0.0^0 branch based on master. Ginkgo version 1.0.0
A numerical linear algebra library targeting many-core architectures
hybrid.hpp
1 /*******************************<GINKGO LICENSE>******************************
2 Copyright (c) 2017-2019, the Ginkgo authors
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions
7 are met:
8 
9 1. Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11 
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15 
16 3. Neither the name of the copyright holder nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19 
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21 IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 ******************************<GINKGO LICENSE>*******************************/
32 
33 #ifndef GKO_CORE_MATRIX_HYBRID_HPP_
34 #define GKO_CORE_MATRIX_HYBRID_HPP_
35 
36 
37 #include <algorithm>
38 
39 
40 #include <ginkgo/core/base/array.hpp>
41 #include <ginkgo/core/base/lin_op.hpp>
42 #include <ginkgo/core/matrix/coo.hpp>
43 #include <ginkgo/core/matrix/ell.hpp>
44 
45 
46 namespace gko {
47 namespace matrix {
48 
49 
50 template <typename ValueType>
51 class Dense;
52 
53 
66 template <typename ValueType = default_precision, typename IndexType = int32>
67 class Hybrid : public EnableLinOp<Hybrid<ValueType, IndexType>>,
68  public EnableCreateMethod<Hybrid<ValueType, IndexType>>,
69  public ConvertibleTo<Dense<ValueType>>,
70  public ReadableFromMatrixData<ValueType, IndexType>,
71  public WritableToMatrixData<ValueType, IndexType> {
72  friend class EnableCreateMethod<Hybrid>;
73  friend class EnablePolymorphicObject<Hybrid, LinOp>;
74  friend class Dense<ValueType>;
75 
76 public:
79 
80  using value_type = ValueType;
81  using index_type = IndexType;
82  using mat_data = matrix_data<ValueType, IndexType>;
83  using coo_type = Coo<ValueType, IndexType>;
84  using ell_type = Ell<ValueType, IndexType>;
85 
95  class strategy_type {
96  public:
101  : ell_num_stored_elements_per_row_(zero<size_type>()),
102  coo_nnz_(zero<size_type>())
103  {}
104 
118  size_type *ell_num_stored_elements_per_row,
119  size_type *coo_nnz)
120  {
121  Array<size_type> ref_row_nnz(row_nnz.get_executor()->get_master(),
122  row_nnz.get_num_elems());
123  ref_row_nnz = row_nnz;
124  ell_num_stored_elements_per_row_ =
125  this->compute_ell_num_stored_elements_per_row(&ref_row_nnz);
126  coo_nnz_ = this->compute_coo_nnz(ref_row_nnz);
127  *ell_num_stored_elements_per_row = ell_num_stored_elements_per_row_;
128  *coo_nnz = coo_nnz_;
129  }
130 
137  {
138  return ell_num_stored_elements_per_row_;
139  }
140 
146  const size_type get_coo_nnz() const noexcept { return coo_nnz_; }
147 
156  Array<size_type> *row_nnz) const = 0;
157 
158  protected:
167  size_type compute_coo_nnz(const Array<size_type> &row_nnz) const
168  {
169  size_type coo_nnz = 0;
170  auto row_nnz_val = row_nnz.get_const_data();
171  for (size_type i = 0; i < row_nnz.get_num_elems(); i++) {
172  if (row_nnz_val[i] > ell_num_stored_elements_per_row_) {
173  coo_nnz +=
174  row_nnz_val[i] - ell_num_stored_elements_per_row_;
175  }
176  }
177  return coo_nnz;
178  }
179 
180  private:
181  size_type ell_num_stored_elements_per_row_;
182  size_type coo_nnz_;
183  };
184 
189  class column_limit : public strategy_type {
190  public:
196  explicit column_limit(size_type num_column = 0)
197  : num_columns_(num_column)
198  {}
199 
201  Array<size_type> *row_nnz) const override
202  {
203  return num_columns_;
204  }
205 
206  private:
207  size_type num_columns_;
208  };
209 
218  public:
225  explicit imbalance_limit(float percent = 0.8) : percent_(percent)
226  {
227  percent_ = std::min(percent_, 1.0f);
228  percent_ = std::max(percent_, 0.0f);
229  }
230 
232  Array<size_type> *row_nnz) const override
233  {
234  auto row_nnz_val = row_nnz->get_data();
235  auto num_rows = row_nnz->get_num_elems();
236  std::sort(row_nnz_val, row_nnz_val + num_rows);
237  if (percent_ < 1) {
238  auto percent_pos = static_cast<size_type>(num_rows * percent_);
239  return row_nnz_val[percent_pos];
240  } else {
241  return row_nnz_val[num_rows - 1];
242  }
243  }
244 
245  private:
246  float percent_;
247  };
248 
255  public:
259  imbalance_bounded_limit(float percent = 0.8, float ratio = 0.0001)
260  : strategy_(imbalance_limit(percent)), ratio_(ratio)
261  {}
262 
264  Array<size_type> *row_nnz) const override
265  {
266  auto num_rows = row_nnz->get_num_elems();
267  auto ell_cols =
268  strategy_.compute_ell_num_stored_elements_per_row(row_nnz);
269  return std::min(ell_cols,
270  static_cast<size_type>(num_rows * ratio_));
271  }
272 
273  private:
274  imbalance_limit strategy_;
275  float ratio_;
276  };
277 
278 
285  public:
290  : strategy_(
291  imbalance_limit(static_cast<double>(sizeof(IndexType)) /
292  (sizeof(ValueType) + 2 * sizeof(IndexType))))
293  {}
294 
296  Array<size_type> *row_nnz) const override
297  {
298  return strategy_.compute_ell_num_stored_elements_per_row(row_nnz);
299  }
300 
301  private:
302  imbalance_limit strategy_;
303  };
304 
305 
310  class automatic : public strategy_type {
311  public:
315  automatic() : strategy_(imbalance_bounded_limit(1.0 / 3.0, 0.001)) {}
316 
318  Array<size_type> *row_nnz) const override
319  {
320  return strategy_.compute_ell_num_stored_elements_per_row(row_nnz);
321  }
322 
323  private:
324  imbalance_bounded_limit strategy_;
325  };
326 
327  void convert_to(Dense<ValueType> *other) const override;
328 
329  void move_to(Dense<ValueType> *other) override;
330 
331  void read(const mat_data &data) override;
332 
333  void write(mat_data &data) const override;
334 
340  value_type *get_ell_values() noexcept { return ell_->get_values(); }
341 
349  const value_type *get_const_ell_values() const noexcept
350  {
351  return ell_->get_const_values();
352  }
353 
359  index_type *get_ell_col_idxs() noexcept { return ell_->get_col_idxs(); }
360 
368  const index_type *get_const_ell_col_idxs() const noexcept
369  {
370  return ell_->get_const_col_idxs();
371  }
372 
379  {
380  return ell_->get_num_stored_elements_per_row();
381  }
382 
388  size_type get_ell_stride() const noexcept { return ell_->get_stride(); }
389 
396  {
397  return ell_->get_num_stored_elements();
398  }
399 
411  value_type &ell_val_at(size_type row, size_type idx) noexcept
412  {
413  return ell_->val_at(row, idx);
414  }
415 
419  value_type ell_val_at(size_type row, size_type idx) const noexcept
420  {
421  return ell_->val_at(row, idx);
422  }
423 
434  index_type &ell_col_at(size_type row, size_type idx) noexcept
435  {
436  return ell_->col_at(row, idx);
437  }
438 
442  index_type ell_col_at(size_type row, size_type idx) const noexcept
443  {
444  return ell_->col_at(row, idx);
445  }
446 
452  const ell_type *get_ell() const noexcept { return ell_.get(); }
453 
459  value_type *get_coo_values() noexcept { return coo_->get_values(); }
460 
468  const value_type *get_const_coo_values() const noexcept
469  {
470  return coo_->get_const_values();
471  }
472 
478  index_type *get_coo_col_idxs() noexcept { return coo_->get_col_idxs(); }
479 
487  const index_type *get_const_coo_col_idxs() const noexcept
488  {
489  return coo_->get_const_col_idxs();
490  }
491 
497  index_type *get_coo_row_idxs() noexcept { return coo_->get_row_idxs(); }
498 
506  const index_type *get_const_coo_row_idxs() const noexcept
507  {
508  return coo_->get_const_row_idxs();
509  }
510 
517  {
518  return coo_->get_num_stored_elements();
519  }
520 
526  const coo_type *get_coo() const noexcept { return coo_.get(); }
527 
534  {
535  return coo_->get_num_stored_elements() +
536  ell_->get_num_stored_elements();
537  }
538 
544  std::shared_ptr<strategy_type> get_strategy() const noexcept
545  {
546  return strategy_;
547  }
548 
556  Hybrid &operator=(const Hybrid &other)
557  {
558  if (&other == this) {
559  return *this;
560  }
561  EnableLinOp<Hybrid<ValueType, IndexType>>::operator=(other);
562  this->coo_->copy_from(other.get_coo());
563  this->ell_->copy_from(other.get_ell());
564  return *this;
565  }
566 
567 protected:
576  Hybrid(
577  std::shared_ptr<const Executor> exec,
578  std::shared_ptr<strategy_type> strategy = std::make_shared<automatic>())
579  : Hybrid(std::move(exec), dim<2>{}, std::move(strategy))
580  {}
581 
591  Hybrid(
592  std::shared_ptr<const Executor> exec, const dim<2> &size,
593  std::shared_ptr<strategy_type> strategy = std::make_shared<automatic>())
594  : Hybrid(std::move(exec), size, size[1], std::move(strategy))
595  {}
596 
607  Hybrid(
608  std::shared_ptr<const Executor> exec, const dim<2> &size,
609  size_type num_stored_elements_per_row,
610  std::shared_ptr<strategy_type> strategy = std::make_shared<automatic>())
611  : Hybrid(std::move(exec), size, num_stored_elements_per_row, size[0],
612  {}, std::move(strategy))
613  {}
614 
625  Hybrid(std::shared_ptr<const Executor> exec, const dim<2> &size,
626  size_type num_stored_elements_per_row, size_type stride,
627  std::shared_ptr<strategy_type> strategy)
628  : Hybrid(std::move(exec), size, num_stored_elements_per_row, stride, {},
629  std::move(strategy))
630  {}
631 
643  Hybrid(
644  std::shared_ptr<const Executor> exec, const dim<2> &size,
645  size_type num_stored_elements_per_row, size_type stride,
646  size_type num_nonzeros = {},
647  std::shared_ptr<strategy_type> strategy = std::make_shared<automatic>())
648  : EnableLinOp<Hybrid>(exec, size),
649  ell_(std::move(ell_type::create(
650  exec, size, num_stored_elements_per_row, stride))),
651  coo_(std::move(coo_type::create(exec, size, num_nonzeros))),
652  strategy_(std::move(strategy))
653  {}
654 
655  void apply_impl(const LinOp *b, LinOp *x) const override;
656 
657  void apply_impl(const LinOp *alpha, const LinOp *b, const LinOp *beta,
658  LinOp *x) const override;
659 
660 private:
661  std::shared_ptr<ell_type> ell_;
662  std::shared_ptr<coo_type> coo_;
663  std::shared_ptr<strategy_type> strategy_;
664 };
665 
666 
667 } // namespace matrix
668 } // namespace gko
669 
670 
671 #endif // GKO_CORE_MATRIX_HYBRID_HPP_
index_type & ell_col_at(size_type row, size_type idx) noexcept
Returns the idx-th column index of the row-th row in the ell part.
Definition: hybrid.hpp:434
Hybrid & operator=(const Hybrid &other)
Copies data from another Hybrid.
Definition: hybrid.hpp:556
size_type get_num_elems() const noexcept
Returns the number of elements in the Array.
Definition: array.hpp:388
value_type * get_coo_values() noexcept
Returns the values of the coo part.
Definition: hybrid.hpp:459
index_type * get_coo_row_idxs() noexcept
Returns the row indexes of the coo part.
Definition: hybrid.hpp:497
imbalance_bounded_limit(float percent=0.8, float ratio=0.0001)
Creates a imbalance_bounded_limit strategy.
Definition: hybrid.hpp:259
ELL is a matrix format where stride with explicit zeros is used such that all rows have the same numb...
Definition: csr.hpp:53
value_type * get_ell_values() noexcept
Returns the values of the ell part.
Definition: hybrid.hpp:340
constexpr T zero()
Returns the additive identity for T.
Definition: math.hpp:292
size_type get_ell_num_stored_elements_per_row() const noexcept
Returns the number of stored elements per row of ell part.
Definition: hybrid.hpp:378
size_type compute_ell_num_stored_elements_per_row(Array< size_type > *row_nnz) const override
Computes the number of stored elements per row of the ell part.
Definition: hybrid.hpp:295
const ell_type * get_ell() const noexcept
Returns the matrix of the ell part.
Definition: hybrid.hpp:452
size_type compute_ell_num_stored_elements_per_row(Array< size_type > *row_nnz) const override
Computes the number of stored elements per row of the ell part.
Definition: hybrid.hpp:200
size_type get_coo_num_stored_elements() const noexcept
Returns the number of elements explicitly stored in the coo part.
Definition: hybrid.hpp:516
size_type get_num_stored_elements() const noexcept
Returns the number of elements explicitly stored in the matrix.
Definition: hybrid.hpp:533
size_type get_ell_stride() const noexcept
Returns the stride of the ell part.
Definition: hybrid.hpp:388
std::size_t size_type
Integral type used for allocation quantities.
Definition: types.hpp:94
index_type * get_ell_col_idxs() noexcept
Returns the column indexes of the ell part.
Definition: hybrid.hpp:359
std::shared_ptr< const Executor > get_executor() const noexcept
Returns the Executor associated with the array.
Definition: array.hpp:413
const value_type * get_const_data() const noexcept
Returns a constant pointer to the block of memory used to store the elements of the Array...
Definition: array.hpp:406
The Ginkgo namespace.
Definition: abstract_factory.hpp:45
const value_type * get_const_ell_values() const noexcept
Returns the values of the ell part.
Definition: hybrid.hpp:349
void read(const mat_data &data) override
Reads a matrix from a matrix_data structure.
index_type * get_coo_col_idxs() noexcept
Returns the column indexes of the coo part.
Definition: hybrid.hpp:478
imbalance_limit(float percent=0.8)
Creates a imbalance_limit strategy.
Definition: hybrid.hpp:225
size_type compute_ell_num_stored_elements_per_row(Array< size_type > *row_nnz) const override
Computes the number of stored elements per row of the ell part.
Definition: hybrid.hpp:231
std::shared_ptr< strategy_type > get_strategy() const noexcept
Returns the strategy.
Definition: hybrid.hpp:544
strategy_type is to decide how to set the hybrid config.
Definition: hybrid.hpp:95
minimal_storage_limit is a stratgy_type which decides the number of stored elements per row of the el...
Definition: hybrid.hpp:284
column_limit is a strategy_type which decides the number of stored elements per row of the ell part b...
Definition: hybrid.hpp:189
strategy_type()
Creates a strategy_type.
Definition: hybrid.hpp:100
size_type compute_ell_num_stored_elements_per_row(Array< size_type > *row_nnz) const override
Computes the number of stored elements per row of the ell part.
Definition: hybrid.hpp:317
imbalance_bounded_limit is a stratgy_type which decides the number of stored elements per row of the ...
Definition: hybrid.hpp:254
Dense is a matrix format which explicitly stores all values of the matrix.
Definition: coo.hpp:55
Definition: lin_op.hpp:134
The EnableLinOp mixin can be used to provide sensible default implementations of the majority of the ...
Definition: lin_op.hpp:509
void convert_to(result_type *result) const override
Definition: polymorphic_object.hpp:558
void move_to(result_type *result) override
Definition: polymorphic_object.hpp:560
virtual size_type compute_ell_num_stored_elements_per_row(Array< size_type > *row_nnz) const =0
Computes the number of stored elements per row of the ell part.
void compute_hybrid_config(const Array< size_type > &row_nnz, size_type *ell_num_stored_elements_per_row, size_type *coo_nnz)
Computes the config of the Hybrid matrix (ell_num_stored_elements_per_row and coo_nnz).
Definition: hybrid.hpp:117
COO stores a matrix in the coordinate matrix format.
Definition: coo.hpp:73
void write(mat_data &data) const override
Writes a matrix to a matrix_data structure.
automatic is a stratgy_type which decides the number of stored elements per row of the ell part autom...
Definition: hybrid.hpp:310
const index_type * get_const_coo_col_idxs() const noexcept
Returns the column indexes of the coo part.
Definition: hybrid.hpp:487
value_type ell_val_at(size_type row, size_type idx) const noexcept
Returns the idx-th non-zero element of the row-th row in the ell part.
Definition: hybrid.hpp:419
size_type get_ell_num_stored_elements() const noexcept
Returns the number of elements explicitly stored in the ell part.
Definition: hybrid.hpp:395
minimal_storage_limit()
Creates a minimal_storage_limit strategy.
Definition: hybrid.hpp:289
const index_type * get_const_ell_col_idxs() const noexcept
Returns the column indexes of the ell part.
Definition: hybrid.hpp:368
const size_type get_coo_nnz() const noexcept
Returns the number of nonzeros of the coo part.
Definition: hybrid.hpp:146
column_limit(size_type num_column=0)
Creates a column_limit strategy.
Definition: hybrid.hpp:196
value_type & ell_val_at(size_type row, size_type idx) noexcept
Returns the idx-th non-zero element of the row-th row in the ell part.
Definition: hybrid.hpp:411
const coo_type * get_coo() const noexcept
Returns the matrix of the coo part.
Definition: hybrid.hpp:526
const value_type * get_const_coo_values() const noexcept
Returns the values of the coo part.
Definition: hybrid.hpp:468
value_type * get_data() noexcept
Returns a pointer to the block of memory used to store the elements of the Array. ...
Definition: array.hpp:397
const index_type * get_const_coo_row_idxs() const noexcept
Returns the row indexes of the coo part.
Definition: hybrid.hpp:506
size_type compute_ell_num_stored_elements_per_row(Array< size_type > *row_nnz) const override
Computes the number of stored elements per row of the ell part.
Definition: hybrid.hpp:263
const size_type get_ell_num_stored_elements_per_row() const noexcept
Returns the number of stored elements per row of the ell part.
Definition: hybrid.hpp:136
This structure is used as an intermediate data type to store a sparse matrix.
Definition: matrix_data.hpp:102
HYBRID is a matrix format which splits the matrix into ELLPACK and COO format.
Definition: dense.hpp:63
imbalance_limit is a strategy_type which decides the number of stored elements per row of the ell par...
Definition: hybrid.hpp:217
automatic()
Creates an automatic strategy.
Definition: hybrid.hpp:315
index_type ell_col_at(size_type row, size_type idx) const noexcept
Returns the idx-th column index of the row-th row in the ell part.
Definition: hybrid.hpp:442