5.8 KiB
Coverage-first shard assignment and tracker-routed inference
The tracker assigns shard ranges to worker nodes using a coverage-first, speed-weighted bin-packing algorithm. The tracker is a control-plane service and public inference API endpoint: it stores registry state, selects routes, enforces billing, and proxies OpenAI-compatible requests to the selected head worker. It does not download or load model weights.
Problem
A 700B model sharded across volunteer nodes of wildly different VRAM (8GB to 128GB+) and different quantization levels (NF4 / INT8 / bfloat16) must be fully covered at all times for inference to work at all. 199 copies of 99% of a model are worthless if the last 1% of layers has zero coverage. Replication only matters after full coverage is achieved.
Decision
Coverage-first bin-packing
The tracker maintains a coverage map: a sorted list of (start_layer, end_layer, node_count) for each model. A layer range with node_count=0 is a coverage gap — the model is unservable until the gap is filled. The tracker's shard assignment algorithm:
- Identify uncovered layer ranges (gaps) first
- Assign new or idle nodes to fill gaps, largest VRAM-fit first
- Once fully covered, assign additional nodes to the most-replicated-needed ranges (latency hotspots) before adding redundancy elsewhere
- Speed-weight: give faster nodes wider shard ranges — fill their VRAM completely, then assign the remainder to the next-fastest available node
Example: 700B NF4 model (~350GB weights). Node A has 128GB, Node B and C each have 80GB and are idle.
- Node A gets layers[0..k_a] filling ~120GB (reserve 8GB for KV cache)
- Node B gets layers[k_a..k_b] filling ~72GB
- Node C gets layers[k_b..N] (the remainder)
- If Node B benchmarks 2× faster than Node C, the tracker shifts the B/C boundary so B carries more layers
Tracker-routed head worker
A worker that serves layers[0..k] is the head worker for that model. The tracker forwards /v1/chat/completions to a live head worker and injects the remaining downstream route. The worker, not the tracker process:
When a client request arrives, the tracker:
- Authenticates/bills the request
- Selects a live head worker and full downstream route from the coverage map
- Proxies the request to that head worker
- Records usage and credits node shares after completion
The head worker:
- Tokenizes the input (owns the tokenizer)
- Runs
model.embed_tokens+model.layers[0..k] - Forwards activations to the next node in the route
- Receives the final hidden state back and streams tokens to the client
This keeps the public tracker lightweight: a standalone HTTP proxy/load-balancer may sit in front to pick which tracker handles the request, but neither proxy nor tracker carries model weights.
Multiple head workers for the same model = multiple inference entry points = horizontal scale for first-layer compute. Multiple trackers scale routing and billing, not model execution.
Last-layer node (tail)
The node assigned layers[N-k..N] also runs model.norm and model.lm_head. It returns decoded token IDs (not hidden states) to the head worker, which assembles the response. The tail shard assignment is marked is_tail: true in the shard registry.
Adaptive quantization
Nodes declare their capabilities at registration:
{
"vram_bytes": 25769803776,
"quantizations": ["nf4", "int8", "bfloat16"],
"benchmark_tokens_per_sec": 12.4,
"benchmark_model": "meta-llama/Llama-3-8B"
}
The tracker uses declared VRAM + quantization to compute max assignable layers:
max_layers = floor(available_vram / bytes_per_layer_at_declared_quant)
where bytes_per_layer_at_declared_quant is a per-model constant stored in the model preset metadata. KV cache headroom (configurable, default 20% of VRAM) is subtracted before the calculation.
A node may serve different models at different quantizations. The tracker tracks (model, quantization, shard_range) triples per node.
Continuous rebalancing
The tracker monitors coverage every 30 seconds and on every node join/leave event. When a coverage gap appears (node drops offline), the tracker issues rebalance directives to idle nodes or nodes with redundant coverage:
LOAD_SHARD(model, start_layer, end_layer, quantization)— download and begin servingDROP_SHARD(model, start_layer, end_layer)— stop serving (safe only when coverage > 1 for that range)
Nodes obey directives asynchronously; the tracker waits up to a configurable timeout before marking the gap critical.
Considered Options
- Static shard assignment (assign once at registration): simple, breaks when nodes leave — rejected
- Replication-first (maximize redundancy before optimizing speed): wastes resources on popular shards, leaves rare shards uncovered — rejected (user: "we have no use of 199 copies of 99% of the model")
- Coverage-first, speed-weighted bin-packing with continuous rebalancing: chosen
Consequences
- The standalone
meshnet-gatewayservice from US-005 becomes a thin compatibility proxy/load-balancer; the public tracker can also serve the OpenAI-compatible endpoint directly - Tracker processes do not download or load model data. Only worker nodes load model shards.
- Benchmark data is self-reported by nodes at registration; the validator can detect fraudulent benchmarks (a node claiming 100 tokens/sec but delivering 2 gets slashed for under-performance)
- VRAM reservation for KV cache means nodes can host fewer layers than their raw VRAM suggests — this is intentional; running out of KV cache during inference causes OOM crashes
- New CONTEXT.md terms: Head Worker (worker node serving first-layer shard for a model), Coverage Map (tracker's per-model layer-range → node-count mapping), Rebalance Directive (tracker instruction to a node to load or drop a shard)