feat(algo): add GDS_PAGE_RANK backed by icebug (NetworKit, zero-copy Arrow) - #30
feat(algo): add GDS_PAGE_RANK backed by icebug (NetworKit, zero-copy Arrow)#30zachwinter wants to merge 1 commit into
Conversation
…Arrow)
First icebug bridge for the algo extension. `CALL GDS_PAGE_RANK('G')` delegates
PageRank to libnetworkit instead of the hand-rolled implementation: the projected
graph's adjacency is materialized as CSR (reusing the Louvain fwd/bwd scan idiom),
handed to a NetworKit::GraphR over Arrow UInt64 buffers, run through
NetworKit::PageRank, and streamed back via the existing GDS result pipeline.
Per the plan to deprecate the hand-rolled algos: the icebug-backed functions live
alongside the existing ones under GDS_* names for one release cycle, then replace
their internals in place.
- gds_page_rank.cpp: the bridge (bind/register scaffold copied from page_rank.cpp).
- cmake/download_icebug.cmake: fetches the prebuilt icebug release into vendor/;
-DICEBUG_SOURCE_DIR=<checkout> links a local source build instead (dev).
- CMake: link libnetworkit + Arrow::arrow_shared + OpenMP::OpenMP_CXX, with rpath
to the vendored lib. Requires Apache Arrow C++ (matching icebug's pinned version)
and OpenMP available to the build.
- Test: gds_page_rank.test (star graph; NetworKit PageRank is a sum-to-1 distribution,
so the hub ranks highest — same ordering as PAGE_RANK, different normalization).
Notes / follow-ups: single-node-table graphs for now (multi-table next); GDS_LOUVAIN,
GDS_NODE2VEC, and personalized PageRank (icebug's built-in personalization) follow the
same pattern.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Pin arrow works on other platforms, but not macosx. Bugscope has the same issue. We'll likely have to update ladybug, icebug and all platform in sync unless we can figure out how to pin on homebrew. |
|
I understand your comment in Discord now! For now, I -SKIP'd gds_page_rank.test for the OFF build. Would you prefer a proper conditional (maybe a SKIP_ICEBUG_DISABLED token mirroring SKIP_COMPRESSION_DISABLED) so it runs automatically once icebug is enabled? I'll open a PR in lbug core if so. |
|
@zachwinter - icebug 13.0 out. Can you see if it fixes the problem here? |
|
Tested 13.0 — short answer: it fixes macOS, but not this CI. And chasing it down turned up a separate crash that I think matters beyond this PR. The version arithmetic
So the CI failure here is unchanged, just one major further away — the log is macOS is genuinely better off, though: 12.8 wanted Arrow 24 after Homebrew had already moved past it, which is exactly the "can't pin on homebrew" problem you hit. 13.0 and Homebrew are both on 25 right now, so they line up. What I verified on 13.0 (macOS arm64)Built the extension against the prebuilt tarball (not a source build — the path CI would take),
(Also noticed The crash worth knowing aboutWhile running the suite I hit a non-deterministic SIGSEGV — ~60% of runs, but only when Arrow's default memory pool is mimalloc-backed, and mimalloc's per-thread bootstrap doesn't survive being reached from ladybug worker threads that already existed before
I observed this on macOS arm64; nothing about it looks macOS-specific, so I'd expect any The proposal: get Arrow off the ABI boundary entirelyBoth problems — the version lockstep and the mimalloc crash — come from the extension having to link real
Happy to prototype (1) against icebug if you're open to it — it's a small surface, and it's the difference between "works today on 25" and "stops mattering". Meanwhile, to get this PR greenI have the interim commit ready: an On your Discord question about the test skip: I also have a |
Summary
First icebug (NetworKit) bridge for the
algoextension:CALL GDS_PAGE_RANK('G') RETURN node, rankdelegates PageRank tolibnetworkitinstead of the hand-rolled implementation. This is the start of wiring icebug into theCALL GDS_*paths we discussed on Discord (deprecating the hand-rolled algos in favor of icebug's zero-copy Arrow columnar engine).Per that plan, the icebug-backed functions coexist with the existing algos under
GDS_*names for one release cycle, then replace their internals in place.PAGE_RANK/PRare untouched.How it works
The bind/register scaffolding is copied verbatim from
page_rank.cpp(GDSFunction::initSharedState/getLogicalPlan/getPhysicalPlan); only thetableFuncbody changes — it builds the CSR, hands it to icebug, and mapspr.scores()back to(node, rank)rows. Node offsets are dense in both worlds, so the mapping is identity.Files
algo/src/function/gds_page_rank.cpp— the bridge.algo/src/include/function/algo_function.h,algo/src/main/algo_extension.cpp— declare + registerGDS_PAGE_RANK.algo/cmake/download_icebug.cmake— fetches the prebuilt icebug release (icebug-<os>-<arch>tag 12.8) intovendor/. Set-DICEBUG_SOURCE_DIR=<icebug checkout>to link a local source build instead (dev).algo/CMakeLists.txt,algo/src/function/CMakeLists.txt— linklibnetworkit+Arrow::arrow_shared+OpenMP::OpenMP_CXX, with rpath to the vendored lib.algo/test/test_files/gds_page_rank.test.Build requirements (needs your input)
The build now needs Apache Arrow C++ and OpenMP available (Arrow is a public dependency of libnetworkit). One thing to confirm for CI: the prebuilt icebug 12.8 links Arrow 24.x — the extension build needs a matching Arrow. Happy to adjust the vendoring (pin Arrow, or a newer icebug release built against the Arrow the CI uses) however you prefer. Locally I validated the full path with a source build of icebug against the system Arrow.
Testing
gds_page_rank.test(star graph): the hub ranks highest, and the ordering matchesPAGE_RANK. Absolute values differ because NetworKit returns a sum-to-1 probability distribution (0.480 / 0.173…) vs the existing implementation's normalization — expected, and NetworKit's is the standard convention.Notes / follow-ups
GDS_LOUVAIN,GDS_NODE2VEC(ARRAY output → the vector extension's HNSW index), and personalized PageRank (icebug's built-inpersonalization/forSources) all follow this same pattern — one bridge, the whole NetworKit catalog.Types of changes
Checklist