# Purpose: every setting the Part 22 scripts read. Copy this file to `.env` beside the # scripts and fill in the empty lines for your own machines. Nothing here is a # secret except the Hugging Face token, which you generate rather than copy and # which is better exported in your shell than written here. # Platform: all # Minimum memory: 24 GB per machine for the two-machine path; 16 GB for the single-machine # path and for the offload lab # Assumes: `cp env-example.txt .env`, then an editor. Every script loads it with # `set -a; . ./.env; set +a` when the file is present, so a value already set in # your shell always wins over a value in the file. # # Part 18's own .env already holds CLUSTER_IFACE, CLUSTER_PEERS, MODELS_DIR and LABBOOK. # The names below are deliberately identical: copy your values across, or source Part 18's # .env first and this one after it, and delete the duplicated lines. # ------------------------------------------------------------------- the two machines # The name of the machine that will do PREFILL, and the name of the machine that will do # DECODE, as the other machines can resolve them. RFC 8375 reserves everything under # `home.arpa` for names that mean something inside one house and nothing outside it, so # names like `node-a.home.arpa` are exactly the intended use. Where a machine has a direct # cable as well as a house connection, use its "-direct" name here: the name you type is # what decides which cable the key-value cache crosses. # # PREFILL_HOST=node-a-direct.home.arpa # DECODE_HOST=node-b-direct.home.arpa # # Leave BOTH empty for the single-machine path; the scripts then use the loopback address # and say so in the notebook line. PREFILL_HOST= DECODE_HOST= # The address THIS machine advertises for the connector handshake, when you are using a # point-to-point connector. It must be an address the other machine can reach, which on a # cluster with a direct cable is the address on the cable and not the one on the switch. # Leave empty on the single-machine path. SIDE_CHANNEL_ADDR= # Distinct handshake ports. Two instances on ONE host must not share one. PREFILL_SIDE_CHANNEL_PORT=5600 DECODE_SIDE_CHANNEL_PORT=5601 # The interface that carries cluster traffic on THIS machine, from Part 18's lab. The # scripts read its byte counters around each load test, and pass it to the transfer # library so that it does not pick the management interface on its own. # Linux ip -br addr e.g. enp1s0f1np1, eno1, enp5s0 # macOS networksetup -listallhardwareports e.g. en0, en5 CLUSTER_IFACE= # ---------------------------------------------------------------------- the connector # Which connector the two instances use. The scripts accept: # shared ExampleConnector over a directory both machines can read and write. # Needs no RDMA, no UCX and no handshake. Start here. # nixl NixlConnector, point to point over UCX. Wants RDMA to be worth doing. # mooncake MooncakeConnector. Needs the mooncake-transfer-engine package. CONNECTOR=shared # For CONNECTOR=shared only: a directory BOTH machines can read and write, on the shared # mount from Part 18. It fills up with key-value blocks; put it somewhere you can delete. KV_SHARED_PATH= # ---------------------------------------------------------------------------- models # The model both instances load. They must load the SAME one: two instances that disagree # about the model, the quantisation or the block size produce blocks the other cannot use, # and the symptom is a silent miss rather than an error. # Qwen3-8B is Apache-2.0 and ungated; at bf16 it needs roughly 17 GB for weights alone, so # use it on the 24 GB path and drop to Qwen3-1.7B for two processes on one small device. MODEL=Qwen/Qwen3-8B # The smaller model for the single-machine path, where one device is split between two # engine processes. Qwen3-1.7B is Apache-2.0. SMALL_MODEL=Qwen/Qwen3-1.7B # The name clients send in the "model" field. Keep it identical on every path so the load # generator's command line never changes between runs. SERVED_NAME=local-chat # Where models are cached on this machine. Part 18's shared library, or a local path. HF_HOME= # --------------------------------------------------------------------------- serving # Ports. The proxy is the only one a client should ever talk to. PREFILL_PORT=8100 DECODE_PORT=8200 PROXY_PORT=8000 # Where the engines bind. Keep this on the loopback address or on your cluster address; # nothing in this part authenticates anything. SERVE_HOST=127.0.0.1 # Context length to allocate, and how many sequences may be in flight. Both instances must # use the same context length. CTX=8192 MAX_SEQS=8 # Fraction of the device each instance may claim. On the single-machine path the two # processes share one device, so this must be well below half for each of them. MEM_FRACTION=0.85 SPLIT_MEM_FRACTION=0.40 # ------------------------------------------------------------- the offload lab (lab 2) # Gibibytes of host memory the engine may use as a key-value tier. Start small: this is # host memory taken away from everything else on the machine. KV_OFFLOAD_GB=8 # Backend for that tier, as the vllm serve CLI reference documents it: "native" for vLLM's # own host-memory offloading, or "lmcache" if you have installed LMCache. KV_OFFLOAD_BACKEND=native # For the llama.cpp reduced path on Tracks X and M: the GGUF file, the number of slots and # where saved slot caches are written. LLAMA_MODEL= LLAMA_PORT=8080 LLAMA_PARALLEL=2 LLAMA_SLOT_SAVE_PATH=./slot-cache LLAMA_CACHE_TYPE=q8_0 # ------------------------------------------------------------------ the load generator # Part 9's load-test.py. Give the path to it; the wrapper refuses to run without it rather # than reimplementing a load generator that already exists. LOAD_TEST=../part-09-vllm-and-sglang/load-test.py # Concurrency levels and requests per level for every run in this part. Keep them the same # across runs or the comparison means nothing. CONCURRENCY=1,4,8 REQUESTS=24 MAX_TOKENS=128 # The prompt set. "shared-prefix" is the workload a phase split is aimed at: a long shared # preamble with a short different question. "mixed" is the control. PROMPT_SET=shared-prefix # Where every script appends its JSON line. The lab notebook from Part 1. LABBOOK=labbook.md # --------------------------------------------------------------------------- secrets # Gated models need a Hugging Face token. Export it in your shell rather than writing it # here if you can; if you do put it here, keep .env out of version control. HF_TOKEN= # The load generator reads an API key, if your server needs one, from the variable named # here. It is never written to the notebook. LOADTEST_API_KEY_ENV=LOADTEST_API_KEY