N5 Max: Proxmox Strix Halo with Docker, ROCm FP4 and MTP - Ultimate Setup Guide

Strix Halo ROCmFP4 + MTP LLM Inference Guide

Hardware: AMD Ryzen AI MAX+ 395 (16C/32T) + Radeon 8060S (gfx1151) + 64 GB unified memory
MINISFORUM N5 MAX AI NAS | AMD Ryzen AI Max+ 395 | 126 TOPS NPU | Radeon™ 8060S graphics

Last tested: 2026-06-06 (Proxmox VE 9.1.1, kernel 6.17.2-1-pve, ROCm 7.2.1)

Background

TODO: video goes here, explainer

My vision for this is to have an “all-in-one” home appliance for AI, Virtual Machines, internet ingress/egress (experimenting with Pangolin on this currently, maybe for a future video).. Home Assistant.. you name it. In a nutshell we’re using Proxmox as our NAS OS then setting up an LXC with full access to the underlying hardware for AI workloads via Docker! The best of both worlds. Or something.

This thing is a beast for any use case.

Models tested:

  • Qwopus3.6-27B-v2 (ROCmFP4, 14 GB),
  • Qwen3.6-27B (Q8_0, ~27 GB)
  • TODO?

Table of Contents

  1. Overview & What’s New
  2. Architecture Overview
  3. Prerequisites & System Inventory
  4. Phase 1: Proxmox Host Preparation
  5. Phase 2: Kernel Boot Parameters (Critical)
  6. Phase 3: Create the LXC Container
  7. Phase 4: GPU Passthrough to LXC
  8. Phase 5: ROCm Installation (Inside LXC)
  9. Phase 6: Build the ROCmFP4 llama.cpp Fork
  10. Phase 7: Build Stock llama.cpp (for Q8 baseline)
  11. Phase 8: Download Models
  12. Phase 9: Run Inference
  13. Phase 10: Benchmarks
  14. vLLM Docker Setup (Alternative Backend)
  15. Troubleshooting
  16. Reference: Key Community Resources

1. Overview & What’s New

This guide covers running ROCmFP4-quantized models (a custom 4-bit format with native FP4 tensor layouts optimized for AMD GPUs) on Strix Halo hardware using a custom llama.cpp fork with Multi-Token Prediction (MTP) support.

Most of the work was done on the Minisforum N5 Max NAS, but I also validated on the GMK Tek Strix Halo, The Minisforum S1 Max and The Framework Desktop Strix Halo machine they offer.

This was quite an adventure to get setup. Many thinks to kyz0 and other resources linked throughout this guide.

What’s different from standard llama.cpp ROCm guides:

Feature Standard ROCm guide This guide
Model format Standard GGUF (Q4_K_M, Q8_0, etc.) ROCmFP4 custom 4-bit GGUF
llama.cpp fork ggml-org/llama.cpp charlie12345/rocmfp4-llama (branch mtp-rocmfp4-strix)
MTP support No Yes — speculative decoding via draft-MTP
HSA_OVERRIDE_GFX_VERSION 11.0.0 (maps gfx1151→gfx1100) 11.5.1 (native gfx1151 FP4 support)
GGML_HIP_ENABLE_UNIFIED_MEMORY Not needed Required for models > 2 GB
-dio flag Required Required for models > ~6 GB
ulimit -l unlimited Not mentioned Required — ROCm locks GPU memory
setsid wrapper Not needed Needed inside lxc-attach shells

2. Architecture Overview

Proxmox Host (kernel 6.17.2-1-pve)
  ├── amdgpu.ko (in-tree, gfx1151 support)
  ├── /dev/dri/card1       ───┐
  ├── /dev/dri/renderD128  ───┤── LXC bind-mount
  ├── /dev/kfd             ───┤
  └── /dev/accel/accel0    ───┘  (NPU — not used for LLM today)
        │
  LXC Container (Ubuntu 24.04, privileged, 56 GB RAM)
    ├── ROCm 7.2.1 userspace (no DKMS — host kernel has drivers)
    ├── rocmfp4-llama fork (built for gfx1151 + ROCmFP4)
    ├── stock llama.cpp (for Q8 baseline comparisons)
    ├── Docker (for vLLM ROCm container)
    └── Models:
        ├── Qwopus3.6-27B-v2-MTP-ROCmFP4 (14 GB)
        └── Qwen3.6-27B-Q8_0 (~27 GB)

3. Prerequisites & System Inventory

Hardware Requirements

Component Minimum Recommended
CPU Ryzen AI 300 series Ryzen AI MAX+ 395
RAM 32 GB 64 GB (128 GB for 70B models)
Proxmox 8.x 9.1+ (Debian 13 base)
Kernel 6.14+ 7+ (Proxmox v9 Kernel 7 series)
Storage 100 GB free 300 GB+ (for multiple models + builds)

Verify your hardware

# CPU
cat /proc/cpuinfo | grep "model name" | head -1

# GPU (should show Radeon 8060S)
lspci | grep -i display

# RAM
grep MemTotal /proc/meminfo

# GPU device nodes
ls -la /dev/dri/* /dev/kfd /dev/accel/accel0

# Kernel version
uname -r

# Proxmox version
pveversion

Expected output

model name : AMD RYZEN AI MAX+ 395 w/ Radeon 8060S
90:00.0 Display controller: AMD/ATI Strix Halo [Radeon 8060S Graphics]
MemTotal:       63407216 kB  (~60.5 GB)
crw-rw---- 1 root render 226, 128 /dev/dri/renderD128
crw-rw---- 1 root render 234,   0 /dev/kfd
6.17.2-1-pve
pve-manager/9.1.1

4. Phase 1: Proxmox Host Preparation

4.1 Enable the no-subscription repository

# Disable the enterprise repo (which will 401 without a subscription key)
rm /etc/apt/sources.list.d/pve-enterprise.sources

# Add the no-subscription repo
cat > /etc/apt/sources.list.d/pve-no-subscription.sources << 'EOF'
Types: deb
URIs: http://download.proxmox.com/debian/pve
Suites: trixie
Components: pve-no-subscription
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
EOF

# Also fix the Ceph repo to use no-subscription
cat > /etc/apt/sources.list.d/ceph.sources << 'EOF'
Types: deb
URIs: http://download.proxmox.com/debian/ceph-squid
Suites: trixie
Components: no-subscription
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
EOF

apt update

4.2 Install necessary tools

apt install -y curl wget pve-headers build-essential

5. Phase 2: Kernel Boot Parameters (Critical)

5.1 Why these parameters

The Strix Halo GPU (gfx1151) needs explicit boot parameters to access all 64 GB of unified memory. Without these, ROCm memory allocation is severely limited.

Parameter Purpose
amd_iommu=off Disables IOMMU for the GPU. Required for the GPU to access all system RAM as unified memory. Without this, ROCm memory allocation is capped at ~2 GB.
amdgpu.gttsize=131072 Sets the GTT (Graphics Translation Table) size to 128 GB. This is a ceiling — it tells the GPU it can map up to 128 GB of system RAM. On a 64 GB system, this effectively enables full unified memory access. The value is in megabytes: 131072 MB = 128 GB.
ttm.pages_limit=31457280 Increases the TTM (Translation Table Manager) page limit. Prevents allocation failures when loading large models. Value = number of 4 KB pages.

Note on GTT sizing: The system has ~60.5 GB of usable RAM. Setting gttsize=131072 (128 GB) is safe — it’s just an upper bound. The GPU will only use what’s physically available. For a 64 GB system, a value of ~57344 (56 GB) would also work, but 131072 is harmless and future-proofs the config for systems with more RAM.

5.2 Apply the parameters

sed -i 's/GRUB_CMDLINE_Linux_DEFAULT="quiet"/GRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=off amdgpu.gttsize=131072 ttm.pages_limit=31457280"/' /etc/default/grub
update-grub
reboot

5.3 Verify after reboot

# Check GTT size (should be ~128 GB)
cat /sys/class/drm/card1/device/mem_info_gtt_total
# Expected: 137438953472 (128 GB)

# Check boot params applied
cat /proc/cmdline | grep -o 'amdgpu.gttsize=[^ ]*\|amd_iommu=[^ ]*\|ttm.pages_limit=[^ ]*'
# Expected: amd_iommu=off amdgpu.gttsize=131072 ttm.pages_limit=31457280

# Verify /dev/kfd exists
ls -la /dev/kfd

6. Phase 3: Create the LXC Container

6.1 Choose a template

Ubuntu 24.04 is recommended over Debian 13 for ROCm compatibility:

pveam available | grep ubuntu-24
pveam download local ubuntu-24.04-standard_24.04-2_amd64.tar.zst

6.2 Create the container

Must be privileged for GPU device access:

CT_ID=100
CT_HOSTNAME=strix-ai
CT_STORAGE=local-lvm

pct create $CT_ID local:vztmpl/ubuntu-24.04-standard_24.04-2_amd64.tar.zst \
  --storage $CT_STORAGE \
  --memory 57344 \
  --swap 0 \
  --cores 16 \
  --unprivileged 0 \
  --hostname $CT_HOSTNAME \
  --net0 name=eth0,bridge=vmbr0,ip=dhcp \
  --rootfs $CT_STORAGE:100 \
  --features nesting=1

Resource notes:

  • --memory 57344 — 56 GB RAM (leaves ~4 GB for Proxmox host)
  • --swap 0 — No swap. With unified memory, swapping would thrash the GPU.
  • --cores 16 — All 16 physical cores.
  • --unprivileged 0 — Privileged container. Required for GPU device nodes to have correct ownership.
  • --rootfs 100 — 100 GB minimum. 300 GB recommended if storing models locally.

6.3 Start and set up

pct start $CT_ID
pct enter $CT_ID

# Inside the container
apt update && apt upgrade -y
apt install -y curl wget git build-essential cmake python3 python3-pip sudo

7. Phase 4: GPU Passthrough to LXC

7.1 Identify device nodes on the host

From the Proxmox host:

ls -la /dev/dri/* /dev/kfd

Expected:

crw-rw---- 1 root video  226,   1 /dev/dri/card1
crw-rw---- 1 root render 226, 128 /dev/dri/renderD128
crw-rw---- 1 root render 234,   0 /dev/kfd

Note the render group GID:

getent group render
# Output: render:x:993:

7.2 Add device passthrough to container config

Edit /etc/pve/lxc/$CT_ID.conf on the Proxmox host:

cat >> /etc/pve/lxc/$CT_ID.conf << 'EOF'

# GPU device nodes (use wildcard for major 226 to cover all minors)
lxc.cgroup2.devices.allow: c 226:* rwm
lxc.cgroup2.devices.allow: c 234:* rwm

# Mount GPU devices into container
lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir
lxc.mount.entry: /dev/kfd dev/kfd none bind,optional,create=file
EOF

7.3 Restart and verify

# On the host
pct stop $CT_ID
pct start $CT_ID

# Inside the container
pct enter $CT_ID
ls -la /dev/dri/* /dev/kfd
# Should show root:render and root:video ownership

8. Phase 5: ROCm Installation (Inside LXC)

8.1 Add the AMD ROCm repository

wget -q -O - https://repo.radeon.com/rocm/rocm.gpg.key | gpg --dearmor > /etc/apt/trusted.gpg.d/rocm.gpg

# Ubuntu 24.04 (noble) — use ROCm 7.2.1 which has noble support
echo "deb [arch=amd64] https://repo.radeon.com/rocm/apt/7.2.1 noble main" > /etc/apt/sources.list.d/rocm.list

# Pin ROCm packages to prefer the AMD repo
cat > /etc/apt/preferences.d/rocm-pin << 'EOF'
Package: *
Pin: release o=repo.radeon.com
Pin-Priority: 600
EOF

apt update

8.2 Install ROCm userspace (no DKMS)

Critical: Do NOT install rocm-dkms. The amdgpu and amdkfd drivers are already in the Proxmox host kernel.

apt install -y rocm-hip-sdk rocwmma-dev

Also install Vulkan SDK (needed by the ROCmFP4 fork build):

apt install -y libvulkan-dev vulkan-tools

8.3 Set up memlock limits (Critical!)

ROCm needs to lock GPU memory pages. The default ulimit is 8 MB — far too low for LLM models:

# Add to /etc/security/limits.conf
echo 'root soft memlock unlimited' >> /etc/security/limits.conf
echo 'root hard memlock unlimited' >> /etc/security/limits.conf

# Apply for current session
ulimit -l unlimited

8.4 Verify ROCm

/opt/rocm/bin/rocminfo

Expected output should show:

Name:                    gfx1151
Marketing Name:          Radeon 8060S Graphics
Compute Unit:            40
Max Clock Frequency:     2900 MHz

Pool Info:
  Segment:               GLOBAL; FLAGS: COARSE GRAINED
  Size:                  125829120 KB  (120 GB GTT — full unified memory)

Also check:

/opt/rocm/bin/rocm-smi

9. Phase 6: Build the ROCmFP4 llama.cpp Fork

9.1 Clone the fork

cd /root
git clone https://github.com/charlie12345/rocmfp4-llama.git
cd rocmfp4-llama
git checkout mtp-rocmfp4-strix

9.2 Build

export PATH=/opt/rocm/bin:/opt/rocm/llvm/bin:$PATH
export HIP_PATH=/opt/rocm
export ROCM_PATH=/opt/rocm
export ROCM_WMMA_INCLUDE=/opt/rocm/include
export GGML_HIP_ROCWMMA_FATTN=ON
export CMAKE_HIP_ARCHITECTURES=gfx1151
export JOBS=$(nproc)

# The build script references a custom rocWMMA path; we set ROCM_WMMA_INCLUDE
# to point to the standard ROCm install location instead.
bash scripts/build-strix-rocmfp4-mtp.sh

Note: The build script enables Vulkan by default, which requires libvulkan-dev. If you get Vulkan compilation errors (e.g., spv namespace issues), reconfigure with -DGGML_VULKAN=OFF:

cmake -S . -B build-strix-rocmfp4 \
  -DCMAKE_BUILD_TYPE=Release \
  -DGGML_HIP=ON \
  -DGGML_HIP_ROCWMMA_FATTN=ON \
  -DGGML_HIP_FORCE_MMQ=ON \
  -DGGML_VULKAN=OFF \
  -DGGML_CUDA=OFF \
  -DCMAKE_HIP_ARCHITECTURES=gfx1151 \
  -DLLAMA_BUILD_SERVER=ON
cmake --build build-strix-rocmfp4 -j$(nproc) --target llama-cli llama-server llama-bench

9.3 Verify

HSA_OVERRIDE_GFX_VERSION=11.5.1 \
GGML_HIP_ENABLE_UNIFIED_MEMORY=1 \
./build-strix-rocmfp4/bin/llama-cli --list-devices

Expected:

Available devices:
  ROCm0: Radeon 8060S Graphics (122880 MiB, 4096 MiB free)

10. Phase 7: Build Stock llama.cpp (for Q8 baseline)

For comparing ROCmFP4 against standard quantization formats:

cd /root
git clone https://github.com/ggml-org/llama.cpp.git stock-llama
cd stock-llama

HIPCXX="$(hipconfig -l)/clang" \
HIP_PATH="$(hipconfig -R)" \
cmake -S . -B build \
  -DGGML_HIP=ON \
  -DGPU_TARGETS=gfx1151 \
  -DGGML_HIP_ROCWMMA_FATTN=ON \
  -DGGML_HIP_NO_VMM=ON \
  -DGGML_HIP_MMQ_MFMA=ON \
  -DCMAKE_BUILD_TYPE=Release

cmake --build build --config Release -j$(nproc) --target llama-cli llama-server llama-bench llama-perplexity

11. Phase 8: Download Models

11.1 ROCmFP4 Model (14 GB)

mkdir -p /models/rocmfp4
cd /models/rocmfp4

wget 'https://huggingface.co/jcbtc/qwopus3.6-27b-v2-chadrock-rocmfp4-mtp/resolve/main/Qwopus3.6-27B-v2-MTP-BF16-to-ROCmFP4-STRIX_LEAN.gguf'

# Optional: vision projection model
wget 'https://huggingface.co/jcbtc/qwopus3.6-27b-v2-chadrock-rocmfp4-mtp/resolve/main/mmproj-F32.mmproj'

Expected SHA256: 1f1c0a9d63b9b38b06fe... (verify after download)

11.2 Qwen3.6-27B Q8 Baseline (~27 GB)

mkdir -p /models/qwen36-27b
cd /models/qwen36-27b

wget 'https://huggingface.co/bartowski/Qwen_Qwen3.6-27B-GGUF/resolve/main/Qwen3.6-27B-Q8_0.gguf'

11.3 Qwen3.6-27B Q4_K_M (~16 GB, optional additional baseline)

wget 'https://huggingface.co/bartowski/Qwen_Qwen3.6-27B-GGUF/resolve/main/Qwen3.6-27B-Q4_K_M.gguf'

12. Phase 9: Run Inference

12.1 Critical: The setsid Workaround

When running llama-cli inside an lxc-attach shell, the process receives SIGTTOU when trying to set terminal attributes because it’s not the foreground process group. Always use setsid -w to create a new session:

# Inside the container via lxc-attach
setsid -w bash -c '
ulimit -l unlimited
HSA_OVERRIDE_GFX_VERSION=11.5.1 \
GGML_HIP_ENABLE_UNIFIED_MEMORY=1 \
/root/rocmfp4-llama/build-strix-rocmfp4/bin/llama-cli \
  -m /models/rocmfp4/Qwopus3.6-27B-v2-MTP-BF16-to-ROCmFP4-STRIX_LEAN.gguf \
  -ngl 999 \
  -fa on \
  -dio \
  -p "Your prompt here." \
  -n 200
'

Alternatively, if you pct enter the container and run interactively (not via lxc-attach), the setsid wrapper is not needed.

12.2 ROCmFP4 Model with MTP (Full Config)

HSA_OVERRIDE_GFX_VERSION=11.5.1 \
GGML_HIP_ENABLE_UNIFIED_MEMORY=1 \
/root/rocmfp4-llama/build-strix-rocmfp4/bin/llama-server \
  -m /models/rocmfp4/Qwopus3.6-27B-v2-MTP-BF16-to-ROCmFP4-STRIX_LEAN.gguf \
  --mmproj /models/rocmfp4/mmproj-F32.mmproj \
  --alias qwopus3.6-27b-v2-chadrock \
  --host 127.0.0.1 \
  --port 8080 \
  --jinja \
  -c 262144 \
  -ngl 999 \
  -fa on \
  -dev ROCm0 \
  -b 512 \
  -ub 512 \
  -t 16 \
  -tb 32 \
  -ctk q4_0 \
  -ctv q4_0 \
  --spec-type draft-mtp \
  --spec-draft-device ROCm0 \
  --spec-draft-ngl all \
  --spec-draft-type-k q4_0 \
  --spec-draft-type-v q4_0 \
  --spec-draft-n-max 4 \
  --spec-draft-n-min 0 \
  --spec-draft-p-min 0.0 \
  --spec-draft-p-split 0.10 \
  --parallel 1 \
  --metrics \
  --no-mmap

12.3 Q8 Baseline (Stock llama.cpp)

HSA_OVERRIDE_GFX_VERSION=11.5.1 \
GGML_HIP_ENABLE_UNIFIED_MEMORY=1 \
/root/stock-llama/build/bin/llama-cli \
  -m /models/qwen36-27b/Qwen3.6-27B-Q8_0.gguf \
  -ngl 999 \
  -fa on \
  -dio \
  -p "Your prompt here." \
  -n 200

12.4 Runtime Flag Reference

Flag Purpose
-ngl 999 Offload all layers to GPU
-fa on Enable flash attention (rocWMMA path)
-dio Required for models > ~6 GB on gfx1151. Without this, loading hangs.
-dev ROCm0 Explicitly select the ROCm device
--no-mmap Disable memory-mapped model loading (needed for some setups)
--spec-type draft-mtp Enable Multi-Token Prediction speculative decoding
--spec-draft-* MTP draft model configuration
HSA_OVERRIDE_GFX_VERSION=11.5.1 Required for ROCmFP4 kernel paths on gfx1151
GGML_HIP_ENABLE_UNIFIED_MEMORY=1 Required — enables GPU access to system RAM beyond dedicated VRAM
ulimit -l unlimited Required — ROCm needs to lock GPU memory pages

13. Phase 10: Benchmarks

13.1 ROCmFP4 Model Benchmark

setsid -w bash -c '
ulimit -l unlimited
HSA_OVERRIDE_GFX_VERSION=11.5.1 \
GGML_HIP_ENABLE_UNIFIED_MEMORY=1 \
/root/rocmfp4-llama/build-strix-rocmfp4/bin/llama-bench \
  -m /models/rocmfp4/Qwopus3.6-27B-v2-MTP-BF16-to-ROCmFP4-STRIX_LEAN.gguf \
  -ngl 999 \
  -fa on \
  -dio \
  -n 512 \
  -p 512
'

13.2 Q8 Baseline Benchmark

setsid -w bash -c '
ulimit -l unlimited
HSA_OVERRIDE_GFX_VERSION=11.5.1 \
GGML_HIP_ENABLE_UNIFIED_MEMORY=1 \
/root/stock-llama/build/bin/llama-bench \
  -m /models/qwen36-27b/Qwen3.6-27B-Q8_0.gguf \
  -ngl 999 \
  -fa on \
  -dio \
  -n 512 \
  -p 512
'

13.3 Large Context Test

# Test prompt processing at 32K context
setsid -w bash -c '
ulimit -l unlimited
HSA_OVERRIDE_GFX_VERSION=11.5.1 \
GGML_HIP_ENABLE_UNIFIED_MEMORY=1 \
/root/rocmfp4-llama/build-strix-rocmfp4/bin/llama-bench \
  -m /models/rocmfp4/Qwopus3.6-27B-v2-MTP-BF16-to-ROCmFP4-STRIX_LEAN.gguf \
  -ngl 999 \
  -fa on \
  -dio \
  -p 32768 \
  -n 128
'

13.4 MTP Speedup Test

Compare with and without --spec-type draft-mtp to measure speculative decoding benefit.


14. vLLM Docker Setup (Alternative Backend)

vLLM provides a production-grade serving backend. On Strix Halo, it requires the ROCm Docker image and the HSA_OVERRIDE_GFX_VERSION=11.0.0 workaround.

We don’t want to run docker on the Proxmox host; we can run it in the LXC Container. I’ve skipped how to install docker in the LXC – you can follow the normal docker installation guide and it’ll work fine, just make sure you’re installing docker inside the lxc (not the Proxmox host).

i.e. run the wget get.docker.com script from inside the LXC then run docker run hello-world to make sure docker is working fine inside the LXC.

14.1 Pull the ROCm vLLM image

docker pull rocm/vllm:latest

14.2 Run vLLM with the Qwen3.6-27B model (HF format)

The model is already available in safetensors format at /nfs/models/Jackrong/Qwopus3.6-27B-v2/ (52 GB).

docker run -it --rm \
  --device=/dev/dri \
  --device=/dev/kfd \
  --group-add=render \
  --ipc=host \
  --network=host \
  -v /nfs/models:/models \
  -e HSA_OVERRIDE_GFX_VERSION=11.0.0 \
  -e HIP_VISIBLE_DEVICES=0 \
  rocm/vllm:latest \
  --model /models/Jackrong/Qwopus3.6-27B-v2 \
  --dtype float32 \
  --max-model-len 4096 \
  --gpu-memory-utilization 0.90

Note: vLLM on Strix Halo requires float32 — bfloat16 causes GPU hangs on current kernel/driver combos. The HSA_OVERRIDE_GFX_VERSION=11.0.0 maps gfx1151 to gfx1100 code paths.

14.3 Benchmark via vLLM

docker exec <container-id> python3 -m vllm.benchmarks.benchmark_throughput \
  --model /models/Jackrong/Qwopus3.6-27B-v2 \
  --dtype float32 \
  --num-prompts 100 \
  --input-len 512 \
  --output-len 256

15. Troubleshooting

If you have a problem not listed here please do comment below so I can improve the guide!

15.1 Model loading hangs with no output

Symptoms: llama-cli starts but produces zero output and never completes.

Causes and fixes:

Cause Fix
SIGTTOU (inside lxc-attach) Use setsid -w wrapper, or run interactively via pct enter
Missing -dio flag Add -dio to the command line
Missing ulimit -l unlimited Set ulimit -l unlimited before running
Missing GGML_HIP_ENABLE_UNIFIED_MEMORY=1 Set this environment variable

15.2 “ROCk module is not loaded” in rocminfo

The amdgpu module is loaded but the ROCm compute path (amdkfd) isn’t initialized.

# On the Proxmox host
cat /boot/config-$(uname -r) | grep CONFIG_HSA_AMD
# Should show: CONFIG_HSA_AMD=y

# If it's a module, load it
modprobe amdkfd

# Check /dev/kfd exists
ls -la /dev/kfd

15.3 “Not enough memory” errors

Check GTT size:

cat /sys/class/drm/card1/device/mem_info_gtt_total

If this shows less than ~60 GB, the amdgpu.gttsize kernel parameter isn’t being applied:

cat /proc/cmdline | grep gttsize

If missing, re-run update-grub and reboot.

15.4 Container can’t see GPU devices

# On the host
ls -la /dev/dri/* /dev/kfd

# Check container config
cat /etc/pve/lxc/$CT_ID.conf | grep -E 'lxc\.(cgroup|mount)'

# Restart the container
pct stop $CT_ID
pct start $CT_ID

15.5 Permission denied on /dev/kfd inside container

Ensure the container is privileged (unprivileged: 0 in config). If using an unprivileged container, add:

lxc.idmap: g 993 993 1

15.6 Vulkan compilation errors during build

The ROCmFP4 fork’s build script enables Vulkan by default. If you get spv namespace errors, rebuild with Vulkan disabled:

cmake -S . -B build-strix-rocmfp4 \
  -DGGML_VULKAN=OFF \
  # ... other flags ...

15.7 Slow performance

  • Verify you’re using the ROCm backend, not CPU fallback: the log should show ggml_rocm_init
  • Check that GPU_TARGETS=gfx1151 was used during build
  • Verify flash attention is enabled: -fa on
  • Check GPU clock speed: rocm-smi
  • For first runs, kernel compilation may slow things down — subsequent runs will be faster

16. Reference: Key Community Resources


Appendix A: Quick-Start Script

DANGER: I am providing this for reference, but again, if it works (or doesn’t) please comment below. Thanks!

#!/bin/bash
# strix-halo-rocmfp4-setup.sh — Run on Proxmox host as root
# WARNING: Review each section before running. This will reboot the host.

set -euo pipefail

CT_ID=${1:-100}
CT_NAME=${2:-strix-ai}

echo "=== Step 1: Add no-subscription repos ==="
rm -f /etc/apt/sources.list.d/pve-enterprise.sources
cat > /etc/apt/sources.list.d/pve-no-subscription.sources << 'EOF'
Types: deb
URIs: http://download.proxmox.com/debian/pve
Suites: trixie
Components: pve-no-subscription
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
EOF
apt update

echo "=== Step 2: Add boot parameters ==="
sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="quiet"/GRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=off amdgpu.gttsize=131072 ttm.pages_limit=31457280"/' /etc/default/grub
update-grub

echo "=== Step 3: Download LXC template ==="
pveam download local ubuntu-24.04-standard_24.04-2_amd64.tar.zst

echo "=== Step 4: Create container ==="
pct create $CT_ID local:vztmpl/ubuntu-24.04-standard_24.04-2_amd64.tar.zst \
  --storage local-lvm \
  --memory 57344 \
  --swap 0 \
  --cores 16 \
  --unprivileged 0 \
  --hostname $CT_NAME \
  --net0 name=eth0,bridge=vmbr0,ip=dhcp \
  --rootfs local-lvm:100 \
  --features nesting=1

echo "=== Step 5: Add GPU passthrough ==="
cat >> /etc/pve/lxc/$CT_ID.conf << 'EOF'

lxc.cgroup2.devices.allow: c 226:* rwm
lxc.cgroup2.devices.allow: c 234:* rwm
lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir
lxc.mount.entry: /dev/kfd dev/kfd none bind,optional,create=file
EOF

echo "=== Done! Reboot to apply the new kernel ==="
echo "After reboot:"
echo "  1. pct start $CT_ID"
echo "  2. pct enter $CT_ID"
echo "  3. Run the inside-container setup (ROCm + llama.cpp builds)"
echo ""
echo "Rebooting in 10 seconds... Ctrl+C to cancel."
sleep 10
reboot

Appendix B: Okay, that’s setup? Where’s my home lab?

So from here, you can setup containers or VMs or run Docker for whatever you like. Check out Proxmox VE Helper-Scripts to get some ideas.

Jellyfin Media Server | Proxmox VE Helper Scripts

Frigate | Proxmox VE Helper Scripts

Home Assistant OS | Proxmox VE Helper Scripts

…and so many more!

6 Likes

Benchmark Results (while leaving plenty of room for VMs and the like)

Note: These are the DENSE models. The A35B models are quite fast but this is more to show the benefits of ROCmFP4 on dense models where the effect is more pronounced.

I think I still recommend Q8 for agentic dev work. However, for everything else, this works great. And for some kinds of agentic dev work this can also work fine.

If you have AMD hardware, it is always worth checking out Lemonade.ai

Hardware: AMD Ryzen AI MAX+ 395 (Strix Halo) with integrated Radeon 8060S Graphics (gfx1151) — 16 cores / 32 threads, 60 GiB unified system memory. This is an APU, so the GPU shares system RAM via GTT (no dedicated VRAM).

Component Size
ROCmFP4 model weights 13.79 GiB
KV cache (trunk, 64 layers, 256k ctx, Q4_0) ~16 GiB
KV cache (MTP head, 1 layer, 256k ctx, Q4_0) ~0.25 GiB
Total with MTP at 256k ~30 GiB
System RAM 60 GiB
Room remaining for VMs ~30 GiB

Benchmark Results — AMD Ryzen AI MAX+ 395 (Strix Halo) / Radeon 8060S (gfx1151)

System: 16C/32T, 60 GiB unified memory. GPU shares system RAM via GTT (no dedicated VRAM).

Environment: All rows use -fa 1 -ctk q4_0 -ctv q4_0. ROCmFP4 fork rows also use HSA_OVERRIDE_GFX_VERSION=11.5.1 and GGML_HIP_ENABLE_UNIFIED_MEMORY=1.

Benchmark method: Rows 1–9 use llama-bench -p 512 -n 256. Row 10 uses llama-server with real prompts.

Memory at 256k context:

Config Model Weights KV Cache Total GPU Free for VMs
ROCmFP4 27B + MTP 13.79 GiB ~16 GiB ~30 GiB ~30 GiB
Q4_K_M 27B 16.74 GiB ~16 GiB ~33 GiB ~27 GiB
Q8_0 27B 27.11 GiB ~16 GiB ~43 GiB ~17 GiB
Q4_K_M 35B MoE 20.60 GiB ~8 GiB ~29 GiB ~31 GiB
Q8_0 35B MoE 35.00 GiB ~8 GiB ~43 GiB ~17 GiB

Results

# Build Model Quant Size KV Offload MTP PP t/s TG t/s
1 Stock b9542 Qwen3.6-27B Q8_0 27.11 GiB GPU no 288 7.8
2 Stock b9542 Qwen3.6-27B Q8_0 27.11 GiB CPU no 259 6.0
3 Stock b9542 Qwen3.6-27B Q4_K_M 16.74 GiB GPU no 312 11.8
4 Lemonade ROCm b1290 Qwen3.6-27B Q4_K_M 16.74 GiB GPU no 310 11.7
5 ROCmFP4 fork b9219 Qwopus3.6 Chadrock ROCmFP4 13.79 GiB GPU no 332 14.0
6 ROCmFP4 fork b9219 Qwopus3.6 Chadrock ROCmFP4 13.79 GiB GPU yes :high_voltage: — 23–36
7 Stock b9542 Qwen3.6-35B-A3B Q8_0 ~40.00 GiB GPU no 337¹ 30¹
8 Stock b9542 Qwen3.6-35B-A3B Q4_K_M 20.60 GiB GPU no 802 50.6
9 ROCmFP4 fork b9219 Qwen3.6-35B-A3B Q4_K_M 20.60 GiB GPU no 859 49.9

¹ Q8_0 35B MoE: model had some quirks, sometimes 600s+ loadtime on this hardware because llama.cpp tries to load into ram before vram even with the option set to skip that. TG ~30 t/s based on Q4_K_M scaling (50.6 × 20.6/35 ≈ 30).

Key takeaways:

  • ROCmFP4 27B + MTP (Row 6) is the best dense option: 23–36 t/s depending on prompt, with only 13.79 GiB for weights.
  • Q4_K_M 35B MoE (Rows 8–9) dominates on throughput: 50+ t/s at 20.6 GiB, with ~3B active params per token. This is the fastest configuration by a wide margin.
  • Q8_0 27B (Row 1) is the slowest dense option at 7.8 t/s, but offers highest quality at 27 GiB.
  • Lemonade ROCm (Row 4) is identical to stock — no special AMD tuning in the binary.
3 Likes

Here’s some more notes from the review, too:

But all that’s covered in the video. This how-to is the real meat and potatos. Applicable to about any Strix Halo machine!

2 Likes

Great guide, wendell — exactly what the gfx1151 crowd needed.

One thing that might be worth adding: from our testing on a Strix Halo box, setting `HSA_ENABLE_SDMA=0` was necessary to avoid intermittent compute artifacts under sustained workloads. We pass it as an env var in docker run alongside the device mappings. Without it things would mostly work but occasionally produce garbage output mid-inference.

On the memory side, ROCm#6050 covers the issue where hipMalloc allocates strictly from VRAM and won’t spill into GTT on APUs — filed against gfx1150 but same family, likely applies. Worth watching if you’re hitting OOM earlier than expected.

Also, hogeheer499’s strix-halo-guide (on github) collects a lot of the community workarounds in one place — good companion reference.

1 Like

A few thoughts/things to note:

  • The ROCmFP4 fork may not be accepted by the llama.cpp maintainers (certainly, 0cc4m doesn’t appear to be looking favourably on it here).
  • The author of that fork seems to suggest in the PR that it’s beneficial for Vulkan too, with similarly improved TG throughput, even for MoE models. I might have a go at it later if I can find a compatible GGUF.
  • Beware MTP in llama.cpp - it still has the problem of no scaling for concurrent requests (if that’s a concern for anybody running it…llama.cpp scales pretty well up to 4 concurrent requests under normal circumstances, but MTP precludes it).

EDIT: OK, I compiled it and gave it a go, comparing the ROCmFP4 quant of Qwen3.6 35B MoE against Unsloth’s Q4_K_XL using Vulkan:

Stock:

| model                          |       size |     params | backend    | ngl | n_ubatch |  fa | dev          |            test |                  t/s |
| ------------------------------ | ---------: | ---------: | ---------- | --: | -------: | --: | ------------ | --------------: | -------------------: |
| qwen35moe 35B.A3B Q4_K - Medium |  21.27 GiB |    35.51 B | Vulkan     |  99 |     1024 |   1 | Vulkan1      |          pp2048 |       4217.26 ± 7.92 |
| qwen35moe 35B.A3B Q4_K - Medium |  21.27 GiB |    35.51 B | Vulkan     |  99 |     1024 |   1 | Vulkan1      |          pp4096 |      4113.51 ± 18.74 |
| qwen35moe 35B.A3B Q4_K - Medium |  21.27 GiB |    35.51 B | Vulkan     |  99 |     1024 |   1 | Vulkan1      |           tg128 |        147.46 ± 0.68 |

ROCmFP4:

| model                          |       size |     params | backend    | ngl | n_ubatch | fa | dev          |            test |                  t/s |
| ------------------------------ | ---------: | ---------: | ---------- | --: | -------: | -: | ------------ | --------------: | -------------------: |
| qwen35moe 35B.A3B Q4_0_ROCMFP4_STRIX |  18.35 GiB |    35.51 B | Vulkan     |  99 |     1024 |  1 | Vulkan1      |          pp2048 |      4354.97 ± 10.22 |
| qwen35moe 35B.A3B Q4_0_ROCMFP4_STRIX |  18.35 GiB |    35.51 B | Vulkan     |  99 |     1024 |  1 | Vulkan1      |          pp4096 |      4254.12 ± 29.19 |
| qwen35moe 35B.A3B Q4_0_ROCMFP4_STRIX |  18.35 GiB |    35.51 B | Vulkan     |  99 |     1024 |  1 | Vulkan1      |           tg128 |        180.10 ± 1.00 |

PP +3%, TG +22%.

This is on an R9700 with VRAM at 2750MHz (from 2516MHz stock), undervolted by 60mv and power limit at 330W (from 300W stock).

To keep this short…when running both cards with -sm row, the PP improvement is similar but the TG is +16%. Still significant, obviously.

Weirdly, the 27B dense model barely saw any change by comparison - from 36.1t/s to 38.4t/s, just +6.3%.

1 Like

I want one, but I don’t need one

1 Like

It looks like the baseline model name changed

wget ‘https://huggingface.co/bartowski/Qwen_Qwen3.6-27B-GGUF/resolve/main/Qwen_Qwen3.6-27B-Q8_0.gguf’

I tried the guide on the N5 Pro 96GB RAM
The -n and -p was causing errors


ggml_rocm_init: found 1 ROCm devices (Total VRAM: 81920 MiB):
  Device 0: AMD Radeon 890M Graphics, gfx1151 (0x1151), VMM: no, Wave Size: 32, VRAM: 81920 MiB
error: invalid parameter for argument: 512

After removing -p and -n:

root@strix-ai:~# setsid -w bash -c '
ulimit -l unlimited
HSA_OVERRIDE_GFX_VERSION=11.5.1 \
GGML_HIP_ENABLE_UNIFIED_MEMORY=1 \
/root/rocmfp4-llama/build-strix-rocmfp4/bin/llama-bench \
  -m /models/rocmfp4/Qwopus3.6-27B-v2-MTP-BF16-to-ROCmFP4-STRIX_LEAN.gguf \
  -ngl 999 \
  -fa 1 \
  -dio \'
ggml_rocm_init: found 1 ROCm devices (Total VRAM: 81920 MiB):
  Device 0: AMD Radeon 890M Graphics, gfx1151 (0x1151), VMM: no, Wave Size: 32, VRAM: 81920 MiB
| model                          |       size |     params | backend    | ngl | fa |            test |                  t/s |
| ------------------------------ | ---------: | ---------: | ---------- | --: | -: | --------------: | -------------------: |
| qwen35 27B Q4_0_ROCMFP4_STRIX_LEAN |  13.79 GiB |    27.32 B | ROCm       | 999 |  1 |           pp512 |        119.38 ± 4.54 |
| qwen35 27B Q4_0_ROCMFP4_STRIX_LEAN |  13.79 GiB |    27.32 B | ROCm       | 999 |  1 |           tg128 |          4.87 ± 0.02 |

build: 79066b667 (9247)

Something doesn’t seem right with that speed, and if you’re saying you’re not using the mtp rocmfp4 community model, that might be why?

Found an old blog post from this guy in relations to lemonade and halo strip, with tons of fun integrations:

Thanks for the guide, Wendell!

I’m having some trouble getting proxmox to recognize the full 128gb on my GMKtec EVO-X3. I would appreciate any advice in the right direction. (Very much beginner, appreciate the patience.)

The UEFI recognize the whole memory (and so did the windows installation), and I left the shared allocation in the UEFI to [auto]

Any suggestions?

# Running:
root@strixhalo:\~# cat /proc/cpuinfo | grep “model name” | head -1 && lspci | grep -i display && echo ---- && grep MemTotal /proc/meminfo && echo ----- && ls -la /dev/dri/\* /dev/kfd /dev/accel/accel0 && uname -r
&& pveversion
# Output
model name      : AMD RYZEN AI MAX+ 395 w/ Radeon 8060S
66:00.0 Display controller: Advanced Micro Devices, Inc. \[AMD/ATI\] Strix Halo \[Radeon Graphics / Radeon 8050S Graphics / Radeon 8060S Graphics\] (rev c1)

MemTotal:       65463868 kB <--------!!!!! This should be 128gb no?!

crw-rw---- 1 root render 261,   0 Aug 23 20:42 /dev/accel/accel0
crw-rw---- 1 root video  226,   1 Aug 23 20:42 /dev/dri/card1
crw-rw---- 1 root render 226, 128 Aug 23 20:42 /dev/dri/renderD128
crw-rw---- 1 root render 511,   0 Aug 23 20:42 /dev/kfd

/dev/dri/by-path:
total 0
drwxr-xr-x 2 root root  80 Aug 23 20:42 .
drwxr-xr-x 3 root root 100 Aug 23 20:42 ..
lrwxrwxrwx 1 root root   8 Aug 23 20:42 pci-0000:66:00.0-card → ../card1
lrwxrwxrwx 1 root root  13 Aug 23 20:42 pci-0000:66:00.0-render → ../renderD128

#versions
7.0.14-12-pve

pve-manager/9.2.2/b9984c6d90a4bd80 (running kernel: 7.0.14-12-pve)

I’ve moved forward with the guide anyway and managed to get the models working with fewer memory, but I fell it will colapse when I try allocating more than proxmox can recognize (download a bigger enough model now to test it).

Here are the specs and outputs of the rest of the tutorial:

# Command run
root@strixhalo:\~# cat /sys/class/drm/card1/device/mem_info_gtt_total && echo \*\*\*\* && cat /proc/cmdline |
grep -o ‘amdgpu.gttsize=\[^ \]*|amd_iommu=\[^ \]*|ttm.pages_limit=\[^ \]\*’ && echo \*\*\* && ls -la /dev/kfd
# Output 
137438953472
---
amd_iommu=off
amdgpu.gttsize=131072
ttm.pages_limit=31457280
---
crw-rw---- 1 root render 511, 0 Aug 23 20:42 /dev/kfd

Thanks in advance

p.s.1
Typo on the step-by-step guide?

The below didn’t work for me, the word “Linux” doesn’t seem to match the case

Here seems the fix: (I ended up using nano… but maybe for a future someone)

sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="quiet"/GRUB_CMDLINE_LINUX_DEFAULT="quiet amd_iommu=off amdgpu.gttsize=131072 ttm.pages_limit=31457280"/' /etc/default/grub

P.s 2
New name for the Gwen download model: The command below do not resolve, the new name has an extra “Gwen_” at the begining of the filename.

The right ones would be:

wget 'https://huggingface.co/bartowski/Qwen_Qwen3.6-27B-GGUF/resolve/main/Qwen_Qwen3.6-27B-Q8_0.gguf'
wget 'https://huggingface.co/bartowski/Qwen_Qwen3.6-27B-GGUF/resolve/main/Qwen_Qwen3.6-27B-Q4_K_M.gguf'

In bios you are reserving 64gb memory just for the GPU. For the guide setup it was 512mb allowing dynamic allocation from “system” memory. Update the reserved memory in bios

1 Like

That did it. On the GMKtec Evo 3x BIOS I could only change it to 1Gb, but it’s displaying correctly now.

I got confused by the video below, which uses Windows in the setup. My mistake, thanks for the clarification.