Ginkgo  Generated from pipelines/2171896597 branch based on develop. Ginkgo version 1.11.0
A numerical linear algebra library targeting many-core architectures
jacobi.hpp
1 // SPDX-FileCopyrightText: 2017 - 2025 The Ginkgo authors
2 //
3 // SPDX-License-Identifier: BSD-3-Clause
4 
5 #ifndef GKO_PUBLIC_CORE_PRECONDITIONER_JACOBI_HPP_
6 #define GKO_PUBLIC_CORE_PRECONDITIONER_JACOBI_HPP_
7 
8 
9 #include <ginkgo/core/base/array.hpp>
10 #include <ginkgo/core/base/lin_op.hpp>
11 #include <ginkgo/core/config/config.hpp>
12 #include <ginkgo/core/config/registry.hpp>
13 #include <ginkgo/core/matrix/csr.hpp>
14 #include <ginkgo/core/matrix/dense.hpp>
15 #include <ginkgo/core/matrix/diagonal.hpp>
16 
17 
18 namespace gko {
24 namespace preconditioner {
25 
26 
27 // TODO: replace this with a custom accessor
36 template <typename IndexType>
39 
41  IndexType group_offset, uint32 group_power)
45  {}
46 
50  IndexType block_offset;
51 
55  IndexType group_offset;
56 
63 
69  GKO_ATTRIBUTES IndexType get_group_size() const noexcept
70  {
71  return one<IndexType>() << group_power;
72  }
73 
86  GKO_ATTRIBUTES size_type
87  compute_storage_space(size_type num_blocks) const noexcept
88  {
89  return (num_blocks + 1 == size_type{0})
90  ? size_type{0}
91  : ceildiv(num_blocks, this->get_group_size()) * group_offset;
92  }
93 
101  GKO_ATTRIBUTES IndexType get_group_offset(IndexType block_id) const noexcept
102  {
103  return group_offset * (block_id >> group_power);
104  }
105 
113  GKO_ATTRIBUTES IndexType get_block_offset(IndexType block_id) const noexcept
114  {
115  return block_offset * (block_id & (this->get_group_size() - 1));
116  }
117 
125  GKO_ATTRIBUTES IndexType
126  get_global_block_offset(IndexType block_id) const noexcept
127  {
128  return this->get_group_offset(block_id) +
129  this->get_block_offset(block_id);
130  }
131 
137  GKO_ATTRIBUTES IndexType get_stride() const noexcept
138  {
139  return block_offset << group_power;
140  }
141 };
142 
143 
186 template <typename ValueType = default_precision, typename IndexType = int32>
187 class Jacobi : public EnableLinOp<Jacobi<ValueType, IndexType>>,
188  public ConvertibleTo<matrix::Dense<ValueType>>,
189  public WritableToMatrixData<ValueType, IndexType>,
190  public Transposable {
191  friend class EnableLinOp<Jacobi>;
192  friend class EnablePolymorphicObject<Jacobi, LinOp>;
193  GKO_ASSERT_SUPPORTED_VALUE_AND_INDEX_TYPE;
194 
195 public:
200  using value_type = ValueType;
201  using index_type = IndexType;
204 
213  size_type get_num_blocks() const noexcept { return num_blocks_; }
214 
224  const noexcept
225  {
226  return storage_scheme_;
227  }
228 
240  const value_type* get_blocks() const noexcept
241  {
242  return blocks_.get_const_data();
243  }
244 
255  {
256  return conditioning_.get_const_data();
257  }
258 
265  {
266  return blocks_.get_size();
267  }
268 
269  void convert_to(matrix::Dense<value_type>* result) const override;
270 
271  void move_to(matrix::Dense<value_type>* result) override;
272 
273  void write(mat_data& data) const override;
274 
275  std::unique_ptr<LinOp> transpose() const override;
276 
277  std::unique_ptr<LinOp> conj_transpose() const override;
278 
283  Jacobi& operator=(const Jacobi& other);
284 
290  Jacobi& operator=(Jacobi&& other);
291 
296  Jacobi(const Jacobi& other);
297 
303  Jacobi(Jacobi&& other);
304 
306  {
315  uint32 GKO_FACTORY_PARAMETER_SCALAR(max_block_size, 32u);
316 
326  uint32 GKO_FACTORY_PARAMETER_SCALAR(max_block_stride, 0u);
327 
345  bool GKO_FACTORY_PARAMETER_SCALAR(skip_sorting, false);
346 
373  nullptr);
374 
386  bool GKO_FACTORY_PARAMETER_SCALAR(aggregate_l1, false);
387 
388  private:
389  // See documentation of storage_optimization parameter for details about
390  // this class
391  struct storage_optimization_type {
392  storage_optimization_type(precision_reduction p)
393  : is_block_wise{false}, of_all_blocks{p}
394  {}
395 
396  storage_optimization_type(
397  const array<precision_reduction>& block_wise_opt)
398  : is_block_wise{block_wise_opt.get_size() > 0},
399  block_wise{block_wise_opt}
400  {}
401 
402  storage_optimization_type(
403  array<precision_reduction>&& block_wise_opt)
404  : is_block_wise{block_wise_opt.get_size() > 0},
405  block_wise{std::move(block_wise_opt)}
406  {}
407 
408  operator precision_reduction() { return of_all_blocks; }
409 
410  bool is_block_wise;
411  precision_reduction of_all_blocks;
413  };
414 
415  public:
483  storage_optimization_type GKO_FACTORY_PARAMETER_VECTOR(
484  storage_optimization, precision_reduction(0, 0));
485 
513  accuracy, static_cast<remove_complex<value_type>>(1e-1));
514  };
517 
534  static parameters_type parse(
535  const config::pnode& config, const config::registry& context,
536  const config::type_descriptor& td_for_child =
537  config::make_type_descriptor<ValueType, IndexType>());
538 
539 protected:
545  explicit Jacobi(std::shared_ptr<const Executor> exec)
546  : EnableLinOp<Jacobi>(exec),
547  num_blocks_{},
548  blocks_(exec),
549  conditioning_(exec)
550  {
551  parameters_.block_pointers.set_executor(exec);
552  parameters_.storage_optimization.block_wise.set_executor(exec);
553  }
554 
562  explicit Jacobi(const Factory* factory,
563  std::shared_ptr<const LinOp> system_matrix)
564  : EnableLinOp<Jacobi>(factory->get_executor(),
565  gko::transpose(system_matrix->get_size())),
566  parameters_{factory->get_parameters()},
567  storage_scheme_{this->compute_storage_scheme(
568  parameters_.max_block_size, parameters_.max_block_stride)},
569  num_blocks_{parameters_.block_pointers.get_size() - 1},
570  blocks_(factory->get_executor(),
571  storage_scheme_.compute_storage_space(
572  parameters_.block_pointers.get_size() - 1)),
573  conditioning_(factory->get_executor())
574  {
575  parameters_.block_pointers.set_executor(this->get_executor());
576  parameters_.storage_optimization.block_wise.set_executor(
577  this->get_executor());
578  this->generate(system_matrix.get(), parameters_.skip_sorting);
579  }
580 
589  block_interleaved_storage_scheme<index_type> compute_storage_scheme(
590  uint32 max_block_size, uint32 param_max_block_stride)
591  {
592  uint32 default_block_stride = 32;
593  // If the executor is hip, the warp size is 32 or 64
594  if (auto hip_exec = std::dynamic_pointer_cast<const gko::HipExecutor>(
595  this->get_executor())) {
596  default_block_stride = hip_exec->get_warp_size();
597  }
598  uint32 max_block_stride = default_block_stride;
599  if (param_max_block_stride != 0) {
600  // if parameter max_block_stride is not zero, set max_block_stride =
601  // param_max_block_stride
602  max_block_stride = param_max_block_stride;
603  if (this->get_executor() != this->get_executor()->get_master() &&
604  max_block_stride != default_block_stride) {
605  // only support the default value on the gpu device
606  GKO_NOT_SUPPORTED(this);
607  }
608  }
609  if (parameters_.max_block_size > max_block_stride ||
610  parameters_.max_block_size < 1) {
611  GKO_NOT_SUPPORTED(this);
612  }
613  const auto group_size = static_cast<uint32>(
614  max_block_stride / get_superior_power(uint32{2}, max_block_size));
615  const auto block_offset = max_block_size;
616  const auto block_stride = group_size * block_offset;
617  const auto group_offset = max_block_size * block_stride;
618  return {static_cast<index_type>(block_offset),
619  static_cast<index_type>(group_offset),
620  get_significant_bit(group_size)};
621  }
622 
632  void generate(const LinOp* system_matrix, bool skip_sorting);
633 
641  void detect_blocks(const matrix::Csr<ValueType, IndexType>* system_matrix);
642 
643  void apply_impl(const LinOp* b, LinOp* x) const override;
644 
645  void apply_impl(const LinOp* alpha, const LinOp* b, const LinOp* beta,
646  LinOp* x) const override;
647 
648 private:
649  block_interleaved_storage_scheme<index_type> storage_scheme_{};
650  size_type num_blocks_;
651  array<value_type> blocks_;
652  array<remove_complex<value_type>> conditioning_;
653 };
654 
655 
656 } // namespace preconditioner
657 } // namespace gko
658 
659 
660 #endif // GKO_PUBLIC_CORE_PRECONDITIONER_JACOBI_HPP_
gko::preconditioner::Jacobi::Factory
Definition: jacobi.hpp:515
gko::preconditioner::Jacobi::parse
static parameters_type parse(const config::pnode &config, const config::registry &context, const config::type_descriptor &td_for_child=config::make_type_descriptor< ValueType, IndexType >())
Create the parameters from the property_tree.
gko::array::set_executor
void set_executor(std::shared_ptr< const Executor > exec)
Changes the Executor of the array, moving the allocated data to the new Executor.
Definition: array.hpp:714
gko::precision_reduction
This class is used to encode storage precisions of low precision algorithms.
Definition: types.hpp:239
gko::preconditioner::block_interleaved_storage_scheme::block_offset
IndexType block_offset
The offset between consecutive blocks within the group.
Definition: jacobi.hpp:50
gko::preconditioner::Jacobi::parameters_type::skip_sorting
bool skip_sorting
true means it is known that the matrix given to this factory will be sorted first by row,...
Definition: jacobi.hpp:345
gko::config::pnode
pnode describes a tree of properties.
Definition: property_tree.hpp:28
gko::LinOp
Definition: lin_op.hpp:117
gko::preconditioner::block_interleaved_storage_scheme::get_group_offset
IndexType get_group_offset(IndexType block_id) const noexcept
Returns the offset of the group belonging to the block with the given ID.
Definition: jacobi.hpp:101
gko::matrix::Dense< value_type >
gko::preconditioner::block_interleaved_storage_scheme::get_group_size
IndexType get_group_size() const noexcept
Returns the number of elements in the group.
Definition: jacobi.hpp:69
gko::preconditioner::Jacobi::get_num_blocks
size_type get_num_blocks() const noexcept
Returns the number of blocks of the operator.
Definition: jacobi.hpp:213
gko::log::profile_event_category::factory
LinOpFactory events.
gko::Transposable
Linear operators which support transposition should implement the Transposable interface.
Definition: lin_op.hpp:433
gko::get_significant_bit
constexpr uint32 get_significant_bit(const T &n, uint32 hint=0u) noexcept
Returns the position of the most significant bit of the number.
Definition: math.hpp:1057
gko::size_type
std::size_t size_type
Integral type used for allocation quantities.
Definition: types.hpp:90
gko::preconditioner::block_interleaved_storage_scheme::get_stride
IndexType get_stride() const noexcept
Returns the stride between columns of the block.
Definition: jacobi.hpp:137
GKO_FACTORY_PARAMETER_SCALAR
#define GKO_FACTORY_PARAMETER_SCALAR(_name, _default)
Creates a scalar factory parameter in the factory parameters structure.
Definition: abstract_factory.hpp:445
gko::preconditioner::Jacobi::move_to
void move_to(matrix::Dense< value_type > *result) override
Converts the implementer to an object of type result_type by moving data from this object.
gko::config::type_descriptor
This class describes the value and index types to be used when building a Ginkgo type from a configur...
Definition: type_descriptor.hpp:39
gko::preconditioner::Jacobi::parameters_type::max_block_stride
uint32 max_block_stride
Stride between two columns of a block (as number of elements).
Definition: jacobi.hpp:326
gko
The Ginkgo namespace.
Definition: abstract_factory.hpp:20
gko::preconditioner::block_interleaved_storage_scheme::group_offset
IndexType group_offset
The offset between two block groups.
Definition: jacobi.hpp:55
gko::get_superior_power
constexpr T get_superior_power(const T &base, const T &limit, const T &hint=T{1}) noexcept
Returns the smallest power of base not smaller than limit.
Definition: math.hpp:1075
gko::preconditioner::Jacobi::convert_to
void convert_to(matrix::Dense< value_type > *result) const override
Converts the implementer to an object of type result_type.
gko::preconditioner::Jacobi
A block-Jacobi preconditioner is a block-diagonal linear operator, obtained by inverting the diagonal...
Definition: jacobi.hpp:187
gko::array< index_type >
gko::preconditioner::block_interleaved_storage_scheme::group_power
uint32 group_power
Then base 2 power of the group.
Definition: jacobi.hpp:62
gko::uint32
std::uint32_t uint32
32-bit unsigned integral type.
Definition: types.hpp:130
gko::matrix_data
This structure is used as an intermediate data type to store a sparse matrix.
Definition: matrix_data.hpp:126
gko::preconditioner::Jacobi::operator=
Jacobi & operator=(const Jacobi &other)
Copy-assigns a Jacobi preconditioner.
GKO_ENABLE_LIN_OP_FACTORY
#define GKO_ENABLE_LIN_OP_FACTORY(_lin_op, _parameters_name, _factory_name)
This macro will generate a default implementation of a LinOpFactory for the LinOp subclass it is defi...
Definition: lin_op.hpp:1017
gko::preconditioner::Jacobi::parameters_type::block_pointers
gko::array< index_type > block_pointers
Starting (row / column) indexes of individual blocks.
Definition: jacobi.hpp:373
gko::preconditioner::Jacobi::get_conditioning
const remove_complex< value_type > * get_conditioning() const noexcept
Returns an array of 1-norm condition numbers of the blocks.
Definition: jacobi.hpp:254
gko::preconditioner::Jacobi::write
void write(mat_data &data) const override
Writes a matrix to a matrix_data structure.
gko::preconditioner::Jacobi::get_blocks
const value_type * get_blocks() const noexcept
Returns the pointer to the memory used for storing the block data.
Definition: jacobi.hpp:240
gko::preconditioner::block_interleaved_storage_scheme::get_global_block_offset
IndexType get_global_block_offset(IndexType block_id) const noexcept
Returns the offset of the block with the given ID.
Definition: jacobi.hpp:126
gko::WritableToMatrixData
A LinOp implementing this interface can write its data to a matrix_data structure.
Definition: lin_op.hpp:660
gko::preconditioner::Jacobi::get_num_stored_elements
size_type get_num_stored_elements() const noexcept
Returns the number of elements explicitly stored in the matrix.
Definition: jacobi.hpp:264
gko::preconditioner::Jacobi::parameters_type::storage_optimization
storage_optimization_type storage_optimization
The precisions to use for the blocks of the matrix.
Definition: jacobi.hpp:484
gko::preconditioner::block_interleaved_storage_scheme
Defines the parameters of the interleaved block storage scheme used by block-Jacobi blocks.
Definition: jacobi.hpp:37
gko::preconditioner::Jacobi::parameters_type::max_block_size
uint32 max_block_size
Maximal size of diagonal blocks.
Definition: jacobi.hpp:315
gko::ConvertibleTo
ConvertibleTo interface is used to mark that the implementer can be converted to the object of Result...
Definition: polymorphic_object.hpp:479
gko::preconditioner::Jacobi::Jacobi
Jacobi(const Jacobi &other)
Copy-constructs a Jacobi preconditioner.
gko::preconditioner::Jacobi::transpose
std::unique_ptr< LinOp > transpose() const override
Returns a LinOp representing the transpose of the Transposable object.
gko::config::registry
This class stores additional context for creating Ginkgo objects from configuration files.
Definition: registry.hpp:167
gko::preconditioner::Jacobi::conj_transpose
std::unique_ptr< LinOp > conj_transpose() const override
Returns a LinOp representing the conjugate transpose of the Transposable object.
GKO_ENABLE_BUILD_METHOD
#define GKO_ENABLE_BUILD_METHOD(_factory_name)
Defines a build method for the factory, simplifying its construction by removing the repetitive typin...
Definition: abstract_factory.hpp:394
gko::preconditioner::Jacobi::get_storage_scheme
const block_interleaved_storage_scheme< index_type > & get_storage_scheme() const noexcept
Returns the storage scheme used for storing Jacobi blocks.
Definition: jacobi.hpp:223
GKO_CREATE_FACTORY_PARAMETERS
#define GKO_CREATE_FACTORY_PARAMETERS(_parameters_name, _factory_name)
This Macro will generate a new type containing the parameters for the factory _factory_name.
Definition: abstract_factory.hpp:280
gko::array::get_const_data
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:696
GKO_FACTORY_PARAMETER_VECTOR
#define GKO_FACTORY_PARAMETER_VECTOR(_name,...)
Creates a vector factory parameter in the factory parameters structure.
Definition: abstract_factory.hpp:461
gko::ceildiv
constexpr int64 ceildiv(int64 num, int64 den)
Performs integer division with rounding up.
Definition: math.hpp:614
gko::preconditioner::block_interleaved_storage_scheme::compute_storage_space
size_type compute_storage_space(size_type num_blocks) const noexcept
Computes the storage space required for the requested number of blocks.
Definition: jacobi.hpp:87
gko::PolymorphicObject::get_executor
std::shared_ptr< const Executor > get_executor() const noexcept
Returns the Executor of the object.
Definition: polymorphic_object.hpp:243
gko::array::get_size
size_type get_size() const noexcept
Returns the number of elements in the array.
Definition: array.hpp:670
gko::LinOp::get_size
const dim< 2 > & get_size() const noexcept
Returns the size of the operator.
Definition: lin_op.hpp:210
gko::remove_complex
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:264
gko::EnableLinOp
The EnableLinOp mixin can be used to provide sensible default implementations of the majority of the ...
Definition: lin_op.hpp:877
gko::LinOp::LinOp
LinOp(const LinOp &)=default
Copy-constructs a LinOp.
gko::preconditioner::block_interleaved_storage_scheme::get_block_offset
IndexType get_block_offset(IndexType block_id) const noexcept
Returns the offset of the block with the given ID within its group.
Definition: jacobi.hpp:113
gko::EnablePolymorphicObject
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition: polymorphic_object.hpp:667