Show HN: SIMD Viterbi Decoder in Rust
摘要
A Rust crate implementing Viterbi and Reed-Solomon forward error correction with SIMD acceleration, achieving faster throughput than the C library libfec on supported codecs.
查看缓存全文
缓存时间: 2026/08/05 01:49
brian-armstrong/fec
Source: https://github.com/brian-armstrong/fec
fec
Forward error correction for SDR, space, and satellite applications.
fec implements two error-correcting codes that show up throughout
software-defined radio and spacecraft links:
- Convolutional codes with a Viterbi decoder (hard and soft decision),
including the common rate-1/2 k=7, rate-1/2 k=9, rate-1/3 k=9, and
rate-1/6 k=15 codes. Supports any rate from 1/2 to 1/8 and any order from
k=4 to k=16. On nightly Rust, the
simdfeature enables a Viterbi decoder with acceleration on SSE/AVX2/AVX512. - Reed–Solomon codes over GF(2⁸) with error and erasure decoding, including the standard CCSDS (255,223) code in both the conventional and the on-the-wire dual-basis (Berlekamp) representations.
fec started as and draws heavy inspiration from the author’s own
libcorrect, a C library
for forward error correction. This crate also credits Phil Karn’s libfec
C library for offering an original implementation of these codes, although
this crate does not borrow any source or have any relationship with that
library, and the name is purely coincidental.
Standard parameters (primitive polynomials, the CCSDS dual-basis transform) are derived from the published CCSDS standard (CCSDS 131.0-B, Annex D for the dual basis).
Performance
With the simd feature, fec decodes faster than libfec on every code.
Measured through libfec’s own test programs with only the codec library
swapped, on a Zen4 laptop (Ryzen 7840HS). Higher is better.
| code | fec (64-bit) | libfec (32-bit) | libfec (64-bit) |
|---|---|---|---|
| conv, rate 1/2, k=7 | 158 Mbps | 148 Mbps1 | 17 Mbps |
| conv, rate 1/2, k=9 | 66 Mbps | 65 Mbps1 | 3 Mbps |
| conv, rate 1/3, k=9 | 61 Mbps | 23 Mbps1 | 2 Mbps |
| conv, rate 1/6, k=15 | 1187 Kbps | 415 Kbps1 | 40 Kbps |
| RS (255,223), general | 568 Mbps | 123 Mbps | 157 Mbps |
| RS (255,223), CCSDS | 568 Mbps | 198 Mbps | 223 Mbps |
| RS (255,223), general, 2 err | 445 Mbps | 108 Mbps | 150 Mbps |
| RS (255,223), CCSDS, 2 err | 443 Mbps | 165 Mbps | 207 Mbps |
Convolutional throughput is decoded payload bits per second. The Reed-Solomon rows decode a (255,223) block, first with no errors (syndromes only) and then with two symbol errors. Reed-Solomon uses no SIMD in either library, so its 32-bit and 64-bit rows differ only by pointer width.
libfec’s SIMD kernels are gated behind #ifdef __i386__, so its fastest
convolutional build is the 32-bit one, running Karn’s SSE2 assembly. A
64-bit libfec build has no SIMD path at all. fec’s SIMD works on both.
See shim/BENCH.md for the full tables, the bit error rate comparison, the 32-bit numbers, and how to reproduce them.
Quick start
Convolutional (Viterbi)
use fec::{ConvEncoder, ConvDecoder};
// Rate-1/2, order-7 NASA code.
let polys = [0o161, 0o127];
let mut enc = ConvEncoder::new(2, 7, &polys);
let mut dec = ConvDecoder::new(2, 7, &polys);
let msg = b"hello, error correction";
let mut encoded = vec![0u8; enc.encode_len(msg.len())];
let num_bits = enc.encode(msg, &mut encoded).unwrap();
// ... encoded is corrupted in transit ...
let mut recovered = vec![0u8; msg.len()];
dec.decode_hard(&encoded, num_bits, &mut recovered).unwrap();
decode_soft takes 8-bit soft symbols instead, which corrects more errors when
the demodulator can report its confidence.
Reed–Solomon
use fec::{RsEncoder, RsDecoder};
// Standard CCSDS (255,223) code.
let mut enc = RsEncoder::new_ccsds();
let mut dec = RsDecoder::new_ccsds();
let msg: Vec<u8> = (0..223).collect();
let mut block = vec![0u8; 255];
enc.encode(&msg, &mut block).unwrap();
// ... block is corrupted in transit ...
let mut recovered = vec![0u8; 223];
let corrected = dec.decode(&block, &mut recovered).unwrap();
println!("corrected {corrected} symbol error(s)");
For real spacecraft telemetry (dual-basis symbols on the wire), use
encode_ccsds_dual / decode_ccsds_dual.
Compatibility
The codes are bit-compatible with libfec
(Phil Karn, KA9Q), so fec can decode data Karn’s library produced and
vice versa. A companion shim crate, fec-shim,
exposes fec under libfec’s C ABI (init_rs_char, create_viterbi27,
encode_rs_ccsds, etc) as a drop-in for existing C codebases.
Roadmap
- More widths for the Reed-Solomon encoder/decoder (narrower than GF(2⁸) and as wide as GF(2¹⁶))
- Hard-decision erasures in the convolutional (Viterbi) decoder
- Punctured codes for the convolutional encoder and decoder
License
BSD-3-Clause.
相似文章
Rust 中的安全 SIMD,即使内部也安全
Rust 的 SIMD 抽象现在允许在不使用 unsafe 代码的情况下安全使用,这得益于 Rust 1.87 引入的 CPU 特性令牌,从而实现了简洁且可移植的向量操作。
Show HN: Hsrs – 用于 Rust 的类型安全 Haskell 绑定生成器
Hsrs 是一个类型安全的 FFI 绑定生成器,允许从 Haskell 调用 Rust 代码,具有自动内存管理、类型转换和 Borsh 序列化功能。它在 Rust 中提供注解,并生成符合语言习惯的 Haskell 包装器。
Show HN: Rscrypto,纯 Rust 加密库,拥有业界领先的公开基准测试
rscrypto 是一个纯 Rust 加密库,提供 RSA、Ed25519、X25519、AEAD、哈希、KDF 等功能,注重可移植性、no_std 支持以及业界领先的基准测试。
我们如何(及为何)将生产环境的C++前端基础设施重写为Rust
NearlyFreeSpeech.NET 将其生产环境的C++前端基础设施(nfsncore)重写为Rust,该系统负责所有传入请求的路由、缓存和访问控制。迁移的动机是Rust的安全性保证、性能、生态系统优势以及老化的C++代码库的局限性。
@charliermarsh: 来自 Trifecta Tech 的纯 Rust zstandard 解码器实现!很荣幸与 Chainguard 共同资助了这项工作……
一个纯 Rust 的 zstandard 解码器实现已经发布,由 Trifecta Tech、Chainguard 和 NLnet 基金会资助。