-
Notifications
You must be signed in to change notification settings - Fork 247
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
[Core] Remove push_back from ModelPart #12903
base: master
Are you sure you want to change the base?
Conversation
Can you use the benchmark to see if there is an improvement? |
I will further review once the CI passes |
template<class TReturnValueType> | ||
struct ReferenceGetter | ||
{ | ||
template<class TInputValueType> |
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.
wow, this needs some explanation to me.
and the GetPointer even more...
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.
comments are added for the use case.
kratos/includes/model_part.h
Outdated
}); | ||
|
||
//now add to the root model part | ||
Container<TContainerType>::GetContainer(p_root_model_part->GetMesh()).insert(begin, end); |
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.
by adding always to the root all of them, a reserve is done in the pointer vector set on the root which increases its 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.
On the other hand, it is not always good to call shrink_to_fit
as well. In the new design, if a user tries to add a range to a submodel part which is a sub-set of the one of the parent model parts, then it will not reserve the parent model parts which a super set of the range being added. I think this solves this problem partially.
In any case, I can expose the method shrink_to_fit
, but I think this should be done if required only.
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.
sorry, but then with the current implementation the size will always grow?
Hi all (@loumalouomega @roigcarlo @rubenzorrilla @RiccardoRossi @pooyan-dadvand @matekelemen @philbucher ) This is ready to be reviewed. I did the performance benchmark as well. The results are attached herewith. I did not put all the benchmarks in the benchmarks for model part because some of them are not supported by the existing implementation. Long story short -> Benchmarks shows that the new implementation is faster. Explanation of the benchmarks: All the benchmarks were run with
|
I have trouble understanding these graphs. Can you help me a bit plz? |
@matekelemen I updated the original comment with the explanations. |
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.
blocking as there are some inefficiencies
// here we can safely use the insert with the rElements.end() as the hint | ||
// because, when reading, we can assume that it was written in the | ||
// sorted order within HDF5. | ||
rElements.insert(rElements.end(), p_elem); |
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 not efficient as you may be creating it out of order
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 cannot be out of order, because we assume HDF5 files are written by the HDF5Application
, hence when we write, we always write in the sorted order.
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.
then i do not understand the role of mIds ...
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.
wait, mIds is ordered?
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'll accept the comment, but ... what if somone writes the hdf5 "by hand"? in that case it will be enormously expensive, correct?
// here we can safely use the insert with the rNodes.end() as the hint | ||
// because, when reading, we can assume that it was written in the | ||
// sorted order within HDF5. | ||
rNodes.insert(rNodes.end(), p_node); |
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.
same
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.
Same comment as before
@@ -1199,7 +1227,10 @@ class PointerVectorSet final | |||
// which is harder to guess, and cryptic. Hence, using the decltype. | |||
using iterator_value_type = std::decay_t<decltype(*Iterator)>; | |||
|
|||
if constexpr(std::is_same_v<iterator_value_type, std::remove_cv_t<TPointerType>>) { | |||
if constexpr(std::is_same_v<TIteratorType, iterator> || std::is_same_v<TIteratorType, reverse_iterator>) { |
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.
@roigcarlo can you take a look into GetPointer and GetReference? these are difficult functions and i am quite afraid of their implications
// here we can safely use the insert with the rElements.end() as the hint | ||
// because, when reading, we can assume that it was written in the | ||
// sorted order within HDF5. | ||
rElements.insert(rElements.end(), p_elem); |
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.
then i do not understand the role of mIds ...
std::sort(first, last, CompareKey()); | ||
auto new_last = std::unique(first, last, EqualKeyTo()); | ||
SortedInsert(first, new_last); | ||
} else { |
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.
sorry i cannot understand 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.
@Myself, this is for the case in which what i comment above is not possible ... still the comment above still holds
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.
then i do not understand the role of mIds ...
mIds
are storing the list of ids from a PVS
when writing. So each rank will write its own local PVS
ids which are sorted. The final list of mIds
in the .h5
file won't be sorted, but it will be sorted for each partition in each rank. So when you read it also, each partition will read its portion of the mIds
from the .h5
file whill will be an already sorted ids list. hence the rElements.insert(rElements.end(), p_elem)
will have the hint which is valid, then PVS
will do a push_back at the backend.
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.
sorry i cannot understand this ...
This is to support iterators coming from const std::vector<NodeType::Pointer>
for the insertion. There we need to sort and unique of the incoming iterators which is not allowed. So, you have to make a copy and do the sort and unique. This has additional overhead, but it cannot be avoided if we allow iterators coming from immutable containers.
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.
yes i understand, however think at the following:
std::vector my_pointer_list ....
pvs.insert(my_pointer_list.begin(), my_pointer_list.end(); //it works
//but here my_pointer_list is ordered... i would not expect this. Is that something we accept? (open question...i am not sure of what would be a standardized behaviour)
indeed
const std::vector my_pointer_list .... //CONST!
//pvs.insert(my_pointer_list.begin(), my_pointer_list.end(); //will int principle not compile
pvs.insert(my_pointer_list.cbegin(), my_pointer_list.cend(); //i understand you will eventually remove the constness inside. Did i get it wrong?
//but here my_pointer_list is NOT ordered (ok, since it was const)
but now in the PVS will i have const pointers? if i do not, aren't we removing the constness wrongly?
to me this is a difficuly programming question, but i am really not clear about what will happen and OF WHAT SHOULD HAPPEN
<< ModelPart::Container<container_type>::GetEntityName() | ||
<< " with Id " << *it_id << " does not exist in the root model part"; | ||
|
||
// here the hint is valid, hence this will be a simple push_back within the PVS. |
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.
oh, you mean that under the hood it will eb a push_back. Ok
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.
exactly :)
// here we can safely use the insert with the rElements.end() as the hint | ||
// because, when reading, we can assume that it was written in the | ||
// sorted order within HDF5. | ||
rElements.insert(rElements.end(), p_elem); |
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.
wait, mIds is ordered?
SortedInsert(first, new_last); | ||
if constexpr(std::is_assignable_v<decltype(*std::declval<InputIterator>()), decltype(*std::declval<InputIterator>())>) { | ||
// first sorts the input iterators and make the input unique if the iterators are assignable | ||
std::sort(first, last, CompareKey()); |
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 means that you are changing the order of the input "in place", correct?
I am not sure if this is what you would expect. I am not sure of what is the praxis in this context. Do you have it clear?
std::sort(first, last, CompareKey()); | ||
auto new_last = std::unique(first, last, EqualKeyTo()); | ||
SortedInsert(first, new_last); | ||
} else { |
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.
@Myself, this is for the case in which what i comment above is not possible ... still the comment above still holds
@@ -39,8 +39,8 @@ namespace Kratos | |||
|
|||
// Auxiliar vectors to store pointers to the new entities | |||
// These vectors will be use when renumbering the entities ids. | |||
ModelPart::NodesContainerType new_nodes_vect; | |||
ModelPart::ConditionsContainerType new_conds_vect; | |||
std::vector<Node::Pointer> new_nodes_vect; |
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 ok to me but @rubenzorrilla i think this is your code, can you take a look
removing my block because of the explanation. However i stil lthink some of the comments are relvant
📝 Description
This PR removes uses of
PointerVectorSet::push_back
method from theModelPart
. Followings are the modifications.erase_count
was not calculated correctly, hence the reserved size is wrong. This was fixedContainer
class which can retireve the correctPointerVectorSet
container from a givenMesh
, and itsstd::string
for nice error message output.Geometries
container cannot be templated since it is in theModelPart
, and all the otherPointerVectorSet
containers are in theMesh
].🆕 Changelog
PointerVectorSet::push_back
uses from theModelPart
Nodes
/Conditions
/Elements
/MasterSlaveConstraints
.Container
class with templates to retrieve givenPointerVectorSet
container from a mesh.