I like having two things simultaneously loaded in memory at all times:
The latest open-weight LLM, for my agentic harnesses. (I'm using Goose at the moment, and another custom-written harness.)
An image-generation system model, for quick sketches and ideas. (Personally, I love InvokeAI with Z-Image Turbo.)
Unfortunately, having both loaded on the same GPU often turns into a VRAM budgeting exercise.
Yes, my RTX 4090 has substantial VRAM for one card - 24 GB. But a modern 27B-class LLM model - and I'm now using Qwen 3.8 - can consume most of that delicious VRAM, before the image model even starts loading.
But a recent round of tuning LM Studio on a Ryzen 9 7950X3D system with an RTX 4090 produced a surprisingly effective compromise:
a vanilla Qwen 3.8-27B Q4 model, running at roughly 19-20 tokens per second;
the full 262,144-token context window;
InvokeAI with Z-Image Turbo running at the same time.
And best of all? No need to reduce GPU model offload.
The key for me was to decide which parts of inference actually deserved precious GPU memory. Here's how I went about it.
GPU utilization and VRAM allocation are separate problems. (A model can sit at 1% GPU utilization while still holding nearly all available VRAM.)
My initial configuration used roughly 22 GB of VRAM for LM Studio alone. That left barely more than 1 GB free on a nominally 24 GB card.
That meant InvokeAI had nowhere useful to load Z-Image Turbo.
My first instinct was to reduce GPU offload, and push transformer layers onto the CPU. That does free memory. But it also attacks inference speed, which I'm trying to prioritize.
LM Studio exposes a setting called:
Offload KV Cache to GPU Memory
Turning that off moved the KV cache into system RAM. I didn't really know what that was, but I clicked it.
The effect was immediate: LM Studio's VRAM consumption dropped by roughly 4.5 GB, from around 22 GB to about 17.5-18 GB.
Wow. Now model weights and transformer computation could remain on the RTX 4090, while the growing attention cache lived in ordinary RAM. (And I had room to spare, with 64 GB RAM mostly unused.)
The architecture effectively became:
RTX 4090
├── Qwen 3.8 - 27B
└── InvokeAI / Z-Image Turbo
System RAM
└── KV cache
This was a good start.
Initially, my model was configured for about 16K context, because the KV cache was on GPU.
Once the KV cache was moved out of VRAM, it became possible to increase the configured context all the way to 262,144 tokens.
Yes. I maxed it out. While still running InvokeAI alongside it.
I then kept testing. The final practical result was better than my original configuration in every useful sense:
BEFORE:
- 16K context
- ~23 GB LM Studio VRAM use
- InvokeAI effectively excluded
AFTER:
- 262K context
- ~19-20 tok/s
- ~20 GB LM Studio VRAM use
- InvokeAI running simultaneously
- GPU model offload retained
LM Studio supports speculative decoding through MTP, so I tested it:
| MTP setting | Generation speed |
|---|---|
| Off | 17-20 tok/s |
| 2 draft tokens | ~19-21 tok/s |
| 3 draft tokens | ~18-19 tok/s |
| 5 draft tokens | ~14 tok/s |
At 2x draft tokens, I got a small 'win' - +1 token.
But then I encountered something I didn't like: lack of smoothness. With MTP disabled, generation felt less jerky and more consistent. There were fewer 'bursts'.
(Arguably this doesn't matter if you're not staring while generation is going on. But I now realize that in local inference tuning, the highest reported token rate is not always the best interactive experience. Hmm.)
I still use MTP with my other models, but I eventually disabled MTP for this config.
Another useful discovery was with Evaluation Batch Size and Physical Batch Size.
Increasing batch size can make the first prefill phase much faster.
Larger evaluation batches let the GPU process more prompt tokens in larger chunks during prefill. (Which is kind of important for agentic workloads.) And so we can reduce time to first token.
I tested successfully with:
Evaluation Batch Size: 4096
Physical Batch Size: 2048
I've looked it up, and my config seems more aggressive than many default configurations. But on my RTX 4090 setup, it worked. And it didn't destabilize my other GPU workload with InvokeAI.
My machine uses an AMD Ryzen 9 7950X3D, with 16 physical cores and 32 threads.
Since the KV cache was now living in system RAM, I wondered if CPU thread tuning would matter substantially. It didn't (for me).
I tested several thread counts. 16 threads performed best, but I felt no real difference.
I also tested KV-cache precision.
I found no obvious speed difference between Q4 and Q8 in my testing. Since I had enough system RAM and wasn't gaining anything noticeable from the lower precision, I preferred to keep Q8_0 for both K and V cache, rather than trade away precision unnecessarily.
My final configuration in the end was this:
K cache: Q8_0
V cache: Q8_0
My resulting LM Studio configuration was approximately this - which I deem optimal for my needs:
Context Length 262144
GPU Offload 65
CPU Thread Pool Size 16
Evaluation Batch Size 4096
Physical Batch Size 2048
Unified KV Cache ON
Context Checkpoints 8
Offload KV Cache to GPU OFF
Keep Model in Memory ON
Try mmap() ON
Speculative Decoding OFF
Flash Attention ON
K Cache Quantization Q8_0
V Cache Quantization Q8_0
I am looking for maximum useful work from the whole machine. As such:
Reasonable inference speed matters more to me, even if reducing GPU offload would have freed additional VRAM. As long as the LLM weight and loaded InvokeAI models fit comfortably enough on one GPU, and perform reasonably speedily (and they do), I'm happy with the arrangement.
I'm not obsessing over using every last gigabyte of VRAM. I observed peak VRAM usage of around 20-22 GB with both Qwen and Z-Image Turbo active. That leaves me with about 2-3 GB of usable VRAM, which is tempting. But workloads can spike or need transient allocations, and I'd rather have room to breathe with a mixed load.
Now my system RAM absorbs the expandable context cache, while the RTX 4090 handles what it is exceptionally good at: smarter models, and image generation. My tuned system delivers:
roughly 20 tok/s;
a 262K context window;
simultaneous image generation;
fast large-context prefill;
and a smoother interactive experience.
Even if a narrowly configured LLM-only benchmark could produce a higher number, I've reached an 'optimal' machine setup in practical terms. And so I'm staying with this setup for now.