v0.5.4

Your GPUs are
underperforming.

Tightwad's smiling cartoon pig mascot

Pool your mismatched CUDA + ROCm + Metal GPUs into one OpenAI-compatible endpoint. Run a model that fits on no single machine — then make it faster with speculative decoding.

Open source. Fully local.View on GitHub →
your junk drawer, unified
$ tightwad start

 Pool       4 GPUs · 52GB VRAM
 Model      Llama 3.3 70B
 Endpoint   localhost:8088

→ 2.2 → 4.1 tok/s · 1.86× faster*
pip install tightwad
70B model across 4 GPUs
1.86× measured speedup*
= same output (greedy)
$0 cloud bill · fully local

* Measured on Llama 3.1 8B → Llama 3.3 70B, 52GB pooled over WiFi, temperature=0. Output matches the target alone with greedy decoding. Results vary. Benchmark details →

Two moves. That's the whole product.

Pool your GPUs so a big model runs at all — then change one URL so it runs fast. Dead simple, both of them.

1 Pool it — so the model runs at all
WON'T FIT
🧠
Llama 3.3 70B
~40GB at Q4
💥
RTX 3060 · 12GB
CUDA out of memory
✗ Too big for any single card you own.
POOLED
🎮
4070 Ti · 16GB
NVIDIA
🎮
3060 · 12GB
NVIDIA
🎮
2070 · 8GB
NVIDIA
🍎
M2 · 16GB
Metal
Tightwad :8088
52GB pooled · one endpoint
✓ A model that fit on nothing now runs on everything.
2 Speed it up — change one URL
BEFORE
💬
Open WebUI
your chat app
🐢
Ollama :11434
Llama 3.3 70B — slow
Base URL: http://192.168.1.10:11434
⏳ Every token generated one at a time. Waiting.
AFTER
💬
Open WebUI
same app, no changes
Tightwad :8088
invisible proxy
70B across the pool
same output quality, 1.86× faster
Base URL: http://192.168.1.10:8088 ← only change
✓ Equivalent output quality. Just faster.
🔗

One URL change

Point your chat app at port 8088 instead of 11434. That's the entire setup from your app's perspective.

🫥

The small model is invisible

The draft model suggests tokens; the large model accepts or corrects them. Your chat app only sees the final output.

🔬

Output quality is preserved

With greedy decoding (temperature=0), output matches the target alone. With sampling, output is statistically equivalent. The large model validates the draft.

🧩

Nothing sits idle

Your main rig, the old GPU you almost sold, an Apple laptop, or a CPU-only machine can all contribute.

That's it. Pool your hardware. Change one URL. Run bigger models, faster.

Set It Up in 30 Minutes →

How a small model makes a big one fast

Speculative decoding is what Google and DeepMind already use to accelerate frontier models. Tightwad puts it on your pooled hardware.

🚀

Draft

A small model proposes a batch of candidate tokens on inexpensive hardware.

🔍

Verify

The large model evaluates the candidates together in a single forward pass.

Accept

Keep matching tokens. At the first disagreement, use the large model's correction.

📡

Stream

Send accepted tokens to your app, with output equivalent to the target alone.

Pick your mode. Stack them.

Six inference modes — pool, speculate, race, cluster, gate, distribute. Run one or run all six. Full details on each →

👑 THE KILLER FEATURE
01

Combined Mode

Pool your GPUs to fit a bigger model, then speculate on top. 1.86× measured on Llama 3.3 70B across four GPUs over WiFi.

  • Run models that fit nowhere else
  • 2.2 → 4.1 tok/s on the 70B pool
How pooling works →
02

Speculative Proxy

A small model drafts; a large model verifies. Accelerate local inference through an OpenAI-compatible proxy, with output equivalent to the target alone.

  • One URL change for your app
  • Live dashboard at /dashboard
Mode details →
03

Multi-Drafter Consensus approximate mode

Race cheap drafters in parallel. When they agree, skip target verification. An opt-in, approximate mode for trading exactness for speed.

  • Skip the GPU when drafters agree
  • Opt-in; consensus tokens may differ from the target
Mode details →
04

RPC Cluster

Spread model layers across CUDA, ROCm, and Metal machines with llama.cpp RPC. One endpoint for your hardware, with hot-swappable models.

  • Mix NVIDIA + AMD + Apple freely
  • 70B+ on consumer hardware
Pool your GPUs →
05

Quality Gate

Let a fleet of inexpensive machines draft full responses. One powerful GPU reviews them, approving, correcting, or rejecting each answer.

  • Put idle CPUs to work
  • tightwad gate start
Mode details →
06

Swarm Transfer

Share model files directly between workers in verified pieces. Downloads resume after interruptions, with delta updates for new versions.

  • Multi-source parallel download
  • Delta updates for new quants
Mode details →

The headline number, and how we got it

1.86× wall-clock speedup

Llama 3.1 8B → Llama 3.3 70B, across a 4-GPU RPC pool (52GB VRAM, over WiFi), greedy decoding (temperature=0). Throughput went from 2.2 → 4.1 tok/s — and the 70B fits on no single machine in the pool. Under greedy decoding the output is mathematically identical to running the target alone.

Other pairings, acceptance rates, and the cloud-API caveats live on the benchmarks page — including which numbers are being re-validated under the v0.5.1+ per-position verifier.

See full benchmarks →

Quick Start

No Docker Compose files with 300 environment variables. No Kubernetes YAML. Just Python and one config file.

1

Install

bash
$ pip install tightwad
# or from source:
$ git clone https://github.com/youngharold/tightwad.git
$ cd tightwad && pip install .
2

Configure your hardware

Connect your draft and target models. Follow the setup guide →

View example configuration
configs/cluster.yaml
proxy:
  host: 0.0.0.0
  port: 8088
  max_draft_tokens: auto          # auto-tunes based on acceptance rate
  fallback_on_draft_failure: true
  draft:
    url: http://192.168.1.50:11434  # Your cheap GPU (Ollama)
    model_name: qwen3:8b
    backend: ollama
  target:
    url: http://192.168.1.100:11434   # Your big GPU (Ollama)
    model_name: qwen3:32b
    backend: ollama
3

Start it & test

bash
$ tightwad proxy start
 Draft model healthy
 Target model healthy
 Proxy listening on http://localhost:8088

# Test it (drop-in for any OpenAI SDK call)
$ curl http://localhost:8088/v1/chat/completions \
    -H "Content-Type: application/json" \
    -d '{"messages": [{"role": "user", "content": "Hello"}], "max_tokens": 50}'

# Check live stats
$ tightwad proxy status
 Rounds: 34 | Draft tokens/round: 32 | Mode: greedy (exact)
1

Build RPC workers (CUDA — Windows/Linux)

bash (worker machine)
# Or use scripts/install-worker.sh
$ cmake -B build -DGGML_CUDA=ON -DGGML_RPC=ON
$ cmake --build build --config Release
$ build/bin/rpc-server -p 50052  # GPU 0
2

Configure cluster topology

Add your coordinator, workers, and model. See the cluster guide →

View example configuration
configs/cluster.yaml
coordinator:
  host: 0.0.0.0
  port: 8080
  backend: hip  # or cuda
  gpus:
    - name: "7900 XTX #0"
      vram_gb: 24

workers:
  - host: 192.168.1.100  # NVIDIA box
    gpus:
      - name: "RTX 4070 Ti Super"
        vram_gb: 16
    rpc_port: 50052

models:
  llama-3.3-70b:
    path: /models/Llama-3.3-70B-Q4_K_M.gguf
    ctx_size: 8192
    flash_attn: true
    default: true
3

Start the cluster

bash
$ tightwad start
 Coordinator started
 Worker @ 192.168.1.100:50052 online
 Model llama-3.3-70b loaded across 52 GB VRAM

# Hot-swap to a different model anytime
$ tightwad swap deepseek-r1-70b

# Run the benchmark
$ tightwad benchmark

Want the full walkthrough on real mismatched hardware?

Homelab cluster in 30 minutes →

Why not vLLM, Ollama, or plain llama.cpp?

Each is great at something. Tightwad's lane is the awkward middle: mismatched, network-separated, consumer hardware.

vLLM / TGI

Built for homogeneous datacenter GPUs and raw throughput. They won't pool a 3060 + an AMD card + a laptop over WiFi. Use them when you have matching cards in one box.

Ollama

Great single-machine runner. But it doesn't pool GPUs across machines or speculate across a network. Tightwad sits in front of Ollama and uses it as a backend.

llama.cpp RPC

The pooling primitive Tightwad builds on. Tightwad adds auto-discovery, config, speculative decoding on top, MoE placement, and a single OpenAI-compatible endpoint.

Honest, side-by-side — including when not to use Tightwad.

Full comparison →