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
Add an abstract base class ReadVector purely for vector access. #15197
Conversation
Another thing template <class MemorySpace>
PetscErrorCode VecGetKokkosView(Vec, Kokkos::View<const PetscScalar *, MemorySpace> *); or by |
Any thoughts? If people are OK with making template <typename Number>
class ReadVector
{
public:
using size_type = types::global_dof_index;
virtual size_type
size() const = 0;
virtual void
extract_elements(const ArrayView<const types::global_dof_index> &indices,
ArrayView<Number> &entries) const = 0;
}; a base class for all of our vector classes we could get rid of a lot of template instantiations - I'd like to get this done for 9.5. We can work on the Kokkos view functions and other advanced features at the workshop. |
Why are you using an |
I used template <typename OtherNumber>
void
extract_subvector_to(const std::vector<size_type> &indices,
std::vector<OtherNumber> & values) const; I don't know if that's any better or worse than an |
The issue is that if you want all the locally owned elements, you first need to create large |
What was your reasoning not to have a
This has the advantage that you don't have to adjust the interface of the vector classes, including the fact that the |
The problem I couldn't figure out how to fix with template <typename Number>
void foo(const VectorView<Number> &v); then AFAICT we cannot do Vector<double> fe_vector;
foo(fe_vector); since template resolution occurs before function overloading. Here's a complete example which doesn't use deal.II: #include <iostream>
#include <vector>
template <typename Number>
struct Vector
{
std::vector<Number> values;
};
template <typename Number>
struct View
{
Number *a;
View(Vector<Number> &b) : a(b.values.data())
{}
};
void foo1(const View<double> &view)
{
std::cout << "foo1()" << std::endl;
}
template <typename Number>
void foo2(const View<Number> &view)
{
std::cout << "foo2()" << std::endl;
}
int main()
{
Vector<double> v;
foo1(v); // OK
foo2(v); // error
} fails to compile with the error
Writing a vector view class in that way would be great but I don't see how to make it work - hence I went with the simpler version of just writing a base class. |
Ah, yes, that's a bummer. I guess that's why we have
But that, too, doesn't work unless you want to write
which works but defeats the purpose :-( |
So what do others think? I don't think it would be too big of a problem to make |
The idea of a vector view is still the right way, IMO, to implement |
w.r.t. using |
/rebuild This patch lowers the total number of symbols in the library from 217k to 209k - another advantage is that it decouples FEValues and the other classes from all of our vector classes. |
632e8b9
to
7a84cd4
Compare
What do we want to do with this patch? I love the direction, including that you've taken the time to also convert places such as |
I would prefer to discuss this after the release since this is not entirely uncontroversial. |
Since its part of #745 etc. I think we should discuss it at the workshop. This patch shows that we can support FEValues and things that only use FEValues with just two vector functions - knowing that can help inform our choices for other changes to the vector classes. |
What about instead of rolling our own class, we use |
As an alternative to the proposed |
We should be able to do that through the access policy of mdspan. |
Do all of our dependencies use contiguous storage for vectors? PETSc does (we convert to a serial vector) but I don't know about the other vector classes. |
Trilinos and our own vector do use contiguous storage. |
But then we still have to convert manually from these vectors to |
I am looking forward to the workshop (albeit I only participate remotely and in some time slots). My view on this is that having a simple way to access these functions would be great. I understand the base class, so that would be good for me; maybe In either case, the performance impact should be small or negligible. We go into these functions with global indices, so they will be much slower than direct array access, and thus another indirection for |
@stefanozampini, I think this is one of the discussions @bangerth was referring to. |
I like the idea and the reduction in the number of instantiations is great. As mentioned earlier, something like |
This gives a common interface to all vectors for use by FEValues.
It sounds like everyone is happy with the current state of this - in the meeting this morning we decided to keep the name |
@@ -63,7 +63,7 @@ test_cell(const FEValuesBase<dim> &fev) | |||
u = 0.; | |||
u(i) = 1.; | |||
w = 0.; | |||
fev.get_function_values(u, indices, uval, true); | |||
fev.get_function_values(u, indices, make_array_view(uval), true); |
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.
Are the changes in these integrators the only places that need to be touched? Do you happen to know why here? Is it because we have std::vector<std::vector<double>>
that can somehow not be automatically converted? I think that might be something we need to describe more clearly in the incompatibilities section of a changelog?
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's because the template instantiation is different: since we instantiate on Number
instead of VectorType
the deduction process is slightly different and we need to explicitly pass an ArrayView (instead of relying on the implicit conversion constructor). I added a changelog entry summarizing the problem.
I reran all the tests which use FEValues or FEFaceValues locally and they all pass so I think I fixed all the relevant ones in this PR.
Its both a new feature and a small incompatibility.
There we go! |
template <typename Number> | ||
void | ||
Vector::extract_subvector_to( |
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 is the change that caused #15580.
For reference, on my laptop: Before:
After:
So about a 4% reduction for the debug library, and 6.5% for the release library. Nice! |
This is
at the proof-of-concept stage anda viable direction for part of #15168.In
FEValues
(and places like the Kelly error estimator andintegrate_difference
in which we only access vectors throughFEValues
) the only vector operation we need is "extract values from a global vector on a single cell". We could eliminate the use ofVectorType
completely in that class by making all of our vectors implement a single common interface for that task. I implemented this as new base classReadVector<T>
which contains virtual functionssize()
andextract_entries()
.FEValues
is one of the most expensive things to compile so reducing the number of instantiations in it by about an of magnitude (by switching from instantiation over all vector classes to instantiation over all scalars) would help a lot.One disadvantage to this approach is that we need to
either delete some checks on vector sizes ormakesize()
virtual.