-
Notifications
You must be signed in to change notification settings - Fork 145
Refactor: Preconditioner function library #5482
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
Changes from 3 commits
a8bb37f
4f4f356
17cac27
0687643
3ac0de2
a0571fb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -130,8 +130,10 @@ class PyDiagoDavSubspace | |
| std::copy(hpsi_ptr, hpsi_ptr + nvec * ld_psi, hpsi_out); | ||
| }; | ||
|
|
||
| hsolver::PreOP<std::complex<double>, base_device::DEVICE_CPU, hsolver::fvec::DivTransMinusEigKernel<std::complex<double>, base_device::DEVICE_CPU>> | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I cannot see any significance of the necessarity of instantiating the hsolver::PreOP. The name of PreOP is also confusing quite much. From the rest of your PR, I can understand it is about preconditioning, but unfortunately you did not name them with much care and enough considerations.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. presently the lines 133, 134 are quite confusing and it is quite difficult for others to know what the operation is. It wastes other's time. You should always consider a clearer way to organize your code like: // instantiate hsolver::PreOP
hsolver::PreOP<std::complex<double>,
base_device::DEVICE_CPU,
hsolver::fvec::DivTransMinusEigKernel<
std::complex<double>,
base_device::DEVICE_CPU>
> pre_op(precond_vec,
hsolver::fvec::div_trans_prevec_minus_eigen<std::complex<double>>,
hsolver::fval::qe_pw<double>);however, do you think naming the instance of |
||
| pre_op(precond_vec, hsolver::fvec::div_trans_prevec_minus_eigen<std::complex<double>>, hsolver::fval::qe_pw<double>); | ||
| obj = std::make_unique<hsolver::Diago_DavSubspace<std::complex<double>, base_device::DEVICE_CPU>>( | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it is the first time that I find there is an instance even named |
||
| precond_vec, | ||
| pre_op.get(), | ||
| nband, | ||
| nbasis, | ||
| dav_ndim, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -137,8 +137,9 @@ class PyDiagoDavid | |
| syncmem_op()(this->ctx, this->ctx, spsi_out, psi_in, static_cast<size_t>(nbands * nrow)); | ||
| }; | ||
|
|
||
| hsolver::PreOP<std::complex<double>> pre_op(precond_vec); | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 其它地方命名都是下划线命名法,PreOP这个名字起得能不能有点默契!
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. https://github.com/MCresearch/abacus-user-guide/blob/master/develop-C++.md |
||
| obj = std::make_unique<hsolver::DiagoDavid<std::complex<double>, base_device::DEVICE_CPU>>( | ||
| precond_vec.data(), | ||
| pre_op.get(), | ||
| nband, | ||
| nbasis, | ||
| dav_ndim, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,16 +13,16 @@ | |
| using namespace hsolver; | ||
|
|
||
| template <typename T, typename Device> | ||
| Diago_DavSubspace<T, Device>::Diago_DavSubspace(const std::vector<Real>& precondition_in, | ||
| Diago_DavSubspace<T, Device>::Diago_DavSubspace(PreFunc&& precondition_in, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. could you explain the necessarity of using rvalue instead of lvalue? |
||
| const int& nband_in, | ||
| const int& nbasis_in, | ||
| const int& david_ndim_in, | ||
| const double& diag_thr_in, | ||
| const int& diag_nmax_in, | ||
| const bool& need_subspace_in, | ||
| const diag_comm_info& diag_comm_in) | ||
| : precondition(precondition_in), n_band(nband_in), dim(nbasis_in), nbase_x(nband_in * david_ndim_in), | ||
| diag_thr(diag_thr_in), iter_nmax(diag_nmax_in), is_subspace(need_subspace_in), diag_comm(diag_comm_in) | ||
| : precondition(precondition_in), n_band(nband_in), dim(nbasis_in), nbase_x(nband_in* david_ndim_in), | ||
| diag_thr(diag_thr_in), iter_nmax(diag_nmax_in), is_subspace(need_subspace_in), diag_comm(diag_comm_in) | ||
| { | ||
| this->device = base_device::get_device_type<Device>(this->ctx); | ||
|
|
||
|
|
@@ -55,14 +55,6 @@ Diago_DavSubspace<T, Device>::Diago_DavSubspace(const std::vector<Real>& precond | |
| resmem_complex_op()(this->ctx, this->vcc, this->nbase_x * this->nbase_x, "DAV::vcc"); | ||
| setmem_complex_op()(this->ctx, this->vcc, 0, this->nbase_x * this->nbase_x); | ||
| //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< | ||
|
|
||
| #if defined(__CUDA) || defined(__ROCM) | ||
| if (this->device == base_device::GpuDevice) | ||
| { | ||
| resmem_real_op()(this->ctx, this->d_precondition, nbasis_in); | ||
| // syncmem_var_h2d_op()(this->ctx, this->cpu_ctx, this->d_precondition, this->precondition.data(), nbasis_in); | ||
| } | ||
| #endif | ||
| } | ||
|
|
||
| template <typename T, typename Device> | ||
|
|
@@ -74,13 +66,6 @@ Diago_DavSubspace<T, Device>::~Diago_DavSubspace() | |
| delmem_complex_op()(this->ctx, this->hcc); | ||
| delmem_complex_op()(this->ctx, this->scc); | ||
| delmem_complex_op()(this->ctx, this->vcc); | ||
|
|
||
| #if defined(__CUDA) || defined(__ROCM) | ||
| if (this->device == base_device::GpuDevice) | ||
| { | ||
| delmem_real_op()(this->ctx, this->d_precondition); | ||
| } | ||
| #endif | ||
| } | ||
|
|
||
| template <typename T, typename Device> | ||
|
|
@@ -334,35 +319,7 @@ void Diago_DavSubspace<T, Device>::cal_grad(const HPsiFunc& hpsi_func, | |
| this->dim); | ||
|
|
||
| // "precondition!!!" | ||
| std::vector<Real> pre(this->dim, 0.0); | ||
| for (int m = 0; m < notconv; m++) | ||
| { | ||
| for (size_t i = 0; i < this->dim; i++) | ||
| { | ||
| // pre[i] = std::abs(this->precondition[i] - (*eigenvalue_iter)[m]); | ||
| double x = std::abs(this->precondition[i] - (*eigenvalue_iter)[m]); | ||
| pre[i] = 0.5 * (1.0 + x + sqrt(1 + (x - 1.0) * (x - 1.0))); | ||
| } | ||
| #if defined(__CUDA) || defined(__ROCM) | ||
| if (this->device == base_device::GpuDevice) | ||
| { | ||
| syncmem_var_h2d_op()(this->ctx, this->cpu_ctx, this->d_precondition, pre.data(), this->dim); | ||
| vector_div_vector_op<T, Device>()(this->ctx, | ||
| this->dim, | ||
| psi_iter + (nbase + m) * this->dim, | ||
| psi_iter + (nbase + m) * this->dim, | ||
| this->d_precondition); | ||
| } | ||
| else | ||
| #endif | ||
| { | ||
| vector_div_vector_op<T, Device>()(this->ctx, | ||
| this->dim, | ||
| psi_iter + (nbase + m) * this->dim, | ||
| psi_iter + (nbase + m) * this->dim, | ||
| pre.data()); | ||
| } | ||
| } | ||
| this->precondition(psi_iter + nbase * this->dim, eigenvalue_iter->data(), this->dim, notconv); | ||
|
|
||
| // "normalize!!!" in order to improve numerical stability of subspace diagonalization | ||
| std::vector<Real> psi_norm(notconv, 0.0); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,7 +6,7 @@ | |
| #include "module_base/module_device/memory_op.h"// base_device::memory | ||
|
|
||
| #include "module_hsolver/diag_comm_info.h" | ||
|
|
||
| #include "module_hsolver/precondition_funcs.h" | ||
| #include <vector> | ||
| #include <functional> | ||
|
|
||
|
|
@@ -21,10 +21,11 @@ class DiagoDavid | |
| // return T if T is real type(float, double), | ||
| // otherwise return the real type of T(complex<float>, complex<double>) | ||
| using Real = typename GetTypeReal<T>::type; | ||
|
|
||
| public: | ||
|
|
||
| DiagoDavid(const Real* precondition_in, | ||
| using PreFunc = fvec::Div<T>; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it possible to give PrecondFunc the interface like HPsi or SPsi? // in precondition lib
using Div = std::function<void(T*, const size_t&, const size_t&)>;Maybe we can give it the form using HPsiFunc = std::function<void(T*, T*, const int, const int)>;
using SPsiFunc = std::function<void(T*, T*, const int, const int)>;
using PrecndFunc = std::function<void(T*, T*, const int, const int)>;
// maybe it's better to change int to size_t, I'll do it on current HPsiFunc and SPsiFuncand pass the preconditioners to this universal function wrapper. Sometimes the source and destination of preconditioning may be different. For example from a temporary block residual r to a block of total search space X[:, nband:nband+notconv]. The results will be directly stored to a new array in such case.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point, see the latest change. And seems on |
||
| public: | ||
|
|
||
| DiagoDavid(PreFunc&& precondition_in, | ||
| const int nband_in, | ||
| const int dim_in, | ||
| const int david_ndim_in, | ||
|
|
@@ -102,8 +103,7 @@ class DiagoDavid | |
| int notconv = 0; | ||
|
|
||
| /// precondition for diag, diagonal approximation of matrix A(i.e. Hamilt) | ||
| const Real* precondition = nullptr; | ||
| Real* d_precondition = nullptr; | ||
| const PreFunc precondition; | ||
|
|
||
| /// eigenvalue results | ||
| Real* eigenvalue = nullptr; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -503,7 +503,9 @@ void HSolverPW<T, Device>::hamiltSolvePsiK(hamilt::Hamilt<T, Device>* hm, | |
| }; | ||
| bool scf = this->calculation_type == "nscf" ? false : true; | ||
|
|
||
| Diago_DavSubspace<T, Device> dav_subspace(pre_condition, | ||
| // const auto pre_op = make_pre_op(pre_condition, fvec::div_trans_prevec_minus_eigen<T, Device>, fval::qe_pw<Real>); | ||
| const PreOP<T, Device, fvec::DivTransMinusEigKernel<T, Device>> pre_op(pre_condition, fvec::div_trans_prevec_minus_eigen<T, Device>, fval::qe_pw<Real>); | ||
| Diago_DavSubspace<T, Device> dav_subspace(pre_op.get(), | ||
| psi.get_nbands(), | ||
| psi.get_k_first() ? psi.get_current_nbas() | ||
| : psi.get_nk() * psi.get_nbasis(), | ||
|
|
@@ -572,7 +574,9 @@ void HSolverPW<T, Device>::hamiltSolvePsiK(hamilt::Hamilt<T, Device>* hm, | |
| ModuleBase::timer::tick("David", "spsi_func"); | ||
| }; | ||
|
|
||
| DiagoDavid<T, Device> david(pre_condition.data(), | ||
| // const auto pre_op = make_pre_op(pre_condition, fvec::div_prevec<T, Device>); | ||
| const PreOP<T, Device> pre_op(pre_condition); | ||
| DiagoDavid<T, Device> david(pre_op.get(), | ||
| nband, | ||
| dim, | ||
| PARAM.inp.pw_diag_ndim, | ||
|
Comment on lines
+579
to
582
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. besides the std::unique_ptr<Diago> dav = make_diago("dav", /* other args */); // or use object directly without pointer |
||
|
|
||

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 name "DivTransMinusEigKernel" is a disaster.
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.
Sorry but do you have any better idea?
Uh oh!
There was an error while loading. Please reload this page.
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 function should be named with following considerations: precisely describe what it does. In present case, you mix the mathematical operation with some rare numerical trick description like "kernel". So there will be quite few people can know what this function does from its name. You should either name the function purely with names mathematical operations, or use human natural language describe the action that what quantity is calculated, additionally from what quantity.