Skip to content

Sparse UDLF backend (replaces UDLF-CSR) - #14

Merged
Gus-prog merged 5 commits into
devfrom
feature/sparse-udlf
Nov 3, 2026
Merged

Gus-prog merged 5 commits into
devfrom
feature/sparse-udlf

Conversation

@Gus-prog

@Gus-prog Gus-prog commented Nov 3, 2026

Copy link
Copy Markdown
Collaborator

Summary

Sparse UDLF is the successor of UDLF-CSR: sparse implementations of CPRR,
LHRR, RDPAC, RFE and BFSTREE for datasets where the dense N x N matrices of UDLF do not fit in memory. This PR makes
it the second backend of pyUDLF, in place of UDLF-CSR:

from pyUDLF import UDLF

sparse = UDLF(bin_path=".udlf/Sparse_UDLF/bin", backend="sparse")   # or UDLF_SPARSE_BIN
res = sparse.run("RDPAC", ranked_lists=rks, params={"l": 50, "k_end": 10}, classes=labels)

On the synthetic dataset, CPRR, LHRR, RDPAC and BFSTREE give ranked lists byte-identical to UDLF 1.70, so the
tests now compare the two backends directly.

Changes

  • scripts/build_sparse.sh: clones Sparse UDLF at a pinned commit (de3c14c) and builds both of its binaries:

    • udlf (fast-math): CPRR and LHRR;
    • udlf_strict: every method.
  • bin_path / UDLF_SPARSE_BIN is the directory of the binaries (or one of them). Each method runs in the binary
    that supports it.

  • Methods accept UDLF or Sparse UDLF names (BFSTREE / BFSTree, CPRR / CPRR_SPARSE).

  • Parameters keep the UDLF 1.70 defaults and validation. Sparse UDLF adds:

    • threads for LHRR (defaults to UDLF(threads=));
    • b and memory_budget_mb for BFSTREE.
  • Each run gets its own UDLF_TMPDIR, so simultaneous runs do not share scratch files.

  • Fixed: the log parser read the "RELATIVE GAINS" block as measures.

  • Removed with UDLF-CSR:

    • engine= and the dense/MKL/BLAS/Eigen engines;
    • the retry of its intermittent startup error (0 failures in 300 Sparse UDLF runs);
    • scripts/build_csr.sh.

    backend="csr" and UDLF_CSR_BIN stay as aliases. A UDLF-CSR binary is detected and rejected with a pointer
    to the build script.

  • examples/csr_engines.py → examples/sparse_methods.py. Updated the README (EN/PT), the examples table and
    the CHANGELOG.

  • CI builds Sparse UDLF (libtbb-dev, libjemalloc-dev).

Known issues of Sparse UDLF de3c14c (reported upstream)

  • RFE cannot run: its PERFORM_CCS, RERANK_BY_EMB and EXPORT_EMBEDDINGS parameters are commented out in
    Validator.hpp, so the config parser drops them. The error message explains it, and a strict-xfail test flags
    when it is fixed. RFE with perform_ccs=True is not ported yet, so pyUDLF runs RFE without connected components
    and warns.
  • The matrix output is all zeros: output="matrix" is refused, and run_config warns.

Tests

  • 283 passed, 1 skipped, 1 xfailed locally (Linux, UDLF 1.70 and Sparse UDLF de3c14c).
  • New suites:
    • tests/test_sparse_binary.py: the binaries run directly, without the wrapper;
    • tests/test_sparse.py: the backend.

Gus-prog and others added 5 commits November 3, 2026 10:29
Sparse UDLF (https://github.com/andreTomi/Sparse_UDLF) replaces UDLF-CSR:
sparse CPRR, LHRR, RDPAC, RFE and BFSTree. The script clones it at a pinned
commit (de3c14c) and builds both of its binaries: bin/udlf (fast-math, CPRR
and LHRR) and bin/udlf_strict (every method; RDPAC, RFE and BFSTree refuse
to run in the fast-math binary). Without libjemalloc-dev it links against
the jemalloc runtime library directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Runs Sparse UDLF (commit de3c14c) directly on configs written by hand and
records what pyUDLF will rely on:
- CPRR_SPARSE, LHRR_SPARSE, RDPAC and BFSTree give ranked lists
  byte-identical to UDLF 1.70 on the synthetic dataset, independent of the
  number of threads; CPRR and LHRR agree between both binaries;
- the fast-math binary refuses RDPAC, RFE and BFSTree;
- RFE cannot run: its PERFORM_CCS, RERANK_BY_EMB and EXPORT_EMBEDDINGS
  parameters are commented out in Validator.hpp, so the parser drops them
  (strict xfail, so the test flags when this is fixed);
- OUTPUT_FILE_PATH is the output file itself, with a copy always written to
  output/reranked_lists.txt; lines have exactly L ids;
- absent keys take defaults, unknown keys are reported on stderr, errors
  exit with code 1, UDLF_TMPDIR sets the scratch directory.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
UDLF(backend="sparse") runs Sparse UDLF (https://github.com/andreTomi/Sparse_UDLF,
commit de3c14c), the successor of UDLF-CSR: sparse CPRR, LHRR, RDPAC, RFE and
BFSTREE. On the synthetic dataset its ranked lists are byte-identical to UDLF
1.70, and the tests now compare the two backends directly.

- bin_path (or UDLF_SPARSE_BIN) is the directory of its two binaries or one of
  them; each method runs in the right one (RDPAC, RFE and BFSTREE need
  udlf_strict). Methods take UDLF or Sparse UDLF names (BFSTREE / BFSTree).
- Parameters keep the UDLF 1.70 defaults and schema; Sparse UDLF adds
  threads (LHRR, defaults to UDLF(threads=)), b and memory_budget_mb (BFSTREE).
  RFE runs without connected components (not ported yet), with a warning.
- Each run gets its own UDLF_TMPDIR inside the run directory, so simultaneous
  runs do not share scratch files.
- The log parser no longer reads the "RELATIVE GAINS" block as measures.
- In de3c14c RFE cannot run (its flags are commented out in Validator.hpp) and
  the matrix output is all zeros: the RFE error explains it, output="matrix" is
  refused, and run_config warns about an all-zero matrix.
- Removed with UDLF-CSR: engine=, the dense/MKL/BLAS/Eigen engines, the retry
  of its intermittent startup error (0 failures in 300 Sparse UDLF runs) and
  scripts/build_csr.sh. backend="csr" and UDLF_CSR_BIN remain as aliases; a
  UDLF-CSR binary is detected and rejected with a pointer to build_sparse.sh.
- examples/csr_engines.py becomes examples/sparse_methods.py; CI builds Sparse
  UDLF (libtbb-dev, libjemalloc-dev).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The unreleased 0.9.0 entry now describes the Sparse UDLF backend instead of
UDLF-CSR, and the open questions list the Sparse UDLF (de3c14c) issues to
report upstream: RFE cannot run, perform_ccs is not ported, the matrix output
is all zeros, the fixed output/reranked_lists.txt copy, and the build needs
(jemalloc, make test-* directories).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- test_former_udlf_csr_is_rejected fakes the binary with a shell script,
  which Windows cannot run: skipped there.
- ubuntu-latest moved to Ubuntu 26.04 (19/10/2026), which has no Python 3.9:
  the 3.9 job runs on ubuntu-24.04.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Gus-prog
Gus-prog merged commit a641b23 into dev Nov 3, 2026
16 checks passed
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