Section E · Reference · Drill mode

Practice Interview Questions

Twenty-eight questions across eight sections. Toggle drill mode to hide answers, study mode to reveal them. Track which you've passed.

How to drill

Read the question aloud. Speak the answer out loud for 60 seconds. Then reveal and compare. Mark a checkbox when you'd give a confident answer cold. Aim for 90%+ confidence across all eight sections before the loop.

1. Serving

vLLM treats KV-cache as virtual memory, divided into fixed-size blocks (e.g. 16 tokens). Each sequence has a block table mapping logical positions to physical blocks. Benefits: near-zero fragmentation (only allocate what's used, not max-context per sequence); copy-on-write sharing of identical prefixes between requests; admission control is exact (we know how many blocks remain). It dramatically improves throughput vs. contiguous KV-cache allocation, especially under varying sequence lengths.

Static batching collects requests until a batch fills or a timeout, then runs the whole batch through. Slowest request determines batch latency; GPU goes idle at batch boundaries. Continuous batching operates at the iteration level — every forward pass, the scheduler adds new sequences and removes finished ones, so the GPU is never idle waiting for slow requests, and new requests join immediately. Operationally: lower TTFT, higher throughput, but the static dynamic-batching knobs (max_queue_delay) become irrelevant; the new knobs are max-num-seqs and KV-cache utilization.

vLLM if the workload is one or a few LLMs with OpenAI-compatible API and latency-sensitive chat. Triton if you have a portfolio of models (tokenizers, embeddings, classifiers, several LLMs), mixed frameworks (TensorRT, ONNX, PyTorch, Python), or want one unified server with model-repository semantics and dynamic batching for non-LLM models. You can also run vLLM inside Triton via the vLLM backend to get both.

Tensor parallel TP=4 over NVLink puts ~35 GB of weights on each GPU, plus shared KV-cache pool and activation memory. Tradeoffs: TP adds an all-reduce per layer (cheap over NVLink, expensive across nodes); pull TP>1 only intra-node for inference. Alternatives: FP8 quantization (~70 GB total → fits on 2× H100); INT4 (~35 GB → fits on 1× H100 with room for cache, at some quality cost); H200/B200 with bigger HBM. The senior answer is to ask what TTFT/throughput target makes the precision/parallelism choice obvious.

2. Scheduling & orchestration

Exclusive for any workload that saturates a GPU (big-model serving, training). MIG when many small inference workloads share a node and you need hardware-isolated SLOs (e.g. multi-tenant inference platform — each tenant gets a guaranteed slice). MPS when you have many small co-trusted clients sharing a GPU and want better utilization than time-slicing, accepting softer isolation. Default time-slicing only for dev/notebooks where utilization matters more than predictability.

Distributed training requires all N workers to start together — if 6 of 8 land and 2 are pending, the 6 idle GPUs are unusable. Vanilla K8s starts the 6 happily. Gang scheduling holds back the start until all N can be scheduled. Implement via Volcano (PodGroup), Kueue (Workload), or Yunikorn. The scheduler reserves capacity for the whole group atomically and only places pods when N can fit.

Hierarchical queues with priority classes. Production gets the highest priority class with preemption rights. Research gets a guaranteed quota plus borrowing rights up to a cohort cap when production is idle. Preemption is graceful: SIGTERM + checkpoint window, not SIGKILL, so research jobs lose at most N steps. Quota enforced via ResourceQuota; queue-level fairness via Kueue / Volcano. Surface a daily "what each team used" report for accountability.

Pending pod age per priority class (online >0 is a page). Time-to-bind p95 rising. Fragmentation — nodes with idle GPUs no pending pod can use due to topology/taints. Preemption rate spikes. Gap between allocatable and SM-active: high gap = bad placement, low utilization despite full allocation. Quota saturated for a team that's still queueing means you need to renegotiate.

3. Observability

Three different things are called utilization. nvidia-smi's "GPU-Util" is the fraction of time any kernel ran — a tiny kernel looping shows 100%. DCGM's SM-active is better. SM-occupancy (warps issued / max) is best for compute-bound work. For LLM decode, the right metric is HBM bandwidth utilization because decode is memory-bound, not compute-bound. A senior answer names which metric you mean.

Top half: fleet SM-active heatmap by node, fleet HBM used heatmap. Middle: top-five services p95 latency + TTFT, request rate, error rate. Queue depth in front of each service by priority class. Bottom: $/million-tokens trendline; quota usage by team; pending pods. The rule: if any panel turns red, that's the team's afternoon.

OpenTelemetry. The gateway opens the root span. Each downstream (auth, router, retriever, embedder, reranker, LLM, response post-process) opens child spans with attributes — model, tokens, cache hit, GPU node. Tail-based sampling keeps all traces with errors or latency > threshold so you have high signal at low storage cost. Export to Tempo/Jaeger/Honeycomb; correlate via the request ID in logs and metrics.

Averages hide tail. A service with p50 of 100ms and p99 of 5s can have a "300ms average" that suggests health when 1% of users see a broken experience. Histograms let you compute any percentile after the fact and roll up across instances. Use Prometheus histogram buckets sized to the actual distribution; compute histogram_quantile(0.99, ...) for tail metrics.

4. Error handling

(1) What changed: recent deploy, driver, traffic shape? (2) Request mix: longer prompts, lower prefix-cache hit rate? (3) KV-cache utilization: cache thrashing under more concurrency? (4) dmesg for Xids; the GPU could be silently throttling on thermal or ECC. (5) Compare to neighbor replicas — if only this one is bad, restart it; if all are bad, look upstream. (6) p95 SM-active and DRAM-active to see whether it's compute or memory bound. The discipline: change → confirm → isolate.

Set NCCL_DEBUG=INFO, re-run, read which rank is waiting for which peer. Usual culprits: firewall blocking NCCL ports between nodes; NCCL_SOCKET_IFNAME picked a management NIC; one rank's pod is still pulling its image; IB link down (ibstat); subnet manager issue. In production, set NCCL_ASYNC_ERROR_HANDLING=1 and TORCH_NCCL_BLOCKING_WAIT=1 so hangs error out within a watchdog timeout instead of stalling forever.

For pure inference: yes — at fixed seed/temp the output is deterministic; otherwise differing samples are acceptable. For inference with tool calls: not without idempotency keys on the tools — the agent layer handles this. For billing: don't bill twice for retried requests that failed before the first token. Accept a client-provided request ID at the gateway, de-dupe within a short window. Streaming retries are usually "retry from scratch" in the contract.

Reject loudly at the edge with 429 + Retry-After. Per-tenant rate limits so one team can't starve others. Queue-time SLO — drop requests that have queued past their deadline (the user gave up). Load-shed low-priority traffic before high-priority. Circuit breaker in front of a melting backend. The principle: predictable 429s beat wandering p99 timeouts.

5. System design

Frame the triangle first: latency-bounded, customer-facing, so optimize TTFT and tail; accept higher cost.

  1. Edge: TLS termination, auth (mTLS or API key), per-tenant rate limiting, request validation, observability injection.
  2. Router: model name → backend pool; weighted routing for canaries; circuit breaker; load shedding.
  3. Backend pools: vLLM with prefix caching enabled, FP8 KV-cache, TP=4 on H100 SXM nodes. Sized for P50 from reserved + P25 on-demand + spot for batch elsewhere.
  4. Autoscaler: KEDA on num_requests_waiting metric, scale-in with long cooldown to preserve KV-cache.
  5. Observability: OTel traces, RED metrics per route, DCGM per node, cost dashboard per tenant.
  6. Failure modes: 429 on saturation, retry-with-jitter advice, circuit breaker on backend health, blue/green for changes.
  7. Capacity math: 10k RPS / 1.6 RPS-per-GPU-equivalent at our token profile = ~6300 GPUs equivalent at saturation; size to 30% headroom = ~9000. Mix of reserved/on-demand based on $/GPU-hour spread.

Pool the hardware by accelerator type; tenants are namespaces with quota + borrowing. Isolation: full GPU for big-model serving, MIG for small models that need SLOs, MPS only where tenants trust each other. Router routes by model name to the right pool. Observability: per-tenant dashboards (latency, throughput, GPU-hours, cost). Self-service "deploy a model" via KServe CRDs. Governance: weekly cost review; quota review quarterly.

Pin via GPU Operator. Build a new driver container image. Deploy first to a dev node, run smoke + perf regression. Then to a single canary in pre-prod, soak 24h, compare DCGM Xids/temp/throughput baselines. Then to 5% of prod (one AZ), soak 24h with on-call watching. Then 25%, 50%, 100% staged across AZs with soak between gates. Pre-defined rollback at each gate. Communicate via incident-style status to stakeholders.

Spot for ~70% of the fleet, on-demand reserve for the rest. Async checkpointing every N minutes to durable storage (object + Lustre cache). On spot warning (2-min for AWS), drain the worker: stop accepting steps, flush state, exit. Re-launch picks up latest checkpoint. Use elastic training (TorchElastic) so jobs survive worker churn without dying. Hedge across instance families and AZs. Track "% time productive" as the headline metric; alert when productivity drops below threshold.

6. Cost optimization

Five-factor: (1) privacy — does the workload touch regulated data? (2) latency — is the API round trip + tail compatible with the SLO? (3) reliability — is the external API a tolerable dependency? (4) cost — at expected volume, blended in-house $/M-tokens vs API $/M-tokens, plus operating overhead. (5) differentiation — is the model fine-tuned or custom? At the company, (1) usually pushes toward in-house even when (4) is close. The cost math always assumes high utilization; idle reserved GPUs flip the answer.

Idle reserved capacity (paying for GPUs no one used). Over-provisioned replicas with rounded-up GPU counts. Spot capacity unused because batch workloads weren't migrated. Cold prefix-cache loss from frequent scale-in. Inefficient quantization (FP16 where FP8 is fine). Lone-tenant nodes with poor packing. The dashboard is "idle GPU-hours per team per day" with a top-N table.

Depends. For LLM decode, 30% SM-active is normal — decode is memory-bandwidth-bound, not compute-bound. Look at DRAM-active; if that's 70-80%, you're saturated and SM-active doesn't matter. For a vision model or training step, 30% SM-active is bad — likely data-loader starvation, small batch size, or sync overhead. The same number means different things depending on the workload shape; the senior framing is "is the bottleneck resource saturated?"

7. Coding

State: capacity, refill_per_sec, current tokens, last_ts. On allow(now, cost): refill = min(capacity, tokens + (now - last_ts) × refill_per_sec); if refill ≥ cost, debit and return True. Constant time, constant memory. Clamp time backwards. Generalize cost for variable-size LLM requests.

Exact: deque of (ts, latency); evict head while head_ts < now − window; sort and pick the 99th element on query. O(n log n) per query. Production: HDR histogram or t-digest for bounded memory and O(log n) updates with small error. Bucketed histogram per second + merge across window also works.

Async loop. submit(item) appends to a buffer and sets a wakeup event. The loop awaits either the event (buffer non-empty) or a timeout (W ms). When B items are present, flush immediately; otherwise on timeout flush whatever is there. Return per-item futures so callers get their result back. Handle shutdown by flushing partials.

First-fit decreasing: sort jobs by size descending; for each, place on first bin with space; open a new bin if none fits. Within 11/9 of optimal for bin packing. Extension to discuss: multi-dimensional (compute + memory) is NP-hard in general; LP-relaxation or Kueue topology-aware schedulers handle real production. Mention this; don't try to derive it.

8. Behavioral

STAR. Situation: scope, scale, severity. Task: your role, what was at stake. Action: how you triaged, what you escalated, the call you made under uncertainty. Result: time to mitigate, blast radius, what changed durably (PIR action that shipped). Bonus: a sentence on what you'd do differently. Avoid heroism; emphasize coordination and the durable fix.

Useful to have a story where you said "no" or "not yet" to a researcher and proposed a better path. Show that you respect the user, understand their goal, and protect the substrate. Resolution: a small experiment that resolved the disagreement with data, not opinion.

Read claims, but verify on your workload — your prompt distribution, your model, your GPUs. Reproduce one benchmark to ground-truth. Stand up a soak in pre-prod. Measure quality regression alongside performance. Cost the operational debt (new tool means new on-call runbooks, new failure modes). Decide on a small bet (a single use case) before fleet adoption. Don't be first; don't be last.

Specific. the company is building in-house AI compute precisely because privacy, latency, and cost matter for a regulated exchange — that's the framing where this team's leverage is highest. Be concrete about what attracts you (the in-house mandate, the senior small team, the chance to own the substrate). Avoid generic "I love AI" — talk about this team's mandate. End with a question.

✓ Check yourself

Answer from memory before opening each one.

  1. A 405B model needs about 810 GB in FP16. Does it fit on one node of eight 80 GB H100s, and what limits you if you serve it in FP8?

    Show answer

    FP16 does not fit, since the node has 640 GB. In FP8 the weights take about 405 GB, so they fit with about 235 GB left across the node for KV-cache and activations. That remainder, not the weights, then sets concurrency. See the serving questions.

  2. You must serve 2,000 requests per second, each GPU handles 4 at saturation, and you target 70 percent utilisation. How many GPUs, and how many four-way replicas?

    Show answer

    2,000 divided by 4 is 500 GPUs at saturation, and dividing by 0.7 gives about 715. At four GPUs per replica that is about 180 replicas. The utilisation target is the headroom for bursts and replica loss, so say it out loud. See the design questions.

  3. Research holds 32 GPUs of quota and has borrowed 16 more from the cohort. Production load spikes and wants them back. What should happen?

    Show answer

    Production's higher priority reclaims the borrowed GPUs by preemption, but gracefully: signal the research jobs, give them a checkpoint window, and then stop them. Research keeps its 32 guaranteed GPUs, and loses at most the steps since its last checkpoint. See the scheduling questions.

  4. A vision model runs at 30 percent SM-active with 20 percent DRAM-active, while an LLM decoder runs at 30 percent SM-active with 75 percent DRAM-active. Which has a problem?

    Show answer

    The vision model: neither compute nor memory is saturated, which points to starvation, such as the data loader, a small batch or synchronisation. The decoder is bandwidth-bound and effectively saturated. The question is whether the bottleneck resource is busy. See the cost questions.

  5. One vLLM replica of twelve shows 40 percent lower throughput while the others are fine. How does that change your first move compared with all twelve being slow?

    Show answer

    A single bad replica points to that node or process, so compare it with its neighbours, check Xids and throttling, and drain it if it stays bad. All twelve slow points upstream: a deploy, driver change, request mix or cache hit rate. Establish what changed first either way. See the error-handling questions.

  6. A workload touches customer identity documents but sends only a few thousand requests a day. The API would be cheaper. What do you recommend?

    Show answer

    Privacy dominates, so favour in-house inference or a contract that satisfies security review. Say the cost case cannot be shown from API prices alone: at low volume, dedicated GPUs sit mostly idle and flip the arithmetic, so a small shared pool or MIG slice may be right. Report the idle cost openly. See the cost questions.

Takeaway

  • Know the memory arithmetic: weights at each precision, shards per GPU, and what is left for KV-cache.
  • Paged attention, continuous batching and the Triton versus vLLM choice are the core serving answers.
  • A fair-sharing answer has priority classes, quota with borrowing, quotas per namespace and graceful preemption.
  • Name the utilisation metric you mean, and judge a number against the workload's bottleneck.
  • Error answers follow what changed, then isolate: one replica against all of them, and a hang read from the NCCL log.
  • System design answers start with the workload and the triangle, then capacity math, then failure modes and cost.
  • Cost answers weigh privacy, latency, reliability, cost and differentiation, and assume utilisation honestly.

Next is the day-of chapter: the checklist, the structural move for design rounds and how to recover when something goes wrong. → Day-Of Tactics