Refactor RasterLayer to use PropertyLayer as backend (#201)#310
Refactor RasterLayer to use PropertyLayer as backend (#201)#310Tejasv-Singh wants to merge 1 commit intomesa:mainfrom
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #310 +/- ##
==========================================
+ Coverage 77.67% 81.28% +3.60%
==========================================
Files 10 10
Lines 954 1031 +77
Branches 146 161 +15
==========================================
+ Hits 741 838 +97
+ Misses 174 153 -21
- Partials 39 40 +1 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
17b05af to
a0a4039
Compare
Update: CI Timeouts & Backward Compatibility ResolvedI have just pushed a major set of optimizations and fixes to resolve the 2-minute timeouts and Here is a summary of the fixes: 1. Resolved the UrbanGrowth / Rainfall CI Timeouts -> O(1) Access
2. Resolved the
3. Fixed
4. Codecov Coverage Restored & setattr Hardened
All checks (including the example models strictly running with Do let me know if this requires any more changes or modifications. 🙌 |
cb2025e to
8b69439
Compare
Summary This PR refactors RasterLayer to use Mesa's new PropertyLayer vectorized backend. This resolves the massive performance and memory bottlenecks caused by eager instantiation of Python objects for every pixel while completely preserving the existing Cell spatial API for backward compatibility. Bug / Issue Resolves mesa#201 Context & Impact: The current implementation of RasterLayer (prior to this PR) proactively creates a Python Cell object (inheriting from Agent) for every single coordinate in a raster. When dealing with moderately-sized to large geographic rasters (e.g., GeoTIFFs), this object-oriented initialization scales extremely poorly, causing severe initialization delays and massive memory consumption overhead. Implementation To address this architectural bottleneck, I transitioned RasterLayer from an object-oriented memory model to a data-oriented (vectorized) memory model using PropertyLayer. - Added Vectorized Storage (PropertyLayer): RasterLayer no longer holds cells; it exclusively manages instances of Python numeric arrays mapped directly to numpy transformations. - Added O(1) Ephemeral Views: _CellWrapper dynamically proxies properties dynamically without permanent Agent object initialization overhead.
c0cbae7 to
4a4301e
Compare
|
Hi @Tejasv-Singh, fantastic work on the backend refactor! Moving the heavy lifting to I was reviewing the architecture for my own GSoC proposal, and I wanted to flag a critical edge case regarding the Because the Furthermore, bypassing To preserve object identity without blowing up memory, we might need to explore a true Flyweight Pattern or completely decouple Happy to help brainstorm solutions for this! The NumPy backend mapping is beautiful, we just need to make sure the frontend API doesn't break existing agent-level logic. |
|
Hi @AdMub, thank you for the thorough review, 🙌 these are completely valid concerns and I'm glad you flagged them 🙌 You're right on both points: Object Identity: The current
I'd love to hear @wang-boyu's take on the Will push an updated branch once I have a clearer signal on the architectural direction. Thanks again! 😄 |
|
Thanks for the PR @Tejasv-Singh and the discussions here @AdMub - appreciate your time and interest in Mesa-Geo. This change touches a major part of the upcoming GSoC project scope, so we're not ready to merge direct implementations at this stage. We want to intentionally keep this space open for ideas / suggestions / discussions through the GSoC application process. As such we'll close this PR for now. This is definitely not against the broader direction or your implementation, but because we're not planning to review this PR towards merging at this time. If you'd like to talk more about it, I'd recommend continuing the discussion at Mesa-Geo discussions.
Not quite sure about the idea of "a pure dataclass", but I do agree that separating However like I mentioned, all ideas / suggestions are welcome, and they don't have to align to my comments above. |
Summary
This PR refactors RasterLayer to use Mesa's new PropertyLayer vectorized backend. This resolves the massive performance and memory bottlenecks caused by eager instantiation of Python objects for every pixel while completely preserving the existing Cell spatial API for backward compatibility.
Bug / Issue
Resolves #201
Context & Impact:
The current implementation of RasterLayer (prior to this PR) proactively creates a Python Cell object (inheriting from
Agent) for every single coordinate in a raster. When dealing with moderately-sized to large geographic rasters (e.g., GeoTIFFs), this object-oriented initialization scales extremely poorly, causing severe initialization delays and massive memory consumption overhead.Implementation
To address this architectural bottleneck, I transitioned RasterLayer from an object-oriented memory model to a data-oriented (vectorized) memory model using PropertyLayer. Here is what was changed and what was deleted:
_initialize_cells): I completely deleted the nested internal loops that iteratively allocated millions of Cell instances into a giant list-of-lists in memory.np.flip(..., axis=0).Tto match bounds and read/write full grids instantly.cell.elevation, it doesn't read the attribute from the cell itself, it dynamically proxies the query directly into the shared PropertyLayer memory inlayer.cells[x][y]does not break existing model code, I added a lightweight wrapper class. It generates ephemeral Cell objects dynamically on the fly, acting as "views" rather than permanently stored agents.Cell.xyStorage: The cell's geographic coordinate is no longer stored inside the object taking up memory. I rewrote the xy property to dynamically calculate itsrio.transform.xylocation on demand using its rowcol offset.Testing
pytest tests/test_RasterLayer.pyverifications (updated the concatenation test to expect the correct 3 bands after fixing the attr_name collision bug).mainintegrating alongside the new PropertyLayer grid changes from PR Add Cell.xy for RasterLayer cell coordinates and clarify pos/indices semantics #299pytest tests/test suite passes gracefully without a single regression or failure. The PropertyLayer backend successfully satisfies the maintainers' newly added apply_raster test suite unconditionally.Additional Notes
@wang-boyu
This is my initial attempt at bridging the experimental PropertyLayer capabilities into Mesa-Geo while keeping the legacy "Cell-centric" user experience intact.
I would really appreciate any feedback, guidance, or structural corrections regarding how the _CellWrapper and descriptors were implemented, and whether you think this meshes well with the long-term vision of integrating
discrete_space. eager to learn from your reviews!