Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings
Discussion options

When using the llama.cpp Python wrapper, I've noticed that inference performance can be unexpectedly slow for very short prompts (under around 50 tokens). Specifically, the time to first token (TTFT) seems worse than when using the plain C++ CLI, and in some cases even slower than when running longer prompts.

Why might this be happening? I'm particularly interested in how Python overhead, backend execution, tokenization, and caching behavior could be contributing to the slowdown. Also, if you were trying to debug and optimize this—ideally without hurting overall throughput—how would you go about identifying the bottleneck and improving TTFT for short prompts?

You must be logged in to vote

Yeah this happens a lot, especially if you’ve only compared the Python wrapper against the raw llama.cpp binary.

The wrapper adds extra cost just for being in Python. If it calls into C++ too often (say per-token callbacks or too much tokenization in Python), that overhead is noticeable when the prompt is short. The GIL can also cause delays if you mix threading or async badly.

Also, The first forward pass is always the heaviest. It needs to build KV caches, maybe dequantize weights, and on GPU it often has to spin up kernels for the first time. That’s why TTFT feels much higher than per-token latency. In C++ CLI they do some of this a bit more directly, so Python shows more of the raw cost.

Replies: 1 comment · 3 replies

Comment options

Yeah this happens a lot, especially if you’ve only compared the Python wrapper against the raw llama.cpp binary.

The wrapper adds extra cost just for being in Python. If it calls into C++ too often (say per-token callbacks or too much tokenization in Python), that overhead is noticeable when the prompt is short. The GIL can also cause delays if you mix threading or async badly.

Also, The first forward pass is always the heaviest. It needs to build KV caches, maybe dequantize weights, and on GPU it often has to spin up kernels for the first time. That’s why TTFT feels much higher than per-token latency. In C++ CLI they do some of this a bit more directly, so Python shows more of the raw cost.

If the wrapper is doing tokenization in Python, that can dominate when the prompt is short. Also if you aren’t using prompt caching, you pay the full cost every time even if the prefix is repeated.

How I’d debug it:

  • Add simple perf_counter timers around tokenization, generation call, and first token callback. That tells me if Python or backend is eating the time.
  • Compare with the C++ CLI on the same prompt to get the baseline. If CLI is faster, the wrapper layer is guilty.
  • Run a warm-up generation right after loading the model. If the second run is much faster, that means initialization/dequantization was the big hit.
  • If it’s GPU, I’d check with Nsight or nvprof to see if kernel launch overhead or transfers are the delay. On CPU, perf or just logging thread pool startup is enough.

How I’d fix it:

  • Move tokenization into the C++ side if possible.
  • Pre-warm the model on startup with a dummy forward pass so users never see that first-hit latency.
  • Keep the model in memory and reuse it between calls.
  • For streaming, batch tokens instead of sending them back to Python one by one.
  • If I absolutely need really low TTFT, I’d consider serving from a thin C++ worker and only talk to it from Python, so Python isn’t in the hot path.

Long story short : Python overhead + cold start cost + tokenization are the usual suspects. The fix is mostly warm-up and pushing more work into native code.

You must be logged in to vote
3 replies
@quantumtensors
Comment options

Thanks Chandra, that was super helpful.

Quick follow up on that ; even after moving things into C++, are there still hardware-level factors that limit TTFT? Like CPU cache misses, NUMA issues, or thread pool startup? And on GPU, how much does kernel launch or PCIe latency actually affect TTFT compared to later tokens?

@chandraprvkvsh
Comment options

I don't have a good understanding of the c++ or the hardware side of things, But try tagging the contributors of the repo as they might have an answer for you.

@quantumtensors
Comment options

Thankyou, Can you guys have a look at it?

@abetlen @Stonelinks @Smartappli @gjmulder @CISC

Answer selected by quantumtensors
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Category
🙏
Q&A
Labels
None yet
2 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.