While working with very large meshes, @mchavezmodena and I identified a serious memory blow-up occurring during face construction.
We traced the problem to the allocation of self%faces in multiple mesh-reading routines, for example:
https://github.com/loganoz/horses3d-gpu/blob/b4a26d1a68dd6dfe70b1179f97b224829c4a86ff/Solver/src/libs/mesh/Read_HDF5Mesh_HOPR.f90#L361
https://github.com/loganoz/horses3d-gpu/blob/b4a26d1a68dd6dfe70b1179f97b224829c4a86ff/Solver/src/libs/mesh/Read_HDF5Mesh_HOPR.f90#L762
https://github.com/loganoz/horses3d-gpu/blob/b4a26d1a68dd6dfe70b1179f97b224829c4a86ff/Solver/src/libs/mesh/Read_SpecMesh.f90#L262
(etc... it occurs in all mesh constructors!)
The case where we found it
We encountered the problem in a large mesh with numberOfFaces = 47607081 that was crashing with
ALLOCATE: 718295638128 bytes requested
In other words, it was trying to allocate 718GB of storage for an array with "only" ~47.6M entries. This is surprising because:
- The
Face derived type has only some (<30) integer/logical scalars + no large data allocated at construction time
https://github.com/loganoz/horses3d-gpu/blob/b4a26d1a68dd6dfe70b1179f97b224829c4a86ff/Solver/src/libs/mesh/FaceClass.f90#L63
- The nested types (MappedGeometryFace, FaceStorage_t) only contain allocatable arrays, which are unallocated at this stage.
- A rough estimate suggests that one
Face object should only require a few hundred bytes.
... So the numbers did not add up.
Cause of the issue
Many Fortran compilers must store allocatable component descriptors inside every element of an array of derived types. These descriptors include lower/upper bounds, rank, type info, vtable/type-binding pointers, and other bookkeeping fields. Therefore, the compiler can explode the required size if you have arrays of derived types with allocatable components. And this is exactly what's happening here.
While working with very large meshes, @mchavezmodena and I identified a serious memory blow-up occurring during face construction.
We traced the problem to the allocation of self%faces in multiple mesh-reading routines, for example:
https://github.com/loganoz/horses3d-gpu/blob/b4a26d1a68dd6dfe70b1179f97b224829c4a86ff/Solver/src/libs/mesh/Read_HDF5Mesh_HOPR.f90#L361
https://github.com/loganoz/horses3d-gpu/blob/b4a26d1a68dd6dfe70b1179f97b224829c4a86ff/Solver/src/libs/mesh/Read_HDF5Mesh_HOPR.f90#L762
https://github.com/loganoz/horses3d-gpu/blob/b4a26d1a68dd6dfe70b1179f97b224829c4a86ff/Solver/src/libs/mesh/Read_SpecMesh.f90#L262
(etc... it occurs in all mesh constructors!)
The case where we found it
We encountered the problem in a large mesh with
numberOfFaces = 47607081that was crashing withIn other words, it was trying to allocate 718GB of storage for an array with "only" ~47.6M entries. This is surprising because:
Facederived type has only some (<30) integer/logical scalars + no large data allocated at construction timehttps://github.com/loganoz/horses3d-gpu/blob/b4a26d1a68dd6dfe70b1179f97b224829c4a86ff/Solver/src/libs/mesh/FaceClass.f90#L63
Faceobject should only require a few hundred bytes.... So the numbers did not add up.
Cause of the issue
Many Fortran compilers must store allocatable component descriptors inside every element of an array of derived types. These descriptors include lower/upper bounds, rank, type info, vtable/type-binding pointers, and other bookkeeping fields. Therefore, the compiler can explode the required size if you have arrays of derived types with allocatable components. And this is exactly what's happening here.