NVIDIA Sold Me Half of My Tensor Cores

Links
- gpu-unlock on GitHub
- NVIDIA's Ampere GA102 whitepaper
- Julien Simon's half rate writeup
- The original rig writeup
- The Blackwell bake-off
- Every result from this run (CSV)
I Paid for the Whole Card
I own four RTX 3090s. They render my images, embed my documents, run my models, and chew through video, and when I ask for something, I want it now.
So when a kernel module called gpu-unlock showed up claiming those cards run AI math at half speed because NVIDIA set them that way, I had one question: how much of the card I paid for have I actually been using?
The repo already has plenty of matrix math benchmarks and a growing pile of news articles repeating them. What I wanted was everything I actually run, before and after, on one rig: image models, video models, LLMs on two engines, embeddings, rerankers, speech, vision, and decision models. More than 30 model and format setups, with controls good enough that I'd believe a bad result.
I expected to write "images got faster, LLMs didn't." The data had other plans.
The Receipt Was in NVIDIA's Own Whitepaper
I went looking for proof this was a conspiracy and found a spec table instead.
NVIDIA's Ampere whitepaper rates the RTX 3090 at 142 TFLOPS for FP16 math with FP16 accumulation. Lovely. Then the next rows drop it to 71 TFLOPS for FP16 or BF16 with FP32 accumulation, which, according to the gpu-unlock README, is the flavor nearly all unquantized AI work uses.
Same whitepaper, Table 3, the RTX A6000 on the same GA102 chip: 154.8 TFLOPS in both modes. No asterisk. (The table with the 3090 also lists a Titan RTX from the previous generation, at 130.5 in both modes, just to twist the knife.)
So my stock card should do about 71. I measured it.
72.0. NVIDIA's spec sheet is extremely honest, in the way a gym contract is honest. It's all in there, you just have to read the appendix.
I can't tell you why NVIDIA did it, because I couldn't find an NVIDIA statement on it. The gpu-unlock FAQ calls it market segmentation, a way to get businesses to pay for the professional cards. That's the author's read, and I happen to share it. Julien Simon's price tracking puts a new RTX A6000 around $5,990 and a used 3090 at $1,100 to $1,400, which doesn't exactly argue with him.
What I can tell you is what I measured: a boot-time kernel module, no hardware change, no driver patch, and the same card did 62.6% more BF16 math. Across the three cards I benchmarked individually, that's 130 extra TFLOPS, or about 1.8 stock 3090s' worth of BF16 math that was already sitting in my rack.
How gpu-unlock Works on an RTX 3090
The module loads before the NVIDIA driver, rewrites the speed selectors on the card, resets it, and then the unmodified driver comes up none the wiser. It's opt-in through a kernel parameter, so I targeted my four 3090s by PCI address and left the RTX PRO 6000 alone.
- Rig: EPYC 7532, 128 GB of RAM, Ubuntu 24.04, driver 580.173.02
- Cards: ASUS Strix (I call the one I tested Strix-B), Zotac, and PNY 3090s, with the PRO 6000 as a control
- Software: ComfyUI, vLLM, llama.cpp, transformers, sentence-transformers
- gpu-unlock: v2.0.0 at commit
7eb51bc
Trying to Prove Myself Wrong
A 60% number deserves suspicion, so I built the run to catch me.
- Same everything: same seeds, same prompts, same 350 W limit on the 3090s, all AI services stopped for both phases
- FP32 control: FP32 math doesn't use the capped path, so it shouldn't move. It went from 24.85 to 24.84 TFLOPS.
- PRO 6000 control: never unlocked, so any change there is drift. Every metric stayed within 2%.
- Solo reruns: the cards run tests side by side, so I repeated a batch with Strix-B alone. Same numbers.
One note on this bench.. my 4-card Z-Image throughput test had a metric bug on my end (the slowest card set the score), and I overwrote the stock logs before I caught it. It's out of the results.
It Was Never Images vs LLMs
Here's the whole post in one picture. Pick any job on the left, follow it through how it does its math, and see what it got.
View the numbers CSVJSON
| Measurements | |
|---|---|
| Decision via Q4 or Q8 GGUF | 1 |
| Embeddings via 16-bit float (BF16, FP16) | 4 |
| Image via 16-bit float (BF16, FP16) | 13 |
| Image via FP8 weights in ComfyUI | 1 |
| Image via INT8 in ComfyUI | 2 |
| LLM decode via 16-bit float (BF16, FP16) | 18 |
| LLM decode via BF16 GGUF on llama.cpp | 3 |
| LLM decode via INT4 on vLLM | 3 |
| LLM decode via Q4 or Q8 GGUF | 18 |
| LLM prefill via 16-bit float (BF16, FP16) | 18 |
| LLM prefill via BF16 GGUF on llama.cpp | 3 |
| LLM prefill via INT4 on vLLM | 3 |
| LLM prefill via Q4 or Q8 GGUF | 18 |
| Reranking via 16-bit float (BF16, FP16) | 2 |
| Speech via 16-bit float (BF16, FP16) | 4 |
| Speech via Q4 or Q8 GGUF | 2 |
| Video via 16-bit float (BF16, FP16) | 1 |
| Video via INT8 in ComfyUI | 2 |
| Vision via Q4 or Q8 GGUF | 1 |
| 16-bit float (BF16, FP16) to +30% or more | 30 |
| 16-bit float (BF16, FP16) to +5 to 30% | 13 |
| 16-bit float (BF16, FP16) to Under 5% | 17 |
| BF16 GGUF on llama.cpp to +30% or more | 2 |
| BF16 GGUF on llama.cpp to +5 to 30% | 1 |
| BF16 GGUF on llama.cpp to Under 5% | 3 |
| FP8 weights in ComfyUI to +30% or more | 1 |
| INT4 on vLLM to +30% or more | 3 |
| INT4 on vLLM to +5 to 30% | 2 |
| INT4 on vLLM to Under 5% | 1 |
| INT8 in ComfyUI to +5 to 30% | 3 |
| INT8 in ComfyUI to Under 5% | 1 |
| Q4 or Q8 GGUF to Under 5% | 40 |
The category barely predicts anything. The math path predicts almost everything. All 40 of my Q4 and Q8 GGUF measurements gained under 5%, and that includes LLMs, speech, vision, and a decision model. Meanwhile a heavily quantized INT4 model on vLLM picked up as much as 52% on prefill, because a low-bit label on the weights doesn't tell you what the rest of the pipeline is doing.
The cleanest proof I have is running the same model twice.
Same weights family, same card, same engine. FLUX.3 Klein gains 54% as BF16 and nothing as INT8. That INT8 result also means the fastest way to dodge NVIDIA's cap is to not use the capped math in the first place, which is a pretty funny thing to learn about a card you bought for AI.
Does gpu-unlock Speed Up Stable Diffusion, FLUX, and Wan?
Yes. Holy shit, yes. Go ahead and play with this one, because the numbers are a lot more fun when you have to sit through them.

Every 16-bit image model landed between 32 and 58%. Qwen-Image went from 26.15 seconds an image to 16.60. Wan 2.2 went from 107 seconds a video to 73, which is the kind of number that changes what you bother trying. Then there are the INT8 video models: LTX 2.5 got 11% and MiniMax H3 got 8%.
And the output? Same seed, same pixels.
That held for 75 of the 81 test groups I could compare across phases. Z-Image on Strix-B wouldn't even reproduce against itself within a single phase, and a few vLLM and SDXL runs only partly matched. The other cards matched exactly on Z-Image, so that looks like a Strix-B quirk. I had enough data and didn't chase it.
Does gpu-unlock Help LLMs and llama.cpp?
This is where I nearly wrote the wrong post. If you only look at decode, the answer is no. Look at the whole request and LLMs split into two completely different stories.
- Prefill on vLLM: Qwen3.5-9B gained 48 to 60% depending on the card. Gemma 4 E4B gained 38%. Qwen3-VL-8B at INT4 gained 52%.
- Prefill on llama.cpp: Ornith-1.5-9B as BF16 GGUF gained 35%, so llama.cpp isn't immune. As Q4 GGUF, the same model gained 2%.
- Decode everywhere: about 4 to 5% on vLLM at 8K, and flat on llama.cpp.
- Splitting across cards: 2-card prefill gained 17% and 4-card gained 11%, a lot less than one card alone (more on that below).
Prefill is the wait before the model starts talking, and it scales with how much you send it. I run coding agents, and they send a lot.
Three seconds off a long prompt adds up fast when an agent makes dozens of turns in a session. (Prompt caching will claw some of that back on a real agent loop, since my test prompts were deliberately uncached.) The decode number looks boring in a benchmark table, but this is the part you feel. Long contexts even pull decode up a little: Qwen3-VL-8B hit +7.9% at 32K.
Decode itself is memory bound and this unlock doesn't touch memory. I sanity checked that on the PRO 6000: Qwen3.8-27B decodes at 28 tok/s with 55.6 GB of weights, which works out to about 1.56 TB/s against a measured 1.64 TB/s of read bandwidth. It's an estimate, but it's hard to argue with.
So yes, if your whole world is chatting with a Q4 GGUF in Ollama, you get nothing here. A lot of hobbyists run exactly that, so plenty of people are going to try this, see no change, and call it fake. It isn't fake. They're just standing in the one spot it doesn't reach.
Embeddings, Reranking, Speech, Vision, and Everything Else
Here's every model I ran. Filter it to whatever you care about.
View the numbers CSVJSON
| Model | Strix-B | Zotac | PNY | Multi-card |
|---|---|---|---|---|
| BF16 GEMM | 62.6% | 62.1% | 58.6% | |
| FP16 GEMM | 58.3% | 60.0% | 57.6% | |
| TF32 GEMM | 64.8% | 77.2% | 64.0% | |
| BF16 attention (SDPA) | 56.5% | 54.8% | 55.7% | |
| FP32 GEMM (control) | 0.0% | 6.1% | -0.1% | |
| Qwen-Image 2.1 | 57.5% | 54.0% | ||
| FLUX.3 Klein | 56.5% | 46.5% | 53.6% | |
| Z-Image Turbo | 52.0% | 40.0% | 48.1% | |
| Krea-2 Turbo | 50.1% | |||
| WAI-Illustrious | 40.8% | |||
| SDXL base | 35.4% | 31.8% | 31.9% | |
| Qwen-Image 2.1 | 8.6% | |||
| FLUX.3 Klein | -3.9% | |||
| Wan 2.2 5B | 45.9% | |||
| LTX 2.5 | 11.3% | |||
| MiniMax H3 | 7.8% | |||
| Qwen3.5-9B | 54.0% | 47.5% | 60.4% | |
| Gemma 4 E4B | 38.1% | |||
| Qwen3-VL-8B | 52.3% | |||
| Ornith-1.5-9B | 34.8% | |||
| Ornith-1.5-9B | 1.8% | |||
| Ornith-1.5-35B | 0.7% | |||
| Qwen3.8-27B | 0.3% | -1.0% | 0.5% | |
| Gemma 4 12B QAT | 1.3% | |||
| Gemma 4 12B | 17.3% | |||
| Qwen3.8-27B | 10.8% | |||
| Qwen3.5-9B | 3.9% | 4.6% | 5.1% | |
| Gemma 4 E4B | 4.5% | |||
| Qwen3-VL-8B | 5.4% | |||
| Ornith-1.5-9B | 0.0% | |||
| Ornith-1.5-9B | 0.6% | |||
| Ornith-1.5-35B | -0.4% | |||
| Qwen3.8-27B | -0.3% | -0.7% | -0.3% | |
| Gemma 4 12B QAT | 0.3% | |||
| Gemma 4 12B | 3.7% | |||
| Qwen3.8-27B | 1.1% | |||
| bge-m3 | 40.0% | 40.7% | 39.9% | |
| Qwen3-Embedding-4B | 41.2% | |||
| mxbai-rerank-large-v2 | 43.0% | |||
| Qwen3-Reranker-4B | 40.7% | |||
| Whisper large-v3-turbo | 12.0% | |||
| Qwen3-ASR 1.7B | 2.4% | 3.9% | 2.2% | |
| Breeze TTS 2 | 1.1% | |||
| Parakeet TDT 0.6B | 0.0% | |||
| Qwen3-VL-8B vision | 0.3% | |||
| Clef-Flash 9B decisions | 0.3% |
- Embeddings: bge-m3 and Qwen3-Embedding-4B both gained about 40%, on every card I ran them on.
- Reranking: mxbai-rerank-large-v2 gained 43% and Qwen3-Reranker-4B gained 41%. Stack those on the embeddings and my whole search pipeline gets faster at both ends, which matters because MyMind leans on it all day.
- Transcription: Whisper large-v3-turbo went from 83x to 93x realtime, or +12%. Qwen3-ASR gained 2 to 4% even though it's BF16, and I can't tell you why.
- Q8 and Q4 GGUF voice, vision, and decisions: Breeze TTS +1%, Parakeet +0%, Qwen3-VL vision +0.3%, and Clef-Flash decisions +0.3%. The cap never touched them.
Does gpu-unlock Use More Power?
This one surprised me. The cards pull about the same watts and finish sooner, so each job costs less.
A third less energy per image, for free, from a kernel parameter. Whisper is the exception, and I'd love for someone to tell me why.
The catch shows up when you lower the power cap. The unlock needs headroom to spend, so at 200 W the gain falls to about 21 to 27%. If you've capped your cards hard to keep the breaker happy, you get a much smaller prize than the headline number.
That's also my best read on why it isn't double, even though the rating doubles. At 350 W the card hits the same power wall and spends the budget at lower clocks: Strix-B sustained around 1,644 MHz stock and 1,347 MHz unlocked at the same 347 W.
Is gpu-unlock Safe?
Short version: it ran clean for me, and it still pokes hardware in ways you should understand first.
- Stability: 0 Xid errors across the entire run, stock and unlocked.
- Kernel: the module is unsigned and taints the kernel. Your logs will say so.
- Privilege masks: my boot log shows it rewriting the FEAT and WPR_CFG privilege masks from
0x4cb8fto wide open values. I'd think twice about that on a shared machine. - Getting back: drop the kernel parameter, then do a real power off. A kernel or driver change means DKMS has to rebuild the module.
- Warranty: the README doesn't address it. I'd assume you're on your own.
- Windows: the author doesn't maintain a port and warns about sketchy installers. Believe him.
- RTX 40 series: listed as experimental, and I didn't test it.
- RTX 50 series: not supported, and the FAQ says it's unlikely to happen. According to Julien Simon's writeup, NVIDIA rates the 5090 at half too, so the newest cards get the cap with no way out.
I've left it on. All four cards have been unlocked since the benchmark finished.
The Part I Can't Explain
Four 3090s running Qwen3.8-27B BF16 prefill only gained about 11%, going from 1,046 to 1,159 tok/s. A single PRO 6000 does around 6,200 on the same model. Each card on its own gets a huge lift, so something in the 4-card setup is eating it, and I haven't isolated what.
I'm also still chewing on Krea-2. It ships as FP8 weights and gained 50%, while upstream lists FP8 as no change. The ComfyUI logs on my rig only show BF16 and FP16 compute, which would explain it, but I never tied that to the Krea run itself.
Every number here is in the summary CSV, and the raw results and 390 W runs are up too. Each chart has its own download as well. If your card disagrees with me, I want to hear about it.
So Did NVIDIA Sell Me Half?
Technically they sold me all of it and rated half of it, right there in the whitepaper. Six years after the 3090 launched, the fix was one kernel module and one line on a command line.
It's a stranger cap than the headlines make it sound. It doesn't care whether you're making images, searching notes, or talking to an LLM. It cares what math you're doing when you do it, and it's been charging a toll on 16-bit math this whole time.
I'd feel worse about it if I weren't currently rendering images 57% faster out of spite.