Repository navigation
set_neighbors: stream neighbourhoods into DuckLake instead of materialising the edge list - #66
Merged
mmyrte merged 3 commits intoOct 10, 2026
Conversation
mmyrte
added this pull request to stack #67
October 6, 2026 09:43
mmyrte
commented
Oct 6, 2026
mmyrte
left a comment
Member
Author
There was a problem hiding this comment.
In general: drop the non-chunked/non-callback version. the callback could always be an accumulator if the users really wished to construct the full table in memory.
This was referenced Oct 7, 2026
Base automatically changed from
claude/gifted-lamport-41q8gv-07-alloc-greedy
to
develop
October 10, 2026 09:18
…lising the edge list distance_neighbors_chunked_cpp() uses the same spatial hash but hands each chunk of complete neighbourhoods (all neighbours of a set of origins, both directions) to an R callback, which commits it inside the existing transaction. Distance classes are coded in C++ with cut(right = FALSE, include.lowest = TRUE) semantics and labelled per chunk. Memory is bounded by chunksize (default now 1e7 pairs) instead of the table: on PIE tiled to 1 M cells, evoland's calibration peak fell from 10.1 to 3.7 GB, and 1.8 M and 4.1 M cells, which ran out of memory on 16 GB, now complete. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D1LLswXe3jLjGTFrBsxgPf
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D1LLswXe3jLjGTFrBsxgPf
Drop distance_neighbors_cpp() and the exported create_neighbors_t(), which built the whole edge list in memory; distance_neighbors_chunked_cpp() with an accumulating callback does the same. Input validation moves to set_neighbors(). test_neighbors_t.R now tests the C++ function directly (incl. chunk disjointness), test_db_evoland.R only the DB behaviour. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D1LLswXe3jLjGTFrBsxgPf
mmyrte
force-pushed
the
claude/gifted-lamport-41q8gv-08-streamed-neighbors
branch
from
October 10, 2026 09:18
991a505 to
045a287
Compare
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.
Last of the stack (#59–#65 are merged); now based on
develop.What
set_neighbors()used to build the whole neighbour edge list in memory withdistance_neighbors_cpp(), key it, add acut()factor, and only then commit it in chunks. At 500 m around 100 m cells that is 79 pairs per cell. So the edge list, not DuckLake, set evoland's memory ceiling.distance_neighbors_chunked_cpp()uses the same spatial hash index but flushes as it goes:set_neighbors()commits each chunk inside one transaction: the first chunk withoverwrite, the rest withappend.id_coord_origin, so the table stays unique by construction.cut(right = FALSE, include.lowest = TRUE), and each chunk is labelled with the labelscut()would give.The in-memory
distance_neighbors_cpp()and the exportedcreate_neighbors_t()are removed. They were only used in tests. A caller who wants the whole table in memory can pass an accumulating callback. Input validation (max_distance,distance_breaks) moved toset_neighbors().Memory is bounded by
chunksize. Its default goes from 1e8 to 1e7 pairs, since it now bounds the computation as well as the writing. With no pairs withinmax_distance, an empty table is still committed.Effect
Measured on the PIE benchmark tiled k × k (mmyrte/evoland-experiments
2026-09-model-comparison/080-scaling; 4 cores, 16 GiB; logistic regression; whole calibration step: set-up, neighbours, fit, prediction):At 4.1 M cells, the remaining peak comes before the neighbour step, from the benchmark's own data ingestion.
Tests
test_neighbors_t.Rtestsdistance_neighbors_chunked_cpp()directly, without a DB, using an accumulating callback. It covers:id_coord_origin, every chunk except the last reacheschunk_rows, and their union equals the single-chunk result.test_db_evoland.Rchecks only the DB behaviour: an empty table for amax_distancewith no pairs, then many small chunks.🤖 Generated with Claude Code
https://claude.ai/code/session_01D1LLswXe3jLjGTFrBsxgPf