fix: add missing @:DEALLOCATE in simulation modules#1476
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #1476 +/- ##
==========================================
- Coverage 60.48% 60.45% -0.04%
==========================================
Files 83 83
Lines 19888 19907 +19
Branches 2951 2954 +3
==========================================
+ Hits 12030 12035 +5
- Misses 5864 5871 +7
- Partials 1994 2001 +7 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Code ReviewReviewed the diff by checking each newly-added OverviewThis PR (part of #1459) replaces a few bare Correctness — verified symmetric ✅For these, the new deallocation matches the allocation guard and structure exactly:
Issue — incomplete deallocation of
|
Add matching @:DEALLOCATE calls in: - m_derived_variables - m_global_parameters - m_hyperelastic - m_rhs - m_riemann_solvers - m_time_steppers Remaining files not yet addressed: - src/common/m_boundary_common.fpp, m_helper.fpp, m_model.fpp, m_mpi_common.fpp, m_variables_conversion.fpp - src/post_process/m_start_up.fpp - src/simulation/m_acoustic_src.fpp, m_bubbles_EE.fpp, m_ibm.fpp (pending PR MFlowCode#1378), m_qbmm.fpp Part of MFlowCode#1459
- m_rhs: fix incomplete qL_prim/qR_prim teardown by walking nested %vf/%sf structure before deallocating containers - m_boundary_common: replace plain deallocate with @:DEALLOCATE - m_mpi_common: replace plain deallocate with @:DEALLOCATE, mirror unified memory path in finalization - m_variables_conversion: add missing @:DEALLOCATE for Res_vc - m_start_up (post_process): annotate FFT arrays as program-lifetime - m_helper, m_model, m_acoustic_src, m_bubbles_EE, m_qbmm: annotate allocations as program-lifetime (no finalize subroutine) Part of MFlowCode#1459
- m_ibm: add @:DEALLOCATE for ghost_points, simplify models deallocation, replace plain deallocate for recv_* arrays - lint_source.py: add check_allocate_deallocate_pairing() to flag @:ALLOCATE without matching @:DEALLOCATE anywhere in src/ Known program-lifetime exemptions are listed explicitly Closes MFlowCode#1459
31573f7 to
9c819d4
Compare
|
Added check_allocate_deallocate_pairing() to lint_source.py to catch any future @:ALLOCATE without a matching @:DEALLOCATE. Currently using a PROGRAM_LIFETIME_EXEMPTIONS set to suppress known pre-existing violations in modules without a finalize subroutine. Open to suggestions on a better design — e.g. an inline comment tag like ! @:PROGRAM_LIFETIME near the allocation — if the hardcoded list is too fragile long-term. |
81de5d4 to
3b3a25e
Compare
…e pairing Replace global exemption list with per-file initialize/finalize subroutine pairing. Only checks modules with both s_initialize_* and s_finalize_* subroutines. Known pre-existing missing deallocations are listed separately.
14a5eb8 to
5b4f846
Compare
recv_forces_snap, recv_torques_snap, recv_ids, and recv_ft are allocated with plain allocate and only touched on the GPU via transient copyin/copy clauses, so they never enter the persistent present table. Using @:DEALLOCATE made the OpenACC runtime attempt an exit-data delete on arrays not in the present table, causing find_in_present_table failures on Frontier. Reverted to plain deallocate to match their allocation.
…S87/MFC into fix/deallocate-missing-arrays
There was a problem hiding this comment.
Pull request overview
Note
Copilot couldn't run its full agentic review because no GitHub Actions runner was available. Make sure your repository has a runner available to run Copilot's review, or add a copilot-setup-steps.yml file specifying one with the runs-on attribute. See the docs for more details.
This PR aims to prevent memory leaks by ensuring @:ALLOCATE calls in module initialization paths have matching @:DEALLOCATE calls in finalize paths, and adds a linter rule to detect missing pairings.
Changes:
- Added a new linter check to flag
@:ALLOCATEins_initialize_*without corresponding@:DEALLOCATEins_finalize_*. - Added/standardized
@:DEALLOCATEusage across multiple Fortran modules (simulation/common/post_process) and replaced some rawdeallocate/ GPU directives with the macro. - Added “program-lifetime allocation” notes in modules that intentionally do not implement
s_finalize_*.
Reviewed changes
Copilot reviewed 16 out of 16 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| toolchain/mfc/lint_source.py | Adds linter rule to enforce ALLOCATE/DEALLOCATE pairing across init/finalize subroutines |
| src/simulation/m_time_steppers.fpp | Adds missing deallocations in module finalize routine |
| src/simulation/m_rhs.fpp | Replaces manual deallocation with macro and adds missing cleanup for allocated arrays |
| src/simulation/m_qbmm.fpp | Documents program-lifetime allocations where no finalize exists |
| src/simulation/m_ibm.fpp | Simplifies deallocation logic and adds missing deallocation for ghost_points |
| src/simulation/m_hyperelastic.fpp | Adds missing deallocation for Gs_hyper |
| src/simulation/m_global_parameters.fpp | Adds missing deallocation for ptil under bubbles_euler |
| src/simulation/m_derived_variables.fpp | Switches to macro deallocation; changes where FD coefficient arrays are deallocated |
| src/simulation/m_bubbles_EE.fpp | Documents program-lifetime allocations where no finalize exists |
| src/simulation/m_acoustic_src.fpp | Documents program-lifetime allocations where no finalize exists |
| src/post_process/m_start_up.fpp | Adds note about program-lifetime allocations (but currently shows duplicated allocation line) |
| src/common/m_variables_conversion.fpp | Adds missing Res_vc deallocation in viscous path |
| src/common/m_mpi_common.fpp | Uses @:DEALLOCATE for MPI buffers when not in NV unified memory path |
| src/common/m_model.fpp | Documents program-lifetime GPU allocations where no finalize exists |
| src/common/m_helper.fpp | Documents program-lifetime allocations where no finalize exists |
| src/common/m_boundary_common.fpp | Replaces raw deallocate calls with @:DEALLOCATE |
| @:ALLOCATE(data_in(Nx*Nyloc*Nzloc)) | ||
| @:ALLOCATE(data_in(Nx*Nyloc*Nzloc)) |
| if (probe_wrt) then | ||
| deallocate (accel_mag, x_accel) | ||
| @:DEALLOCATE(accel_mag) | ||
| @:DEALLOCATE(x_accel) | ||
| if (n > 0) then | ||
| deallocate (y_accel) | ||
| @:DEALLOCATE(y_accel) | ||
| if (p > 0) then | ||
| deallocate (z_accel) | ||
| @:DEALLOCATE(z_accel) | ||
| end if | ||
| end if | ||
| @:DEALLOCATE(fd_coeff_x) | ||
| if (n > 0) then | ||
| @:DEALLOCATE(fd_coeff_y) | ||
| end if | ||
| if (p > 0) then | ||
| @:DEALLOCATE(fd_coeff_z) | ||
| end if | ||
| end if |
| allocate_re = re.compile(r"@:ALLOCATE\((\w[\w%]*)") | ||
| deallocate_re = re.compile(r"@:DEALLOCATE\((\w[\w%]*)") |
| for name, lineno in allocated.items(): | ||
| if name not in deallocated and name not in KNOWN_MISSING: | ||
| errors.append(f" {rel}:{lineno} @:ALLOCATE({name}...) in s_initialize_* has no matching " f"@:DEALLOCATE in s_finalize_*. Fix: add @:DEALLOCATE in the finalize subroutine") |
| all_errors.extend(check_fypp_list_duplicates(repo_root)) | ||
| all_errors.extend(check_duplicate_lines(repo_root)) | ||
| all_errors.extend(check_hardcoded_byte_size(repo_root)) | ||
| all_errors.extend(check_allocate_deallocate_pairing(repo_root)) |
…op duplicate data_in allocate
Claude Code ReviewHead SHA: 8308a00 Files changed:
FindingsMemory leak in
|
Description
Part of #1459
Add matching @:DEALLOCATE calls in:
Remaining files not yet addressed:
Type of change
Testing
Ran ./mfc.sh test -j 4 locally on Ubuntu/WSL with GNU compiler and MPI.
578 tests passed, 0 failed. Spelling and lint checks passed.
Checklist
See the developer guide for full coding standards.
GPU changes (expand if you modified
src/simulation/)AI code reviews
Reviews are not triggered automatically. To request a review, comment on the PR:
@coderabbitai review— incremental review (new changes only)@coderabbitai full review— full review from scratch/review— Qodo review/improve— Qodo code suggestions@claude full review— Claude full review (also triggers on PR open/reopen/ready)claude-full-review— Claude full review via label