Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
**/*cache*/
# venv
venv/
.venv/

# python cache
__pycache__/
*.pyc

# generic caches
**/*cache*/

*.*/
#files
images/

Dockerfile
# logs (optional but recommended)
.logs/
.config/
36 changes: 35 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,16 @@ Purpose:
* Preserve downloaded models between runs
* Avoid repeated downloads across container executions

### `.cache/vllm/` and `.cache/triton/`

These directories are mounted into Docker containers to persist vLLM and Triton compile caches.

Purpose:

* Reduce repeated `torch.compile` and CUDA graph capture time across runs
* Make Strix Halo profiling runs closer to steady-state behavior after the first cold start
* Improve repeatability when comparing baselines across models

---

### `.config/`
Expand Down Expand Up @@ -145,7 +155,13 @@ Run directly on the host system:
* `generate_gpu_yaml.sh`
Helper script to auto-generate a `gpus.yaml` template

**NOTE**: *This script is currently defunct and you will have to create your own .yaml config based on the one provided in the README and your own setup*
Usage:

```bash
scripts/host/generate_gpu_yaml.sh
```

This generates `.config/gpus.yaml` from the local `/dev/dri/renderD*` devices.

* Future host utilities will also live here

Expand Down Expand Up @@ -209,3 +225,21 @@ Notes:
* Improved automation and validation
* Expanded profiling support
* Potential non-Linux support

---

## Portability Notes

* Host scripts now resolve workspace paths from the repository root, so running commands from different working directories is supported.
* Use `disabled_on` in `yaml/models.yaml` to prevent known-problematic models on specific devices.

Example:

```yaml
models:
- name: Qwen/Qwen3-VL-4B-Instruct
type: multimodal
script: qwen_vl.py
disabled_on:
- Strix Halo
```
46 changes: 33 additions & 13 deletions scripts/host/docker_tool.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ def prepare_env():

def run_container(args, script_args):
env = prepare_env()
hf_cache_dir = Path(args.hf_cache_dir)
if not hf_cache_dir.is_absolute():
hf_cache_dir = (ROOT_DIR / hf_cache_dir).resolve()

cmd = [
"docker",
"run",
Expand Down Expand Up @@ -81,34 +85,50 @@ def run_container(args, script_args):

# huggingface cache dir
hf_cache_container = "/root/.cache/huggingface"
Path(args.hf_cache_dir).mkdir(parents=True, exist_ok=True)
cmd.extend(["-v", f"{args.hf_cache_dir}:{hf_cache_container}"])
print(f"Mounting HuggingFace cache: {args.hf_cache_dir} -> {hf_cache_container}")
hf_cache_dir.mkdir(parents=True, exist_ok=True)
cmd.extend(["-v", f"{hf_cache_dir}:{hf_cache_container}"])
print(f"Mounting HuggingFace cache: {hf_cache_dir} -> {hf_cache_container}")

# vLLM and Triton compile caches
cache_mounts = {
"/root/.cache/vllm": ROOT_DIR / ".cache" / "vllm",
"/root/.cache/triton": ROOT_DIR / ".cache" / "triton",
}
for container_cache_dir, host_cache_dir in cache_mounts.items():
host_cache_dir.mkdir(parents=True, exist_ok=True)
cmd.extend(["-v", f"{host_cache_dir}:{container_cache_dir}"])
print(f"Mounting cache: {host_cache_dir} -> {container_cache_dir}")

# local container scripts dir
scripts_container = str(container_workspace / "scripts")
cmd.extend(["-v", f"./scripts/container:{scripts_container}"])
print(f"Mounting ./scripts/container -> {scripts_container}")
host_scripts_dir = ROOT_DIR / "scripts" / "container"
cmd.extend(["-v", f"{host_scripts_dir}:{scripts_container}"])
print(f"Mounting {host_scripts_dir} -> {scripts_container}")

# local prompts dir
prompts_container = str(container_workspace / "prompts")
cmd.extend(["-v", f"./prompts:{prompts_container}"])
print(f"Mounting ./prompts -> {prompts_container}")
host_prompts_dir = ROOT_DIR / "prompts"
cmd.extend(["-v", f"{host_prompts_dir}:{prompts_container}"])
print(f"Mounting {host_prompts_dir} -> {prompts_container}")

# logs dir
logs_container = str(container_workspace / "logs")
cmd.extend(["-v", f"./.logs:{logs_container}"])
print(f"Mounting ./.logs -> {logs_container}")
host_logs_dir = ROOT_DIR / ".logs"
host_logs_dir.mkdir(parents=True, exist_ok=True)
cmd.extend(["-v", f"{host_logs_dir}:{logs_container}"])
print(f"Mounting {host_logs_dir} -> {logs_container}")

# images dir
images_container = str(container_workspace / "images")
cmd.extend(["-v", f"./images:{images_container}"])
print(f"Mounting ./images -> {images_container}")
host_images_dir = ROOT_DIR / "images"
cmd.extend(["-v", f"{host_images_dir}:{images_container}"])
print(f"Mounting {host_images_dir} -> {images_container}")

# yaml dir
yaml_container = str(container_workspace / "yaml")
cmd.extend(["-v", f"./yaml:{yaml_container}"])
print(f"Mounting ./yaml -> {yaml_container}")
host_yaml_dir = ROOT_DIR / "yaml"
cmd.extend(["-v", f"{host_yaml_dir}:{yaml_container}"])
print(f"Mounting {host_yaml_dir} -> {yaml_container}")

shell_cmd = []

Expand Down
63 changes: 33 additions & 30 deletions scripts/host/generate_gpu_yaml.sh
Original file line number Diff line number Diff line change
@@ -1,33 +1,36 @@
#!/usr/bin/env bash

echo "THE SCRIPT generate_gpu_yaml.sh IS CURRENTLY DEFUNCT"
echo "GENERATE THE FILE MANUALLY"
echo "EXAMPLE:"
echo "gpus:
0:
name: Radeon RX 7900 XTX
device: /dev/dri/renderD128
1:
name: AMD Radeon RX 9070 XT
device: /dev/dri/renderD129
2:
name: AMD Radeon RX 6700 XT
device: /dev/dri/renderD130"
# TODO: ENABLE USING ROCMINFO

exit 1

echo "gpus:"

i=0
for dev in /dev/dri/renderD*; do
name=$(udevadm info --query=property --name="$dev" \
| grep ID_MODEL= \
| cut -d= -f2)

echo " gpu$i:"
echo " name: ${name:-unknown}"
echo " device: $dev"

((i++))
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
OUT_FILE="${ROOT_DIR}/.config/gpus.yaml"

mkdir -p "${ROOT_DIR}/.config"

mapfile -t render_devices < <(ls /dev/dri/renderD* 2>/dev/null | sort || true)

if [[ ${#render_devices[@]} -eq 0 ]]; then
echo "No /dev/dri/renderD* devices found; cannot generate ${OUT_FILE}" >&2
exit 1
fi

echo "gpus:" > "${OUT_FILE}"

for dev in "${render_devices[@]}"; do
name=$(udevadm info --query=property --name="$dev" 2>/dev/null \
| awk -F= '/^ID_MODEL_FROM_DATABASE=/{print $2; found=1; exit} /^ID_MODEL=/{if (!found) print $2}' \
| sed 's/_/ /g' \
|| true)

if [[ -z "${name}" ]]; then
name="${dev##*/}"
fi

cat >> "${OUT_FILE}" <<EOF
- name: "${name}"
device: "${dev}"
disabled: false
EOF
done

echo "Generated ${OUT_FILE} with ${#render_devices[@]} GPU device(s)."
11 changes: 9 additions & 2 deletions scripts/host/orchestrator.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from pathlib import Path
import yaml
import os
import sys

PROJECT_ROOT = Path(__file__).parent.parent.parent

Expand All @@ -32,7 +33,11 @@ def prepare_tokens():
def parse_gpus():
file_path = PROJECT_ROOT / ".config" / "gpus.yaml"
if not file_path.exists():
subprocess.run(["generate_gpu_yaml.sh"], check=True)
subprocess.run(
[str(PROJECT_ROOT / "scripts" / "host" / "generate_gpu_yaml.sh")],
check=True,
cwd=PROJECT_ROOT,
)
with file_path.open("r") as f:
return [
gpu for gpu in yaml.safe_load(f)["gpus"] if not gpu.get("disabled", False)
Expand Down Expand Up @@ -102,7 +107,8 @@ def run(docker_image, num_procs, script, duration, iterations, models_filter):
]
result = subprocess.run(
[
"scripts/host/docker_tool.py",
sys.executable,
str(PROJECT_ROOT / "scripts" / "host" / "docker_tool.py"),
"run",
"--image-name",
docker_image,
Expand All @@ -116,6 +122,7 @@ def run(docker_image, num_procs, script, duration, iterations, models_filter):
]
+ script_args,
env=os.environ.copy() | env,
cwd=PROJECT_ROOT,
)


Expand Down
1 change: 1 addition & 0 deletions yaml/env_vars.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ env_vars:
- NCCL_NVLS_ENABLE
- TORCH_NCCL_AVOID_RECORD_STREAMS
- PYTORCH_CUDA_ALLOC_CONF
- PYTORCH_ALLOC_CONF
4 changes: 3 additions & 1 deletion yaml/models.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ models:
- name: Qwen/Qwen3-VL-4B-Instruct
type: multimodal
script: qwen_vl.py
disabled_on:
- Strix Halo
env:
VLLM_WORKER_MULTIPROC_METHOD: 'spawn'
MAX_MODEL_LEN: '20000'
MAX_MODEL_LEN: '2048'
SP_TEMPERATURE: '0.0'
SP_MAX_TOKENS: '1024'
# - name: deepseek-ai/DeepSeek-OCR
Expand Down