Skip to content

GKR: lookup tables and bucketing - #146

Open
xrvdg wants to merge 14 commits into
mainfrom
xr/lut
Open

xrvdg wants to merge 14 commits into
mainfrom
xr/lut

Conversation

@xrvdg

@xrvdg xrvdg commented Oct 22, 2026 •

Copy link
Copy Markdown
Collaborator

Implements lookup tables, bucketing and an efficient way to create the nibbles needed for lookup. This only targets the first round. Later PRs will focus on pushing this optimisations through more rounds of sumcheck.

Partially implements

xrvdg added 14 commits October 8, 2026 15:54
gpgkr_prove takes the LayerWitnesses. The round loop moves out of
prove_layer into prove_rounds, so a table-backed round 1 can hand its
bound halves to the dense rounds through round_one: Option<Field>.

The gkr tests build bit tables at (7, 15), the smallest shape the gates
accept, and check the prover against the leaves built one bit at a time.
Layers 2, 1 and the leaves are no longer materialised. Round 1 of each
reads the bit matrix and the 16-entry lookup tables through LutLayers
and writes only the children it has bound, [left′ | right′], into one
allocation sized for the leaves'. prove_rounds takes over from round 2.

The leaves and layer 1 sum round 1's eq weights in buckets, with eq
split into eq_hi · eq_lo; layer 2 works node by node. The sent sums are
named after their points: sum_b at the boolean point b, sum_inf at ∞.

gkr bench at (10, 15): 116.2 -> 71.5 ms on all threads, 215.7 -> 166-168
ms on one.
Flattened in pairs and zipped per position, every round-1 loop over the
lookup tables compiled to a per-position state machine: a nibble
counter, a branch and a variable shift per position, and for layer 2
the iterator state on the stack. pairs now yields one item per word,
and each user zips the words with 16-position chunks of its own data
and loops inside: the leaf sums unroll, the others become counted loops.

gkr bench at (10, 15), one thread: 124.6e9 -> 116.8e9 instructions,
168 -> 159.5 ms fastest; all threads: 71 -> 70.3 ms fastest.
LayerWitnesses holds the LutLayers that batched_eval builds, and layer3
reads the lookup tables through LutLayers::pieces and pairs, as round 1
of layer 1 does. lower_luts, layer3 and fold_layers run on rayon with the
same PARALLEL_MIN_LANES threshold as the sumcheck. LutLayers::new now
asserts that each lookup table's run holds at least a word of nibbles,
which layer3 used to check. fold_into is gone.

gkr bench at (10, 15), all threads: 70.35 -> 66.1-66.6 ms fastest;
one thread unchanged (159.4 ms, 116.8e9 instructions).
Nothing reads layers 0 to 2 in full any more, so lower_layers,
IntoIterator for LayerWitnesses and lut_nodes are gone.
lut_layers_match_the_leaf_construction compares the output and layer 3
and up; lut_layers_prove_from_any_top_coordinate covers layers 0 to 2
through the sumchecks that read them.

The docs of LayerWitnesses, gpgkr_prove's witnesses, EqTables::new and
alloc_storage say what they hold now, and the layout comment in
GrandProductCircuit::new and the test comments speak of trees, node
positions and nibbles instead of rows and columns.

gkr bench at (10, 15) unchanged: 116.8e9 instructions on one thread.
@xrvdg
xrvdg marked this pull request as draft October 22, 2026 04:22
@xrvdg
xrvdg changed the base branch from main to xr/bittable October 22, 2026 04:23
@xrvdg
xrvdg added this pull request to stack #147 October 22, 2026 04:24
@xrvdg
xrvdg marked this pull request as ready for review October 22, 2026 04:55
@xrvdg
xrvdg requested a review from zkfriendly October 22, 2026 04:55
@xrvdg xrvdg mentioned this pull request Oct 22, 2026
21 tasks
@xrvdg xrvdg changed the title Xr/lut GKR: lookup tables and bucketing Oct 22, 2026
Base automatically changed from xr/bittable to main October 22, 2026 05:18
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