-
Notifications
You must be signed in to change notification settings - Fork 707
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
Template TpetraWrappers::SparseMatrix::vmult on the vector type. #16614
Conversation
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 will leave this one to @masterleinad given that it does all of this view magic...
template <typename Number, typename MemorySpace> | ||
Number * | ||
begin(LinearAlgebra::TpetraWrappers::Vector<Number, MemorySpace> &V) | ||
{ | ||
return V.trilinos_vector().getDataNonConst().get(); | ||
} | ||
|
||
template <typename Number, typename MemorySpace> | ||
const Number * | ||
begin(const LinearAlgebra::TpetraWrappers::Vector<Number, MemorySpace> &V) | ||
{ | ||
return V.trilinos_vector().getData().get(); | ||
} | ||
|
||
template <typename Number, typename MemorySpace> | ||
Number * | ||
end(LinearAlgebra::TpetraWrappers::Vector<Number, MemorySpace> &V) | ||
{ | ||
return V.trilinos_vector().getDataNonConst().get() + | ||
V.trilinos_vector().getLocalLength(); | ||
} | ||
|
||
template <typename Number, typename MemorySpace> | ||
const Number * | ||
end(const LinearAlgebra::TpetraWrappers::Vector<Number, MemorySpace> &V) | ||
{ | ||
return V.trilinos_vector().getData().get() + | ||
V.trilinos_vector().getLocalLength(); | ||
} |
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.
Instead of providing these overloads here, why not just add begin()
and end()
functions to the LinearAlgebra::TpetraWrappers::Vector
class? Then you won't need any of these functions 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.
Sure, I will change this!
But do all other vector classes In deal.II implement begin()
and end()
?
I saw, at least dealii::vector<Number>
has a begin()
and end()
method 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.
Good question. I don't actually know whether all vectors have begin()
and end()
, but even if they did it's not clear what semantics that would follow: Only the locally owned? locally stored? all elements?
Perhaps what you have is better. In fact, perhaps it would be better to call these functions begin_locally_owned()
and end_locally_owned()
to make this clear.
Kokkos::View< | ||
typename VectorType::impl_scalar_type **, | ||
Kokkos::LayoutLeft, | ||
Kokkos::Device<typename MemorySpace::kokkos_space::execution_space, | ||
typename MemorySpace::kokkos_space>> | ||
kokkos_view_src(raw_src, src_local_size); |
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.
Do you really need a two-dimensional View
here?
Kokkos::View< | |
typename VectorType::impl_scalar_type **, | |
Kokkos::LayoutLeft, | |
Kokkos::Device<typename MemorySpace::kokkos_space::execution_space, | |
typename MemorySpace::kokkos_space>> | |
kokkos_view_src(raw_src, src_local_size); | |
Kokkos::View< | |
typename VectorType::impl_scalar_type *, | |
typename MemorySpace::kokkos_space> | |
kokkos_view_src(raw_src, src_local_size); |
How do you know the memory space of InputVectorType
?
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.
How do you know the memory space of
InputVectorType
?
Good point!
I thought I had to provide the memory space of the target vector. But you are right; this is not true. We need to provide the memory space of the source vector. So we need to be way more careful here...
For most vector types, the memory space is always Host
. The only exceptions I am aware of is the TpetraWrappers::Vector<Number, MemorySpace>
and the distributed::Vector<Number, MemorySpace>
.
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.
Do you really need a two-dimensional
View
here?How do you know the memory space of
InputVectorType
?
The Tpetra::Vector always expects a two-dimensional View, as far as I know.
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.
OK. In this case, you still have to provide extents for both dimensions in the View constructor.
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.
OK. In this case, you still have to provide extents for both dimensions in the View constructor.
I am not that experienced with Kokkos::View
, what constructor should I use 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.
It should be
Kokkos::View<
typename VectorType::impl_scalar_type **,
Kokkos::LayoutLeft,
Kokkos::Device<typename MemorySpace::kokkos_space::execution_space,
typename MemorySpace::kokkos_space>>
kokkos_view_src(raw_src, src_local_size, 1);
so that you provide the pointer and an argument for the extent in every dimension. This should be strictly enforced in newer Kokkos
versions. Also, there is not much of a point to provide a full Device
template argument. In the end, we only need the MemorySpace
. For managed Views you could provide an execution space instance as runtime argument to make sure it uses a particular stream (and fences less) or even decide not to initialize the allocation at all. None of that really matters for unmanaged Views like here, of course.
// For the src vector: | ||
// create a Kokkos::View from the src vector | ||
typename VectorType::impl_scalar_type *raw_src = | ||
reinterpret_cast<typename VectorType::impl_scalar_type *>( |
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.
Why do you need a reinterpret_cast
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.
It seems like the Tpetra::Vector
expects this type.
Since this is just a complicated alias for Number
, I can give it a try and remove this cast.
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 would be very suspicious of any reinterpret_cast
we are doing in these classes since we don't really have a buffer that we would use with placement new. Whenever we need a different type we should copy values instead.
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 agree with this. x.begin()
does not always return a pointer. It could just be an iterator. reinterpret_cast
will in such cases not result in anything useful, with no error message. I think there ought to be a better way.
What are the types you're casting 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.
We do not need the reinterpret_cast
here. But at another point, we need a const_cast
.
I specialized the function so we know which vector type we are working on, so we can ensure that the cast is working correctly.
I reworked the |
typename SparseMatrix<Number, MemorySpace>::VectorType tpetra_src( | ||
M.trilinos_matrix().getDomainMap(), kokkos_dual_view_src); | ||
|
||
M.trilinos_matrix().apply(tpetra_src, tpetra_dst, mode, alpha, beta); |
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.
Does this also sync
the DualView
?
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 just assumed it does. I just verified it passed the test:
trilinos_tpetra/sparse_matrix_vector_08.cc
Since it passed that test, I assumed it was okay as it was.
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.
If there is only one memory space, sync
doesn't do anything anyway. I think it's reasonable to assume that apply
makes sure the two Views
are in sync, though.
2aed16a
to
dda3577
Compare
typename SparseMatrix<Number, MemorySpace>::VectorType tpetra_src( | ||
M.trilinos_matrix().getDomainMap(), kokkos_dual_view_src); | ||
|
||
M.trilinos_matrix().apply(tpetra_src, tpetra_dst, mode, alpha, beta); |
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.
If there is only one memory space, sync
doesn't do anything anyway. I think it's reasonable to assume that apply
makes sure the two Views
are in sync, though.
You'll have to fix the indentation. diff --git a/include/deal.II/lac/trilinos_tpetra_sparse_matrix.templates.h b/include/deal.II/lac/trilinos_tpetra_sparse_matrix.templates.h
index 87a3723e0..6ba2d5613 100644
--- a/include/deal.II/lac/trilinos_tpetra_sparse_matrix.templates.h
+++ b/include/deal.II/lac/trilinos_tpetra_sparse_matrix.templates.h
@@ -83,9 +83,8 @@ namespace LinearAlgebra
dst.begin(), dst_local_size, 1);
// get a Kokkos::DualView
- auto mirror_view_dst =
- Kokkos::create_mirror_view_and_copy(typename MemorySpace::kokkos_space{},
- kokkos_view_dst);
+ auto mirror_view_dst = Kokkos::create_mirror_view_and_copy(
+ typename MemorySpace::kokkos_space{}, kokkos_view_dst);
typename SparseMatrix<Number, MemorySpace>::VectorType::dual_view_type
kokkos_dual_view_dst(mirror_view_dst, kokkos_view_dst);
@@ -99,9 +98,8 @@ namespace LinearAlgebra
const_cast<Number *>(src.begin()), src_local_size, 1);
// get a Kokkos::DualView
- auto mirror_view_src =
- Kokkos::create_mirror_view_and_copy(typename MemorySpace::kokkos_space{},
- kokkos_view_src);
+ auto mirror_view_src = Kokkos::create_mirror_view_and_copy(
+ typename MemorySpace::kokkos_space{}, kokkos_view_src);
typename SparseMatrix<Number, MemorySpace>::VectorType::dual_view_type
kokkos_dual_view_src(mirror_view_src, kokkos_view_src); Otherwise, this looks good to me now. |
11ca285
to
3874de7
Compare
Thank you for all the feedback! I fixed the indentation and squashed everything into one commit. |
3874de7
to
c205c21
Compare
/rebuild |
c205c21
to
9db41cd
Compare
I fixed the failing test. |
Rework from
LinearAlgebra::TpetraWrappers::SparseMatrix<Number, MemorySpace>::vmult
(andTvmult
,vmult_add
,Tvmult_add
) such that it takes arbritraty vector types.Initially, this was part of #16588, but I moved it into a separate pull request because it contains a few points I would like to discuss.
Each function of vmult, Tvmult, vmult_add, and Tvmult_add contains a part that converts the raw data of the input vectors into a Kokkos::DualView. I was thinking about moving that conversion into a separate (internal) function (and marking that function as inline).
And this is the most convenient way to convert the raw data from a vector into a Kokkos::DualView I came up with. But if there is a more elegant way to do that, please let me know!
Furthermore, we need a more elegant way to initialize all templates.
Since some tests include a
vmult
between aTrilinosWrappers::SparseMatrix
and adealii::Vector
, this should help with #16611 as well.