O(n log n) technique for PAR2? #2
Replies: 4 comments 7 replies
|
Thanks Ike Devolder and Anime Tosho for discussion place. PAR2 Encoding is done as multiplication of matrix and vector. (Decoding is multiplication of inverted matrix and vector.) Fast Matrix-Vector Multiplication for Structured Matrices I found some papars and C source code for Vandermonde matrix. But, it's difficult for me. The fast transposed Vandermonde solver and its implementation in C Implementing Kaltofen and Yagati’s fast transposed Vandermonde solver Some papars are available for Reed-Solomon Codes, too. Because PAR2's generator matrix may not be full-rank, I'm not sure that fast multiplication works always or fails rarely. Anyway, it seems that PAR2 has a chance to improve speed. Fast En/Decoding of Reed-Solomon Codes for Failure Recovery Efficient Erasure Decoding for Generalized Reed Solomon Codes New Decoding of Reed-Solomon Codes Based on FFT and Modular Approach A Fast Decoding Algorithm for Generalized Reed-Solomon Codes and Alternant Codes |
|
Thanks for sharing these @Yutaka-Sawada. When reading these papers, it's imporant to check which (finite) field they operate on. Some of them work only in prime fields (GF(p) ) while the ones most useful to us are those that work on fields of characteristic 2 (GF(2^k), like GF(2^16) that is used by PAR 2.0). It may sometimes be possible to adapt an algorithm from one field to another but it's far from trivial. |
Introducting PAR2AFFTYesterday I cheated a bit and asked ChatGPT to help me develop an O(n log n) algorithm for multiplication of a transpose Vandermonde matrix by a vector. The idea was to develop a fast algorithm for multiplying any vector by the entire 65536x65536 transpose Vandermonde matrix defined as VT_ij = j^i for (0 ≤ i, j < 2^16), similar to what Frédéric Didier did in Efficient erasure decoding of Reed-Solomon codes, but using the Additive Fast Fourier Transform (AFFT) to make it run in O(n log n) time. The AFFT requires converting the input to a different basis that has been called the Cantor basis in Leopard 1.0, and is also called “novel polynomial basis” or LCH basis after the 2014 paper by Lin, Chung, and Han. I have no idea if what parfast does is similar; the author talked about “Forney transforms” on reddit, but I cannot find anything about how that works, and while Wikipedia does have an article on Forney's algorithm it's not obvious how it applies here, and the AI-generated code is too difficult for me to navigate. Show me the code!Back to practical matters: I was able to develop this into a working tool that generates Par2 files with high numbers of blocks much faster than Parpar. The code is here: https://github.com/maksverver/par2afft The core algorithm was generated by ChatGPT but it's not too complex: gf16_vandermonde_transpose.c It looks even simpler if I strip away the code used for initialization and testing: core-algorithm.c This is very little code but it's where 99% of CPU cycles are spent! It's not hard to see that gf16_vandermonde_transpose_multiply() runs in O(q log q) time, where q is the field size, in our case q=2^16. The C code is also quite simple, and has lots of room for potentional optimizations, for example using SIMD, or unrolling some of the recursive calls. PerformanceTo check how well this runs in practice, I included a benchmark which processes about 40 MiB/s of input data per CPU core. Note that for PAR 2.0 we can use at most half of that since only 32768 constants are used for inputs. By comparison: Leopard 1.0 does about 600 MiB/s. That's 15x faster, but Leopard was heavily optimized with SIMD instructions. I also did a simple test generating an actual par2 file from 10×100 MiB input files with 32768 input blocks and 32768 recovery blocks using parfast-1.6.0, my new par2afft code, and parpar 0.4.5 for reference. Measuring just CPU time I get the following results (details here:
Note that parfast and parpar actually finish faster than this because they use multiple threads, but this is a fairly trivial optimization, so I only measured CPU seconds to keep things fair. My tool really struggles with I/O because I simply mmap() all input and output files into memory, which puts a lot of pressure on the page cache. It works well on a system with a lot of free memory and a fast SSD. This confirms my suspicion that with fast algorithms like Leopard, a lot of the difficulty of making fast tools shifts from optimizing the CPU logic to optimizing the I/O to make sure the CPU has access to the data it needs without reading the entire input into RAM. The conclusion is that parfast is really fast, but only within a factor 4x of the AFFT code I wrote in a day. That makes me pretty optimistic about the possibility of optimizing it further to match parfast performance. At the very least, this should be an explicit demonstration that O(n log n) performance is possible while remaining compatible with the the existing PAR 2.0 file format. Future workThere are a number of things I may want to explore in the future:
|
Thanks Maks Verver for nice improvement. Using FFT will be a new trend for Reed-Solomon Codes.
Forney algorithm seems to be used in decoder. Because PAR2 requires Erasure Correction only (no need Error Locator), the decoder would be simpler than classic Reed-Solomon Codes. Anyway, I cannot understand the math. |
Uh oh!
There was an error while loading. Please reload this page.
This branches off discussion from this post, where Parfast has seemingly implemented an FFT style technique on PAR2's Vandermonde matrix.
I have no idea of the math and don't know how it works, but if anyone wants to comment or provide info/speculation/discoveries etc, here's a place which won't pollute the existing PAR3 discussion.
All reactions