-
Notifications
You must be signed in to change notification settings - Fork 99
Allow to use ValueType in template of preconditioner IC #1811
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
Conversation
a371088
to
62e7195
Compare
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.
Suggestion for how we could make the changes less intrusive, and more consistent with other LinOpFactory types
06f44f1
to
9138755
Compare
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.
Looks good for the most part, a handful of questions and suggestions, and one concern about mixed precision. Maybe change the title to remove ILU?
if (!comp) { | ||
GKO_NOT_SUPPORTED(comp); | ||
if constexpr (std::is_same_v<value_type, void>) { | ||
GKO_NOT_IMPLEMENTED; |
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.
GKO_NOT_SUPPORTED maybe?
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.
GKO_NOT_SUPPORTED require a object, so I currently put the GKO_NOT_IMPLEMENTED
lh_solver_ = as<lh_solver_type>(l_solver_->conj_transpose()); | ||
if constexpr (std::is_same_v<l_solver_type, LinOp>) { | ||
// linop can not have a default factory generation | ||
GKO_NOT_IMPLEMENTED; |
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.
GKO_NOT_SUPPORTED
this->set_cache_to(b); | ||
if (l_solver_->apply_uses_initial_guess()) { | ||
cache_.intermediate->copy_from(b); | ||
} | ||
l_solver_->apply(b, cache_.intermediate); | ||
if (lh_solver_->apply_uses_initial_guess()) { | ||
x->copy_from(cache_.intermediate); | ||
} | ||
lh_solver_->apply(cache_.intermediate, x); |
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.
This changes the mixed-precision behavior slightly, meaning we require more allocations, and may lose some precision. Is that intended?
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.
I miss to delete the copy_from
in the set_cache_to
.
I think the current one will be less than the original one.
assume the LSolver have the same precision as IC, so cache vector is not needed to copy for precision
original one does not support mixed precision.
original: (no matter the underlying support mixed or not)
input (copy in), output (copy in)
Lsolver (always copy in set_cache_to without considering initial_guess), LHsolver no precision change
output (copy out)
now:
LSolver (copy input (in))
LHSolver (copy output (inout))
if the underlying solver support mixed precision, it will reduce the copy.
When we consider more different settings: the LSolver and LHSolver do not use the same precision
original will need to pay Lsolver(input, cache) LHSolver(cache, output) additionally because it dispatches the precision first.
but the current one: only need to pay cache conversion in LSolver and LHsolver additionally, which is less than the original one.
This is one of reason for additional stuff may need for mixed-precision (internally not just outside)
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.
ah, do you only mean the x->copy_from(cache)
?
If so, you are right, it should use the user input directly.
This part is the original behavior
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.
It is more than what I thought because of real apply on the complex vector. I will move this out of the current pr. the apply and set_cache_to should be the same function as the original one
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 change to accepting ValueType
as first template parameter seems not to be done fully.
9138755
to
69a30a4
Compare
using factory_type = typename factory_type_impl<Type>::type; | ||
|
||
template <typename Type> | ||
constexpr bool is_ginkgo_linop = std::is_convertible_v<Type*, LinOp*>; |
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.
IMO std::is_base_of
would be a better check.
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.
I thought is_convertible_v
more appropriate check?
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.
At least not to me. Here we want to know if LinOp
is a base class of Type
, which the first suggestion does very explicitly. For the other one you have to remember that this is equivalent to LinOp being a base class.
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.
I see your point from readability.
If we do not face the some situation (like private or ambiguous base) mentioned by std, we can go for that
is_instantiation_of<Type, solver::Ir>::value || | ||
is_instantiation_of<Type, solver::Gmres>::value || | ||
is_instantiation_of<Type, preconditioner::LowerIsai>::value; | ||
std::is_same_v<gko::detail::get_solver_type<SolverTypeOrValueType>, LinOp>; |
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.
I think this is more direct:
std::is_same_v<gko::detail::get_solver_type<SolverTypeOrValueType>, LinOp>; | |
!detail::is_ginkgo_linop<SolverTypeOrValueType>; |
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.
I change it a bit to only require the class not the first template, which will simplify the process for Ilu
f70c7b6
to
71e45e6
Compare
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.
Only two minor comments left.
2b7c086
to
3bc88de
Compare
3bc88de
to
e09c3a9
Compare
if LSolverType is LinOp, value_type will be void and Ic will not give the default factory for l_solver and factorization
… as template Co-authored-by: Marcel Koch <marcel.koch@kit.edu> Co-authored-by: Tobias Ribizel <mail@ribizel.de>
… revert the apply due to real apply on complex vector Co-authored-by: Marcel Koch <marcel.koch@kit.edu>
Co-authored-by: Marcel Koch <marcel.koch@kit.edu>
|
This PR gives different way than adding a new type (#1029), which allows ValueType can be used in template LSolverType of preconditioner::Ic (similar to Ilu later).
Both PRs aims to reduce the challenges of instantiating many types for preconditioner::Ic and preconditioner::Ilu because we need to instantiate them first such that users can select one of them.
when the SolverType is LinOp,
TODO:
apply to ILU (will be next pr)Allow to use ValueType in template of preconditioner ILU #1828