feat(algo): add GDS_PAGE_RANK backed by icebug (NetworKit, zero-copy Arrow) - #30
Conversation
|
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 |
|
LadybugDB/ladybug#774 has been merged. See if the issues are fixed? |
…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>
a47cad7 to
5605c8c
Compare
|
Thanks both for the thorough discussion on the Arrow version lockstep. I took this branch for a spin on Windows (MSVC 14.51) to see how the icebug bridge holds up. Windows build (ENABLE_ICEBUG=ON): compiles and links cleanly
Two small fixes for the ENABLE_ICEBUG gating
Both are tiny — happy to open a PR against your branch with them. The C Data Interface direction ( |
5605c8c to
68688a8
Compare
|
@chiangchenghsin-hash thank you for testing. I'm trying to get CI to pass and land this PR. Please open a new PR once this lands. |
28495f8 to
edf73be
Compare
|
Next blocker:
This can only be solved by making an icebug release built in a manylinux 2_28 container - the same one that ladybug uses. |
|
Rerunning CI with the just released icebug 13.1 binaries which should be compatible with glibc 2.28+ |
edf73be to
c9c96c5
Compare
|
One more thought on the multi-table follow-up mentioned in the roadmap — I ran into exactly this while implementing Leiden for the algo extension, and ended up with a working flat-index mapping across node tables ( If it helps, I'd be happy to extract that into a shared utility once the base bridge lands — saves you the follow-up effort and gives GDS_PAGE_RANK multi-table support out of the gate for the next release cycle. The Leiden heterogeneous regression tests (400 nodes across two tables) are already passing, so there's test coverage to borrow. No rush of course — just wanted to flag it while the CSR path is fresh in my mind. |
|
I was thinking efficient merging of multiple tables into one could be a cypher query (so users have some flexibility in how they order the nodes in the projected graph). The base bridge has landed (but not included in the 0.19.1 that just went out). |
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