-
Notifications
You must be signed in to change notification settings - Fork 421
Adding support to memory collection of Particles and MultiFabs within a grid #4629
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
Adding support to memory collection of Particles and MultiFabs within a grid #4629
Conversation
Src/Base/AMReX_MultiFabUtil.H
Outdated
// We have tried to work with more templated version, but it didn't work. What is the most appropriate way to do it? | ||
LayoutData<std::size_t> CapacityOfFabs (BoxArray const& ba, | ||
DistributionMapping const& dm, | ||
std::vector<MultiFab*> const& mfs); |
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.
Could we remove BoxArray and DistributionMapping from the function arguments? The assumption here is all multifabs must have the same boxarray (ignoring the index type) and distributionmapping.
Could make argument be Vector<MultiFab const*> const& mfs
. Vector provides bound check if assertion is on. We are not changing the data in mulitfabs. Thus we should pass them in as const*
.
If we want it be consistent with how it's done in particle container, we could make this a member function of FabArray. That might be better. That will also solve the template "issue".
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 believe it's possible to remove the BoxArray
and the DistributionMapping
if we have a way to access this information from MultiFabUtil
. In the implementation at the .cpp
file, we need those to create our LayoutData
object that will hold the memory information for each box (7a29e92#diff-e104e0f29e7a0e37ad2ee839c42e2c317091f995556dcc35c18b47d66506761fR67)
Sounds good about the Vector! We weren't sure if our approach was the best :)
We have tried to implement this function over FabArrayUtil
, and we had a hard time calling it from an "user-end" code. If you have a suggestion on how to make it work in the FabArray I would appreciate!
For context, I have tested both implementations using examples from the AMReX Tutorials.
More specifically, I have used this example for the Particles https://github.com/AMReX-Codes/amrex-tutorials/blob/main/ExampleCodes/Particles/NeighborList/main.cpp and this for the MultiFabs https://github.com/AMReX-Codes/amrex-tutorials/blob/main/ExampleCodes/Basic/HeatEquation_EX0_C/Source/main.cpp
On the MultiFabs, I used the following code to get the memory information
std::vector<amrex::MultiFab*> multifabs_to_check;
multifabs_to_check.push_back(&phi_old);
multifabs_to_check.push_back(&phi_new);
amrex::LayoutData<std::size_t> mem_usage = amrex::CapacityOfFabs(ba, dm, multifabs_to_check);
long total_bytes = 0;
for (amrex::MFIter mfi(mem_usage); mfi.isValid(); ++mfi) {
amrex::Print() << "Box " << mfi.index() << " uses "
<< mem_usage[mfi] << " bytes\n";
}
Please, let me know if I am missing something or if there's another approach for 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.
MultiFab is derived from FabArray, which has member functions that return BoxArray and DistributionMapping used to build the MultiFab. Something like
auto const& ba = mf_ptr->boxArray();
auto const& dm = mf_ptr->DistributionMap();
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.
Thank you! I have pushed an updated version with adjustments. I have tested with the same code example as shared above and got the same results, so I believe it is producing correct data.
About the point on
Vector provides bound check if assertion is on.
I am not doing any assertions at this point. Should I?
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 @WeiqunZhang's suggestion to make CapacityofFabs
a member function of FabArray
. Other than that, looks good to me.
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.
Nice, do you also want to change the particle version to use the same interface? I think this will be helpful when there is more than on ParticleContainer
in an application (as there is in WarpX).
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 think it makes sense to change ParticleContainer
to this format! The only concern is that doing so will result in this function having a slightly different signature than other ParticleContainer
functions that perform similar tasks, but are not directly memory-related (like https://github.com/AMReX-Codes/amrex/blob/development/Src/Particle/AMReX_ParticleContainerI.H#L496). Do you think this is 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.
I'm okay with that. That function has a slightly different use case. I believe it was added for IO, where we write separate files for each species anyway, so we don't need to aggregate the totals over multiple species, as you do 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.
Ok! Working on it!
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! 7fb20d4
Src/Base/AMReX_FabArray.H
Outdated
template <class F, std::enable_if_t<IsBaseFab<F>::value,int> FOO> | ||
void | ||
FabArray<FAB>::capacityOfFabs(LayoutData<std::size_t>& mem) { | ||
// Should we have assertions here? What should be asserted? |
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 would be good to assert that mem
and *this
use the same BoxArray and DistributionMap. You can use the CellEqual
method for BoxArray and the ==
operator for the DistributionMap.
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.
Got it! Just pushed the assertion on 7a29e92
Co-authored-by: Andrew Myers <atmyers@lbl.gov>
I have committed fixes for errors pointed out by two pipelines. There were two other pipelines "oneAPI" that failed because of a GPG key error. Not sure if I can fix this on my side |
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 function is straightforward enough that I don't think we need to add tests for it.
Src/Base/AMReX_FabArray.H
Outdated
void setDomainBndry (value_type val, int strt_comp, int ncomp, const Geometry& geom); | ||
|
||
// Get capacity of the FabArray | ||
template <class F=FAB, std::enable_if_t<IsBaseFab<F>::value,int> = 0> |
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.
For flexibility, we could also make the integer type a template typename here and for in particle containers. For example,
template <typename I, class F=FAB, std::enable_if_t<IsBaseFab<F>::value && std::is_integral_v<I> && sizeof(I) >= sizeof(Long), int> = 0>
void capacityOfFabs (LayoutData<I>& mem) const;
And in the implementation, we also want to do explicit static_cast before adding the values.
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! Working on the update for 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.
Actually, do you think it's worth doing it? Because I know that it is a best practice in C++ to use std::size_t
for memory-related math (size_t
was created for holding sizeof
returns https://en.cppreference.com/w/cpp/types/size_t.html)
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.
Actually the best practice is proably to avoid unsigned integers in almost all cases.
Even Stroustrup does not like unsigned integers. https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/p1428r0.pdf Stroustrup said,
Unfortunately, sizeof yields an unsigned (and it would be hard to change that), but we don’t have to
follow that for all types with something to do with sizes
Java does not even have build-in unsigned integer types. https://www.artima.com/articles/james-gosling-on-java-may-2001 Goshling said,
In programming language design, one of the standard problems is that the language grows so complex that nobody can understand it. One of the little experiments I tried was asking people about the rules for unsigned arithmetic in C. It turns out nobody understands how unsigned arithmetic in C works. There are a few obvious things that people understand, but many people don't understand it.
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.
Hmm, got it! Interesting that the unsigned is such unknown territory. Will start working on including the template you suggested in both functions
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.
Just update both function signatures with the new template 55d4a34
Co-authored-by: Weiqun Zhang <WeiqunZhang@lbl.gov>
Co-authored-by: Weiqun Zhang <WeiqunZhang@lbl.gov>
Co-authored-by: Weiqun Zhang <WeiqunZhang@lbl.gov>
Co-authored-by: Weiqun Zhang <WeiqunZhang@lbl.gov>
Co-authored-by: Weiqun Zhang <WeiqunZhang@lbl.gov>
Co-authored-by: Weiqun Zhang <WeiqunZhang@lbl.gov>
I asked Jessica to add those. Maybe these new functions could just be called somewhere in an existing test, instead creating new ones? |
I could include the Particles call in the |
I think that if you 1) Remove the new particle test added in this PR, in lieu of the modification to the existing NeighborList one, and 2) move/rename the MultiFab one to |
Sounds good! Did that on 64e1e84 |
LGTM. Hopefully, one last thing. For the test to run, we need to add it to Line 128 of amrex/Tests/CMakeLists.txt. |
Cool! Pushed here 2b01097 |
Pull in AMReX-Codes/amrex#4629 for #6166. Signed-off-by: Axel Huebl <axel.huebl@plasma.ninja>
Summary
This PR adds functions to return memory usage from
Particles
andFabArray
/MultiFabs
within a grid/box. The main goal is to use this information for load balancing. We aim to consider the memory allocated to a worker as a factor in the load-balancing algorithms for AMReX, so there is a need to capture specific grid/box memory information.Additional background
Checklist
The proposed changes: