1888/apply - #2070
Conversation
1c82140 to
ed710a9
Compare
a4150cd to
89a9e63
Compare
ed710a9 to
1dc8c10
Compare
4f68eec to
d2ab30c
Compare
1dc8c10 to
d0862a3
Compare
removed functionality: - implicit Diag * Csr - implicit Csr * Csr
Keep the header for alpha release and give a compiler error if used. The header will be removed in the full release.
This is unncessary, since it can be recreated by using the run function and the existing create functions.
d0862a3 to
d22dff9
Compare
| virtual bool apply_uses_initial_guess() const { return false; } | ||
|
|
||
| [[nodiscard]] precision get_precision() const noexcept; | ||
| [[nodiscard]] precision get_precision() const noexcept { return value_t_; } |
There was a problem hiding this comment.
at some point we might need to split to two core library: one is the utils which can be used by the backend and the other composes the backend together.
| * Implementers of LinOp should override this function instead | ||
| * of apply(const LinOp *, const LinOp *, const LinOp *, LinOp *). |
There was a problem hiding this comment.
adding some note for the default implementation without mixed precision support
| std::visit( | ||
| [&](auto p) { | ||
| using value_type = std::decay_t<decltype(p)>; | ||
| auto dense_alpha = alpha->as_precision(this); | ||
| auto dense_beta = beta->as_precision(this); | ||
| auto x_clone = converted_x->clone(); | ||
| this->apply_impl(converted_b.get(), x_clone.get()); | ||
| converted_x->scale(dense_beta.get()); | ||
| converted_x->add_scaled(dense_alpha.get(), x_clone); | ||
| }, | ||
| precision_to_variant(this->get_precision())); |
There was a problem hiding this comment.
| std::visit( | |
| [&](auto p) { | |
| using value_type = std::decay_t<decltype(p)>; | |
| auto dense_alpha = alpha->as_precision(this); | |
| auto dense_beta = beta->as_precision(this); | |
| auto x_clone = converted_x->clone(); | |
| this->apply_impl(converted_b.get(), x_clone.get()); | |
| converted_x->scale(dense_beta.get()); | |
| converted_x->add_scaled(dense_alpha.get(), x_clone); | |
| }, | |
| precision_to_variant(this->get_precision())); | |
| auto dense_alpha = alpha->as_precision(this); | |
| auto dense_beta = beta->as_precision(this); | |
| auto x_clone = converted_x->clone(); | |
| this->apply_impl(converted_b.get(), x_clone.get()); | |
| converted_x->scale(dense_beta.get()); | |
| converted_x->add_scaled(dense_alpha.get(), x_clone); |
value_type is not used, so you do not need the visit, right?
There was a problem hiding this comment.
Yes, you're right. I will change this.
| void write_data(json& output) { output["iterations"] = this->num_iters; } | ||
|
|
||
| protected: | ||
| void on_iteration_complete( |
There was a problem hiding this comment.
this is considered public interface break, so we need to note it
There was a problem hiding this comment.
I don't think we consider the benchmarks public interface. They are not even exported/installed.
| } | ||
|
|
||
|
|
||
| TEST_F(Dense, ApplyToMixedComplexIsEquivalentToRef) |
There was a problem hiding this comment.
these MixedComplex needs to be recovered?
There was a problem hiding this comment.
No, they were deliberately removed, since this isn't (directly) supported anymore. We talked about this internally a while ago. The issue is essentially that this always requires two steps
- convert complex to real (no precision conversion)
- convert real to required precision
This creates two temporaries, which both need to be kept alive. I think it's best to leave it for the user to manage this. They can easily do it by themselves:
auto real = complex->create_real_view();
auto converted = real->as_precision(fp16)Or switch the two steps.
There was a problem hiding this comment.
IIRC, we start to use A(real) b (complex) is from IDR. Do we use it in other place.
Another option can be that we even do not support V x Complex.
Users can use A->apply(b->create_real_view(), x->create_real_view()) because create_real_view is here, so it will still valid when the internal temporary conversion get destroyed.
| max_relative_norm2 = | ||
| std::max(host_absolute_norm->at(0, i) / host_answer_norm->at(0, i), | ||
| max_relative_norm2); |
There was a problem hiding this comment.
compute_norm will return multivector no matter it is distributed or not
There was a problem hiding this comment.
Yes, all reductions (compute_dot/compute_norm) use gko::matrix::MultiVector for their result. This is also how it is currently. Maybe if we have a column distributed vector it would make sense to return something else, but for now it doesn't.
| scale_diag->apply(diag_mtx_, diag_mtx_); | ||
| scale_diag->apply(off_diag_mtx_, off_diag_mtx_); | ||
| auto diag_mtx_csr = | ||
| as<gko::matrix::Csr<ValueType, LocalIndexType>>(diag_mtx_); | ||
| auto off_diag_mtx_csr = | ||
| as<gko::matrix::Csr<ValueType, LocalIndexType>>(off_diag_mtx_); | ||
|
|
||
| scale_diag->apply(diag_mtx_csr, diag_mtx_csr); | ||
| scale_diag->apply(off_diag_mtx_csr, off_diag_mtx_csr); |
There was a problem hiding this comment.
I am thinking how to make generalized in the future when we support more scale on the matrix format.
Diagonal only scale csr and dense. here only deal with csr.
Dispatch here might be easy solution but it will not support user owned format, or we need to have feature class to allow that.
There was a problem hiding this comment.
I think a feature class would be reasonable. But I think that is very far future right now, so I wouldn't worry too much.
| apply_precision_dispatch<ValueType>( | ||
| [this](auto dense_alpha, auto view_b, auto dense_beta, auto view_x, | ||
| auto...) { |
There was a problem hiding this comment.
In the mixed precision case it's used to pass through the actual value types of the arguments. But here it is not necessary, so I will remove it. That might also give better differentiation between the two dispatches.
This PR changes the
applyinterface to only allow applying linops to multivectors. The apply implementations are changed to use the precision dispatch built into the multi vector interface.