TT Lab
Blog

한국어 English 日本語 中文

Get started
Blog

Blog

Checking the Principles of Voice Conversations with Numbers: Decoding is Memory Bandwidth, Synthesis is Number of Frames, and Streaming is Cache

Status: Draft (2026-10-06), Principles article. The principle explanations are based on official materials for each model (linked at the end of the article) and general inference theory, while the numbers used for cross-checking are values measured directly by the author in Episode 20. The formulas are simplified to understand the phenomenon, and each section clarifies which parts were verified and which parts were estimated. Writing rule: Measured data is the default, and unmeasured items are marked as 「Unmeasured」.

Table of Contents

1. At a Glance: What Determines Time Varies by Component

The values in Episode 20 were about 「how long it took」, whereas this article is about 「why it takes that long」.

Component What Determines Time Value Predicted by Principles Directly Measured Value Match
Conversational LLM, Token Generation Time to read the entire set of weights from memory per token Upper bound approx. 129 tok/s (based on measured bandwidth) 85.6 tok/s 66% of upper bound
Conversational LLM, Input Processing Amount of computation Much faster than generation 700 tok/s (67 tokens), approx. 75–80% of compute limit for 1,024 tokens or more Match, short inputs are slower
Bandwidth Upper Bound of Generation Speed Weight bytes × Speed ≤ Bandwidth Measured bandwidth 250 GB/s 86–98% across four models Match
Text-to-Speech (VoxCPM2) Number of patches (steps) to create 1 second of audio = 6.25 patches (one patch = 160ms worth) 0.475 seconds per second, approx. 76ms per patch Connected via calculation, matches paper architecture
Streaming Speech Recognition Chunk = Number of frames × 80ms 5 chunk types Cross-check matches the 5 values on the card Match

2. Conversational LLM: Reading the Entire Model Every Time a Token is Generated

Principle

For a Transformer to compute a single next token, it must use the weights of all layers once. With a single request, each weight undergoes only one or two multiplications and finishes, leaving the GPU compute units idle while the speed at which weights are fetched from memory (memory bandwidth) determines the time. Therefore, the theoretical upper bound of token generation speed is as follows.

초당 토큰 수 ≤ 메모리 대역폭 ÷ 가중치 바이트 수

Conversely, the input (prompt) processing stage computes dozens of tokens all at once, so multiple tokens reuse the same weights, making compute capacity the bottleneck. This is why input processing is much faster than generation on the same model.

Cross-check

Item Value Source
GPU Memory Bandwidth Approx. 905 GB/s(24GB class consumer GPU, read-only sum, 3 repetitions 903–905) Direct measurement (PyTorch test reading a 1 GiB tensor). Copy (read + write) is 865 GB/s. The spec sheet's approx. 936 GB/s was a memory-based value and is not used.
Weights (4-bit QAT) 7.0 GB Model file size verified via public API
Theoretical Upper Bound 905 ÷ 7.0 ≈ 129 tok/s Calculation
Measured Generation Speed 85.6 tok/s(11.6ms per token) Measured in Episode 20, matches server telemetry
Efficiency 85.6 ÷ 129 ≈ 66% Calculation
Input Processing Speed 700 tok/s(95.7ms for 67 tokens) Server telemetry

Direct Verification: Confirming the Upper Bound with Models of Different Sizes and Precisions

Since the cross-check above sourced its bandwidth value from the specifications, we could not verify whether the upper bound itself was correct. Therefore, we measured the bandwidth directly firston a single 8GB-class GPU and measured the generation speeds of four models of differing sizes and precisions using the same method (vLLM 0.31.0, 1 concurrent request, median of 5 runs for 128 generated tokens).

Model Loaded Weights Generation Speed Weight × Speed Vs. Measured Bandwidth
0.6B, bf16 1.12 GiB 180.4 tok/s 217 GB/s 87%
1.7B, bf16 3.22 GiB 68.8 tok/s 238 GB/s 95%
1.7B, fp8 1.90 GiB 105.7 tok/s 216 GB/s 86%
4B, fp8 4.32 GiB 52.7 tok/s 244 GB/s 98%

Weight size is the loaded memory from server logs, and 「Weight × Speed」 is a calculation assuming weights are read once per generated token.

Why Speed Doesn't Drop Even When Concurrent Requests Increase, and Its Limitations

Since the cost of reading weights occurs only once regardless of the number of requests, batching multiple requests together for processing (continuous batching) amortizes the read cost. In Episode 20, when 2 requests were sent simultaneously, the first token took 0.206 seconds, and for 4 requests, the median was 0.352 seconds. Because this server only had 2 slots open, the 4-request case involved queuing in pairs of two, so it was not an experiment that cleanly demonstrated the benefits of batching.

Therefore, we opened the four models above with 16 slots and increased the number of concurrent requests to measure total throughput (generating 128 tokens per request, median of 3 runs).

Concurrent Requests 0.6B bf16 1.7B bf16 1.7B fp8 4B fp8
1 180 69 106 53
4 670 264 405 205
16 2,484 1,007 1,544 775
Multiple of 1 request when at 16 requests 13.8x 14.6x 14.6x 14.7x
Speed of a single request at 16 requests 155(86%) 63(91%) 97(91%) 48(92%)

The unit is total throughput (tok/s), and the last two rows were calculated from the table above. Although requests were increased 16-fold, individual requests slowed down by only 8–14%, while total throughput reached nearly 14–15x. The principle of sharing the weight-reading cost manifests directly.

The point where this benefit ends was only estimated through calculation. Since each token requires 2 operations per parameter, based on the measured compute throughput (31.8 TFLOPS) and measured bandwidth (250 GB/s), compute becomes the bottleneck past approximately 130 concurrent requests for bf16 and approximately 64 for fp8 (calculated, simplifying by ignoring attention and KV cache reads). Since we only opened up to 16 requests this time, that threshold was not verified (unmeasured), and even the 4B model at the 16-request mark used only about 18% of its measured compute limit (2 × 3.6B × 775 ≈ 5.6 TFLOPS), keeping it firmly in the bandwidth-bound region.

Input Processing is Compute-Bound, and Short Inputs Come Out Slower

Input processing was measured using the same server, with prefix caching disabled and using distinct random inputs per request.

Input Length 1.7B bf16 4B fp8
256 tokens 5,709 tok/s (45ms) 3,129 tok/s (82ms)
1,024 tokens 8,634 tok/s (119ms) 3,438 tok/s (298ms)
2,048 tokens 8,730 tok/s (235ms) 3,365 tok/s (609ms)
3,500 tokens 8,244 tok/s (425ms) 3,182 tok/s (1.10s)

3. Text-to-Speech: Repeat as many times as the number of patches to create

Principle

Neither of the two synthesis models outputs sound all at once, but rather produce short units (160ms worth of patches for VoxCPM2, codec frames for Magpie) one by one from the beginning (autoregression). Therefore, time is directly proportional to the audio length, and a fixed cost independent of length is attached to the beginning of the sentence. The formula fitted to twelve points in Part 20 has this shape.

합성 시간 ≈ 0.475 × 오디오 길이(초) + 0.23초

VoxCPM2: 76ms per patch

According to the VoxCPM2 technical report, this model does not use discrete tokens, but rather has a structure that generates continuous latent representations through diffusion and autoregression . It reduces speech to 25 latent frames (40ms) per second, groups 4 frames into a patch, and creates patches one at a time. Therefore, one step of autoregression corresponds to 160ms of audio, which is 6.25 stepsper second. Connecting this number with the measurements yields the following.

Item Value
Steps (patches) required for 1 second of audio 6.25
Time to generate 1 second of audio (measured slope) 0.475 seconds
Time spent per step (patch) 0.475 ÷ 6.25 ≈ 76ms
Diffusion repetition count in server settings 10(inference_timesteps=10, confirmed in server code)
Per diffusion step (the 76ms above divided by 10) About 7.6ms (upper bound. The time per step includes one language model step and decoding, and according to the paper, Classifier-Free Guidance (CFG), which computes the diffusion module twice per diffusion step, is also included, so the actual value per step may be smaller)

This means that the cost of running one language model step and 10 diffusion stepsfor each step is 76ms, and in this structure, it can be expected that reducing the number of diffusion repetition steps will speed things up almost proportionally. The speed and quality when reducing the number of repetitions were not tested (unmeasured). The fixed cost of 0.23 seconds could not be found in the paper either. The real-time factor in the paper is a wall-clock value including the fixed cost, so the longer the length, the closer it gets to the slope. No material indicates whether this 0.23 seconds is sentence encoding, reference voice processing, decoder initialization, or the server wrapper, and it was not broken down (unconfirmed).

Official descriptions state that this model supports streaming generation (generate_streaming), and the technical report (Table 11) reports a real-time factor of 0.30 for a PyTorch implementation on a single high-end consumer GPU (24GB class) (peak VRAM about 8GB), and 0.13 when using a serving engine (Nano-vLLM). Our measured slope of 0.475 is about 1.6 times slower than the 0.30 in the paper, but it could not be determined whether this was due to the GPU type, the server method of synthesizing and returning entire sentences, or wrapper overhead (unconfirmed). VRAM (6,600 to 6,900 MiB) is in the same range as the paper's roughly 8GB.

Magpie TTS: Two frames at a time

Magpie TTS Multilingual is an encoder-decoder transformer with 364 million parameters. The official description has two core points: Frame stackingis a method where the decoder predicts two audio frames at once in a single step, cutting the number of repetitions in half, and local transformersare small modules that refine the dependencies between the frames created this way to recover the reduced quality. This essentially halves the number of decoder steps required to produce the same length of sound.

Item VoxCPM2 Magpie TTS
Parameters About 2 billion About 364 million
Generation method Continuous latent representations via diffusion and autoregression Codec frames via autoregression (two frames at a time)
GPU memory (measured) About 6,600 to 6,900 MiB About 750 MiB
Real-time factor (measured) 0.494 to 0.582, median 0.521 0.447 to 0.541, median 0.466 (excluding Korean)

Why streaming synthesis reduces the time to first sound

Because patches are generated from the beginning, there is no need to wait until the end of the sentence; playback can begin as soon as the first patch comes out (the VoxCPM2 report explains that it is structured to convert generated patches into sound immediately). The time to the first sound is reduced from the 「total sentence synthesis time」 (Part 20 measurement: 1.2 to 2.1 seconds) to the 「fixed cost per sentence plus the time of the first single patch」 (0.23 seconds + 0.08 seconds, about 0.3 seconds). This is a calculation and was not tested on the server used for measurements. Since playback is slower than synthesis (real-time factor 0.5), the condition that subsequent audio does not stutter is also required.

4. Streaming Speech Recognition: Do not recompute what has already been computed

Principle

The speech recognition model Nemotron 3.5 ASR consists of 24 FastConformer encoder layers and an RNNT decoder. Two things create latency.

  1. Frame length. The encoder reduces the sound by a factor of 8, making a single encoder frame 80ms (based on the general setting of extracting features at 10ms intervals, and the chunk value of 80ms in the model card matches this interpretation).
  2. Right context (amount of look-ahead). To determine the meaning of the current frame, we want to look a little bit into future frames. Since we must wait until those frames arrive, the amount of look-ahead is precisely the latency.

The model determines these two with att_context_size = [왼쪽, 오른쪽] . The 56 left frames are the amount remembering 4.48 seconds of the past (56 x 80ms), and the right side determines the chunk. The length of a chunk processed at once is (right + 1) x 80ms.

att_context_size Calculation: (Right + 1) x 80ms Model card chunk value Match
[56, 0] 1 x 80 = 80ms 80ms Match
[56, 1] 2 x 80 = 160ms 160ms Match
[56, 3] 4 x 80 = 320ms 320ms Match
[56, 6] 7 x 80 = 560ms 560ms Match
[56, 13] 14 x 80 = 1,120ms 1.12 seconds Match

Since all five values match the table in the card, it can be considered correct to interpret that 「chunk = (right context + 1) x 80ms」.

What the cache does

Older streaming methods (buffer methods) cut recent audio into overlapping windows and re-encoded from the beginning every time. This essentially computes overlapping sections multiple times. The cache-aware method stores the encoder representations of all self-attention layers and convolution layers in the cache, and when new audio arrives, it only computes the new frames to update the cache. As official explanations state, each frame is processed exactly once. As a result, the amount of computation is proportional to the newly incoming length, not the audio length. Throughput figures are vendor specs: the multilingual 3.5 model card lists about 240 concurrent streams for an 80ms chunk setting on a single H100 (baseline Parakeet 1.1B using the buffer method is about 14), and about 2,400 streams for the 1.12-second setting (baseline about 400), while the NVIDIA blog for the English-only model lists 560 streams at a 320ms chunk (these are values for two different models and should not be mixed up). 「Median 24ms until final results」 is a partner pipeline value from the English model blog. It was not reproduced in the author's experimental environment.

Because the RNNT decoder is structured to output a character (or a blank token meaning 「none yet」) every time an encoder frame is produced, characters are outputted sequentially as frames come in. Therefore, results stream out before speech ends, and once speech ends, only the final chunk needs to be finalized.

Does increasing chunk size improve accuracy?

Generally, the longer the right context, the more future the model sees to make decisions, which typically increases accuracy while also increasing latency. Applying chunk-size settings to the same 12 voices and measuring the average character error rate yields the following (this is an approximation applying settings to the entire file, not actual streaming).

Chunk 80ms 160ms 320ms 560ms 1,120ms
Average Character Error Rate 4.3% 4.0% 3.9% 3.9% 11.3%

5. Putting Them Together: The Type of Bottleneck Varies by Component

Component Type of Bottleneck Direction of Reduction Method
Speech Recognition Compute (proportional to number of new frames), very lightweight Almost no need to touch
Conversational LLM Memory bandwidth Smaller weights (quantization), wider bandwidth GPUs, disabling thinking
Text-to-Speech (TTS) Iteration creating frames sequentially Streaming, shorter phrases first, adjusting iteration count

This is why synthesis accounted for 60-85% of the calculation time in a single turn of part 20. Speech recognition is lightweight computation, and LLMs are already utilizing 66% of the bandwidth upper limit with little room to squeeze further, leaving only synthesis 「repeating as much as the audio length」 structure, causing time to increase linearly as sentences get longer.

6. Potential Interview Questions

External Evidence: Verification via Papers and Official Materials

The numerical values in this article are directly measured, and the underlying principles were cross-checked against the materials below. External figures were not directly compared due to differing models, GPUs, and workloads; only structural and directional alignmentwas evaluated.

Topic Source Material and Checked Location Verified Content and Conditions Relationship to This Article
Memory Limits of Decoding Pope et al., "Efficiently Scaling Transformer Inference", arXiv 2211.05102, Section 2. Yuan et al., "LLM Inference Unveiled: Survey and Roofline Model Insights", arXiv 2402.16363, Section 3.1.1 Small batches and context make weight reading time dominant, while large batches shift the bottleneck to computation. Compressing weights does not reduce time in the compute-bound region (Llama-2-13b, context 1,024). Supports. Consistent with the principles in Section 2. No paper was found that states the formula "Upper Limit = Bandwidth ÷ Weight Bytes" in a single line; the formula in this article is a simplification that omits KV reading terms.
Bandwidth Utilization Databricks Tech Blog, "LLM Inference Performance Engineering: Best Practices" (2023-10-12) Model Bandwidth Utilization (MBU) at batch size 1 is 60% for 2×H100 and 55% for 4×A100-40GB (TensorRT-LLM, Tensor Parallelism). Decreases as batch size grows. Partially supports. Since the denominator is the peak bandwidth from the datasheet, it is not the same metric as our 86-98% (where the denominator is directly measured read bandwidth).
Variance in Utilization Chen, "Memory-Bound but Not Bandwidth-Limited", arXiv 2605.30571 (2026, single-author preprint, unpeer-reviewed) Reports about 81% on L4 and about 27% on H100 at batch size 1 using PyTorch default paths, explaining it is due to execution startup overhead. Partially supports. High-bandwidth GPUs may not achieve the same attainment rates. Our values were verified only on two GPUs (8GB class and 24GB class).
VoxCPM2 Architecture "VoxCPM2 Technical Report", arXiv 2606.06928, Sections 3.1, 3.7, Table 11 in Section 4.6 Groups four 25Hz latent frames into a single patch for 6.25Hz autoregression (one step = 160ms). Computes diffusion modules twice per diffusion step (CFG). Single high-end consumer GPU (24GB class) PyTorch real-time factor 0.30, peak VRAM approx. 8GB, serving engine 0.13. Partially supports. The length-proportional structure is correct. The breakdown of time per step and the 0.23-second fixed cost have no basis in the paper, and our slope of 0.475 is 1.6x slower than the paper.
Frame Stacking Fejgin et al. (NVIDIA), "Frame-Stacked Local Transformers for Efficient Multi-Codebook Speech Generation", arXiv 2509.19592, ICASSP 2026 In an English model based on NanoCodec (21.5 frames/sec, 8 codebooks), with a stacking factor of 2, the autoregressive local transformer is 2.1x faster than the parallel prediction baseline. Related. Uses the same method as Magpie's "two frames at once" explanation, but the model card does not clarify whether it is the same experimental model as the published multilingual model.
Cache-Aware Streaming ASR Noroozi et al., "Stateful Conformer with Cache-based Inference for Streaming ASR", arXiv 2312.17279, ICASSP 2024, Tables 1 and 2 Approx. 114M parameters, LibriSpeech test-other, RNN-T Word Error Rate (WER) by lookahead amount: 0ms 9.5%, 240ms 7.8%, 520ms 7.5%, 1,360ms 6.3%. Shorter latency and higher accuracy than the buffer-based baseline (RNN-T 11.3%, average latency 2,000ms). Supports. Accuracy improves with longer context. The term "latency" in the paper has a different definition than chunk size.
Korean Accuracy per Chunk nvidia/nemotron-3.5-asr-streaming-0.6b Model Card (FLEURS, language-specified mode) Korean Character Error Rate (CER): 80ms 7.59, 160ms 7.70, 320ms 7.27, 560ms 7.18, 1.12s 7.12 (%). Chunk values of 80, 160, 320, 560, 1,120ms match att_context_size 's (right context + 1) × 80ms Supports. Aligns with the direction of the chunk interpretation in Section 4's table. Re-evaluating with 30 human FLEURS speech sentences showed Korean CER flattening out from chunk 1,120 down to 80ms at 5.8, 5.9, 5.6, 6.2, 6.1%, which does not contradict the model card (7.12-7.70%). The anomaly where only 1,120ms performed poorly across 12 synthetic speech samples was not reproduced.
Non-Native Speech McGuire, arXiv 2503.06924, Tables 2 and 3 (L2-ARCTIC read speech). Kim et al., LearnerVoice, Interspeech 2024, arXiv 2407.04280. Oh et al., ETRI Journal 42(5), 2020 Whisper large-v3 error rates on read speech: native speakers 0.007, Korean speakers 0.033 (approx. 4.7x), Chinese speakers 0.053, Vietnamese speakers 0.124. Korean learner English spontaneous speech WER 19.18% (similar to native conversation levels, indicating spontaneous conversational traits are also a major factor). Older Korean models: native speakers 3.42%, non-native speakers 36.74% (syllable error rate). Supports. Serves as the basis for the statement that synthetic speech values are optimistic. There is no basis for the general multiplier to apply to synthetic speech values. Measurements of modern models on Korean, Japanese, and Chinese learner speech were not found in accessible literature.

Vendor figures (such as H100 concurrent streams in model cards) were cited only for directional trends because conditions were only partially specified on the cards. PNAS and certain model cards had restricted access, so we read alternative copies or papers instead, and omitted figures from materials we could not open.

Unverified Items

References

Verified Versions and Dates

As of 2026-10-06. llama.cpp b11429, Gemma 4 12B QAT q4_0, vLLM 0.31.0 (bandwidth, concurrency, and input processing verified using Qwen3 0.6B, 1.7B, and 4B-Instruct-2507 FP8), VoxCPM2 (voxcpm 2.0.3), Nemotron 3.5 ASR Streaming 0.6B, NeMo 3.0.0.

Sign in to like

Comments

No comments yet.

Sign in to leave a comment