Skip to content

perf(rsema1d): encode parity in cache-resident column stripes in parallel - #1003

Draft
citizen-stig wants to merge 1 commit into
mainfrom
perf/rsema1d-striped-parity
Draft

perf(rsema1d): encode parity in cache-resident column stripes in parallel#1003
citizen-stig wants to merge 1 commit into
mainfrom
perf/rsema1d-striped-parity

Conversation

@citizen-stig

@citizen-stig citizen-stig commented Sep 2, 2026

Copy link
Copy Markdown
Collaborator

fill_parity encoded every row as one Leopard shard on the calling thread. For K=4096/N=12288 the high-rate work buffer is 16384 shards, so 32 KiB rows make it 512 MiB and every IFFT/FFT pass streams from DRAM: 770 ms per 128 MiB blob on one core, and running several encoders at once did not scale (4 processes: 1.3x total).

Leopard applies the same transform independently to each 64-byte block position of a shard, so the rows are now split into column stripes and each stripe is encoded by its own HighRateEncoder on a rayon worker. The stripe width is chosen so that all workers' work buffers together stay within 32 MiB (cache-resident); encoders are kept in a thread-local and reused across calls. The parity region is faulted in sequentially before the striped scatter, since concurrent first-touch of interleaved pages serialised in the kernel (105 ms vs 6 ms for a 24 MiB region).

Output is byte-identical to a single encoder over whole rows, which is what the Go verifier (klauspost Leopard GF16) recomputes: a unit test checks this for the production shape and for a row size that does not divide evenly, and the Go cross-implementation vectors (254 cases including K=4096/N=12288) pass.

criterion, target-cpu=native, Ryzen 9 3950X (32 rayon threads):
  rsema1d encode_in_place/128MB_k4096_n12288   821 ms -> 207 ms
  rsema1d encode_in_place/8MB_k4096_n12288    52.6 ms -> 17.3 ms
  fibre   blob_new/128MB                       985 ms -> 408 ms
  fibre   blob_new/8MB                        64.1 ms -> 29.3 ms

…llel

fill_parity encoded every row as one Leopard shard on the calling thread.
For K=4096/N=12288 the high-rate work buffer is 16384 shards, so 32 KiB rows
make it 512 MiB and every IFFT/FFT pass streams from DRAM: 770 ms per
128 MiB blob on one core, and running several encoders at once did not
scale (4 processes: 1.3x total).

Leopard applies the same transform independently to each 64-byte block
position of a shard, so the rows are now split into column stripes and
each stripe is encoded by its own HighRateEncoder on a rayon worker. The
stripe width is chosen so that all workers' work buffers together stay
within 32 MiB (cache-resident); encoders are kept in a thread-local and
reused across calls. The parity region is faulted in sequentially before
the striped scatter, since concurrent first-touch of interleaved pages
serialised in the kernel (105 ms vs 6 ms for a 24 MiB region).

Output is byte-identical to a single encoder over whole rows, which is what
the Go verifier (klauspost Leopard GF16) recomputes: a unit test checks
this for the production shape and for a row size that does not divide
evenly, and the Go cross-implementation vectors (254 cases including
K=4096/N=12288) pass.

criterion, target-cpu=native, Ryzen 9 3950X (32 rayon threads):
  rsema1d encode_in_place/128MB_k4096_n12288   821 ms -> 207 ms
  rsema1d encode_in_place/8MB_k4096_n12288    52.6 ms -> 17.3 ms
  fibre   blob_new/128MB                       985 ms -> 408 ms
  fibre   blob_new/8MB                        64.1 ms -> 29.3 ms

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VPtihoV1GJ9VcNkd7oMRUf
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