Quickstart — Slurm#
Slurm mode submits Hyperloom optimization jobs to a Slurm cluster, where each
job launches a ROCm serving container (sglang / vllm) on one node and runs the
inference_optimizer CLI inside it. It is the batch-scheduler counterpart to the
Kubernetes layout in the self-hosting and operations guide,
and suits teams whose AMD GPU fleet is managed by Slurm rather than Kubernetes.
The submission scripts wrap the full flow: resolve the model row → build the sbatch command → start the container → set the gateway host alias → mount the CA bundle → install the optimizer → launch the backend. They never start optimization on the login node; work only runs inside the scheduled job.
The ready-to-use scripts ship under
src/hyperloom/inference_optimizer/assets/slurm/:
File |
Purpose |
|---|---|
|
Generic submitter: validates the model key, wires the config dir, applies cluster overrides, and submits one job per model. |
|
Preset wrapper (MI355X / docker / |
|
The job body: starts the container, sets the gateway host alias, mounts the CA bundle, installs the optimizer, and launches the backend. |
|
Model table (key / repo / framework / image / TP / precision / ISL / OSL / concurrency / model-class / max-hours / target-gain). |
|
Gateway connectivity profile. Copy to |
Prerequisites#
The following table lists the prerequisites and their implications for running Hyperloom on Slurm.
Aspect |
Assumption |
Consequence |
|---|---|---|
Scheduler |
Slurm ( |
— |
Container runtime |
pyxis/enroot or docker |
Auto-detected; override with |
GPU |
AMD Instinct (for example MI355X |
Image and |
Slurm GPU gres |
GPUs might or might not be registered as gres |
If not registered you cannot use |
Shared filesystem |
A cross-node mount (WekaFS, VAST/NFS, …) |
Holds source, artifacts, and the CA bundle. |
LLM gateway |
Reachable directly or through a jump host |
Might need a host alias plus an internal CA. |
Container registry |
Public or private |
A private registry unreachable from compute nodes requires a locally cached image. |
Step 1: Get the scripts#
For a full source checkout, the scripts are already present under the assets directory:
git clone https://github.com/AMD-AGI/Hyperloom.git && cd Hyperloom
cd src/hyperloom/inference_optimizer/assets/slurm
For a standalone setup on a login node, copy that slurm/ directory to a shared
location the scheduler can read (for example /mnt/vast/hyperloom-slurm) and run
submit.sh from there.
Step 2: Configure LLM credentials#
Hyperloom is an LLM-driven agent: the orchestrator and kernel agent call the gateway throughout the run, so a working key and a reachable endpoint are hard requirements (the installer’s preflight enforces them).
Copy the template and fill it in:
cp proxy.env.template proxy.env
In proxy.env, replace the three ak-REPLACE_ME placeholders with your SaFE API
key (issued from the Primus-SaFE LLM Gateway page), and set HL_HOST_ALIAS_IP to
your gateway jump-host IP if the domain does not resolve on compute nodes.
run_hyperloom.sbatch reads proxy.env (not the template) from the same
directory as submit.sh. Verify the key before submitting:
set -a; . ./proxy.env; set +a
# Map your gateway hostname (the one in $OPENAI_BASE_URL) to its jump-host IP.
curl -sS --resolve <your-gateway-host>:443:<GATEWAY_JUMP_HOST_IP> \
"$OPENAI_BASE_URL/models" -H "Authorization: Bearer $OPENAI_API_KEY"
HTTP 200 plus a model list means the key works. Note the model names in the list — they are needed in LLM model-name constraints.
See Authentication and credentials for the full credential model, including the split Anthropic-/OpenAI-compatible provider setup.
Step 3: Prepare cluster access#
Build a combined CA bundle#
If the gateway uses an internal CA, the job still needs to reach
huggingface.co and github.com over public TLS. A CA bundle containing
only the internal certificate makes public TLS fail with
CERTIFICATE_VERIFY_FAILED. Merge the system roots with the internal CA into a
single bundle and point HL_CA_BUNDLE_HOST at it:
cat /etc/ssl/certs/ca-certificates.crt internal-ca.pem > ca-combined.pem
Leave HL_CA_BUNDLE_HOST empty if the container image already trusts every CA
you need.
Confirm the container image is reachable#
If models.tsv references a private registry (a <REGISTRY>/... prefix) that
compute nodes cannot resolve, docker fails with no such host. Either
docker login the reachable registry, or replace the image with a node-local
cached image name (drop the registry prefix). List cached images and match the
variant to the hardware (for example a mi35x build for MI355X):
ssh <node> 'docker images | grep -iE "sglang|vllm"'
Stage the Hyperloom source#
Copy a complete source checkout (src-layout, src/hyperloom/...) to the
shared mount and point submit.sh --source-dir at it to skip the runtime
git clone. It must be a complete snapshot: an old flat layout or a snapshot
missing src/hyperloom/inference_optimizer/cli/ causes ModuleNotFoundError
(see Troubleshooting). If --source-dir is omitted, the job
clones main from GitHub at runtime, which requires GitHub egress on the node.
Step 4: Submit a job#
# Generic (pyxis/enroot or docker auto-detected; requests TP GPUs by default)
./submit.sh deepseek_r1_sglang
# Preset for a docker / /mnt/vast cluster
./submit-vultr.sh deepseek_r1_sglang
# Print the sbatch command without submitting
./submit.sh --dry-run deepseek_r1_sglang
# claude-code backend (the image must ship the claude CLI)
./submit.sh -b claude deepseek_r1_sglang
Example model keys in models.tsv: deepseek_r1_sglang, deepseek_r1_vllm,
gptoss_vllm (edit the file to add your own).
Useful submit.sh options (run ./submit.sh --help for the full list):
Option |
Meaning |
|---|---|
|
Launch backend (default |
|
Slurm partition. |
|
GPUs to request (default: the model’s TP; use |
|
Slurm |
|
Override the optimizer |
|
Shared FS bind-mounted into the container. |
|
Existing Hyperloom checkout to use instead of cloning. |
|
Artifact root (default |
|
Print the sbatch command, do not submit. |
Clusters without GPU gres#
If compute nodes do not register GPUs as Slurm gres (scontrol show node
reports Gres=(null)), any --gpus N>0 request stays PENDING (Resources)
forever. The convention is then “one job takes a whole node; the container grabs
the GPUs directly”:
pass
-g 0so the job requests only a placeholder CPU and lands on the node;submit.shemits--gpusonly when-gis non-zero;run_hyperloom.sbatchcarries no#SBATCH --gpusdirective.
The container still receives every GPU through --device=/dev/kfd --device=/dev/dri, so TP=8 works. If your GPUs are registered as gres
(Gres=gpu:...:8), use the standard --gpus 8 and skip -g 0.
Step 5: Monitor and read artifacts#
squeue -p <partition> # queue
tail -f hyperloom-hl-<key>-<backend>-<jobid>.out # job output (submit dir)
SID=$(ls -t <data-root>/<key> | head -1)
cat <data-root>/<key>/$SID/state.json
The artifact directory <data-root>/<model_key>/<CLAW_SESSION_ID>/ contains:
state.json: live status (baseline_tput,current_best,cumulative_gain);manifest.json: session manifest;ci_metrics.json: baseline/optimized throughput plusgain_pct;optimizer_runs/:launch_<sid>.jsonand logs;runtime/:kernel-agent.env.shand other files produced by the installer.
A healthy run logs, in order: container start → install complete → framework root
discovery (sglang=ok aiter=ok) → model gate passed → Ray head (--num-gpus=8)
→ model load → baseline throughput → optimization iterations. GPU memory and
utilization ramp up only after the model-load step.
LLM model-name constraints#
The job calls the gateway for orchestration and for the kernel agent (GEAK). Model names must exist in your key’s catalog, and the orchestration model is hard-allowlisted:
Use |
Environment variable |
Allowed values |
Notes |
|---|---|---|---|
Orchestration |
|
|
Enforced by the optimizer’s model gate; other names are rejected. |
Kernel agent (GEAKv4 Claude Code workflow) |
|
for example |
Defaults from |
Codex / external |
|
for example |
Use a gpt/codex-family model. |
Do not use suffixed variants (for example
claude-opus-4-7-thinking-xhigh); the gateway returnsInvalid model name(which can surface misleadingly as401 missing subscription key).To use an orchestration model outside the allowlist, set
INFERENCE_OPTIMIZER_ALLOW_CUSTOM_ORCH_MODEL=1(this switches to catalog validation). Not recommended.These variables are set in
proxy.envand are on the docker-eallowlist inrun_hyperloom.sbatch. If you add a new model variable, add it to that allowlist too, or it will not reach the container.
Tunable environment variables#
Variable |
Default |
Meaning |
|---|---|---|
|
|
docker |
|
|
Force |
|
— |
Override |
|
|
Shared FS bind-mounted into the container. |
|
|
Artifact root. |
|
— |
Combined CA bundle path (see Build a combined CA bundle). |
|
unset |
Set |
Troubleshooting#
The following items address common Slurm job and cluster configuration problems.
Job stuck
PD (Resources)while the node isidle: the node has no GPU gres, so--gpuscan never be satisfied. Submit with-g 0and confirm there is no#SBATCH --gpus(see Clusters without GPU gres).docker: ... no such hostwhen pulling the image: the private registry is unreachable from the node. Use a node-cached local image name, ordocker logina reachable registry.CERTIFICATE_VERIFY_FAILED: unable to get local issuer(huggingface/github): the CA bundle has only the internal cert. Use a combined CA bundle.ModuleNotFoundError: No module named '...cli': the source snapshot is incomplete or an old layout. Stage a complete src-layout checkout (src/hyperloom/...).--gpu-type: invalid choice: 'MI355X': the CLI is case-sensitive. Use lowercase (for examplemi355x;submit-vultr.shalready does).--claude-model=... is not allowed: the orchestration model is not in the allowlist. Useclaude-opus-4-8for orchestration.Invalid model name/401 missing subscription key: the model name is not in the key catalog (often a suffixed variant). Use a name fromcurl $OPENAI_BASE_URL/models.Server fails to start / OOM in shm:
/dev/shmis too small. RaiseHL_SHM_SIZE(default64g).DNS failure / connection timeout to the gateway: the host alias was not applied. The docker path uses
--add-host; confirm the node can reach the jump host on:443.
Suggested triage order: GPU gres → image reachability → combined CA → complete source → gpu-type casing → orchestration-model allowlist.
Known limitations#
The following are known limitations of the Slurm integration.
A source snapshot without
.git(a plain rsync copy) leavescode_revisionempty inmanifest.json. Sync with.gitif you need provenance.The docker path exposes all node GPUs to the container, so TP=8 occupies a whole node. Running multiple jobs per node requires isolating devices with
HIP_VISIBLE_DEVICES/ROCR_VISIBLE_DEVICES(the scripts do not do this).The installer pip-installs Magpie and clones InferenceX / GEAK / TraceLens from GitHub, so nodes need GitHub egress. A fully offline setup must bake these into the image and pre-stage model weights on the shared mount.
If the gateway’s upstream lacks subscription credentials, real completions might return
missing subscription keyeven though listing models and auth succeed; that is a gateway-side issue.