Repository navigation
Conversation
hxu129
marked this pull request as ready for review
October 22, 2026 05:26
liuanji
added a commit
that referenced
this pull request
Nov 4, 2026
…piled form across processes (`@njit(cache = True)`, as 32 other functions here) -- without it every new process recompiled them on its first irregular layer. MEASURED, `juice.compile`, median of 4 fresh processes, warm Numba cache: #66's example 1.109 -> 0.909 s, HCLT-32 1.424 -> 1.252 s, HMM-64 1.260 -> 1.241 s (a regular circuit never reaches them). The first process on a machine still compiles, about 1.2 s on #66's example. The cost was found by hxu129 in #66, whose second implementation of the DP this makes unnecessary: 0.881 s, 1.371 s and 1.248 s there. These functions call no other jitted function, so Numba's cache, keyed on this file, cannot go stale through one. Against main on 4000 random inputs, int16 to int64, cold and warm: the same values and dtypes; a read-only cache location recompiles as before. The full suite runs once the pending PRs are merged.
Member
|
Closing, with thanks: the cost you found is real, and it is now addressed another way. These functions had no Numba cache, so every new process recompiled them. 41eb5f6 on
Your note on the fixed-column backtrace was useful as well: we will look at it when we revisit compilation. |
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.
Small irregular circuits can pay for CPU degree sorting, coalescing and Numba metadata compilation during
juice.compile. This adds a bounded histogram path fordp_with_coalesce, then runs the existing weighted partition recurrence with NumPy integer tables.The path accepts one-dimensional CPU integer tensors with positive degrees at most 4096, at most 64 occupied bins, 2–16 requested partitions, and
max_degree * num_nodes < 2**31 - 1. It preserves the coalescing endpoints/counts, first-minimum ties, stopping threshold, return dtype, and existing fixed-column backtrace behavior. Two-bin histograms retain the existing weighted DP; inputs outside the bounded domain retain the existing dispatch. Circuit floating-point arithmetic is unchanged.The focused tests include an independent scalar recurrence, comparisons with the unchanged compiled DP, dtype/noncontiguous-input and fallback cases, and an ordinary two-variable categorical circuit with irregular product-parent degrees. The CUDA cases compare compiled index tables and parameters, forward masses, linear/logspace leaf flows, and sample frequencies.
On an RTX 4090 with Python 3.10.14, PyTorch 2.4.0+cu121, Triton 3.0.0, NumPy 1.26.4 and Numba 0.66.0, the standalone benchmark compared unmodified upstream
3b44e329with this patch. Each row uses five fresh processes per version on the same GPU, withOMP_NUM_THREADS=1. Times below are medians in seconds.juice.compile, before → afterThe first request includes PyJuice import, node construction, compilation, device transfer, and one native forward/backward query with CPU outputs for all nine observations. All 20 runs passed independent FP64 literal-mixture checks and produced identical recorded outputs across versions. PyTorch peak allocated CUDA tensor memory was 23,040 bytes in every run. These measurements describe this small fixture and software stack; disk caches were not cleared, and the timings are observations rather than confidence intervals. Other dependency versions and the full test suite have not been validated here.
To run the focused tests:
Result: 32 passed in 12.70 s: 30 CPU partition cases and two actual CUDA mixture cases, covering linear/logspace flows. Each CUDA case also checks the sample law with 8,192 draws. Against unmodified upstream, the same test file run with
-k test_random_histograms_match_independent_recurrence_without_metadata_jit -xstops at the first selected case: the old path invokes_coalesce_fnand raises the test's injectedAssertionError("coalesce JIT")(1 failed, 17 deselected, 3.81 s). This verifies that the regression check detects the metadata JIT being avoided.To reproduce the old dispatch failure in a clean checkout of this PR, keep the new tests and restore only the partition implementation:
git show 3b44e329:src/pyjuice/layer/backend/node_partition.py > src/pyjuice/layer/backend/node_partition.py PYTHONPATH=src python -m pytest -q tests/layer/compact_histogram_partition_test.py -k test_random_histograms_match_independent_recurrence_without_metadata_jit -x git restore -- src/pyjuice/layer/backend/node_partition.pyTo reproduce the timing boundary from this PR checkout, use its benchmark script for both source versions:
Repeat with
--gpu-compilationand fresh output names. The JSON records individual stages, numerical checks, memory, versions and source fingerprints. No downloaded model or dataset is needed.AI assistance was used to prepare the implementation, tests and this description. Validation and its limits are stated above.