Ginkgo Generated from branch based on master. Ginkgo version 1.7.0
A numerical linear algebra library targeting many-core architectures
Loading...
Searching...
No Matches
hybrid.hpp
1/*******************************<GINKGO LICENSE>******************************
2Copyright (c) 2017-2023, the Ginkgo authors
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions
7are met:
8
91. Redistributions of source code must retain the above copyright
10notice, this list of conditions and the following disclaimer.
11
122. Redistributions in binary form must reproduce the above copyright
13notice, this list of conditions and the following disclaimer in the
14documentation and/or other materials provided with the distribution.
15
163. Neither the name of the copyright holder nor the names of its
17contributors may be used to endorse or promote products derived from
18this software without specific prior written permission.
19
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
21IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31******************************<GINKGO LICENSE>*******************************/
32
33#ifndef GKO_PUBLIC_CORE_MATRIX_HYBRID_HPP_
34#define GKO_PUBLIC_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/csr.hpp>
44#include <ginkgo/core/matrix/ell.hpp>
45
46
47namespace gko {
48namespace matrix {
49
50
51template <typename ValueType>
52class Dense;
53
54template <typename ValueType, typename IndexType>
55class Csr;
56
57
70template <typename ValueType = default_precision, typename IndexType = int32>
71class Hybrid
72 : public EnableLinOp<Hybrid<ValueType, IndexType>>,
73 public EnableCreateMethod<Hybrid<ValueType, IndexType>>,
74 public ConvertibleTo<Hybrid<next_precision<ValueType>, IndexType>>,
75 public ConvertibleTo<Dense<ValueType>>,
76 public ConvertibleTo<Csr<ValueType, IndexType>>,
77 public DiagonalExtractable<ValueType>,
78 public ReadableFromMatrixData<ValueType, IndexType>,
79 public WritableToMatrixData<ValueType, IndexType>,
81 remove_complex<Hybrid<ValueType, IndexType>>> {
82 friend class EnableCreateMethod<Hybrid>;
84 friend class Dense<ValueType>;
85 friend class Csr<ValueType, IndexType>;
86 friend class Hybrid<to_complex<ValueType>, IndexType>;
87
88
89public:
90 using EnableLinOp<Hybrid>::convert_to;
91 using EnableLinOp<Hybrid>::move_to;
92 using ConvertibleTo<
93 Hybrid<next_precision<ValueType>, IndexType>>::convert_to;
94 using ConvertibleTo<Hybrid<next_precision<ValueType>, IndexType>>::move_to;
95 using ConvertibleTo<Dense<ValueType>>::convert_to;
96 using ConvertibleTo<Dense<ValueType>>::move_to;
99 using ReadableFromMatrixData<ValueType, IndexType>::read;
100
101 using value_type = ValueType;
102 using index_type = IndexType;
107 using absolute_type = remove_complex<Hybrid>;
108
109
120 public:
125 : ell_num_stored_elements_per_row_(zero<size_type>()),
126 coo_nnz_(zero<size_type>())
127 {}
128
144 {
145 array<size_type> ref_row_nnz(row_nnz.get_executor()->get_master(),
146 row_nnz.get_num_elems());
148 ell_num_stored_elements_per_row_ =
149 this->compute_ell_num_stored_elements_per_row(&ref_row_nnz);
150 coo_nnz_ = this->compute_coo_nnz(ref_row_nnz);
151 *ell_num_stored_elements_per_row = ell_num_stored_elements_per_row_;
152 *coo_nnz = coo_nnz_;
153 }
154
161 {
162 return ell_num_stored_elements_per_row_;
163 }
164
170 size_type get_coo_nnz() const noexcept { return coo_nnz_; }
171
180 array<size_type>* row_nnz) const = 0;
181
182 protected:
191 size_type compute_coo_nnz(const array<size_type>& row_nnz) const
192 {
193 size_type coo_nnz = 0;
194 auto row_nnz_val = row_nnz.get_const_data();
195 for (size_type i = 0; i < row_nnz.get_num_elems(); i++) {
196 if (row_nnz_val[i] > ell_num_stored_elements_per_row_) {
197 coo_nnz +=
198 row_nnz_val[i] - ell_num_stored_elements_per_row_;
199 }
200 }
201 return coo_nnz;
202 }
203
204 private:
205 size_type ell_num_stored_elements_per_row_;
206 size_type coo_nnz_;
207 };
208
214 public:
221 : num_columns_(num_column)
222 {}
223
225 array<size_type>* row_nnz) const override
226 {
227 return num_columns_;
228 }
229
235 auto get_num_columns() const { return num_columns_; }
236
237 private:
238 size_type num_columns_;
239 };
240
249 public:
256 explicit imbalance_limit(double percent = 0.8) : percent_(percent)
257 {
258 percent_ = std::min(percent_, 1.0);
259 percent_ = std::max(percent_, 0.0);
260 }
261
263 array<size_type>* row_nnz) const override
264 {
265 auto row_nnz_val = row_nnz->get_data();
266 auto num_rows = row_nnz->get_num_elems();
267 if (num_rows == 0) {
268 return 0;
269 }
270 std::sort(row_nnz_val, row_nnz_val + num_rows);
271 if (percent_ < 1) {
272 auto percent_pos = static_cast<size_type>(num_rows * percent_);
273 return row_nnz_val[percent_pos];
274 } else {
275 return row_nnz_val[num_rows - 1];
276 }
277 }
278
284 auto get_percentage() const { return percent_; }
285
286 private:
287 double percent_;
288 };
289
296 public:
300 imbalance_bounded_limit(double percent = 0.8, double ratio = 0.0001)
301 : strategy_(imbalance_limit(percent)), ratio_(ratio)
302 {}
303
305 array<size_type>* row_nnz) const override
306 {
307 auto num_rows = row_nnz->get_num_elems();
308 auto ell_cols =
310 return std::min(ell_cols,
311 static_cast<size_type>(num_rows * ratio_));
312 }
313
319 auto get_percentage() const { return strategy_.get_percentage(); }
320
326 auto get_ratio() const { return ratio_; }
327
328 private:
329 imbalance_limit strategy_;
330 double ratio_;
331 };
332
333
340 public:
345 : strategy_(
347 (sizeof(ValueType) + 2 * sizeof(IndexType))))
348 {}
349
355
361 auto get_percentage() const { return strategy_.get_percentage(); }
362
363 private:
364 imbalance_limit strategy_;
365 };
366
367
372 class automatic : public strategy_type {
373 public:
377 automatic() : strategy_(imbalance_bounded_limit(1.0 / 3.0, 0.001)) {}
378
384
385 private:
386 imbalance_bounded_limit strategy_;
387 };
388
389 friend class Hybrid<next_precision<ValueType>, IndexType>;
390
391 void convert_to(
392 Hybrid<next_precision<ValueType>, IndexType>* result) const override;
393
394 void move_to(Hybrid<next_precision<ValueType>, IndexType>* result) override;
395
396 void convert_to(Dense<ValueType>* other) const override;
397
398 void move_to(Dense<ValueType>* other) override;
399
400 void convert_to(Csr<ValueType, IndexType>* other) const override;
401
402 void move_to(Csr<ValueType, IndexType>* other) override;
403
404 void read(const mat_data& data) override;
405
406 void read(const device_mat_data& data) override;
407
408 void read(device_mat_data&& data) override;
409
410 void write(mat_data& data) const override;
411
412 std::unique_ptr<Diagonal<ValueType>> extract_diagonal() const override;
413
414 std::unique_ptr<absolute_type> compute_absolute() const override;
415
417
423 value_type* get_ell_values() noexcept { return ell_->get_values(); }
424
433 {
434 return ell_->get_const_values();
435 }
436
442 index_type* get_ell_col_idxs() noexcept { return ell_->get_col_idxs(); }
443
452 {
453 return ell_->get_const_col_idxs();
454 }
455
462 {
463 return ell_->get_num_stored_elements_per_row();
464 }
465
471 size_type get_ell_stride() const noexcept { return ell_->get_stride(); }
472
479 {
480 return ell_->get_num_stored_elements();
481 }
482
494 value_type& ell_val_at(size_type row, size_type idx) noexcept
495 {
496 return ell_->val_at(row, idx);
497 }
498
502 value_type ell_val_at(size_type row, size_type idx) const noexcept
503 {
504 return ell_->val_at(row, idx);
505 }
506
517 index_type& ell_col_at(size_type row, size_type idx) noexcept
518 {
519 return ell_->col_at(row, idx);
520 }
521
525 index_type ell_col_at(size_type row, size_type idx) const noexcept
526 {
527 return ell_->col_at(row, idx);
528 }
529
535 const ell_type* get_ell() const noexcept { return ell_.get(); }
536
542 value_type* get_coo_values() noexcept { return coo_->get_values(); }
543
552 {
553 return coo_->get_const_values();
554 }
555
561 index_type* get_coo_col_idxs() noexcept { return coo_->get_col_idxs(); }
562
571 {
572 return coo_->get_const_col_idxs();
573 }
574
580 index_type* get_coo_row_idxs() noexcept { return coo_->get_row_idxs(); }
581
590 {
591 return coo_->get_const_row_idxs();
592 }
593
600 {
601 return coo_->get_num_stored_elements();
602 }
603
609 const coo_type* get_coo() const noexcept { return coo_.get(); }
610
617 {
618 return coo_->get_num_stored_elements() +
619 ell_->get_num_stored_elements();
620 }
621
627 std::shared_ptr<strategy_type> get_strategy() const noexcept
628 {
629 return strategy_;
630 }
631
639 template <typename HybType>
640 std::shared_ptr<typename HybType::strategy_type> get_strategy() const;
641
647
654
659 Hybrid(const Hybrid&);
660
667
668protected:
677 Hybrid(
678 std::shared_ptr<const Executor> exec,
679 std::shared_ptr<strategy_type> strategy = std::make_shared<automatic>())
680 : Hybrid(std::move(exec), dim<2>{}, std::move(strategy))
681 {}
682
692 Hybrid(
693 std::shared_ptr<const Executor> exec, const dim<2>& size,
694 std::shared_ptr<strategy_type> strategy = std::make_shared<automatic>())
695 : Hybrid(std::move(exec), size, size[1], std::move(strategy))
696 {}
697
708 Hybrid(
709 std::shared_ptr<const Executor> exec, const dim<2>& size,
711 std::shared_ptr<strategy_type> strategy = std::make_shared<automatic>())
712 : Hybrid(std::move(exec), size, num_stored_elements_per_row, size[0],
713 {}, std::move(strategy))
714 {}
715
726 Hybrid(std::shared_ptr<const Executor> exec, const dim<2>& size,
728 std::shared_ptr<strategy_type> strategy)
729 : Hybrid(std::move(exec), size, num_stored_elements_per_row, stride, {},
730 std::move(strategy))
731 {}
732
744 Hybrid(
745 std::shared_ptr<const Executor> exec, const dim<2>& size,
748 std::shared_ptr<strategy_type> strategy = std::make_shared<automatic>())
749 : EnableLinOp<Hybrid>(exec, size),
750 ell_(ell_type::create(exec, size, num_stored_elements_per_row,
751 stride)),
752 coo_(coo_type::create(exec, size, num_nonzeros)),
753 strategy_(std::move(strategy))
754 {}
755
766 void resize(dim<2> new_size, size_type ell_row_nnz, size_type coo_nnz);
767
768 void apply_impl(const LinOp* b, LinOp* x) const override;
769
770 void apply_impl(const LinOp* alpha, const LinOp* b, const LinOp* beta,
771 LinOp* x) const override;
772
773private:
774 std::unique_ptr<ell_type> ell_;
775 std::unique_ptr<coo_type> coo_;
776 std::shared_ptr<strategy_type> strategy_;
777};
778
779
780template <typename ValueType, typename IndexType>
781template <typename HybType>
782std::shared_ptr<typename HybType::strategy_type>
784{
785 static_assert(
786 std::is_same<HybType, Hybrid<typename HybType::value_type,
787 typename HybType::index_type>>::value,
788 "The given `HybType` type must be of type `matrix::Hybrid`!");
789
790 std::shared_ptr<typename HybType::strategy_type> strategy;
791 if (std::dynamic_pointer_cast<automatic>(strategy_)) {
792 strategy = std::make_shared<typename HybType::automatic>();
793 } else if (auto temp = std::dynamic_pointer_cast<minimal_storage_limit>(
794 strategy_)) {
795 // minimal_storage_limit is related to ValueType and IndexType size.
796 if (sizeof(value_type) == sizeof(typename HybType::value_type) &&
797 sizeof(index_type) == sizeof(typename HybType::index_type)) {
798 strategy =
799 std::make_shared<typename HybType::minimal_storage_limit>();
800 } else {
801 strategy = std::make_shared<typename HybType::imbalance_limit>(
802 temp->get_percentage());
803 }
804 } else if (auto temp = std::dynamic_pointer_cast<imbalance_bounded_limit>(
805 strategy_)) {
806 strategy = std::make_shared<typename HybType::imbalance_bounded_limit>(
807 temp->get_percentage(), temp->get_ratio());
808 } else if (auto temp =
809 std::dynamic_pointer_cast<imbalance_limit>(strategy_)) {
810 strategy = std::make_shared<typename HybType::imbalance_limit>(
811 temp->get_percentage());
812 } else if (auto temp = std::dynamic_pointer_cast<column_limit>(strategy_)) {
813 strategy = std::make_shared<typename HybType::column_limit>(
814 temp->get_num_columns());
815 } else {
816 GKO_NOT_SUPPORTED(strategy_);
817 }
818 return strategy;
819}
820
821
822} // namespace matrix
823} // namespace gko
824
825
826#endif // GKO_PUBLIC_CORE_MATRIX_HYBRID_HPP_
ConvertibleTo interface is used to mark that the implementer can be converted to the object of Result...
Definition polymorphic_object.hpp:499
The diagonal of a LinOp implementing this interface can be extracted.
Definition lin_op.hpp:772
The EnableAbsoluteComputation mixin provides the default implementations of compute_absolute_linop an...
Definition lin_op.hpp:823
This mixin implements a static create() method on ConcreteType that dynamically allocates the memory,...
Definition polymorphic_object.hpp:776
The EnableLinOp mixin can be used to provide sensible default implementations of the majority of the ...
Definition lin_op.hpp:908
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition polymorphic_object.hpp:691
Definition lin_op.hpp:146
A LinOp implementing this interface can read its data from a matrix_data structure.
Definition lin_op.hpp:634
A LinOp implementing this interface can write its data to a matrix_data structure.
Definition lin_op.hpp:689
An array is a container which encapsulates fixed-sized arrays, stored on the Executor tied to the arr...
Definition array.hpp:187
This type is a device-side equivalent to matrix_data.
Definition device_matrix_data.hpp:63
COO stores a matrix in the coordinate matrix format.
Definition coo.hpp:87
CSR is a matrix format which stores only the nonzero coefficients by compressing each row of the matr...
Definition csr.hpp:146
Dense is a matrix format which explicitly stores all values of the matrix.
Definition dense.hpp:136
ELL is a matrix format where stride with explicit zeros is used such that all rows have the same numb...
Definition ell.hpp:89
automatic is a strategy_type which decides the number of stored elements per row of the ell part auto...
Definition hybrid.hpp:372
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:379
automatic()
Creates an automatic strategy.
Definition hybrid.hpp:377
column_limit is a strategy_type which decides the number of stored elements per row of the ell part b...
Definition hybrid.hpp:213
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:224
column_limit(size_type num_column=0)
Creates a column_limit strategy.
Definition hybrid.hpp:220
auto get_num_columns() const
Get the number of columns limit.
Definition hybrid.hpp:235
imbalance_bounded_limit is a strategy_type which decides the number of stored elements per row of the...
Definition hybrid.hpp:295
auto get_percentage() const
Get the percent setting.
Definition hybrid.hpp:319
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:304
imbalance_bounded_limit(double percent=0.8, double ratio=0.0001)
Creates a imbalance_bounded_limit strategy.
Definition hybrid.hpp:300
auto get_ratio() const
Get the ratio setting.
Definition hybrid.hpp:326
imbalance_limit is a strategy_type which decides the number of stored elements per row of the ell par...
Definition hybrid.hpp:248
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:262
auto get_percentage() const
Get the percent setting.
Definition hybrid.hpp:284
imbalance_limit(double percent=0.8)
Creates a imbalance_limit strategy.
Definition hybrid.hpp:256
minimal_storage_limit is a strategy_type which decides the number of stored elements per row of the e...
Definition hybrid.hpp:339
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:350
auto get_percentage() const
Get the percent setting.
Definition hybrid.hpp:361
minimal_storage_limit()
Creates a minimal_storage_limit strategy.
Definition hybrid.hpp:344
strategy_type is to decide how to set the hybrid config.
Definition hybrid.hpp:119
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.
strategy_type()
Creates a strategy_type.
Definition hybrid.hpp:124
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:160
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:141
size_type get_coo_nnz() const noexcept
Returns the number of nonzeros of the coo part.
Definition hybrid.hpp:170
HYBRID is a matrix format which splits the matrix into ELLPACK and COO format.
Definition hybrid.hpp:81
size_type get_num_stored_elements() const noexcept
Returns the number of elements explicitly stored in the matrix.
Definition hybrid.hpp:616
index_type * get_coo_row_idxs() noexcept
Returns the row indexes of the coo part.
Definition hybrid.hpp:580
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:494
size_type get_ell_stride() const noexcept
Returns the stride of the ell part.
Definition hybrid.hpp:471
size_type get_coo_num_stored_elements() const noexcept
Returns the number of elements explicitly stored in the coo part.
Definition hybrid.hpp:599
std::unique_ptr< absolute_type > compute_absolute() const override
Gets the AbsoluteLinOp.
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:525
index_type * get_coo_col_idxs() noexcept
Returns the column indexes of the coo part.
Definition hybrid.hpp:561
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:502
const index_type * get_const_coo_row_idxs() const noexcept
Returns the row indexes of the coo part.
Definition hybrid.hpp:589
Hybrid(Hybrid &&)
Move-assigns a Hybrid matrix.
void write(mat_data &data) const override
Writes a matrix to a matrix_data structure.
const value_type * get_const_ell_values() const noexcept
Returns the values of the ell part.
Definition hybrid.hpp:432
const ell_type * get_ell() const noexcept
Returns the matrix of the ell part.
Definition hybrid.hpp:535
std::unique_ptr< Diagonal< ValueType > > extract_diagonal() const override
Extracts the diagonal entries of the matrix into a vector.
value_type * get_ell_values() noexcept
Returns the values of the ell part.
Definition hybrid.hpp:423
void read(const mat_data &data) override
Reads a matrix from a matrix_data structure.
size_type get_ell_num_stored_elements() const noexcept
Returns the number of elements explicitly stored in the ell part.
Definition hybrid.hpp:478
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:461
const index_type * get_const_coo_col_idxs() const noexcept
Returns the column indexes of the coo part.
Definition hybrid.hpp:570
Hybrid(const Hybrid &)
Copy-assigns a Hybrid matrix.
void read(const device_mat_data &data) override
Reads a matrix from a device_matrix_data structure.
index_type * get_ell_col_idxs() noexcept
Returns the column indexes of the ell part.
Definition hybrid.hpp:442
void compute_absolute_inplace() override
Compute absolute inplace on each element.
const index_type * get_const_ell_col_idxs() const noexcept
Returns the column indexes of the ell part.
Definition hybrid.hpp:451
std::shared_ptr< strategy_type > get_strategy() const noexcept
Returns the strategy.
Definition hybrid.hpp:627
const coo_type * get_coo() const noexcept
Returns the matrix of the coo part.
Definition hybrid.hpp:609
value_type * get_coo_values() noexcept
Returns the values of the coo part.
Definition hybrid.hpp:542
Hybrid & operator=(const Hybrid &)
Copy-assigns a Hybrid matrix.
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:517
const value_type * get_const_coo_values() const noexcept
Returns the values of the coo part.
Definition hybrid.hpp:551
void read(device_mat_data &&data) override
Reads a matrix from a device_matrix_data structure.
Hybrid & operator=(Hybrid &&)
Move-assigns a Hybrid matrix.
The Ginkgo namespace.
Definition abstract_factory.hpp:48
constexpr T one()
Returns the multiplicative identity for T.
Definition math.hpp:803
typename detail::remove_complex_s< T >::type remove_complex
Obtain the type which removed the complex of complex/scalar type or the template parameter of class b...
Definition math.hpp:354
typename detail::next_precision_impl< T >::type next_precision
Obtains the next type in the singly-linked precision list.
Definition math.hpp:490
typename detail::to_complex_s< T >::type to_complex
Obtain the type which adds the complex of complex/scalar type or the template parameter of class by a...
Definition math.hpp:373
constexpr T zero()
Returns the additive identity for T.
Definition math.hpp:775
std::size_t size_type
Integral type used for allocation quantities.
Definition types.hpp:120
A type representing the dimensions of a multidimensional object.
Definition dim.hpp:55
This structure is used as an intermediate data type to store a sparse matrix.
Definition matrix_data.hpp:155