# Two models on one 8 GB GPU: making the LLM wait for the TTS after every sentence stopped my voice assistant from stuttering

> Source: <https://discuss.huggingface.co/t/two-models-on-one-8-gb-gpu-making-the-llm-wait-for-the-tts-after-every-sentence-stopped-my-voice-assistant-from-stuttering/190635#post_3>
> Published: 2026-10-16 02:49:39+00:00

Thank you for reading the code this carefully. The handoff details and the two different “first audio” endpoints were both right, and the PCM trace you suggested was worth running, so I ran it.

**What I recorded.** The standalone server now also logs, per answer, when each sentence goes to the TTS, every PCM block with its duration, and each batch of frames released to the Pacer after the tail hold. Three answers each for “both on the GPU at once” and “taking turns”, same question as before. Replaying the Pacer on the recorded release times gives the same number of gaps the server reported in every run, totals within 0.011 s, so the replay below is usable.

**On your answer to my first question (sharing the GPU on Windows).** The trace agrees with the time-slicing picture, at least at the application boundary. Running at once, the first PCM arrives 2.3 to 2.5 s after the TTS request instead of 1.0 to 1.2 s, the first sentence runs at a wall-clock RTF of about 1.5, and every gap falls in the first 13 s, while the LLM is generating or just after it finishes; none come later in the 64 to 73 s answers. I haven’t located the cause below that, so I’ll keep turn-taking rather than chase MPS or a single-process design.

**On your answer to the second (another GPU).** Your deadline framing gives a number that is easy to compare across cards: how long a player would have to wait before starting to get zero gaps. On this card it is 0 to 0.12 s when taking turns and 1.9 to 3.4 s when running at once. I also replayed 5, 7 and 9 frames of prebuffer, but those come out identical by construction: the prebuffer only limits how far ahead the server sends, and the gap estimate assumes playback starts with the first frame. So that replay can’t tell whether a bigger buffer helps on the board; the start delay is the variable that matters. I’ve put your results template in the write-up so someone with a different card can fill it in.

**The small early gap.** It turned out to be the tail hold, not the GPU. The TTS delivers its first 1.0 to 1.2 s of audio as one burst, never more than the 1.2 s `tail_hold_ms`, so no frame goes out until the next block arrives about 0.19 s later. In one of the three turn-taking runs only a single 60 ms frame was released at that point and the board ran dry for 0.13 s; the other two released several frames and had a 0.01 s gap and none. Replaying the first segment as if PCM could be sent on arrival, none of the three has a gap and the first frame comes 0.19 s earlier. (The config comment saying the hold doesn’t delay first audio was wrong; it is fixed now.)

**Endpoints**, as you pointed out: “first frame” is the server sending its first audio frame; the board’s own buffering and decoding come after that and aren’t measured.

Traces, the replay script and the write-up: [gpu-duet/bench/results/traces-2026-10-16 at main · korexil/gpu-duet · GitHub](https://github.com/korexil/gpu-duet/tree/main/bench/results/traces-2026-10-16)

I may try releasing held audio when the board would otherwise run dry, or padding less silence in the TTS so the hold can shrink, and will re-run the same traces if I do.
