Reduce peak memory use in destination choice and large trip models - #1110
Open
jpn-- wants to merge 7 commits into
Open
Reduce peak memory use in destination choice and large trip models#1110jpn-- wants to merge 7 commits into
jpn-- wants to merge 7 commits into
Conversation
Chunk logsum joins and release allocator pages between model segments. Preserve tracing run IDs for programmatic multiprocess runs and include example resources in built packages.
Apply outer chooser chunking and memory release only when explicit chunking is configured.
Pass zero chunk sizes to logsum calculations, preserve configured outer chunking, and add trip-period data during post-choice annotations with regression coverage.
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
Critical nested-chunking behavior and unresolved memory/chunk-boundary issues must be fixed before approval.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Reduces peak and retained memory in large ActivitySim runs by widening chunk boundaries, avoiding full-table copies, releasing native allocator memory, and improving production-run support.
Changes:
- Streams destination-choice and logsum pipelines through bounded chooser chunks.
- Reuses trip scheduling and mode-choice working frames.
- Adds cross-platform allocator memory release.
- Includes run-ID forwarding, packaging updates, and regression tests.
File summaries
| File | Description |
|---|---|
pyproject.toml |
Packages example resources. |
activitysim/core/workflow/runner.py |
Forwards tracing run IDs. |
activitysim/core/test/test_workflow_runner.py |
Tests run-ID forwarding. |
activitysim/core/test/test_mem.py |
Adds basic memory-release coverage; cross-platform and fallback branches remain untested. |
activitysim/core/mem.py |
Adds cross-platform allocator memory release. |
activitysim/abm/test/trip_dest/test_trip_destination.py |
Compares chunked destination results. |
activitysim/abm/test/test_trip_mode_choice.py |
Tests temporary trip-period handling. |
activitysim/abm/test/test_misc/test_tour_destination_sampling.py |
Tests chunked tour-destination processing. |
activitysim/abm/test/test_location_choice.py |
Tests chunk-local person joins. |
activitysim/abm/models/util/tour_destination.py |
Chunks tour-destination logsums. |
activitysim/abm/models/util/logsums.py |
Supports explicit chunk-size overrides. |
activitysim/abm/models/trip_scheduling.py |
Reuses scheduling frames. |
activitysim/abm/models/trip_mode_choice.py |
Processes purpose-sized segments, but retained skim-wrapper targets can prevent timely memory release. |
activitysim/abm/models/trip_destination.py |
Streams destination stages, but incorrectly enables outer chunking outside explicit mode and reapplies chunking internally. |
activitysim/abm/models/location_choice.py |
Chunks location-choice logsums. |
Review details
Suppressed comments (1)
activitysim/core/test/test_mem.py:7
- This test only exercises whichever native branch happens to match the test host, so the macOS and Windows ctypes calls—and the promised fallback when symbols or calls are unavailable—remain untested. Mock
sys.platformand the ctypes loaders/functions to cover successful and failing calls on all three branches, including restoration of a previously disabled garbage collector.
def test_release_memory_is_advisory():
assert isinstance(mem.release_memory(), bool)
- Files reviewed: 15/15 changed files
- Comments generated: 3
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| lifecycle because they intentionally consume the complete sample table. | ||
| """ | ||
|
|
||
| if estimator or want_sample_table or not model_settings.explicit_chunk: |
| trips_chunk, | ||
| alternatives, | ||
| tours_merged, | ||
| model_settings, |
Comment on lines
+277
to
+278
| del trips_segment, base_trips_segment | ||
| mem.release_memory() |
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.
Summary
This PR reduces peak and retained memory in large ActivitySim runs, particularly during location choice, tour/trip destination choice, trip scheduling, and trip mode choice.
The main change is to move chunk boundaries outward so that entire high-memory pipelines—not only utility evaluation—operate on bounded chooser subsets. Large sampled-alternative joins, preprocessors, TAZ-to-MAZ expansion, logsum calculations, and final simulation are completed and released one chunk at a time.
It also adds a cross-platform, best-effort mechanism for returning unused native allocator pages to the operating system between large model segments.
Motivation
Existing evaluator chunking limits the size of individual utility calculations, but several model components still constructed complete merged chooser or sampled-alternative tables before entering those evaluators. At production scale, these intermediate tables can contain millions of rows and many derived columns per worker.
This caused two problems:
The in-development Boston full scale model exposed these issues with approximately 3.6 million households, 8.7 million persons, and more than 30 million generated trips.
Changes
Bound location and tour-destination logsums
Workplace, school, and tour-destination logsum calculations now:
This prevents a complete sampled-alternative/person merge and its derived columns from remaining live throughout logsum evaluation.
The logsum utility accepts an optional explicit chunk-size override so callers can distinguish configured outer chunking from disabled inner chunking.
Bound the complete trip-destination pipeline
When
explicit_chunkis configured, trip destination now streams each chooser chunk through:Only the final one-row-per-trip choices are retained between chunks.
Additional changes include:
Estimation and destination-sample-table workflows retain their original whole-segment lifecycle because they intentionally consume the complete sampled table.
If explicit chunking is not configured, trip-destination sampling follows the legacy unchunked path. This preserves compatibility with existing models and lightweight test settings objects.
Reduce full trip-table copies
Trip scheduling now reuses its existing working trip frame instead of creating a second complete copy near the end of the component. Temporary scheduling columns are removed, and any pre-existing columns used as scratch space are restored.
For school-escort runs, the first working frame is released before reconstructing the complete trip table.
Trip mode choice now:
Post-choice annotations temporarily receive
trip_periodfor the complete trips table so three-dimensional skim expressions remain correctly aligned. The temporary column is removed afterward, preserving the original table schema.Return unused allocator memory
A new
mem.release_memory()helper:malloc_trimon Linux when available.malloc_zone_pressure_reliefon macOS when available.These calls are advisory and do not affect model behavior if the allocator declines to release memory.
Supporting production-run fixes
Two supporting fixes were needed for programmatic and containerized benchmarking:
activitysim createare explicitly included in built packages, avoiding incomplete wheels in Docker or source-only build contexts.These changes are logically separate from model chunking but support running and validating large production models outside the CLI.
Compatibility and model results
The changes do not require updates to existing model specifications or prototype regression targets.
Both Sharrow and non-Sharrow execution paths remain supported.
Note: This PR is a result of work for CTPS (Boston MPO) on model optimization, not a consortium funded task.