Inside Zagitta/gpu-unlock: How a Linux Kernel Module Unlocks Full-Rate FP16 & BF16 Tensor Core Math on NVIDIA RTX 30-Series GPUs
For home AI builders and ML researchers, the NVIDIA GeForce RTX 3090 and RTX 3090 Ti remain legendary price-to-performance workhorses thanks to their 24 GB of GDDR6X VRAM. However, anyone who has benchmarked dense FP16 or BF16 matrix multiplication (GEMM) on consumer Ampere silicon knows about a frustrating artificial ceiling: NVIDIA throttles FP32-accumulated Tensor Core throughput on GeForce cards to half the rate of professional Ampere workstation and datacenter GPUs.
The physical Tensor Cores inside the GA102 die aren't missing the transistors—the instruction issue rate is capped by firmware via internal hardware speed selector registers.
Enter Zagitta/gpu-unlock, a rapidly trending open-source Linux kernel module (kmod) that removes NVIDIA's FP16/BF16 Tensor Core rate limit on RTX 30-series GPUs during early boot—without flashing a custom VBIOS or modifying the proprietary NVIDIA driver.
Let's break down how NVIDIA's Ampere instruction cap works, how gpu-unlock bypasses it in initramfs, and what real-world TFLOPS gains look like across dense GEMM and local LLM workloads.
The Hardware Bottleneck: Why Consumer Ampere Tensor Cores Run at Half Speed
On NVIDIA's Ampere architecture (GA102, GA103, GA104, GA106), Tensor Cores support mixed-precision matrix multiply-accumulate (MMA) operations where inputs are FP16 or BF16 and the accumulator is either FP16 or FP32.
While FP16 accumulation runs at full speed on GeForce cards, modern deep learning training, LoRA fine-tuning, and many inference kernels rely on FP32 accumulation (FP16 -> FP32 and BF16 -> FP32) and TF32 to maintain numerical stability. On consumer RTX 30-series cards, firmware locks the hardware speed selectors to half rate for these instructions:
| Precision Mode (Dense GEMM) | Professional Ampere (Full Rate) | Consumer GeForce RTX 30-Series (Stock) |
| FP16 (FP16 Accumulate) | Full Issue Rate | Full Issue Rate |
| FP16 (FP32 Accumulate) | Full Issue Rate | Half Rate (Throttled) |
| BF16 (FP32 Accumulate) | Full Issue Rate | Half Rate (Throttled) |
| TF32 (TensorFloat-32) | Full Issue Rate | Half Rate (Throttled) |
How Zagitta/gpu-unlock Lifts the Cap Without Patching the NVIDIA Driver
Previous attempts to unlock consumer NVIDIA features either required risky hardware VBIOS modifications or patching binary blobs inside nvidia.ko—an approach that breaks every time your Linux distribution updates the kernel or NVIDIA driver.
Zagitta/gpu-unlock takes a much cleaner pre-driver timing approach via an initramfs kernel module:
Linux Early Boot (initramfs)
│
▼
1. gpu_unlock.ko binds to target Ampere PCIe device(s)
│
▼
2. Executes V67 / PLM coprocessor privilege sequence
│
▼
3. Writes internal Speed Selector registers:
• SS0 = 0x88888888 (Full BF16 instruction issue rate)
• SS1 = 0x8 (4-bit IMLA4 configuration)
│
▼
4. Triggers PCIe Function Level Reset (FLR) & unbinds
│
▼
5. Unmodified proprietary nvidia.ko driver loads normally
with full-rate Tensor Core throughput preserved!
1. The V67 / PLM Unlock Sequence
Derived from prior research into NVIDIA CMP (Cryptomining Processor) hardware unlockers, the module uses the V67 / PLM (Privilege Level Mask) sequence on the GPU's embedded microcontroller to temporarily gain write access to protected hardware configuration registers.
2. Reprogramming SS0 and SS1 Speed Selectors
Once privilege masks are lowered, gpu_unlock writes directly to the hardware Speed Selector registers:
SS0 (0x88888888): Switches BF16 / FP16-with-FP32-accumulate Tensor Core pipelines from half-rate to full instruction issue rate.
SS1 (0x8): Configures the 4-bit IMLA4 selector value.
3. Function Level Reset (FLR) and Clean Handoff
After writing the registers, the module issues a PCIe Function Level Reset (FLR) so the new speed selector latches take effect cleanly, then unbinds from the GPU. Moments later in the boot sequence, the stock, unmodified NVIDIA driver (nvidia.ko) binds to the card and inherits the unlocked Tensor Core issue rates.
Benchmark Results: Stock vs. Unlocked (RTX 3090 Ti / RTX 3090)
In dense matrix multiplication (GEMM) benchmarks, unlocking the speed selectors produces dramatic throughput increases on GA102 hardware:
| Workload / Precision | Stock RTX 3090 Ti | Unlocked (gpu-unlock) | Throughput Gain |
| BF16 GEMM (FP32 Accum) | ~87.50 TFLOPS | ~157.41 TFLOPS | +79.9% |
| TF32 GEMM | ~42.58 TFLOPS | ~82.61 TFLOPS | +94.0% |
| FP16 GEMM (FP32 Accum) | ~87.46 TFLOPS | ~118.39 TFLOPS | +35.4% |
(On standard RTX 3090 cards, community benchmarks similarly report dense BF16 GEMM climbing from ~77.5 TFLOPS to ~129.6 TFLOPS, depending on board power limits and clock speeds.)
What Does This Mean for Real-World AI Workloads?
It is important to separate compute-bound workloads from memory-bandwidth-bound workloads:
- Prompt Processing (Prefill) & Fine-Tuning: Compute-bound operations—such as processing long context prompts in
llama.cpp or vLLM, running vision encoders/diffusion models in BF16, or training/LoRA fine-tuning—benefit directly from the unlocked BF16, FP16, and TF32 matrix math throughput.
- Single-Batch Token Generation (Decode): Autoregressive token generation at batch size 1 is bottlenecked by GDDR6X memory bandwidth (936 GB/s on an RTX 3090), so decode tokens/sec see only minor changes unless you are running larger batch sizes.
Supported GPUs
Zagitta/gpu-unlock targets NVIDIA Ampere consumer silicon across four die families:
- GA102: RTX 3090 Ti, RTX 3090, RTX 3080 Ti, RTX 3080 (10GB / 12GB)
- GA103: RTX 3080 Ti Laptop / GA103 desktop variants
- GA104: RTX 3070 Ti, RTX 3070, RTX 3060 Ti
- GA106: RTX 3060 (12GB)
Installation & Kernel Parameter Configuration
Because gpu-unlock integrates with DKMS and your system's initramfs (initramfs-tools or dracut), installation is straightforward on modern Linux distributions:
# 1. Clone the repository
git clone https://github.com/Zagitta/gpu-unlock.git
cd gpu-unlock
# 2. Build and install via DKMS + update initramfs
sudo make install
Next, enable the unlock on boot by adding the kernel command-line parameter (for example, in /etc/default/grub under GRUB_CMDLINE_LINUX_DEFAULT):
gpu_unlock.targets=all
(You can also target specific PCIe bus IDs instead of all in multi-GPU rigs.)
To revert your GPU back to factory stock behavior at any time, simply remove gpu_unlock.targets=all from your kernel parameters or uninstall the DKMS module and reboot—since nothing is flashed to the VBIOS EEPROM, a cold reboot always restores factory defaults.
Key Takeaways
Zagitta/gpu-unlock is a masterclass in low-level Linux kernel and PCIe hardware engineering. By combining pre-driver initramfs timing with register-level speed selector configuration and Function Level Reset (FLR), it breathes huge new compute life into existing RTX 30-series GPUs without touching VBIOS flash chips or proprietary driver binaries.
Explore the source code, register documentation, and benchmark scripts on GitHub: https://github.com/Zagitta/gpu-unlock