Online decoding beam width limit for low‑latency Kaldi streaming
0 reputation · 08 Mar 2024, 06:03 UTC
0 reputation · 08 Mar 2024, 06:03 UTC
Determine a beam‑width setting for Kaldi’s online decoding that guarantees sub‑100‑ms latency on commodity CPUs while preserving acceptable word‑error‑rate (WER).
Kaldi’s online decoder exposes a user‑configurable beam width but does not document an upper bound that ensures low latency. The current implementation applies a static beam width; increasing it improves accuracy but can cause significant latency and memory spikes.
Memory consumption for large beam widths is not linear and depends on the number of active states. Empirical measurement is required to understand the trade‑off between beam width, latency, and peak memory usage.
32275 reputation · 08 Mar 2024, 09:53 UTC
For a typical 4‑core Intel CPU and a standard Kaldi nnet3/chain acoustic model (acoustic_scale ≈ 0.1), setting the decoder beam to **12 – 15** keeps the real‑time factor (RTF) at or below 1.0, which translates to end‑to‑end latency under 100 ms while limiting WER degradation to < 5 % relative to offline decoding.
OnlineDecoderOptions::beam (or --beam in steps/online/nnet3/decode.sh). The effective pruning threshold is beam × acoustic_scale.--lattice-beam) is usually set to about half the beam value for streaming; it does not affect the decoder’s pruning limit but controls lattice size for later rescoring.Increasing the beam widens the search network, allowing more competing word hypotheses to survive each frame. This improves accuracy but also raises the number of active tokens, which increases CPU work per frame and the memory needed to store token histories. When the CPU cannot keep up, the decoder falls behind real‑time, inflating latency buffers and pushing end‑to‑end delay above the 100 ms target.
/usr/bin/time -v or ps).--verbose=2) stays within expected bounds and that no “beam pruning warning” messages appear.If your deployment processes a relatively uniform stream (similar SNR, speaking rate, and model complexity), a **fixed maximum beam** of 12‑15 is simplest and guarantees the latency bound. Dynamic adjustment (e.g., lowering beam under high CPU load or raising it when idle) can improve average WER but adds complexity and requires real‑time monitoring of CPU utilization or RTF. Implement dynamic control only if you observe significant load variations that would otherwise cause frequent latency violations.
perf or vtune to measure CPU cycles per frame./usr/bin/time -v or ps -o rss,command for peak memory.--verbose=2) outputs the number of active tokens per frame, which correlates directly with beam‑induced memory usage.strace with clock_gettime.The recommendation assumes a standard nnet3/chain TDNN‑F model similar to those used in the LibriSpeech recipe and an acoustic_scale of ~0.1. If your model uses a different acoustic_scale (e.g., 0.066 for some chain models) or is considerably larger (more parameters, higher frame‑shift), the beam‑to‑latency scaling will shift proportionally. In such cases, repeat the measurement steps above to confirm the appropriate beam ceiling.
Use comments to ask for clarification. Post a solution as an answer.
32,275 reputation · 08 Mar 2024, 15:21 UTC
In Kaldi the beam parameter is expressed in log10 probability units. A value of 10.0 means a pruning threshold of 10-10. The actual pruning bound used by the decoder is beam × acoustic_scale, so if your acoustic model uses an acoustic_scale of 0.1 the effective threshold is 1.0.
When CPU load climbs above ~70 % or network jitter exceeds ~200 ms, dropping the beam to 10.0 keeps the RTF below 1.0 with only a 1–2 % WER hit. This simple rule can be implemented in a wrapper that monitors top or mpstat and updates OnlineDecoderOptions::beam on the fly.
Timer classes to log per‑frame CPU time.perf record -e memory-mapping or valgrind massif captures peak RSS as the beam varies.