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
jacobi.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_PRECONDITIONER_JACOBI_HPP_
34 #define GKO_CORE_PRECONDITIONER_JACOBI_HPP_
35 
36 
37 #include <ginkgo/core/base/array.hpp>
38 #include <ginkgo/core/base/lin_op.hpp>
39 #include <ginkgo/core/matrix/dense.hpp>
40 
41 
42 namespace gko {
48 namespace preconditioner {
49 
50 
51 // TODO: replace this with a custom accessor
62 template <typename IndexType>
67  IndexType block_offset;
68 
72  IndexType group_offset;
73 
80 
86  GKO_ATTRIBUTES IndexType get_group_size() const noexcept
87  {
88  return one<IndexType>() << group_power;
89  }
90 
103  GKO_ATTRIBUTES size_type compute_storage_space(size_type num_blocks) const
104  noexcept
105  {
106  return (num_blocks + 1 == size_type{0})
107  ? size_type{0}
108  : ceildiv(num_blocks, this->get_group_size()) * group_offset;
109  }
110 
118  GKO_ATTRIBUTES IndexType get_group_offset(IndexType block_id) const noexcept
119  {
120  return group_offset * (block_id >> group_power);
121  }
122 
130  GKO_ATTRIBUTES IndexType get_block_offset(IndexType block_id) const noexcept
131  {
132  return block_offset * (block_id & (this->get_group_size() - 1));
133  }
134 
142  GKO_ATTRIBUTES IndexType get_global_block_offset(IndexType block_id) const
143  noexcept
144  {
145  return this->get_group_offset(block_id) +
146  this->get_block_offset(block_id);
147  }
148 
154  GKO_ATTRIBUTES IndexType get_stride() const noexcept
155  {
156  return block_offset << group_power;
157  }
158 };
159 
160 
199 template <typename ValueType = default_precision, typename IndexType = int32>
200 class Jacobi : public EnableLinOp<Jacobi<ValueType, IndexType>>,
201  public ConvertibleTo<matrix::Dense<ValueType>>,
202  public WritableToMatrixData<ValueType, IndexType> {
203  friend class EnableLinOp<Jacobi>;
204  friend class EnablePolymorphicObject<Jacobi, LinOp>;
205 
206 public:
209  using value_type = ValueType;
210  using index_type = IndexType;
212 
221  size_type get_num_blocks() const noexcept { return num_blocks_; }
222 
232  const noexcept
233  {
234  return storage_scheme_;
235  }
236 
248  const value_type *get_blocks() const noexcept
249  {
250  return blocks_.get_const_data();
251  }
252 
263  {
264  return conditioning_.get_const_data();
265  }
266 
273  {
274  return blocks_.get_num_elems();
275  }
276 
277  void convert_to(matrix::Dense<value_type> *result) const override;
278 
279  void move_to(matrix::Dense<value_type> *result) override;
280 
281  void write(mat_data &data) const override;
282 
284  {
290  uint32 GKO_FACTORY_PARAMETER(max_block_size, 32u);
291 
318 
319  private:
320  // See documentation of storage_optimization parameter for details about
321  // this class
322  struct storage_optimization_type {
323  storage_optimization_type(precision_reduction p)
324  : is_block_wise{false}, of_all_blocks{p}
325  {}
326 
327  storage_optimization_type(
328  const Array<precision_reduction> &block_wise_opt)
329  : is_block_wise{block_wise_opt.get_num_elems() > 0},
330  block_wise{block_wise_opt}
331  {}
332 
333  storage_optimization_type(
334  Array<precision_reduction> &&block_wise_opt)
335  : is_block_wise{block_wise_opt.get_num_elems() > 0},
336  block_wise{std::move(block_wise_opt)}
337  {}
338 
339  operator precision_reduction() { return of_all_blocks; }
340 
341  bool is_block_wise;
342  precision_reduction of_all_blocks;
344  };
345 
346  public:
414  storage_optimization_type GKO_FACTORY_PARAMETER(
415  storage_optimization, precision_reduction(0, 0));
416 
444  };
445  GKO_ENABLE_LIN_OP_FACTORY(Jacobi, parameters, Factory);
447 
448 protected:
454  explicit Jacobi(std::shared_ptr<const Executor> exec)
455  : EnableLinOp<Jacobi>(exec),
456  num_blocks_{},
457  blocks_(exec),
458  conditioning_(exec)
459  {
460  parameters_.block_pointers.set_executor(exec);
461  parameters_.storage_optimization.block_wise.set_executor(exec);
462  }
463 
471  explicit Jacobi(const Factory *factory,
472  std::shared_ptr<const LinOp> system_matrix)
473  : EnableLinOp<Jacobi>(factory->get_executor(),
474  transpose(system_matrix->get_size())),
475  parameters_{factory->get_parameters()},
476  storage_scheme_{compute_storage_scheme(parameters_.max_block_size)},
477  num_blocks_{parameters_.block_pointers.get_num_elems() - 1},
478  blocks_(factory->get_executor(),
479  storage_scheme_.compute_storage_space(
480  parameters_.block_pointers.get_num_elems() - 1)),
481  conditioning_(factory->get_executor())
482  {
483  if (parameters_.max_block_size >= 32 ||
484  parameters_.max_block_size < 1) {
485  GKO_NOT_SUPPORTED(this);
486  }
487  parameters_.block_pointers.set_executor(this->get_executor());
488  parameters_.storage_optimization.block_wise.set_executor(
489  this->get_executor());
490  this->generate(lend(system_matrix));
491  }
492 
498  static constexpr size_type max_block_stride_ = 32;
499 
508  static block_interleaved_storage_scheme<index_type> compute_storage_scheme(
509  uint32 max_block_size) noexcept
510  {
511  const auto group_size = static_cast<uint32>(
512  max_block_stride_ / get_superior_power(uint32{2}, max_block_size));
513  const auto block_offset = max_block_size;
514  const auto block_stride = group_size * block_offset;
515  const auto group_offset = max_block_size * block_stride;
516  return {static_cast<index_type>(block_offset),
517  static_cast<index_type>(group_offset),
518  get_significant_bit(group_size)};
519  }
520 
527  void generate(const LinOp *system_matrix);
528 
536  void detect_blocks(const matrix::Csr<ValueType, IndexType> *system_matrix);
537 
538  void apply_impl(const LinOp *b, LinOp *x) const override;
539 
540  void apply_impl(const LinOp *alpha, const LinOp *b, const LinOp *beta,
541  LinOp *x) const override;
542 
543 private:
545  size_type num_blocks_;
546  Array<value_type> blocks_;
547  Array<remove_complex<value_type>> conditioning_;
548 };
549 
550 
551 } // namespace preconditioner
552 } // namespace gko
553 
554 
555 #endif // GKO_CORE_PRECONDITIONER_JACOBI_HPP_
constexpr int64 ceildiv(int64 num, int64 den)
Performs integer division with rounding up.
Definition: math.hpp:280
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:495
This class is used to encode storage precisions of low precision algorithms.
Definition: types.hpp:228
const parameters_type & get_parameters() const noexcept
Returns the parameters of the factory.
Definition: abstract_factory.hpp:175
size_type get_num_elems() const noexcept
Returns the number of elements in the Array.
Definition: array.hpp:388
const value_type * get_blocks() const noexcept
Returns the pointer to the memory used for storing the block data.
Definition: jacobi.hpp:248
IndexType block_offset
The offset between consecutive blocks within the group.
Definition: jacobi.hpp:67
ConvertibleTo interface is used to mark that the implementer can be converted to the object of Result...
Definition: polymorphic_object.hpp:380
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:103
This mixin inherits from (a subclass of) PolymorphicObject and provides a base implementation of a ne...
Definition: polymorphic_object.hpp:505
void write(StreamType &&os, MatrixType *matrix, layout_type layout=layout_type::array)
Reads a matrix stored in matrix market format from an input stream.
Definition: mtx_io.hpp:134
std::uint32_t uint32
32-bit unsigned integral type.
Definition: types.hpp:134
#define GKO_FACTORY_PARAMETER(_name,...)
Creates a factory parameter in the factory parameters structure.
Definition: lin_op.hpp:751
Defines the parameters of the interleaved block storage scheme used by block-Jacobi blocks...
Definition: jacobi.hpp:63
Definition: jacobi.hpp:445
std::size_t size_type
Integral type used for allocation quantities.
Definition: types.hpp:94
IndexType get_stride() const noexcept
Returns the stride between columns of the block.
Definition: jacobi.hpp:154
The Ginkgo namespace.
Definition: abstract_factory.hpp:45
CSR is a matrix format which stores only the nonzero coefficients by compressing each row of the matr...
Definition: coo.hpp:51
IndexType group_offset
The offset between two block groups.
Definition: jacobi.hpp:72
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:476
size_type get_num_stored_elements() const noexcept
Returns the number of elements explicitly stored in the matrix.
Definition: jacobi.hpp:272
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:118
const block_interleaved_storage_scheme< index_type > & get_storage_scheme() const noexcept
Returns the storage scheme used for storing Jacobi blocks.
Definition: jacobi.hpp:231
A block-Jacobi preconditioner is a block-diagonal linear operator, obtained by inverting the diagonal...
Definition: jacobi.hpp:200
uint32 group_power
Then base 2 power of the group.
Definition: jacobi.hpp:79
IndexType get_group_size() const noexcept
Returns the number of elements in the group.
Definition: jacobi.hpp:86
Dense is a matrix format which explicitly stores all values of the matrix.
Definition: coo.hpp:55
The EnableLinOp mixin can be used to provide sensible default implementations of the majority of the ...
Definition: lin_op.hpp:509
const remove_complex< value_type > * get_conditioning() const noexcept
Returns an array of 1-norm condition numbers of the blocks.
Definition: jacobi.hpp:262
IndexType get_global_block_offset(IndexType block_id) const noexcept
Returns the offset of the block with the given ID.
Definition: jacobi.hpp:142
size_type get_num_blocks() const noexcept
Returns the number of blocks of the operator.
Definition: jacobi.hpp:221
std::enable_if< detail::have_ownership< Pointer >), detail::pointee< Pointer > * >::type lend(const Pointer &p)
Returns a non-owning (plain) pointer to the object pointed to by p.
Definition: utils.hpp:249
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:130
A LinOp implementing this interface can write its data to a matrix_data structure.
Definition: lin_op.hpp:446
#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: lin_op.hpp:611
typename detail::remove_complex_impl< T >::type remove_complex
Obtains a real counterpart of a std::complex type, and leaves the type unchanged if it is not a compl...
Definition: math.hpp:93
#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:691
#define GKO_ENABLE_BUILD_METHOD(_factory_name)
Defines a build method for the factory, simplifying its construction by removing the repetitive typin...
Definition: lin_op.hpp:730
This structure is used as an intermediate data type to store a sparse matrix.
Definition: matrix_data.hpp:102
constexpr dim< 2, DimensionType > transpose(const dim< 2, DimensionType > &dimensions) noexcept
Returns a dim<2> object with its dimensions swapped.
Definition: dim.hpp:234