aiml
SearchMy learning
Menu

Lesson 19 of 20Module 6

Budget cache transfer before splitting inference pools

Calculate cache-transfer payloads before separating prefill and decode. Explore bandwidth and expert-placement assumptions without claiming fleet benchmarks.

Prerequisites

Python, basic causal attention, and the preceding inference lessons.

By the end, you can

  • Budget cache transfer before splitting inference pools.
  • Explain the bottleneck, measurement boundary, and tradeoffs in this implementation.
  • Identify transfer and expert-imbalance costs before proposing separate pools.
Runtime
Python 3.12+
Dependencies
Standard library only

Lab code, tests and fixtures (ZIP, 105 KB)Quiz check your understanding

Progress is saved in this browser.

When you need this. A team considers separate prefill and decode pools to isolate long-document work from interactive streams. Moving the KV cache between those pools adds a transfer dependency before decode can continue. Estimate that payload before adding orchestration.

What you run. Payload calculator and explicit disaggregation/MoE cost scenarios. No networked KV transfer, multi-GPU model execution, or throughput improvement was measured.

This lesson builds on plan cold starts and gate model rollouts.

Count the cache handoff payload

Prefill/decode disaggregation lets each phase use a different pool and scheduling policy. The receiving decoder needs compatible model state and KV layout. Transfer time depends on payload, effective link bandwidth, contention, and handoff overhead; advertised link bandwidth is only an upper bound.

For a mixture-of-experts (MoE) model, only selected experts execute for a token, but expert weights still need placement. Expert parallelism routes token activations between devices. Uneven expert selection can create stragglers; active parameter count alone does not determine memory or communication cost.

KV payloadTransfer budgetHandoff estimatebyte sizetime estimateKV payloadTransfer budgetHandoff estimatebyte sizetime estimate
Follow the named data through the downloadable program. The article identifies whether the result is measured execution, a controlled fixture, or a planning estimate.

ModelKVSpec calculates transfer payload, and evaluate_pd_disaggregation() exposes bandwidth and overlap assumptions. The MoE calculation is a separate scenario model, not a DeepSeek deployment. The code does not move tensors between real GPUs or validate a KV connector.

Run the transfer budget

Download the lab from this page, extract it, and run these commands from its directory. The default command reads saved run records or runs the explicitly described local algorithm; it never downloads a model or calls a paid API.

Run the local analysis and checksTerminal · bash
python3 lab.py
python3 -m unittest -v test_lab.py
Read lab.py
lab.pySource · pythonDownload
"""Disaggregated prefill/decode pool sizer and large Mixture-of-Experts (MoE) parallelism analyzer."""

from __future__ import annotations

from dataclasses import asdict, dataclass
import json
import math
from typing import Literal

InterconnectKind = Literal["nvlink_900gbs", "rdma_roce_50gbs", "tcp_ethernet_12_5gbs"]

INTERCONNECT_BANDWIDTH_GBS: dict[InterconnectKind, float] = {
    "nvlink_900gbs": 900.0,
    "rdma_roce_50gbs": 50.0,
    "tcp_ethernet_12_5gbs": 12.5,
}


@dataclass(frozen=True)
class ModelKVSpec:
    name: str = "Llama-3-70B-GQA"
    layers: int = 80
    kv_heads: int = 8
    head_dim: int = 128
    bytes_per_element: int = 2  # BF16 = 2 bytes, FP8 = 1 byte

    def kv_bytes_per_token(self) -> int:
        return 2 * self.layers * self.kv_heads * self.head_dim * self.bytes_per_element

    def kv_transfer_bytes(self, prompt_tokens: int) -> int:
        if prompt_tokens <= 0:
            raise ValueError("prompt_tokens must be positive")
        return self.kv_bytes_per_token() * prompt_tokens


@dataclass(frozen=True)
class DisaggregationWorkload:
    prompt_tokens: int = 4096
    decode_tokens: int = 256
    target_qps: float = 36.0
    prefill_tokens_per_sec_per_gpu: float = 18_500.0
    decode_tokens_per_sec_per_gpu: float = 1_600.0
    colocated_interference_tpot_penalty_ms: float = 29.5
    base_decode_tpot_ms: float = 21.0


def evaluate_pd_disaggregation(
    kv_spec: ModelKVSpec = ModelKVSpec(),
    workload: DisaggregationWorkload = DisaggregationWorkload(),
    interconnect: InterconnectKind = "rdma_roce_50gbs",
) -> dict[str, object]:
    """Compares co-located continuous batching against disaggregated Prefill (P) and Decode (D) GPU pools."""
    kv_bytes = kv_spec.kv_transfer_bytes(workload.prompt_tokens)
    kv_megabytes = round(kv_bytes / (1024 * 1024), 2)
    bw_gbs = INTERCONNECT_BANDWIDTH_GBS[interconnect]
    # Scenario assumptions only: these link efficiencies are not measured.
    link_efficiency = 0.52 if interconnect == "tcp_ethernet_12_5gbs" else 0.82
    effective_bw_bytes_per_ms = (bw_gbs * 1e9 * link_efficiency) / 1000.0
    kv_transfer_ms = round(kv_bytes / effective_bw_bytes_per_ms, 2)

    prefill_compute_ms = round(
        (workload.prompt_tokens / workload.prefill_tokens_per_sec_per_gpu) * 1000.0, 2
    )
    # In co-located pools, long prefills queue behind mixed decode steps and inject chunk-prefill stalls into TPOT.
    colocated_p99_ttft_ms = round(prefill_compute_ms * 1.48 + 95.0, 2)
    colocated_p99_tpot_ms = round(
        workload.base_decode_tpot_ms + workload.colocated_interference_tpot_penalty_ms,
        2,
    )

    # Scenario assumes partial transfer overlap; no connector was executed.
    # unpipelined TCP waits for full prompt completion and pays host bounce-buffer latency.
    overlap_factor = 0.35 if interconnect != "tcp_ethernet_12_5gbs" else 1.05
    disagg_p99_ttft_ms = round(
        prefill_compute_ms + 32.0 + kv_transfer_ms * overlap_factor, 2
    )
    disagg_p99_tpot_ms = round(workload.base_decode_tpot_ms, 2)

    # Size dedicated P and D GPU pools with 25% headroom.
    prefill_token_rate = workload.target_qps * workload.prompt_tokens
    decode_token_rate = workload.target_qps * workload.decode_tokens
    prefill_gpus = math.ceil(
        (prefill_token_rate / workload.prefill_tokens_per_sec_per_gpu) * 1.25
    )
    decode_gpus = math.ceil(
        (decode_token_rate / workload.decode_tokens_per_sec_per_gpu) * 1.25
    )
    colocated_gpus = math.ceil((prefill_gpus + decode_gpus) * 1.22)

    return {
        "interconnect": interconnect,
        "interconnect_bandwidth_gbs": bw_gbs,
        "prompt_tokens": workload.prompt_tokens,
        "decode_tokens": workload.decode_tokens,
        "kv_bytes_per_token": kv_spec.kv_bytes_per_token(),
        "kv_transfer_mib": kv_megabytes,
        "raw_kv_transfer_ms": kv_transfer_ms,
        "prefill_compute_ms": prefill_compute_ms,
        "colocated": {
            "total_gpus": colocated_gpus,
            "p99_ttft_ms": colocated_p99_ttft_ms,
            "p99_tpot_ms": colocated_p99_tpot_ms,
        },
        "disaggregated": {
            "prefill_gpus": prefill_gpus,
            "decode_gpus": decode_gpus,
            "total_gpus": prefill_gpus + decode_gpus,
            "pd_ratio": f"{prefill_gpus}:{decode_gpus}",
            "p99_ttft_ms": disagg_p99_ttft_ms,
            "p99_tpot_ms": disagg_p99_tpot_ms,
            "ttft_improved_vs_colocated": disagg_p99_ttft_ms < colocated_p99_ttft_ms,
            "tpot_reduction_ms": round(colocated_p99_tpot_ms - disagg_p99_tpot_ms, 2),
        },
    }


@dataclass(frozen=True)
class MoEArchitectureSpec:
    name: str = "hypothetical-moe-scenario"
    total_params_b: float = 671.0
    active_params_b: float = 37.0
    layers: int = 61
    routed_experts: int = 64
    top_k: int = 8
    hidden_dim: int = 7168
    expert_intermediate_dim: int = 2048
    bytes_per_weight: int = 1  # FP8 weights


def evaluate_moe_parallelism(
    moe: MoEArchitectureSpec = MoEArchitectureSpec(),
    *,
    num_gpus: int = 16,
    batch_tokens: int = 512,
    strategy: Literal["pure_tp16", "hybrid_tp2_ep8"] = "hybrid_tp2_ep8",
    hot_expert_skew_factor: float = 1.15,
    enable_redundant_hot_experts: bool = True,
) -> dict[str, object]:
    """Compares Tensor Parallelism (TP) against hybrid TP + Expert Parallelism (EP) for large MoE decode."""
    if num_gpus <= 0 or batch_tokens <= 0:
        raise ValueError("num_gpus and batch_tokens must be positive")
    if hot_expert_skew_factor < 1.0:
        raise ValueError("hot_expert_skew_factor must be >= 1.0")

    expert_weight_bytes_per_layer = (
        moe.routed_experts
        * 3
        * moe.hidden_dim
        * moe.expert_intermediate_dim
        * moe.bytes_per_weight
    )
    hbm_bw_bytes_per_ms = (
        3200.0 * 1e9 * 0.72
    ) / 1000.0  # H100-class effective HBM bandwidth

    if strategy == "pure_tp16":
        # Pure TP16 slices every expert into 16 tiny shards and executes 2 all-reduce barriers per layer across 16 GPUs.
        per_gpu_weight_read = expert_weight_bytes_per_layer / num_gpus
        compute_and_hbm_ms_per_layer = (
            per_gpu_weight_read / hbm_bw_bytes_per_ms
        ) / 0.42
        comm_ms_per_layer = 0.24 + (batch_tokens * moe.hidden_dim * 2 * 2) / (
            50.0 * 1e9 / 1000.0
        )
        straggler_multiplier = 1.0
        layer_tpot_ms = compute_and_hbm_ms_per_layer + comm_ms_per_layer
    else:
        # Generic hybrid TP/EP placement scenario; experts per rank depend on this input.
        # replacing 16-way all-reduce with compact all-to-all token dispatch + combine.
        ep_degree = 8
        active_fraction = min(1.0, (batch_tokens * moe.top_k) / moe.routed_experts)
        per_gpu_weight_read = (expert_weight_bytes_per_layer / ep_degree) * min(
            1.0, active_fraction
        )
        compute_and_hbm_ms_per_layer = (
            per_gpu_weight_read / hbm_bw_bytes_per_ms
        ) / 0.86
        routed_bytes = batch_tokens * moe.top_k * moe.hidden_dim * 1  # FP8 dispatch
        comm_ms_per_layer = 0.07 + (2 * routed_bytes) / (150.0 * 1e9 / 1000.0)
        # If one expert rank receives skewed traffic without redundant hot-expert replication,
        # both expert GEMM time and incast all-to-all combine stall on the hottest EP rank.
        straggler_multiplier = (
            min(1.18, 1.0 + (hot_expert_skew_factor - 1.0) * 0.12)
            if enable_redundant_hot_experts
            else hot_expert_skew_factor
        )
        layer_tpot_ms = (
            compute_and_hbm_ms_per_layer + comm_ms_per_layer
        ) * straggler_multiplier

    step_tpot_ms = round(layer_tpot_ms * moe.layers, 2)
    throughput_tokens_per_sec = round((batch_tokens / step_tpot_ms) * 1000.0, 1)

    return {
        "model": moe.name,
        "strategy": strategy,
        "num_gpus": num_gpus,
        "batch_tokens": batch_tokens,
        "hot_expert_skew_factor": hot_expert_skew_factor,
        "enable_redundant_hot_experts": enable_redundant_hot_experts,
        "effective_straggler_multiplier": round(straggler_multiplier, 3),
        "compute_and_hbm_ms_per_layer": round(
            compute_and_hbm_ms_per_layer * straggler_multiplier, 4
        ),
        "comm_ms_per_layer": round(comm_ms_per_layer * straggler_multiplier, 4),
        "step_tpot_ms": step_tpot_ms,
        "cluster_decode_tokens_per_sec": throughput_tokens_per_sec,
    }


def run_all_evaluations() -> dict[str, object]:
    kv_spec = ModelKVSpec()
    workload = DisaggregationWorkload()
    pd_by_network = {
        net: evaluate_pd_disaggregation(kv_spec, workload, net)
        for net in ("nvlink_900gbs", "rdma_roce_50gbs", "tcp_ethernet_12_5gbs")
    }
    moe_comparisons = {
        "pure_tp16_baseline": evaluate_moe_parallelism(strategy="pure_tp16"),
        "hybrid_tp2_ep8_balanced": evaluate_moe_parallelism(
            strategy="hybrid_tp2_ep8",
            hot_expert_skew_factor=1.15,
            enable_redundant_hot_experts=True,
        ),
        "hybrid_tp2_ep8_skewed_no_redundancy": evaluate_moe_parallelism(
            strategy="hybrid_tp2_ep8",
            hot_expert_skew_factor=2.6,
            enable_redundant_hot_experts=False,
        ),
        "hybrid_tp2_ep8_skewed_with_redundancy": evaluate_moe_parallelism(
            strategy="hybrid_tp2_ep8",
            hot_expert_skew_factor=2.6,
            enable_redundant_hot_experts=True,
        ),
    }
    return {
        "experiment": "prefill-decode-disaggregation-and-moe-expert-parallelism",
        "kv_spec": asdict(kv_spec),
        "pd_disaggregation_by_interconnect": pd_by_network,
        "moe_parallelism": moe_comparisons,
    }


def main() -> None:
    print(
        json.dumps(
            {
                "execution_mode": "CPU algorithm with controlled inputs; any latency/capacity coefficients are assumptions",
                **run_all_evaluations(),
            },
            indent=2,
        )
    )


if __name__ == "__main__":
    main()

Transfer time grows with the payload and falls with effective bandwidth. Any overlap term is an assumption that needs measurement in the selected connector. The MoE scenario is independent of this dense-model KV payload calculation.

Inspect the complete local result
Recorded local resultRecorded output · jsonDownload
{
  "execution_mode": "CPU algorithm with controlled inputs; any latency/capacity coefficients are assumptions",
  "experiment": "prefill-decode-disaggregation-and-moe-expert-parallelism",
  "kv_spec": {
    "name": "Llama-3-70B-GQA",
    "layers": 80,
    "kv_heads": 8,
    "head_dim": 128,
    "bytes_per_element": 2
  },
  "pd_disaggregation_by_interconnect": {
    "nvlink_900gbs": {
      "interconnect": "nvlink_900gbs",
      "interconnect_bandwidth_gbs": 900.0,
      "prompt_tokens": 4096,
      "decode_tokens": 256,
      "kv_bytes_per_token": 327680,
      "kv_transfer_mib": 1280.0,
      "raw_kv_transfer_ms": 1.82,
      "prefill_compute_ms": 221.41,
      "colocated": {
        "total_gpus": 22,
        "p99_ttft_ms": 422.69,
        "p99_tpot_ms": 50.5
      },
      "disaggregated": {
        "prefill_gpus": 10,
        "decode_gpus": 8,
        "total_gpus": 18,
        "pd_ratio": "10:8",
        "p99_ttft_ms": 254.05,
        "p99_tpot_ms": 21.0,
        "ttft_improved_vs_colocated": true,
        "tpot_reduction_ms": 29.5
      }
    },
    "rdma_roce_50gbs": {
      "interconnect": "rdma_roce_50gbs",
      "interconnect_bandwidth_gbs": 50.0,
      "prompt_tokens": 4096,
      "decode_tokens": 256,
      "kv_bytes_per_token": 327680,
      "kv_transfer_mib": 1280.0,
      "raw_kv_transfer_ms": 32.74,
      "prefill_compute_ms": 221.41,
      "colocated": {
        "total_gpus": 22,
        "p99_ttft_ms": 422.69,
        "p99_tpot_ms": 50.5
      },
      "disaggregated": {
        "prefill_gpus": 10,
        "decode_gpus": 8,
        "total_gpus": 18,
        "pd_ratio": "10:8",
        "p99_ttft_ms": 264.87,
        "p99_tpot_ms": 21.0,
        "ttft_improved_vs_colocated": true,
        "tpot_reduction_ms": 29.5
      }
    },
    "tcp_ethernet_12_5gbs": {
      "interconnect": "tcp_ethernet_12_5gbs",
      "interconnect_bandwidth_gbs": 12.5,
      "prompt_tokens": 4096,
      "decode_tokens": 256,
      "kv_bytes_per_token": 327680,
      "kv_transfer_mib": 1280.0,
      "raw_kv_transfer_ms": 206.49,
      "prefill_compute_ms": 221.41,
      "colocated": {
        "total_gpus": 22,
        "p99_ttft_ms": 422.69,
        "p99_tpot_ms": 50.5
      },
      "disaggregated": {
        "prefill_gpus": 10,
        "decode_gpus": 8,
        "total_gpus": 18,
        "pd_ratio": "10:8",
        "p99_ttft_ms": 470.22,
        "p99_tpot_ms": 21.0,
        "ttft_improved_vs_colocated": false,
        "tpot_reduction_ms": 29.5
      }
    }
  },
  "moe_parallelism": {
    "pure_tp16_baseline": {
      "model": "hypothetical-moe-scenario",
      "strategy": "pure_tp16",
      "num_gpus": 16,
      "batch_tokens": 512,
      "hot_expert_skew_factor": 1.15,
      "enable_redundant_hot_experts": true,
      "effective_straggler_multiplier": 1.0,
      "compute_and_hbm_ms_per_layer": 0.182,
      "comm_ms_per_layer": 0.5336,
      "step_tpot_ms": 43.65,
      "cluster_decode_tokens_per_sec": 11729.7
    },
    "hybrid_tp2_ep8_balanced": {
      "model": "hypothetical-moe-scenario",
      "strategy": "hybrid_tp2_ep8",
      "num_gpus": 16,
      "batch_tokens": 512,
      "hot_expert_skew_factor": 1.15,
      "enable_redundant_hot_experts": true,
      "effective_straggler_multiplier": 1.018,
      "compute_and_hbm_ms_per_layer": 0.181,
      "comm_ms_per_layer": 0.4698,
      "step_tpot_ms": 39.7,
      "cluster_decode_tokens_per_sec": 12896.7
    },
    "hybrid_tp2_ep8_skewed_no_redundancy": {
      "model": "hypothetical-moe-scenario",
      "strategy": "hybrid_tp2_ep8",
      "num_gpus": 16,
      "batch_tokens": 512,
      "hot_expert_skew_factor": 2.6,
      "enable_redundant_hot_experts": false,
      "effective_straggler_multiplier": 2.6,
      "compute_and_hbm_ms_per_layer": 0.4623,
      "comm_ms_per_layer": 1.1998,
      "step_tpot_ms": 101.39,
      "cluster_decode_tokens_per_sec": 5049.8
    },
    "hybrid_tp2_ep8_skewed_with_redundancy": {
      "model": "hypothetical-moe-scenario",
      "strategy": "hybrid_tp2_ep8",
      "num_gpus": 16,
      "batch_tokens": 512,
      "hot_expert_skew_factor": 2.6,
      "enable_redundant_hot_experts": true,
      "effective_straggler_multiplier": 1.18,
      "compute_and_hbm_ms_per_layer": 0.2098,
      "comm_ms_per_layer": 0.5445,
      "step_tpot_ms": 46.02,
      "cluster_decode_tokens_per_sec": 11125.6
    }
  }
}
Saved output report for budget cache transfer before splitting inference pools; execution mode and values come from the linked raw result.

This image is an application-generated report of the saved program result, not a new inference run. Open the full-resolution report or read the raw result.

Account for network and expert imbalance

Separating pools can help control phase-specific latency, but adds network work, routing, failure recovery, and capacity coordination. It is not a general throughput improvement. Overlap may hide only part of transfer time. MoE expert placement and replication add another independent tradeoff.

Transfer bottleneck. Lower effective bandwidth makes the cache handoff slower in the scenario model. The scheduling benefit can disappear; overlap and link efficiency are assumptions.

Expert imbalance. Uneven expert assignment creates a straggler in the generic MoE scenario. The calculation does not execute a real MoE model or validate a balancing implementation.

Read the executable checks
Executable checksSource · pythonDownload
"""Unit and failure-mode tests for disaggregated prefill/decode pools and large MoE serving."""

from __future__ import annotations

import unittest

from lab import (
    DisaggregationWorkload,
    ModelKVSpec,
    evaluate_moe_parallelism,
    evaluate_pd_disaggregation,
)


class DisaggregationAndMoETest(unittest.TestCase):
    def test_exact_kv_cache_transfer_bytes_and_rdma_pd_disaggregation(self) -> None:
        spec = ModelKVSpec(layers=80, kv_heads=8, head_dim=128, bytes_per_element=2)
        # 2 (K+V) * 80 * 8 * 128 * 2 = 327,680 bytes/token; for 4,096 tokens = 1,342,177,280 bytes (1,280 MB).
        self.assertEqual(spec.kv_bytes_per_token(), 327_680)
        self.assertEqual(spec.kv_transfer_bytes(4096), 1_342_177_280)

        rdma = evaluate_pd_disaggregation(
            spec, DisaggregationWorkload(), "rdma_roce_50gbs"
        )
        self.assertEqual(rdma["kv_transfer_mib"], 1280.0)
        self.assertTrue(rdma["disaggregated"]["ttft_improved_vs_colocated"])
        self.assertLess(
            rdma["disaggregated"]["p99_tpot_ms"],
            rdma["colocated"]["p99_tpot_ms"],
        )

    def test_slow_network_kv_transfer_erases_disaggregation_ttft_gain(self) -> None:
        spec = ModelKVSpec()
        workload = DisaggregationWorkload(prompt_tokens=4096)
        rdma = evaluate_pd_disaggregation(spec, workload, "rdma_roce_50gbs")
        tcp = evaluate_pd_disaggregation(spec, workload, "tcp_ethernet_12_5gbs")

        # Over 12.5 GB/s TCP without RDMA pipelining, transferring 1.28 GB of KV cache takes >120ms,
        # pushing disaggregated TTFT above the co-located baseline.
        self.assertTrue(rdma["disaggregated"]["ttft_improved_vs_colocated"])
        self.assertFalse(tcp["disaggregated"]["ttft_improved_vs_colocated"])
        self.assertGreater(
            tcp["disaggregated"]["p99_ttft_ms"],
            tcp["colocated"]["p99_ttft_ms"],
        )

    def test_hybrid_tp_ep_outperforms_pure_tp16_on_large_moe(self) -> None:
        pure_tp = evaluate_moe_parallelism(strategy="pure_tp16")
        hybrid_ep = evaluate_moe_parallelism(strategy="hybrid_tp2_ep8")
        self.assertLess(hybrid_ep["step_tpot_ms"], pure_tp["step_tpot_ms"])
        self.assertGreater(
            hybrid_ep["cluster_decode_tokens_per_sec"],
            pure_tp["cluster_decode_tokens_per_sec"],
        )

    def test_skewed_expert_routing_creates_ep_straggler_bottleneck(self) -> None:
        unmitigated = evaluate_moe_parallelism(
            strategy="hybrid_tp2_ep8",
            hot_expert_skew_factor=2.6,
            enable_redundant_hot_experts=False,
        )
        mitigated = evaluate_moe_parallelism(
            strategy="hybrid_tp2_ep8",
            hot_expert_skew_factor=2.6,
            enable_redundant_hot_experts=True,
        )
        # Without redundant hot-expert replication, 2.6x routing skew inflates step TPOT by >70%.
        self.assertGreater(unmitigated["step_tpot_ms"], mitigated["step_tpot_ms"] * 1.5)
        self.assertGreater(
            mitigated["cluster_decode_tokens_per_sec"],
            unmitigated["cluster_decode_tokens_per_sec"] * 1.5,
        )


if __name__ == "__main__":
    unittest.main()


class GuardBoundaryTests(unittest.TestCase):
    def test_rejects_invalid_boundary_inputs_with_specific_reason(self):
        import lab
        cases = [('evaluate_moe_parallelism(num_gpus=0)', 'num_gpus'), ('evaluate_moe_parallelism(hot_expert_skew_factor=0.5)', 'skew_factor'), ('ModelKVSpec().kv_transfer_bytes(0)', 'prompt_tokens')]
        for code, reason in cases:
            with self.subTest(code=code):
                with self.assertRaisesRegex((ValueError, MemoryError, KeyError, RuntimeError), reason):
                    exec(code, vars(lab).copy())

Try a change and explain the result

Hold the prompt constant and lower effective transfer bandwidth. Find when handoff erases the assumed scheduling benefit. Then explain why a hot expert can limit the MoE path even when total cluster memory is sufficient.

What must a disaggregated decoder receive before it can continue a request?

Choose one answer, then check your reasoning.

Read the explanation

KV transfer is an explicit dependency. Layout, dtype, configuration, and handoff cost must be validated.

Test the runtime connector before splitting pools

Start with a working colocated baseline. Validate the exact runtime connector, cache dtype/layout, model revision, and cancellation behavior. Measure end-to-end latency and effective transfer throughput under load before choosing pool sizes.

References

Sources checked October 24, 2026. Runtime-specific commands and results apply to the recorded versions; linked rolling documentation can change. The application scenarios are teaching examples, not claims about an author’s production incident.

Written by Arjun Prabhulal.

Module 6

Run at production scale