Home · ASPLOS 2024 · Machine Learning Systems

SpotServe: Serving Generative Large Language Models on Preemptible Instances

Xupeng Miao, Chunan Shi, Jiangfei Duan, Xiaoli Xi, Dahua Lin, Bin Cui and 1 other

Conference
ASPLOS 2024
Published
2024
Pages
1112-1127
Citations
65

Spot GPU instances cost a fraction of on-demand ones but can vanish on 30 seconds' notice — SpotServe serves large language models across them anyway, reshaping the parallel layout on the fly, migrating weights and attention state instead of reloading them, and committing generation progress token by token so no work is ever redone.

The argument in one glance

  1. Problem

    LLM serving is priced like a luxury; spot instances are the discount rack

    A single GPT-3-scale inference pipeline needs more than 16 NVIDIA A100 GPUs just to hold the weights — over $66 per hour on AWS. Clouds sell spare capacity as "spot" (preemptible) instances at up to 90% off, with one catch: the cloud can take them back at any moment, giving roughly 30 seconds of warning (the grace period).

  2. What people did

    Spot serving exists — for models that fit on one machine

    Systems like MArk and Cocktail serve small models on spot instances by reroute-and-retry (send interrupted requests to another replica) or by redundant computation (run every request twice). Each replica is independent, so losing one instance costs exactly one instance.

  3. Why it fell short

    Model parallelism makes preemptions contagious

    An LLM is served by a pipeline of instances bound together by tensor and pipeline parallelism. One preemption halts every GPU in that pipeline — and can break several pipelines at once if they share the machine. Restart is brutal: loading a 120-billion-parameter model from storage takes over 2 minutes, and every in-flight generation is recomputed from scratch, while new requests stack up.

  4. This paper's idea

    Adapt the layout, migrate the state, commit every token

    SpotServe treats the parallel configuration as a live variable, re-optimizing it whenever instances come or go. It maps surviving GPUs to positions in the new layout with a matching algorithm that maximizes reusable bytes, migrates weights and attention caches instead of reloading, and — exploiting the token-by-token nature of LLM decoding — resumes each generation exactly where it stopped. Result: 2.4–9.1× lower tail latency than prior approaches and 54% lower cost than on-demand serving.

Why this problem is worth solving

Generative large language models (LLMs) produce text one token at a time, and each token touches every parameter of the model. The parameters alone outgrow single machines: the paper’s smallest test model (OPT-6.7B) needs 25 GB, the largest (LLaMA-30B) 111.8 GB — a minimum of 4 and 16 GPUs respectively on the NVIDIA T4 hardware used in the evaluation. GPT-3 class models need more than 16 A100 GPUs, above $66 per hour for a single inference pipeline. For most organizations this makes LLM serving on regular cloud instances prohibitively expensive.

Clouds already sell the solution — with a trap inside. Spot instances (AWS spot, Azure spot VMs) rent the cloud’s spare capacity at up to 90% below on-demand prices; on the paper’s test hardware the gap is 1.9 versus 3.9 dollars per hour. The trap: the cloud may preempt the instance whenever a paying customer needs the capacity, giving only a grace period — about 30 seconds — to wrap up. Spot instances built a whole ecosystem of cheap serving for small models. Nobody had made them work for models that must be spread across many machines, which is exactly where the cost pressure is worst.

What people did before, and where it broke

How distributed LLM inference works. A served LLM combines three kinds of parallelism, written in this paper as a configuration (D, P, M): D data-parallel pipelines each independently serving requests; each pipeline split into P pipeline stages (consecutive layers on different instances, passing activations stage to stage); each stage sharded across M GPUs by tensor parallelism (every GPU holds a slice of each weight matrix, synchronized by collective communication). During generation, each request also accumulates a

key/value cache — the stored attention state of all tokens produced so far, which lets each new token avoid recomputing the whole prefix; about 1.7 GB per sequence for LLaMA-13B
.

Spot serving for small models. MArk reroutes requests around preempted replicas; Cocktail absorbs preemptions inside a model ensemble; other systems duplicate computation so a lost instance never loses work. All assume the unit of failure equals the unit of serving — one independent replica per instance.

Why that assumption dies with LLMs. Pipeline dependencies and tensor collectives have no fault tolerance: preempt one instance and every other instance in its pipeline hangs idle. A multi-GPU machine can host slices of several pipelines, so one preemption can break many at once — the paper calls this chain crashing. Rerouting now drops an entire pipeline’s worth of capacity, and redundancy would mean duplicating a 16-GPU deployment. Training-side systems (Varuna, Bamboo) do adapt parallelism to preemptions, but training tolerates lost iterations; serving has live requests with latency targets and per-request state. Existing LLM serving engines (FasterTransformer, Orca, DeepSpeed) simply assume dedicated instances.

SpotServe's architecture

  1. Inference server (on-demand CPU box) new

    A cheap, never-preempted coordinator hosting the request manager (batches and dispatches requests), the instance manager (receives preemption/acquisition notices from the cloud), and the meta-context manager (orchestrates migrations).

  2. Parallelization controller new

    On every availability or workload change, picks the best (D, P, M) configuration — enough throughput for the current arrival rate, then lowest latency, then lowest cost — in under a second, using latency estimates profiled offline.

  3. Device mapper new

    Maps surviving GPUs to positions in the new configuration by maximum-weight bipartite matching (Kuhn-Munkres algorithm), where each edge weighs the bytes of weights and KV cache a GPU could reuse at that position.

  4. Migration planner new

    Orders the moves: cache context first, then weights layer by layer in pipeline-stage order, so early stages finish migrating and resume serving while later stages are still transferring.

  5. Inference engine + context daemon (each GPU instance) new

    A FasterTransformer-based engine, plus a separate daemon process that owns the model weights and KV cache in GPU memory — engines can restart without reloading anything. An interruption arranger decides, when a grace period starts, exactly how many more tokens to decode before migrating.

Implemented in 5.6K lines of C++ and 2.2K of Python on top of FasterTransformer; migrations use batched asynchronous NCCL transfers, with CUDA inter-process communication sharing GPU tensors between the daemon and the engine.

The idea

SpotServe’s answer to preemption has three layers, one per challenge.

Treat the parallel configuration as a live variable. With spot instances, the number of available machines N changes constantly — and the request arrival rate changes too. A configuration that is optimal at twelve instances may be infeasible at nine and wasteful at fifteen. The parallelization controller re-solves the choice on every change: among configurations whose throughput covers the observed arrival rate, pick the one with the lowest inference latency, preferring fewer instances at a tie (money). If no configuration can cover the arrival rate, maximize throughput instead — controlled degradation rather than an unbounded queue. The search runs online in under a second because every configuration’s latency was profiled offline. SpotServe also keeps a couple of spare instances as a buffer and can mix in on-demand instances when spot capacity dries up.

Migrate state; never restart. Changing configuration used to mean restarting every engine and reloading weights from storage — minutes of downtime. SpotServe observes that most of the bytes the new configuration needs are already sitting in GPU memory, just possibly on the wrong machine. The context daemon keeps weights and KV caches alive across engine restarts. The device mapper then decides which physical GPU takes which logical position (d, p, m) in the new layout — formalized as bipartite matching where an edge’s weight is the size of the overlap between what the GPU holds and what the position needs, and solved optimally by the Kuhn-Munkres algorithm. What cannot be reused is transferred GPU-to-GPU, in pipeline-stage order, so migration overlaps with inference: stage 0 can serve while stage 2 is still receiving weights.

Commit progress at the token, not the request. Here the paper exploits what LLMs are. Autoregressive decoding produces one token per iteration, and the KV cache is a complete checkpoint of progress so far — no snapshot format needed. So an interrupted request need not restart: migrate its KV cache and continue from the next token. The interruption arranger runs this as a

a per-instance decision, made when a grace-period notification arrives, of exactly how many more decoding iterations to run before stopping to migrate
: before a preemption, decode as many tokens as fit in the remaining grace period minus the migration time (use the doomed instance to the last second); before an acquisition finishes initializing, decode as few as possible (the migration can only start after the new instance is ready). Both cases are guarded by a sanity rule — if migration would cost more than the work it saves, just reroute the request the old-fashioned way.

Thirty seconds: a preemption arrives mid-generation

(D, P, M) = data-parallel pipelines × pipeline stages × tensor shards per stage. KV cache = per-request attention state (the generation progress). Grace period = ~30 s warning before the cloud takes a spot instance. Numbers follow the paper's GPT-20B example on 4-GPU instances; the request-level details are illustrative.

Step 1 of 6

Steady state — then the notice

GPT-20B serves as (D=2, P=2, M=8): two pipelines, each two stages of eight tensor shards. Requests are decoding, token by token. The cloud notifies: one instance will be preempted in 30 seconds. Under prior systems this kills a whole pipeline — half the serving capacity — the moment it fires.

config: (2, 2, 8)
grace period: 30 s countdown starts

Why it works

  • Model parallelism couples instances → one preemption stalls whole pipelines → the only fix that preserves capacity is changing the parallel shape itself → SpotServe makes (D, P, M) a runtime decision re-solved in under a second.
  • Weights and caches already live in GPU memory across the cluster → restarting from storage throws that away (2+ minutes for a 120B model) → matching GPUs to new positions by reusable bytes turns reconfiguration into a small, optimally-chosen set of GPU-to-GPU transfers that fit inside a 30-second grace period.
  • Decoding is autoregressive → the KV cache is a byte-exact record of progress → committing per token is free, and resuming costs one cache transfer instead of re-decoding hundreds of tokens → tail latency stops being dominated by recomputation.
  • Migration follows pipeline-stage order → early stages serve while late stages transfer → reconfiguration downtime shrinks from “system restart” to “one stage’s transfer time.”
  • The grace period is spent, not wasted → the doomed instance decodes to the last safe second before preemption, and waits before acquisitions → every second of cheap compute is harvested.

What it costs

  • A latency premium versus on-demand serving. The 54% cost saving comes with average latency below 18% higher and P99 tail latency about 90% higher than an all-on-demand deployment — acceptable for many workloads, not for hard real-time ones.
  • Standby resources. A dedicated on-demand CPU coordinator, a small pool (about two) of spare instances, and optional on-demand GPU mixing when spot capacity vanishes.
  • Memory and bandwidth for migration. Context transfers need communication buffers in GPU memory (mitigated by the memory-aware planner) and consume network bandwidth during reconfigurations.
  • Offline profiling. Latency and migration-cost models must be profiled per model and per instance type before deployment.
  • Scope limits. One GPU instance type at a time (no heterogeneous or cross-cloud mixing), a latency-first objective rather than strict SLO guarantees, and reactive handling only — SpotServe responds to preemption notices; it does not predict them.

The evaluation

SpotServe was evaluated on AWS g4dn.12xlarge instances (4 NVIDIA T4 GPUs each), replaying two 20-minute segments of a real 12-hour spot availability trace — one calm, one turbulent — optionally mixed with on-demand instances, plus a rescaled production workload trace from Microsoft Azure Functions for fluctuating request rates. Three models were served: OPT-6.7B, GPT-20B, and LLaMA-30B (25 to 111.8 GB of weights, needing 4 to 16 GPUs minimum). Since no distributed LLM spot serving system existed, both baselines were built by the authors on the same FasterTransformer engine, representing the two prior philosophies.

Handling preemptions: three philosophies on identical engines

PropertyRerouting (small-model style)Reparallelization (Varuna style)SpotServe
When an instance is preempted
P99 tail latency, stable workload (LLaMA-30B)
P99 tail latency, fluctuating arrival rates (Azure trace)
Cost versus all-on-demand (GPT-20B)
AWS g4dn.12xlarge (4× T4) replaying real spot preemption traces; request arrivals at 1.5 / 0.35 / 0.2 requests/s for OPT-6.7B / GPT-20B / LLaMA-30B with bursty Gamma arrivals (CV = 6); 512 input, 128 output tokens; both baselines share SpotServe's FasterTransformer-based engine so only the preemption-handling philosophy differs. Redundancy baselines were excluded — duplicating an LLM deployment is exactly the cost the paper is trying to avoid.Underlined values explain themselves when clicked.

The ablation assigns credit cleanly: the parallelization controller matters most under load (removing it inflates tail latency 179% on the turbulent trace, because the system stops adapting throughput to the queue), the migration planner is next (1.4× / 3.1× on the two traces, and its memory-aware scheduling cut GPT-20B’s minimum from 16 to 12 GPUs), and the interruption arranger contributes a further 29% tail reduction by saving the KV caches of in-flight requests.

Check your understanding

  1. 1. GPT-20B is serving as (D=2, P=2, M=8) on twelve 4-GPU instances when one instance is preempted. Predict what a rerouting-based system loses, versus SpotServe.

  2. 2. Why can SpotServe commit inference progress per token with essentially no checkpointing machinery?

  3. 3. When reconfiguring, SpotServe assigns physical GPUs to logical positions with the Kuhn-Munkres bipartite matching algorithm. What is it actually optimizing?

  4. 4. The interruption arranger maximizes remaining decode iterations before a preemption, but minimizes them before an instance acquisition completes. Why the asymmetry?

Related papers on Machine Learning Systems

See all 212 →