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
Vectorize NonMatching::MappingInfo #15137
Vectorize NonMatching::MappingInfo #15137
Conversation
Very nice! |
*/ | ||
std::vector<unsigned int> unit_points_index; | ||
AlignedVector<unsigned int> unit_points_index; |
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 need to be AlignedVector
? In general, we've been trying to use AlignedVector
only where necessary, i.e., large data structures (where we might profit from first-touch and similar) and for VectorizedArray
fields. (The latter will be resolved once we require C++17, because then std::vector
can respect alignment of types > 16 bytes, i.e., VectorizedArray
.)
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 inspired by MappingInfoStorage
, see
AlignedVector<unsigned int> quadrature_point_offsets; |
I can use std::vector
if it aligns the memory properly for unsigned int
.
/rebuild |
aux.resize(dim - 1); | ||
aux[0].resize(n_original_q_points); | ||
if (dim > 2) | ||
aux[1].resize(n_original_q_points); |
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 is this better?
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.
@jh66637 this?
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 am not sure if this was the initial intention for this change, but with these changes, empty quadrature
s can be handled. I think in case of an empty quadrature rule a shortcut could be made, i.e., if (quadrature.size() == 0) return;
in the first line of the function (or sth. similar).
@bergbauer @peterrum What do you think about this?
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.
In my opinion the shortcut should not be in this function but in the reinit*
functions of MappingInfo
. Above change is necessary to resize the inner AlignedVector
s correctly which is necessary if the InternalData
object is reused.
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 goes to the right direction. I have some small comments left.
internal::FEPointEvaluation:: | ||
EvaluatorTypeTraits<dim, n_components, Number>::set_value( | ||
val_and_grad.first, v, values[qb * stride + v]); | ||
for (unsigned int v = 0; v < stride && q + v < n_q_points_scalar; ++v) |
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.
Is the compiler able to see that the second condition is a subset of the outer loop in line 1574 and hence removes the if
statement altogether in vectorized mode with stride = 1
?
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.
mapping_data.jacobians[point_index * n_lanes + v][d][s]; | ||
return vectorized_jacobian; | ||
AssertIndexRange(point_index, n_q_points); | ||
Assert(jacobian_ptr != nullptr, ExcMessage("jacobian_ptr is not set!")); |
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 message does not really help. I think in the case of FEEval
the message tells you what to do:
dealii/include/deal.II/matrix_free/fe_evaluation.h
Lines 4522 to 4524 in aef0f70
Assert(this->jacobian != nullptr, | |
internal::ExcMatrixFreeAccessToUninitializedMappingField( | |
"update_gradients")); |
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 you suggesting declaring an own exception with a verbose message what to do or to improve the current messages in place?
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 have a verbose exception now which tells the user what to do!
read_value(const ScalarNumber vector_entry, | ||
const unsigned int component, | ||
value_type & result) | ||
scalar_value_type &result) |
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 looks odd. Different styles ScalarNumber
vs. scalar_value_type
. Could we write ScalarValueType
. This is not really something what the user should use!?
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 style dates back to the first implementation of this class and is therefore not the scope of this PR. I agree that it should be ScalarValueType
. This should be done in a follow-up. The user should not use this but we expose it publicly with the using
statements at the top of FEPointEvaluation
.
mapping_data.initialize(quadrature.size(), update_flags_mapping); | ||
|
||
// reuse internal_mapping_data for MappingQ to avoid memory allocations | ||
if (const MappingQ<dim, spacedim> *mapping_q = |
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 (const MappingQ<dim, spacedim> *mapping_q = | |
if (const MappingQ<dim, spacedim> * = |
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.
Done
9e42a0d
to
0f1cad6
Compare
|
0f1cad6
to
17a4b28
Compare
This PR proposes to vectorize
NonMatching::MappingInfo
depending on the newly introduced template parameterNumber
. As this class interacts withFEPointEvaluation
, which is vectorized internally also for scalarNumber
template arguments, the unit points are always stored vectorized to make them easily accessible.To enable vectorized storage, separate
AlignedVector
objects are created for Jacobians, ... and a temporaryinternal::FEValuesImplementation::MappingRelatedData
local object is used to use the interfaces whichMapping
provides to compute mapping data.The result is a 100% - 10% speedup in throughput of
FEPointEvaluation
depending on the polynomial degree and the dimension of the problem in my Laplace type benchmark.