Skip to content

Avoid ST6 IRANGE heap allocations in source loops - #16

Merged
ezhilsabareesh8 merged 5 commits into
dev/2026.03from
ezhil_st6_irange_memory_growth_clean
Jul 6, 2026
Merged

ezhilsabareesh8 merged 5 commits into
dev/2026.03from
ezhil_st6_irange_memory_growth_clean

Conversation

@ezhilsabareesh8

@ezhilsabareesh8 ezhilsabareesh8 commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

This PR fixes the WW3 memory leak issue ACCESS-NRI/access-om3-configs#1003

The change removes repeated allocatable-function calls from hot ST6 source-term loops. These calls were causing allocator churn and steady RSS growth in long coupled ACCESS-OM3 runs using WW3.

What changed

The fix updates two WW3 source files:

model/src/w3src6md.F90
model/src/w3swldmd.F90

The affected ST6 routines were calling IRANGE() inside frequently executed source-term loops:

IKN = IRANGE(1,NSPEC,NTH)

IRANGE() returns an allocatable array. Although each allocation is small, these calls occur repeatedly inside the sea-point/source-term loop, so long continuous runs gradually increased resident memory on the WW3 ranks.

This PR replaces those hot-loop IRANGE() calls with explicit non-allocating loops, for example:

DO IK = 1, NK
  IKN(IK) = 1 + (IK-1)*NTH
END DO

The same approach is applied in W3SIN6, W3SDS6, W3SWL6, and the 10 Hz extension calculation. The PR also adds explicit guarded deallocation for local allocatables in TAU_WAVE_ATMOS.

No science change is intended. The generated index values are the same as before; the change only avoids temporary allocatable arrays in the inner source-term loop.

Why this fixes the issue

The memory growth was traced to the ST6 wind-input and dissipation source terms. The repeated IRANGE() allocatable-function calls were creating small heap allocations/deallocations in a very hot loop. Over long runs this caused monotonic RSS growth on the WW3 ranks and eventually led to OOM failures.

By replacing the allocatable-function calls with direct loops, the source-term code no longer creates these temporary heap allocations at every call, removing the allocator churn responsible for the RSS growth.

Validation

The fix was tested using the ACCESS-OM3 build here:

ACCESS-NRI/ACCESS-OM3#109 (comment)

The updated build is now running the yearly MCW_100km_era5_iaf_KPP runs without the previous WW3 memory issue. Five simulated years have completed successfully so far.

Current performance from the yearly runs:

Throughput: ~4.2–4.4 simulated years per wall-day
Cost:       ~2.3 kSU per simulated year

@anton-seaice anton-seaice left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't just remove the ALLOCATABLE and ALLOCATE from

WW3/model/src/w3swldmd.F90

Lines 450 to 455 in 3372234

INTEGER, ALLOCATABLE :: IX(:)
INTEGER :: N
INTEGER :: I
!
N = INT(REAL(X1-X0)/REAL(DX))+1
ALLOCATE(IX(N))
?

Or set

INTEGER :: IKN(NK), ITH
to be ALLOCATABLE ?

Comment thread model/src/w3src6md.F90 Outdated
Comment on lines +1201 to +1208
!
IF (ALLOCATED(IK10Hz)) DEALLOCATE(IK10Hz)
IF (ALLOCATED(SIG10Hz)) DEALLOCATE(SIG10Hz)
IF (ALLOCATED(CINV10Hz)) DEALLOCATE(CINV10Hz)
IF (ALLOCATED(DSII10Hz)) DEALLOCATE(DSII10Hz)
IF (ALLOCATED(SDENSX10Hz)) DEALLOCATE(SDENSX10Hz)
IF (ALLOCATED(SDENSY10Hz)) DEALLOCATE(SDENSY10Hz)
IF (ALLOCATED(UCINV10Hz)) DEALLOCATE(UCINV10Hz)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think these deallocates don't do anything - it's implicit in fotran that they get deallocated (because they were allocated in this subroutine)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @anton-seaice , that makes sense. I’ve removed the explicit DEALLOCATE block in TAU_WAVE_ATMOS in this commit 65b55f7

@ezhilsabareesh8 ezhilsabareesh8 Jul 2, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anton-seaice in the MCW test with the updated executable, removing the explicit DEALLOCATE block brought the WW3 memory growth back and the job reached ~794 GB. Restoring the block matches the tested passing behaviour.

So I think we should keep the explicit deallocations here, even if they are theoretically redundant.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated executable, removing

I can't see any deployments this PR which use the comment without the deallocate statements ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one ACCESS-NRI/ACCESS-OM3#109 (comment), which uses this commit

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hich uses this commit

Uses:

https://github.com/ACCESS-NRI/ACCESS-OM3/blob/13c4bf2fc6dfee6b19d333139f9dd6258439944f/spack.yaml#L36

git.3372234ec8898d21498f71e57e057d63b2c1095a=2026.03.000

which looks liek the head of the default branch (https://github.com/ACCESS-NRI/WW3/tree/dev/2026.03)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@anton-seaice Removed the deallocate block in this commit 10fa061 and tested with the executable ACCESS-NRI/ACCESS-OM3#109 (comment), it's running fine

@ezhilsabareesh8

Copy link
Copy Markdown
Collaborator Author

Can't just remove the ALLOCATABLE and ALLOCATE from

WW3/model/src/w3swldmd.F90

Lines 450 to 455 in 3372234

INTEGER, ALLOCATABLE :: IX(:)
INTEGER :: N
INTEGER :: I
!
N = INT(REAL(X1-X0)/REAL(DX))+1
ALLOCATE(IX(N))

?
Or set

INTEGER :: IKN(NK), ITH

to be ALLOCATABLE ?

I kept the direct loops at the ST6 call rather than making IKN allocatable. IKN is already fixed-size with NK, so making it allocatable would add allocation into the same source-term routines we are trying to keep allocation-free.

@anton-seaice anton-seaice left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok - you better remove the IRANGE functions and all the references to it in the code comments

@ezhilsabareesh8

Copy link
Copy Markdown
Collaborator Author

Ok - you better remove the IRANGE functions and all the references to it in the code comments

@anton-seaice Done in this commit ad9870e

@ezhilsabareesh8
ezhilsabareesh8 merged commit 0a23b2c into dev/2026.03 Jul 6, 2026
6 checks passed
@ezhilsabareesh8
ezhilsabareesh8 deleted the ezhil_st6_irange_memory_growth_clean branch July 6, 2026 06:56
@ezhilsabareesh8
ezhilsabareesh8 restored the ezhil_st6_irange_memory_growth_clean branch July 17, 2026 01:15
@ezhilsabareesh8
ezhilsabareesh8 deleted the ezhil_st6_irange_memory_growth_clean branch July 17, 2026 01:16
ezhilsabareesh8 added a commit that referenced this pull request Jul 22, 2026
* Remove W3_IS2 compile guard from IC5 floe diameter update in w3wavemd

* Avoid ST6 IRANGE heap allocations in source loops (#16)

* Avoid ST6 IRANGE heap allocations in source loops

* Remove the explicit DEALLOCATE block

* Avoid ST6 IRANGE heap allocations in source loops

* Remove IRANGE

* Remove the explicit DEALLOCATE block
ezhilsabareesh8 added a commit to ACCESS-NRI/access-om3-configs that referenced this pull request Aug 10, 2026
**1. Summary**:

This build updates the component versions to MOM6 `2026.05.002`, CICE6
`CICE6.6.3-2`, and WW3 `2026.03.001`. It includes MOM6 diagnostic and
numerical fixes, a CICE supergrid fix, and WW3 memory leak and floe size
output fixes.

**2. Issues Addressed:**

- Add a minimum-thickness clamp in `mixedlayer_restrat_Bodner` ([MOM6
#61](ACCESS-NRI/MOM6#61)).
- Add the `FILE_DYE_TRACER_ACCUMULATE` parameter for file-based dye
tracers ([MOM6 #67](ACCESS-NRI/MOM6#67)).
- Save the correct thickness for the `vert_remap_h` diagnostic ([MOM6
#66](ACCESS-NRI/MOM6#66)).
- Add a numerical-mixing diagnostic ([MOM6
#57](ACCESS-NRI/MOM6#57)).
- Fix `ANGLE` and tripole closure in the MOM supergrid ([CICE
#50](ACCESS-NRI/CICE#50)). This is
answer-changing.
- Remove the `W3_IS2` compile guard from the IC5 floe-diameter update
([WW3 #15](ACCESS-NRI/WW3#15)).
- Avoid ST6 `IRANGE` heap allocations in source loops ([WW3
#16](ACCESS-NRI/WW3#16)).

**3. Dependencies (e.g. on payu, model or om3-scripts)**

This change requires changes to (note required version where true):
- [ ] payu:
- [x] access-om3: 2026.05.003
- [ ] om3-scripts:

**5. CI Testing**

- [x] `!test repro` or `!test repro commit` has been run

The determinism tests pass for the new build.

**6. Reproducibility**

Is this reproducible with the previous commit? (If not, why not?)
- [ ] Yes
- [x] No

The CICE supergrid fix is answer-changing

**7. Documentation**

The docs folder has been updated with output from running the model?
- [ ] Yes
- [x] N/A

A PR has been created for updating the documentation?
- [ ] Yes: <!--link-->
- [x] N/A

**8. Formatting**

Changes to MOM_input have been copied from model output in
docs/MOM_parameter_docs.short?
- [ ] Yes
- [x] N/A

**9. Merge Strategy**

- [ ] Merge commit
- [ ] Rebase and merge
- [x] Squash

---------

Co-authored-by: access-bot <113399144+access-bot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants