Add test for model unload/reload lifecycle#732
Merged
neworderofjamie merged 2 commits intogenn-team:masterfrom Jan 16, 2026
Merged
Add test for model unload/reload lifecycle#732neworderofjamie merged 2 commits intogenn-team:masterfrom
neworderofjamie merged 2 commits intogenn-team:masterfrom
Conversation
Tests for Issue genn-team#587 to verify that models can be cleanly unloaded and reloaded with proper cleanup of variable references. Test creates comprehensive model with: - Neuron populations - Synapse populations with STDP - Current sources - Custom updates Verifies: - Model loads and runs correctly - After unload, all variable views/arrays are None - Model can be reloaded - Reloaded model runs correctly The critical check ensures all variable references to the shared library are cleared, allowing the library to properly unload and free memory. Closes genn-team#587
neworderofjamie
requested changes
Jan 16, 2026
Contributor
neworderofjamie
left a comment
There was a problem hiding this comment.
Nice work! Just a few minor comments and I'll merge
Comment on lines
114
to
137
| # Check neuron population variables | ||
| for var_name, var in pre.vars.items(): | ||
| assert var._view is None, f"pre.vars[{var_name}]._view not cleared" | ||
| assert var._array is None, f"pre.vars[{var_name}]._array not cleared" | ||
|
|
||
| for var_name, var in post.vars.items(): | ||
| assert var._view is None, f"post.vars[{var_name}]._view not cleared" | ||
| assert var._array is None, f"post.vars[{var_name}]._array not cleared" | ||
|
|
||
| # Check synapse population variables | ||
| for var_name, var in syn.vars.items(): | ||
| assert var._view is None, f"syn.vars[{var_name}]._view not cleared" | ||
| assert var._array is None, f"syn.vars[{var_name}]._array not cleared" | ||
|
|
||
| # Check current source variables | ||
| for var_name, var in cs.vars.items(): | ||
| assert var._view is None, f"cs.vars[{var_name}]._view not cleared" | ||
| assert var._array is None, f"cs.vars[{var_name}]._array not cleared" | ||
|
|
||
| # Check custom update variables | ||
| cu_data = model.custom_updates["TestUpdate"] | ||
| for var_name, var in cu_data.vars.items(): | ||
| assert var._view is None, f"custom_update.vars[{var_name}]._view not cleared" | ||
| assert var._array is None, f"custom_update.vars[{var_name}]._array not cleared" |
Contributor
There was a problem hiding this comment.
why not put this in a function that can test either than views and arrays are or aren't None and use this whenever you test between unloads
Comment on lines
147
to
168
| # Reset state to initial conditions for reproducibility | ||
| pre.vars["V"].view[:] = -70.0 | ||
| pre.vars["RefracTime"].view[:] = 0.0 | ||
| post.vars["V"].view[:] = -70.0 | ||
| post.vars["RefracTime"].view[:] = 0.0 | ||
| pre.vars["V"].push_to_device() | ||
| pre.vars["RefracTime"].push_to_device() | ||
| post.vars["V"].push_to_device() | ||
| post.vars["RefracTime"].push_to_device() | ||
|
|
||
| # Run simulation again | ||
| for _ in range(10): | ||
| model.step_time() | ||
| model.custom_update("CustomUpdate") | ||
|
|
||
| # Get reloaded values | ||
| reloaded_pre_V = pre.vars["V"].view[:].copy() | ||
| reloaded_post_V = post.vars["V"].view[:].copy() | ||
|
|
||
| # Verify reloaded model produces valid results | ||
| assert np.isfinite(reloaded_pre_V).all(), "Reloaded pre values contain NaN/Inf" | ||
| assert np.isfinite(reloaded_post_V).all(), "Reloaded post values contain NaN/Inf" |
Contributor
There was a problem hiding this comment.
I don't think this is relevant to this test
Suggested change
| # Reset state to initial conditions for reproducibility | |
| pre.vars["V"].view[:] = -70.0 | |
| pre.vars["RefracTime"].view[:] = 0.0 | |
| post.vars["V"].view[:] = -70.0 | |
| post.vars["RefracTime"].view[:] = 0.0 | |
| pre.vars["V"].push_to_device() | |
| pre.vars["RefracTime"].push_to_device() | |
| post.vars["V"].push_to_device() | |
| post.vars["RefracTime"].push_to_device() | |
| # Run simulation again | |
| for _ in range(10): | |
| model.step_time() | |
| model.custom_update("CustomUpdate") | |
| # Get reloaded values | |
| reloaded_pre_V = pre.vars["V"].view[:].copy() | |
| reloaded_post_V = post.vars["V"].view[:].copy() | |
| # Verify reloaded model produces valid results | |
| assert np.isfinite(reloaded_pre_V).all(), "Reloaded pre values contain NaN/Inf" | |
| assert np.isfinite(reloaded_post_V).all(), "Reloaded post values contain NaN/Inf" |
| ) | ||
|
|
||
|
|
||
| def test_model_load_unload_cycle(make_model, backend): |
Contributor
There was a problem hiding this comment.
Suggested change
| def test_model_load_unload_cycle(make_model, backend): | |
| pytest.mark.parametrize("precision", [types.Double, types.Float]) | |
| def test_model_load_unload_cycle(make_model, backend, precision): |
It's not especially relevant to this test but we typically run most tests at different precisions
Comment on lines
13
to
14
| create_var_ref, | ||
| ) |
Contributor
There was a problem hiding this comment.
Suggested change
| create_var_ref, | |
| ) | |
| create_var_ref, | |
| types, | |
| ) |
Changes: 1. Created _check_vars_cleared() helper function to reduce code duplication 2. Removed reset/reproducibility code (not relevant to test) 3. Added precision parametrization to test both Float and Double 4. Imported types module from pygenn Test results: Both precision variants pass (3.52s total) )
neworderofjamie
approved these changes
Jan 16, 2026
Contributor
neworderofjamie
left a comment
There was a problem hiding this comment.
Fantastic! Thank you so much for your work on this
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Tests for Issue #587 to verify that models can be cleanly unloaded
and reloaded with proper cleanup of variable references.
Test creates a comprehensive model with:
Verifies:
The critical check ensures all variable references to the shared library are cleared, allowing the library to unload and free memory properly.
Closes #587