-
Notifications
You must be signed in to change notification settings - Fork 143
Mixed-precision parallel linear solver #7048
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
nrseman
wants to merge
19
commits into
OPM:master
Choose a base branch
from
haugenlabs:mixed-istl
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
e172bfc
mixed: noop mixed-adapter implementation
22aff65
mixed: dummy mixed-precision adapter
274a354
mixed: working adapter with basic mixed spmv
e289894
mixed: removing stale code
6a5bd28
mixed: wrap mixed bsr matrix to interface with operator
901c794
mixed: unify parallel and sequential
dfe5a79
mixed: wrap mixed ilu0 preconditioner
b8c1e68
mixed: add mixed dilu option
3a4eefa
mixed: optimized sequential scalar product
058bf20
mixed: add destructors and documentation
343b537
mixed: renaming aesthetics
82e44bd
mixed: update list of public header files
1012385
mixed: update README file
960fb43
mixed: minor updates to documentation of bsr matrix
8cefef1
mixed: minor updates to MixedWrapper.hpp
fcb5abb
mixed: extract sparsity pattern using iterators
a2d7a80
mixed: remove block size as explicit template parameter
5db7457
mixed: renamed MixedAdapter to MixedBiCGSTABSolver
da0b6c5
mixed: throw error for unsupported matrix operators
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| #ifndef OPM_MIXED_MATRIX_HEADER_INCLUDED | ||
| #define OPM_MIXED_MATRIX_HEADER_INCLUDED | ||
|
|
||
|
|
||
| #include <opm/simulators/linalg/mixed/bsr.h> | ||
|
|
||
| namespace Opm | ||
| { | ||
|
|
||
| //! @brief Wraps c-implementation of mixed-precision matrix | ||
| //! | ||
| //! @note matrix is stored in single precision, but all | ||
| //! operations are performed in double-precision | ||
| //! | ||
| //! @tparam Vector the block-vector used by linear operator | ||
| //! @tparam b block size | ||
| template <class Vector> | ||
| class MixedMatrixWrapper | ||
| { | ||
| public: | ||
|
|
||
| // extract block size | ||
| static constexpr auto block_size = Vector::block_type::dimension; | ||
|
|
||
| virtual void mv(const Vector& x, Vector& y) const; | ||
| virtual void umv(const Vector& x, Vector& y) const; | ||
| virtual void usmv(double alpha, const Vector& x, Vector& y) const; | ||
|
|
||
| //! @brief constructor | ||
| //! | ||
| //! @param nrows number of block rows | ||
| //! @param nnz number of nonzero blocks | ||
| MixedMatrixWrapper(int nrows, int nnz) | ||
| { | ||
| if constexpr(block_size!=3) OPM_THROW(std::invalid_argument, "MixedMatrixWrapper only supports block size == 3! \n"); | ||
|
|
||
| nnz_=nnz; | ||
| M_ = bsr_alloc(); | ||
| bsr_init(M_, nrows, nnz, block_size); | ||
| } | ||
|
|
||
| //! @brief destructor | ||
| ~MixedMatrixWrapper() {bsr_free(M_);} | ||
|
|
||
| void update(double const *data); | ||
|
|
||
| int *rowptr(){return M_->rowptr;} | ||
| int *colidx(){return M_->colidx;} | ||
|
|
||
| private: | ||
| int nnz_; | ||
| bsr_matrix *M_; | ||
| }; | ||
|
|
||
| template <class Vector> | ||
| void MixedMatrixWrapper<Vector>:: | ||
| mv(const Vector& x, Vector& y) const | ||
| { | ||
| // mixed-precision block spmv (y = M.x) | ||
| bsr_vmspmv3(M_, &x[0][0], &y[0][0]); | ||
| } | ||
|
|
||
| template <class Vector> | ||
| void MixedMatrixWrapper<Vector>:: | ||
| umv(const Vector& x, Vector& y) const | ||
| { | ||
| // mixed-precision block spmv with update (y += M.x) | ||
| bsr_vmspumv3(M_, &x[0][0], &y[0][0], 1.0); | ||
| } | ||
|
|
||
| template <class Vector> | ||
| void MixedMatrixWrapper<Vector>:: | ||
| usmv(double alpha, const Vector& x, Vector& y) const | ||
| { | ||
| // scaled mixed-precision block spmv with update (y += alpha * M.x) | ||
| bsr_vmspumv3(M_, &x[0][0], &y[0][0], alpha); | ||
| } | ||
|
|
||
| template <class Vector> | ||
| void MixedMatrixWrapper<Vector>:: | ||
| update(double const *data) | ||
| { | ||
| // transpose each dense block to make them column-major | ||
| int const b = block_size; | ||
| int const bb=b*b; | ||
| double B[bb]; | ||
| for(int k=0;k<nnz_;k++) | ||
| { | ||
| for(int i=0;i<b;i++) for(int j=0;j<b;j++) B[b*j+i] = data[bb*k + b*i + j]; | ||
| for(int i=0;i<bb;i++) M_->dbl[bb*k + i] = B[i]; | ||
| } | ||
|
|
||
| // downcast to single precision | ||
| bsr_downcast(M_); | ||
| } | ||
| } // namespace Opm | ||
| #endif // OPM_MIXED_MATRIX_HEADER_INCLUDED | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| #ifndef OPM_MIXED_PREC_HEADER_INCLUDED | ||
| #define OPM_MIXED_PREC_HEADER_INCLUDED | ||
|
|
||
| #include <opm/simulators/linalg/mixed/prec.h> | ||
|
|
||
| namespace Opm { | ||
|
|
||
| //! @brief Wraps c-implementation of mixed-precision preconditioner | ||
| //! | ||
| //! @tparam Vector the block-vector used by linear operator | ||
| //! @tparam M block-sparse matrix type | ||
| //! @tparam X block-vector input type | ||
| //! @tparam Y block vector output type | ||
| template <class M, class X, class Y> | ||
| class MixedPreconditioner : public Dune::PreconditionerWithUpdate<X, Y> | ||
| { | ||
| public: | ||
|
|
||
| using domain_type = X; | ||
| static constexpr auto block_size = domain_type::block_type::dimension; | ||
|
|
||
| //! @brief constructor | ||
| //! | ||
| //! @param A block-sparse matrix | ||
| //! @param use_dilu toggle between dilu or ilu0 factorization | ||
| MixedPreconditioner(const M& A, bool use_dilu = false) | ||
| { | ||
| // Access double precision matrix data | ||
| int nrows = A.N(); | ||
| int nnz = A.nonzeroes(); | ||
| double_data_ = &A[0][0][0][0]; | ||
| prec_ = prec_alloc(); | ||
|
|
||
| // allocate and initialize mixed-precision matrix | ||
| mixed_matrix_ = bsr_alloc(); | ||
| bsr_init(mixed_matrix_, nrows, nnz, block_size); | ||
|
|
||
| // copy sparsity pattern from double preccision matrix | ||
| int *rows = mixed_matrix_->rowptr; | ||
| int *cols = mixed_matrix_->colidx; | ||
|
|
||
| int irow = 0; | ||
| int icol = 0; | ||
| rows[0] = 0; | ||
| for(auto row=A.begin(); row!=A.end(); row++) | ||
| { | ||
| for(auto col = row->begin(); col != row->end(); ++col) | ||
| { | ||
| cols[icol++] = col.index(); | ||
| } | ||
| rows[irow+1] = icol; | ||
| irow++; | ||
| } | ||
|
|
||
| // allocate and initialize preconditioner | ||
| prec_init(prec_,mixed_matrix_); | ||
|
|
||
| // attribute initialization | ||
| nnz_ = nnz; | ||
| use_dilu_ = use_dilu; | ||
|
|
||
| // perform matrix factorization | ||
| update(); | ||
| }; | ||
|
|
||
| //! @brief destructor | ||
| ~MixedPreconditioner() | ||
| { | ||
| bsr_free(mixed_matrix_); | ||
| prec_free(prec_); | ||
| } | ||
|
|
||
| virtual void update() override; | ||
| virtual bool hasPerfectUpdate() const override {return true;} | ||
| virtual void pre ([[maybe_unused]] X& x, [[maybe_unused]] Y& y) override {}; | ||
| virtual void post ([[maybe_unused]] X& x) override {}; | ||
| virtual void apply ([[maybe_unused]] X& x, [[maybe_unused]] const Y& y) override; | ||
| virtual Dune::SolverCategory::Category category() const override { return Dune::SolverCategory::sequential; }; | ||
|
|
||
| private: | ||
| bool use_dilu_; | ||
| double const *double_data_; | ||
| bsr_matrix *mixed_matrix_; | ||
| prec_t *prec_; | ||
| int nnz_; | ||
| }; | ||
|
|
||
| template <class M, class X, class Y> | ||
| void MixedPreconditioner<M,X,Y>:: | ||
| update () | ||
| { | ||
| // transpose each dense block to make them column-major | ||
| int b = block_size; | ||
| int bb=b*b; | ||
| double B[bb]; | ||
| for(int k=0;k<nnz_;k++) | ||
| { | ||
| for(int i=0;i<b;i++) for(int j=0;j<b;j++) B[b*j+i] = double_data_[bb*k + b*i + j]; | ||
| for(int i=0;i<bb;i++) mixed_matrix_->dbl[bb*k + i] = B[i]; | ||
| } | ||
|
|
||
| use_dilu_ ? prec_dilu_factorize(prec_, mixed_matrix_) : prec_ilu0_factorize(prec_, mixed_matrix_); // choose dilu or ilu0 | ||
| prec_downcast(prec_); | ||
| } | ||
|
|
||
| template <class M, class X, class Y> | ||
| void MixedPreconditioner<M,X,Y>:: | ||
| apply ([[maybe_unused]] X& x, [[maybe_unused]] const Y& y) | ||
| { | ||
| x=y; | ||
| prec_mapply3c(prec_,&x[0][0]); | ||
| } | ||
|
|
||
| } | ||
| #endif // OPM_MIXED_PREC_HEADER_INCLUDED |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The update of the matrix transposes the blocks of the original matrix into the new buffer, in double precision. Later it downcasts the entire matrix to its single precision buffer. Now, I don't understand why to have the double precision in the first place? After all, the operations in this wrapper only operate on the single precision matrix. Maybe I am missing something here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your observation is correct, @SoilRos! This is an artifact from the original mixed-precision implementation where the interface was at the solver level. In that case, the double-precision matrix was required for incomplete factorization purposes. Now that the interfaces are at the preconditioner and linear operator levels, the original design has introduced some redundancies. The situation is actually slightly worse for the preconditioner. Addressing the issue is not that difficult, and will be taken care of. Of course, using column-major blocks throughout OPM would eliminate almost all redundancies ;-)