Repository navigation
RDCON: free each Galerkin element matrix once it is assembled (LU) - #352
Conversation
…s assembled The element matrices (cell%mat, 256 mpert^2 bytes per cell) and the global band (gal%mat) were both resident during assembly, and the band was zeroed up front. With LU, each element matrix is now freed right after it is added to the band, and the band is zeroed column by column only as assembly reaches it, so peak memory is about max(element matrices, band) instead of their sum. Cholesky keeps the element matrices, since its LU fallback reassembles from them; the fallback itself then frees them as above. Delta' is bit-identical. The saving needs an allocator that returns freed blocks to the system. glibc keeps freed ~1 MB blocks once its dynamic mmap threshold has risen above them; MALLOC_MMAP_THRESHOLD_=131072 in rdcon's environment keeps them mmapped. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
A note on solver choice: with this PR, |
…element matrices return to the system
matt-pharr
left a comment
There was a problem hiding this comment.
This is handy and great for doing scans. I made a tweak with an extra fortran file that fixes the behavior of this addition on mac. Darwin handles memory differently in compiled fortran applications so we have to make it explicit by hacking in this C symbol, but it works and is definitely an improvement. Thanks Stuart
RDCON's Galerkin solve keeps every element matrix (
cell%mat, about 256 mpert² bytes per cell) in memory while it builds the banded global matrix, and it zeroes the whole band up front. Both are resident at once, so the peak is roughly element matrices + band + right-hand sides. With many rational surfaces this reaches tens of GB: the DIII-D resistive example at n = 8 peaks at 34 GiB.With
solver = "LU", this PR frees each element matrix as soon as it has been added to the band. It also zeroes the band column by column only as assembly reaches it, so the element matrices drain while the band fills and the peak drops to about max(element matrices, band) + right-hand sides. Δ′ is bit-identical. Withsolver = "cholesky"the element matrices are kept, because the LU fallback reassembles from them; if the fallback is taken, it frees them in the same way. The first commit changesrdcon/gal.fonly.The memory only goes back to the system if the allocator returns freed blocks. glibc keeps freed blocks of this size once its dynamic mmap threshold has grown past them, so the second commit has rdcon fix that threshold itself on Linux:
rdcon/gal_mmap.Fcalls glibc'smallopt(M_MMAP_THRESHOLD, 131072)at the start ofgal_solve. This is the same as settingMALLOC_MMAP_THRESHOLD_=131072, so no environment variable is needed. The build definesHAVE_MALLOPTfor rdcon whenuname -sis Linux (install/RULES.inc). macOS has nomalloptand already returns these blocks, so there the call is compiled out. The "without the MALLOC setting" column below is the first commit alone on glibc.Checked with the second commit and no environment variable, DIII-D resistive example,
develop→ this PR, all outputs (delta_gw,pest3_data) byte-identical:GPEC examples, same machine,
develop→ this PR, both withMALLOC_MMAP_THRESHOLD_=131072:The
delta_gwandpest3_dataoutputs were byte-identical in all 12 example runs. On 32 reconstructed DIII-D equilibria at n = 1–4 (our GPEC branch with and without this commit), Δ′ was bit-identical in all 32, and the largest peak went from 37.9 to 24.8 GiB. The zip holds the script that runs the examples (run_demo.sh DEVELOP_DIR PR_DIR OUT), the plotting script, both tables and the plot.rdcon_free_mats_demo.zip
🤖 Generated with Claude Code