perf(rsema1d): encode parity in cache-resident column stripes in parallel - #1003
Draft
citizen-stig wants to merge 1 commit into
Draft
perf(rsema1d): encode parity in cache-resident column stripes in parallel#1003citizen-stig wants to merge 1 commit into
citizen-stig wants to merge 1 commit into
Conversation
…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
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.
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.