Skip to content

perf(gfql/index): index-accelerated get_degrees + EXISTS-prune (#5 degree-cache / #3 membership)#1697

Open
lmeyerov wants to merge 7 commits into
feat/gfql-graphframes-benchfrom
feat/gfql-index-degrees
Open

perf(gfql/index): index-accelerated get_degrees + EXISTS-prune (#5 degree-cache / #3 membership)#1697
lmeyerov wants to merge 7 commits into
feat/gfql-graphframes-benchfrom
feat/gfql-index-degrees

Conversation

@lmeyerov

@lmeyerov lmeyerov commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

Stacked on #1668 (→ #1661#1658 → master). First L4 index-acceleration unit off the #1658 CSR registry.

What

Node degrees + has-edge membership fall straight out of the resident CSR adjacency index (degree = diff(group_offsets), membership = keys_sorted), turning O(E) group_by+join into an O(N) searchsorted gather.

  • index/degrees.pydegrees_from_index (per-node in/out degree, engine-native searchsorted, arbitrary node ids) + adjacency_membership_keys (Document API with pydoc #3, per-direction / undirected union).
  • get_degrees fast path — ComputeMixin.get_degrees (pandas/cudf) + get_degrees_polars (polars/polars-gpu). Feeds q8-style degree-products and any degree analytics / CALL.
  • EXISTS { (n)--() } prune-isolated_pattern_alias_keys_polars routes the bare pattern through membership instead of chain_polars.
  • Cost: none needed (bulk over all nodes always beats the scan); index_policy='off' skips; try/except → scan fallback (never wrong); strict guards decline any filtered/neq/multi-hop shape.

Perf (parity-exact throughout)

  • Prototype (1M/5M, pandas): exists_prune 342→2.7ms (128×), q8 541→0.8ms (664×).
  • Real op (200k/800k, polars): EXISTS {(n)--()} scan 1206ms → index 16.5ms (73×); scales to sub-second at the 10m receipt (was 35s).

Tests

graphistry/tests/compute/gfql/index/test_index.py: get_degrees parity ×4 engines + self-loops/isolated + policy='off'; exists_prune membership parity + policy-off. Local non-GPU green (56 index tests); cudf/polars-gpu verified on dgx.

Notes / follow-ups

🤖 Generated with Claude Code

lmeyerov and others added 4 commits July 6, 2026 12:51
…membership)

Read node degrees straight from a resident CSR adjacency index (degree =
diff(group_offsets), gathered per node via searchsorted) instead of the O(E)
group_by(endpoint)+join. Bulk over all nodes -> always profitable when a valid
index is resident; index_policy='off' skips; try/except falls back to the scan
path (never wrong). New graphistry/compute/gfql/index/degrees.py
(degrees_from_index), engine-native (numpy pandas/polars, cupy cudf). Wired into
ComputeMixin.get_degrees (pandas/cudf).

Prototype (1M/5M pandas): exists_prune 342->2.7ms (128x), q8 541->0.8ms (664x),
exact parity. Unit + end-to-end parity green (arbitrary node ids + self-loops).
WIP: polars get_degrees_polars wiring + index-suite parity tests + 4-engine dgx.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Same resident-CSR fast path (degrees_from_index) in get_degrees_polars — eager
frames only (LazyFrame would force a collect), policy 'off' skips, try/except
falls back to the group_by scan. Parity green vs group_by baseline (degree /
degree_in / degree_out, arbitrary node ids + self-loops). Covers polars +
polars-gpu (numpy-host arrays). cudf/polars-gpu GPU parity pending dgx verify.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Parity vs group_by scan + self-loop/isolated contract + index_policy='off'
fallback, engine-parametrized. Local: pandas/polars/polars-gpu pass; cudf needs
GPU (cupy init) — verified on dgx.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…membership)

Bare EXISTS pattern (no endpoint/edge filters, no drop-self neq) = "node has an
edge in this direction" = CSR adjacency membership. Route _pattern_alias_keys_polars
through adjacency_membership_keys (union of edge_out/in_adj keys_sorted for
undirected; per-direction otherwise) instead of the O(E) chain_polars; strict guard
falls through for any richer shape. New adjacency_membership_keys in index/degrees.py.
Parity + policy-off tests. Perf (200k/800k, polars): scan 1206ms -> index 16.5ms
(73x); parity exact incl self-loop-only nodes.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@lmeyerov lmeyerov force-pushed the feat/gfql-index-degrees branch from cd6f8ae to 3b6b855 Compare July 6, 2026 19:51
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.

1 participant