Skip to content
  • Home
  • Splunk Stuff
  • Random Things
  • Linux
  • IBM AIX
  • AI / ML
  • About
Procyon Labs

Procyon Labs

A Place For My Stuff

Intel Arc Pro Xe2 on openSUSE Tumbleweed and Unsloth Studio

Posted on 2026-09-032026-09-03 By beaker No Comments on Intel Arc Pro Xe2 on openSUSE Tumbleweed and Unsloth Studio
openSUSEopenSUSE TumbleweedIntel ArcUnsloth Studio

Abstract

I spent almost a year developing a project that made llama.cpp easy to use, and implemented some pretty wacky math to get multi-GPU balancing as close to OOM‘ing as possible (I paid for the VRAM, I’m gonna use all the VRAM). Then Unsloth released Studio. I was hesitant to try it, because so much crap is being made that I’ve just had vibe-slop-overload.

But then I tried it. Damn! It’s does everything, and well. So I set mine on fire, and decided to let someone else maintain a complicated pile of bits.

I chose openSUSE Tumbleweed because I have strong feelings for openSUSE, and Leap‘s kernel is too old for these GPUs.

My system has two Intel Arc B60 GPUs (I like a challenge) – but this guide should apply to any in the Battlemage (Xe2) architecture.

NOTE: There is a quirk that I call the Intel ECC VRAM Robbery Scheme. Basically, Intel skims a little VRAM off the top to pay for ECC operations. ECC is great for lots of things, and other vendors handle it better. See the end of this guide for a workaround.

Be advised that I jump around logically. These guides are my progress notes, and I often have to go back and re-write whole sections as a result of failures or sub-optimal results. Pick and choose what matters to you, but I recommend you go the intellectually curious route and play the whole game <3

Table of Contents
  • Abstract
  • Install and Ready the Operating Environment
  • Install the Native Intel Level Zero Compute Driver
  • Intel oneAPI DPC++ Library (oneDPL) / SYCL
  • Vulkan
  • Unsloth Studio
  • SYCL vs Vulkan
    • Training / Fine-Tuning (LoRA, QLoRA, etc.)
    • Chat / GGUF Inference
  • Intel ECC VRAM Robbery Scheme – Work Around
    • The Fix
  • But What About SYCL?
    • Stats
      • Qwen3.8-27B-GGUF UD-Q6_K_XL
  • Things I Broke So You Don’t Have To (Landmines & Guardrails)
    • The Auto-Fit Blind Spot
    • The OOM I Walked Into
    • Guardrails for Your Own Tuning
  • Helpful Links

Install and Ready the Operating Environment

Do a “Server” installation of openSUSE Tumbleweed. Pretty simple. From there, the adventure begins.

First, we need to verify that the GPU(s) are properly detected:

beaker@SAL9000:~> lspci -Dnnk | grep -A3 Battlemage
0000:01:00.0 VGA compatible controller [0300]: Intel Corporation Battlemage G21 [Arc Pro B60] [8086:e211]
        Subsystem: Device [207e:a023]
        Kernel driver in use: xe
        Kernel modules: xe
0000:02:00.0 VGA compatible controller [0300]: Intel Corporation Battlemage G21 [Arc Pro B60] [8086:e211]
        Subsystem: Device [207e:a023]
        Kernel driver in use: xe
        Kernel modules: xe

beaker@SAL9000:~> ls -l /dev/dri/renderD*
crw-rw----. 1 root render 226, 128 Aug 31 17:03 /dev/dri/renderD128
crw-rw----. 1 root render 226, 129 Aug 31 17:03 /dev/dri/renderD129

beaker@SAL9000:~> lsmod | grep '^xe'
xe                   4493312  2

Install the Native Intel Level Zero Compute Driver

beaker@SAL9000:~> sudo zypper --non-interactive install level-zero level-zero-devel libze_intel_gpu1 libze_intel_gpu_raytracing intel-gpu-tools clinfo intel-opencl

You’ll also need to give your user GPU access. This one keeps biting me, because I usually just YOLO as root:

beaker@SAL9000:~> sudo usermod -aG render,video "$USER"

Don’t forget to logout and back in for this to take affect. Then this command should work for you:

beaker@SAL9000:~> clinfo -l
Platform #0: Intel(R) OpenCL Graphics
 +-- Device #0: Intel(R) Arc(TM) Pro B60 Graphics
 `-- Device #1: Intel(R) Arc(TM) Pro B60 Graphics

Intel oneAPI DPC++ Library (oneDPL) / SYCL

Right now, only the OpenCL side of the compute-runtime stack is working. Now for the fun stuff.

On the Linux side, Intel seems to only love Ubuntu – which is odd, because Ubuntu is Debian made shitty. But I digress…

We’re going to be doing some manual labor here, but we like that! First, the prerequisites:

beaker@SAL9000:~> sudo zypper --non-interactive install -t pattern devel_C_C++
beaker@SAL9000:~> sudo zypper --non-interactive install cmake

Next add Intel’s oneAPI repo (separate from Tumbleweed’s own repos… this is Intel’s official YUM-style repo, which works fine with zypper):

beaker@SAL9000:~> sudo rpm --import https://yum.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB
beaker@SAL9000:~> sudo zypper addrepo https://yum.repos.intel.com/oneapi oneAPI
beaker@SAL9000:~> sudo zypper refresh

Now, install and activate the DPC++/C++ compiler + SYCL runtime. This installs to /opt/intel/oneapi, fully separate from the libze_intel_gpu1/level-zero packages from Tumbleweed’s repo we already have. No conflicts, they weirdly coexist fine. Note that we need to source the environment as well. This feels hacky, because it is:

beaker@SAL9000:~> sudo zypper --non-interactive install intel-oneapi-compiler-dpcpp-cpp intel-oneapi-mkl-devel
beaker@SAL9000:~> source /opt/intel/oneapi/setvars.sh
 
:: initializing oneAPI environment ...
   -bash: BASH_VERSION = 5.3.15(1)-release
   args: Using "$@" for setvars.sh arguments: 
:: compiler -- latest
:: debugger -- latest
:: dev-utilities -- latest
:: dpl -- latest
:: tbb -- latest
:: tcm -- latest
:: umf -- latest
:: oneAPI environment initialized ::

Tip: If you don’t want to source that setvars.sh every time you want to work with those tools, run this to modify your PATH in .bashrc:

beaker@SAL9000:~> cat >> ~/.bashrc << 'EOF'

# Intel oneAPI environment (for xpu-smi / SYCL / icpx toolchain)

if [ -f /opt/intel/oneapi/setvars.sh ]; then
source /opt/intel/oneapi/setvars.sh > /dev/null 2>&1
fi
EOF

Trust… but verify:

beaker@SAL9000:~> sycl-ls
[level_zero:gpu][level_zero:0] Intel(R) oneAPI Unified Runtime over Level-Zero V2, Intel(R) Arc(TM) Pro B60 Graphics 20.1.0 [1.15.39122]
[level_zero:gpu][level_zero:1] Intel(R) oneAPI Unified Runtime over Level-Zero V2, Intel(R) Arc(TM) Pro B60 Graphics 20.1.0 [1.15.39122]
[opencl:cpu][opencl:0] Intel(R) OpenCL, AMD EPYC 7513 32-Core Processor                 OpenCL 3.0 (Build 0) [2026.21.7.0.24_160000]

beaker@SAL9000:~> icpx --version
Intel(R) oneAPI DPC++/C++ Compiler 2026.1.1 (2026.1.1.20260724)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /opt/intel/oneapi/compiler/2026.1/bin/compiler
Configuration file: /opt/intel/oneapi/compiler/2026.1/bin/compiler/../icpx.cfg

Vulkan

Easy:

beaker@SAL9000:~> sudo zypper --non-interactive install libvulkan1 libvulkan_intel vulkan-tools

Verify:

beaker@SAL9000:~> vulkaninfo --summary
'DISPLAY' environment variable not set... skipping surface info
WARNING: [../src/intel/vulkan/anv_physical_device.c:2836] Code 0 : Unable to open device : No such file or directory (VK_ERROR_INCOMPATIBLE_DRIVER)
==========
VULKANINFO
==========

Vulkan Instance Version: 1.4.357


Instance Extensions: count = 26
-------------------------------
VK_EXT_acquire_drm_display             : extension revision 1
VK_EXT_acquire_xlib_display            : extension revision 1
VK_EXT_debug_report                    : extension revision 10
VK_EXT_debug_utils                     : extension revision 2
VK_EXT_direct_mode_display             : extension revision 1
VK_EXT_display_surface_counter         : extension revision 1
VK_EXT_headless_surface                : extension revision 1
VK_EXT_layer_settings                  : extension revision 2
VK_EXT_surface_maintenance1            : extension revision 1
VK_EXT_swapchain_colorspace            : extension revision 5
VK_KHR_device_group_creation           : extension revision 1
VK_KHR_display                         : extension revision 23
VK_KHR_external_fence_capabilities     : extension revision 1
VK_KHR_external_memory_capabilities    : extension revision 1
VK_KHR_external_semaphore_capabilities : extension revision 1
VK_KHR_get_display_properties2         : extension revision 1
VK_KHR_get_physical_device_properties2 : extension revision 2
VK_KHR_get_surface_capabilities2       : extension revision 1
VK_KHR_portability_enumeration         : extension revision 1
VK_KHR_surface                         : extension revision 25
VK_KHR_surface_maintenance1            : extension revision 1
VK_KHR_surface_protected_capabilities  : extension revision 1
VK_KHR_wayland_surface                 : extension revision 6
VK_KHR_xcb_surface                     : extension revision 6
VK_KHR_xlib_surface                    : extension revision 6
VK_LUNARG_direct_driver_loading        : extension revision 1

Instance Layers: count = 1
--------------------------
VK_LAYER_MESA_device_select Linux device selection layer 1.4.303  version 1

Devices:
========
GPU0:
        apiVersion         = 1.4.354
        driverVersion      = 26.2.1
        vendorID           = 0x8086
        deviceID           = 0xe211
        deviceType         = PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
        deviceName         = Intel(R) Arc(tm) Pro B60 Graphics (BMG G21)
        driverID           = DRIVER_ID_INTEL_OPEN_SOURCE_MESA
        driverName         = Intel open-source Mesa driver
        driverInfo         = Mesa 26.2.1
        conformanceVersion = 1.4.0.0
        deviceUUID         = 868011e2-0000-0000-0100-000000000000
        driverUUID         = beb33ed6-1b6b-4804-f218-acbcea808065
GPU1:
        apiVersion         = 1.4.354
        driverVersion      = 26.2.1
        vendorID           = 0x8086
        deviceID           = 0xe211
        deviceType         = PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
        deviceName         = Intel(R) Arc(tm) Pro B60 Graphics (BMG G21)
        driverID           = DRIVER_ID_INTEL_OPEN_SOURCE_MESA
        driverName         = Intel open-source Mesa driver
        driverInfo         = Mesa 26.2.1
        conformanceVersion = 1.4.0.0
        deviceUUID         = 868011e2-0000-0000-0200-000000000000
        driverUUID         = beb33ed6-1b6b-4804-f218-acbcea808065

NOTE: Mesa’s Vulkan loader walks every DRM node it finds, including card0 (the software bochs-drm framebuffer on my Proxmox VE hypervisor). That device has no render node and can’t back a Vulkan physical device, so Mesa logs the warning and moves on. It’s noise from the virtual console, not from the passed-through GPUs. Pay no mind.

Unsloth Studio

By default, the installation script for Unsloth Studio checks macOS (eww), then nvidia-smi ($$$), then AMD ROCm (rocminfo/amd-smi) – and that’s it. There is no Intel/XPU probe anywhere in the auto-detect path (the installer’s “gpu: none (CPU-only)” notice is a disgusting lie. Let’s get out the duct tape.

Running the installer with an explicit override resolves to PyTorch’s official XPU index. It’ll also pull in an XPU-enabled bitsandbytes (≥0.50.0, needed for 4-bit QLoRA on Intel) as a separate step gated on the same XPU index detection.

Remember! Before you install or update Unsloth Studio, also define “export UNSLOTH_TORCH_INDEX_FAMILY=xpu” first – otherwise, no XPU.

beaker@SAL9000:~> export UNSLOTH_TORCH_INDEX_FAMILY=xpu
beaker@SAL9000:~> curl -fsSL https://unsloth.ai/install.sh | sh

  🦥 Unsloth Studio Installer
  ────────────────────────────────────────────────────

  platform       linux
  deps           using prebuilt llama.cpp (missing: libcurl4-openssl-dev)
                 Not required to run: Unsloth downloads a prebuilt inference engine.
  venv           creating Python 3.13 virtual environment
                 /home/beaker/.unsloth/studio/unsloth_studio
  venv           using environment
                 /home/beaker/.unsloth/studio/unsloth_studio
  gpu            none (CPU-only)
                 installing PyTorch (https://download.pytorch.org/whl/xpu)...
                 installing unsloth (this may take a few minutes)...
  unsloth        2026.8.22 installed
                 installing bitsandbytes with Intel XPU kernels...
  setup          running unsloth studio update...

  🦥 Unsloth Studio Setup
  ────────────────────────────────────────────────────
  frontend       bundled (pip install)
                 installing isolated Node (system Node/npm left untouched)...
  node           v24.18.0 | npm 11.16.0 (isolated)
  frontend       up to date
  deps           [==------------------]  2/15  torch check (xpu)   
   replacing triton 3.8.0 with triton-xpu==3.6.0 (Intel XPU)
  deps           [======--------------]  5/15  dependency overrides
                 torch 2.10.0+xpu detected -- installing torchao==0.16.0
  deps           [=========-----------]  7/15  flash-attn          
  warning        No compatible flash-attn prebuilt wheel found
  deps           [====================] 15/15  torch final (xpu)   
   replacing triton 3.8.0 with triton-xpu==3.6.0 (Intel XPU)
  deps           installed
  transformers   5.3.0 pre-installed
  transformers   5.5.0 pre-installed
  transformers   5.10.2 pre-installed
  gpu            Intel GPU detected (XPU runtime)
                 PyTorch XPU (SYCL) provides training and GPU inference on this GPU.
                 installing prebuilt llama.cpp...
  llama.cpp      prebuilt installed and validated
                 installed release: unslothai/llama.cpp@b10715-mix-86bd2d3 (tag b10715)
  whisper.cpp    prebuilt installed
  ────────────────────────────────────────────────────
  Unsloth Studio Installed
  ────────────────────────────────────────────────────
  launch         unsloth studio -p 8888
                 (add -H 0.0.0.0 for LAN / cloud access; exposes the raw port only, not a public URL)
                 (add -H 0.0.0.0 --cloudflare for a public Cloudflare HTTPS link, or --secure to keep the raw port private; anyone with the API key can run code)

                 Created Unsloth Studio shortcut

  Unsloth Studio installed!
  ────────────────────────────────────────────────────


  Start Unsloth Studio now? [Y/n] 

Oooooh, it worked!

Because we want to access this instance from other workstations, launch it manually with LAN access allowed. What you do from there is your business. Just know I’m scanning the Internet constantly \m/

Go change the world with your new toy:

beaker@SAL9000:~> unsloth studio -p 8888 -H 0.0.0.0
Starting Unsloth Studio on http://WAN.IP:8888
Session log: /home/beaker/.unsloth/studio/logs/server/server-20260902-011057-pid10791.log
{"timestamp": "2026-09-02T05:10:57.957849Z", "level": "info", "event": "run_server startup begin api_only=False host=0.0.0.0 port=8888"}
Loading Unsloth Studio, please wait... (this can take a few minutes)
  - loading PyTorch, Unsloth and Transformers...
{"timestamp": "2026-09-02T05:11:01.656084Z", "level": "info", "event": "Imported FastAPI app in 3589.0ms"}
  - Starting server...
{"timestamp": "2026-09-02T05:11:01.658754Z", "level": "info", "event": "Ensured Unsloth directories in 3705.6ms"}
[OK] Frontend loaded from /home/beaker/.unsloth/studio/unsloth_studio/lib/python3.13/site-packages/studio/frontend/dist
{"timestamp": "2026-09-02T05:11:01.723571Z", "level": "info", "event": "run_server pre-uvicorn setup completed in 3770.4ms"}
INFO:     Started server process [10791]
INFO:     Waiting for application startup.
{"timestamp": "2026-09-02T05:11:01.843283Z", "level": "info", "event": "Removing unsloth compiled cache: /home/beaker/.unsloth/studio/compiled_cache"}
{"timestamp": "2026-09-02T05:11:02.021233Z", "level": "info", "event": "lifespan pre-auth setup completed in 179.1ms"}

============================================================
DEFAULT ADMIN ACCOUNT CREATED
    username: unsloth
    password saved to: /home/beaker/.unsloth/studio/auth/.bootstrap_password
    Open the Unsloth UI to sign in and change it.
============================================================

{"timestamp": "2026-09-02T05:11:02.087297Z", "level": "info", "event": "lifespan startup completed in 245.2ms"}
INFO:     Application startup complete.
INFO:     Unsloth Studio running on http://WAN.IP:8888 (To stop: press Ctrl+C -- on macOS, Control+C not Command+C)
{"timestamp": "2026-09-02T05:11:02.091028Z", "level": "info", "event": "Uvicorn startup hook completed in 4137.9ms"}
{"timestamp": "2026-09-02T05:11:02.091493Z", "level": "info", "event": "run_server uvicorn ready after 4138.3ms"}
{"timestamp": "2026-09-02T05:11:02.673099Z", "level": "info", "event": "Unsloth will shut down in 3600s unless the default admin password is changed."}

🦥 Unsloth Studio is running
────────────────────────────────────────────────────
  On this machine -- open this in your browser:
    http://127.0.0.1:8888
    (same as http://localhost:8888)

  From another device on your network / to share:
    http://WAN.IP:8888

  API & health:
    http://127.0.0.1:8888/api
    http://127.0.0.1:8888/api/health
────────────────────────────────────────────────────
Hardware detected: XPU — Intel(R) Arc(TM) Pro B60 Graphics
{"timestamp": "2026-09-02T05:11:03.685336Z", "level": "info", "event": "InferenceOrchestrator initialized (subprocess mode)"}

  Reachability check: http://WAN.IP:8888/ is NOT reachable from the public internet (3/3 probe nodes failed).
    Usually a cloud firewall (AWS security group, GCP firewall / Azure NSG rule) or home router isn't allowing inbound TCP 8888.
    No firewall change needed -- SSH local-forward from your own computer:
        ssh -L 8888:localhost:8888 <user>@WAN.IP
    then open http://localhost:8888/ in your browser.
  You can access Unsloth Studio locally in the meantime: http://127.0.0.1:8888
  Cloudflare tunnel: OFF (default). Unsloth is reachable on your local network only. Pass --cloudflare to expose a public Cloudflare HTTPS link.
Server-side tools follow each request's enable_tools; the Unsloth UI's tool toggles decide. Pass --enable-tools to force them on for every request.

  To stop Unsloth Studio: press Ctrl+C (Control+C, not Command+C, on macOS).
────────────────────────────────────────────────────

{"timestamp": "2026-09-02T05:11:14.105065Z", "level": "info", "event": "torch warm finished in 12018.2ms"}

Note: It will always display your WAN’s IP address, when it really means your host’s IP address. Odd it does’t make that clearer.

SYCL vs Vulkan

Here’s some knowledge for you – because after logging into Unsloth Studio, you probably saw this and thought “WTF? We setup SYCL and only Vulkan is available!”:

Well, two distinct GPU-acceleration paths exist inside Unsloth Studio, and each uses a different backend for Intel.

Training / Fine-Tuning (LoRA, QLoRA, etc.)

Runs through PyTorch, which uses the XPU (SYCL) backend over Level Zero. This is the layer we setup (xe kernel driver → Level Zero → oneAPI-style +xpu PyTorch wheel)

Chat / GGUF Inference

Runs through a bundled llama.cpp prebuilt binary, entirely separate code from PyTorch. install_llama_prebuilt.py has zero references to SYCL anywhere. For any non-NVIDIA/non-AMD GPU, the logic is explicit:

log(f"Intel GPU detected -- using upstream Vulkan prebuilt {vulkan_name}")

Unsloth only ships/downloads prebuilt llama.cpp binaries for CUDA, ROCm/HIP, Vulkan, and CPU. There is no SYCL-flavored llama.cpp prebuilt in their release assets, so Intel GPUs always fall through to the Vulkan build for this component — regardless of what PyTorch is doing.

llama.cpp does have an upstream SYCL build target, but Unsloth doesn’t build/ship it as a prebuilt. Vulkan is their catch-all for “any other GPU,” which happens to work fine on Arc/Xe2 hardware since Intel has Vulkan compute support.

Training will use SYCL/XPU via PyTorch, and GGUF chat/inference will use Vulkan via llama.cpp. If you specifically want SYCL-accelerated llama.cpp instead of Vulkan (I’ve found it to be more performant – mostly), that would mean building llama.cpp yourself with -DGGML_SYCL=ON against the oneAPI
toolkit we already installed, replacing Studio’s prebuilt. Pain in the ass, but possible nonetheless.

Intel ECC VRAM Robbery Scheme – Work Around

As I mentioned at the top of this guide, we have a quirk with the VRAM on these cards. In my testing, the B60 went from a spec-sheet “24GB” to Memory Physical Size: 24480.00 MiB usable once I disabled ECC – meaning with ECC on by default, roughly 4GB of that 24GB was gone before I ever loaded a model. Nobody’s published that number that I could find (this hardware is too new), so take it as my measurement, not a documented spec – but a 16.7% cut is a lot, especially compared to Nvidia’s own GDDR6X cards: RTX 4090 owners lose 24GB → 22.5GB (a 6.25% cut) when its on-die ECC-like mode gets switched on (https://dev.to/maximsaplin/4090-ecc-on-vs-ecc-off-36m4). If Intel’s real-world number holds up as more people use these cards, that’s more than double Nvidia’s overhead for the same underlying memory technology. My guess is Intel’s parity/reservation scheme is comparatively wasteful, or they’re reserving more than strict parity bits alone – but that’s speculation on my part.

GDDR6 has no dedicated sideband channel for this. There’s no extra physical bit lane reserved for parity – GDDR6 was designed as a cost-optimized, high-clock commodity memory standard, not a check-bit-aware one (GDDR6 vs HBM (https://www.exxactcorp.com/blog/hpc/gddr6-vs-hbm-gpu-memory)). So any vendor implementing ECC over GDDR6 has to do it the only way available: carve parity storage out of the same visible memory pool the GPU already has. Nvidia eats that cost on the 4090 as shown above; I’d expect AMD’s GDDR6 workstation cards (Radeon Pro W-series) to take a similar hit when ECC is on, though I don’t have a verified number for those to point to, so don’t quote me on AMD specifically. HBM2 (and HBM2E) sidesteps the whole problem with a dedicated sideband ECC path – extra pins/bits alongside the main data bus, purpose-built for parity, instead of stealing from the same pool your models have to live in. That’s one reason I still like my AMD Instinct MI100 and Nvidia Tesla V100 GPUs better, despite being older.

The Fix

Intel’s xpu-smi (from the XPU Manager project) exposes a firmware-level ECC toggle via IGSC (Intel Graphics System Controller): xpu-smi config -d –memoryecc 0. It’s not in Tumbleweed’s repos, and Intel currently only ships .deb builds in their GitHub releases (no RPM despite their docs still describing SLES/RHEL install). The .deb is just one binary + a resources folder, and its only two missing runtime deps (libigsc.so.1, libhwloc.so.15) are both available straight from Tumbleweed’s own OSS repo – everything else it needs (libze_loader, libpciaccess, libstdc++, libz) we already have.

ECC is only really important for activities like training. Inference can be a little more relaxed, that’s why we’re doing this.

Install the two missing runtime libs:

beaker@SAL9000:~> sudo zypper --non-interactive install igsc libhwloc15

Grab and extract the xpu-smi .deb (no RPM exists, so we’ll lift the binary out manually):

beaker@SAL9000:~> curl -fsSL -o /tmp/xpu-smi.deb "https://github.com/intel/xpumanager/releases/download/v2.1.0/xpu-smi_2.1.0%2B26.33.6468cec-1.24.04_amd64.deb"
beaker@SAL9000:~> mkdir -p /tmp/xpu-smi-extract && cd /tmp/xpu-smi-extract
beaker@SAL9000:/tmp/xpu-smi-extract> ar x /tmp/xpu-smi.deb
beaker@SAL9000:/tmp/xpu-smi-extract> zstd -d data.tar.zst -o data.tar
data.tar.zst        : 3696640 bytes                                            
beaker@SAL9000:/tmp/xpu-smi-extract> tar xf data.tar
beaker@SAL9000:/tmp/xpu-smi-extract> sudo cp usr/bin/xpu-smi /usr/local/bin/
beaker@SAL9000:/tmp/xpu-smi-extract> sudo mkdir -p /usr/local/share/xpum
beaker@SAL9000:/tmp/xpu-smi-extract> sudo cp -r usr/share/xpum/resources /usr/local/share/xpum/

Note: Installed under /usr/local, not /usr – it’s an unmanaged file drop, not a zypper tracked package, so keep it out of /usr proper.

Confirm xpu-smi works, and then disable ECC on both GPUs (device IDs from the discovery output -almost certainly 0 and 1):

Note: openSUSE’s default /etc/sudoers sets secure_path="/usr/sbin:/usr/bin:/sbin:/bin", which deliberately excludes /usr/local/bin (unlike Debian, which include it by default). Your normal shell’s PATH finds the binary fine, but sudo ignores the PATH entirely and only searches its own hardcoded secure_path.

Quick fix: Just use the full path:
sudo /usr/local/bin/xpu-smi discovery
sudo /usr/local/bin/xpu-smi config -d 0 --memoryecc 0
sudo /usr/local/bin/xpu-smi config -d 1 --memoryecc 0

Permanent fix (adds /usr/local/bin to sudo’s search path so bare sudo xpu-smi ... works going forward):
echo 'Defaults secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"' | sudo tee /etc/sudoers.d/local-path
sudo chmod 0440 /etc/sudoers.d/local-path
sudo visudo -c

visudo -c checks syntax across all sudoers files/drop-ins. If it doesn’t report an error, the change is safe and live immediately. A malformed sudoers file can lock out sudo entirely.

beaker@SAL9000:~> sudo xpu-smi discovery
                                                                  
  Device ID     Device Information                                
  0             Device Name: Intel(R) Arc(TM) Pro B60 Graphics    
                Device State: normal                              
                Vendor Name: Intel(R) Corporation                 
                SOC UUID: 00000000-0000-0001-0000-0000e2118086    
                PCI BDF Address: 0000:01:00.0                     
                DRM Device: /dev/dri/card1                        
                Function Type: physical                           
                                                                  
  1             Device Name: Intel(R) Arc(TM) Pro B60 Graphics    
                Device State: normal                              
                Vendor Name: Intel(R) Corporation                 
                SOC UUID: 00000000-0000-0002-0000-0000e2118086    
                PCI BDF Address: 0000:02:00.0                     
                DRM Device: /dev/dri/card2                        
                Function Type: physical  

beaker@SAL9000:~> sudo xpu-smi config -d 0 --memoryecc 0
Successfully disabled ECC memory setting on GPU 0 
Please perform Warm reset of the card for the change to take effect.
beaker@SAL9000:~> sudo xpu-smi config -d 1 --memoryecc 0
Successfully disabled ECC memory setting on GPU 1 
Please perform Warm reset of the card for the change to take effect.

If this is a bare metal system, a reboot works in this case. This is a firmware/VBIOS-level setting via IGSC, it won’t take effect live.

However, if you’re like me, and this system is a VM with PCIe passthrough on a Proxmox VE hypervisor, you need to kick the cards hard from the Proxmox host itself (my PVE is named tethys, and the VM is, if you haven’t already guessed, SAL9000).

A host-level sysfs reset (SBR/FLR) is not sufficient. A qm stop/qm start VM-level cycle is also not sufficient. What did work: shutdown -h now on the PVE host followed by powering it back on (a soft ACPI poweroff/poweron cycle). A plain warm reboot of the host was not tested, so it’s unknown whether that alone would suffice.

I used this as an opportunity to finally update my PVE node. Because honestly, how often do we want to shutdown all the VMs and reboot this thing?

Your System is up-to-date


Seems you installed a kernel update - Please consider rebooting
this node to activate the new kernel.

starting shell
root@tethys:~# shutdown -h now

Then verify (confirm the ECC field now reads disabled/0 on both devices) and revel in your success:

beaker@SAL9000:~> sudo xpu-smi config -d 0 | grep -A 2 ECC
                                         Memory ECC:
                                          Current: disabled                                                                                       Pending: disabled                                           
beaker@SAL9000:~> sudo xpu-smi config -d 1 | grep -A 2 ECC
                                         Memory ECC:
                                          Current: disabled                                                                                       Pending: disabled   

beaker@SAL9000:~> sudo xpu-smi discovery -d 0
                                                                  
  Device ID     Device Information                                
  0             Device Type: Discrete GPU                         
                Device Name: Intel(R) Arc(TM) Pro B60 Graphics    
                Device State: normal                              
                PCI Device ID: 0xe211                             
                Vendor Name: Intel(R) Corporation                 
                SOC UUID: 00000000-0000-0001-0000-0000e2118086    
                Serial Number: unknown                            
                Part Number: unknown                              
                Core Clock Rate: 2400 MHz                         
                Stepping: A0                                      
                SKU Type: Production ES                           
                                                                  
                Driver Version: 17012946                          
                Kernel Version: 7.2.2-1-default                   
                GFX Firmware Name: GFX                            
                GFX Firmware Version: BMG__21.1177                
                GFX Firmware Status: normal                       
                                                                  
                PCI BDF Address: 0000:01:00.0                     
                PCI Slot: N/A                                     
                PCIe Generation: N/A                              
                PCIe Max Link Width: N/A                          
                PCIe Max Bandwidth: N/A                           
                                                                  
                Memory Physical Size: 24480.00 MiB                
                Max Mem Alloc Size: 23256.00 MiB                  
                ECC State: disabled                               
                Number of Memory Channels: 6                      
                Memory Bus Width: 192                             
                Max Hardware Contexts: 65536                      
                Max Command Queue Priority: 0                     
                                                                  
                Number of EUs: 160                                
                Number of Tiles: 1                                
                Number of Slices: 5                               
                Number of Sub Slices per Slice: 4                 
                Number of Threads per EU: 8                       
                Physical EU SIMD Width: 16                        
                Number of Media Engines: 2                        
                Number of Media Enhancement Engines: 2                                           
                                                                  
beaker@SAL9000:~> sudo xpu-smi discovery -d 1
                                                                  
  Device ID     Device Information                                
  1             Device Type: Discrete GPU                         
                Device Name: Intel(R) Arc(TM) Pro B60 Graphics    
                Device State: normal                              
                PCI Device ID: 0xe211                             
                Vendor Name: Intel(R) Corporation                 
                SOC UUID: 00000000-0000-0002-0000-0000e2118086    
                Serial Number: unknown                            
                Part Number: unknown                              
                Core Clock Rate: 2400 MHz                         
                Stepping: A0                                      
                SKU Type: Production ES                           
                                                                  
                Driver Version: 17012946                          
                Kernel Version: 7.2.2-1-default                   
                GFX Firmware Name: GFX                            
                GFX Firmware Version: BMG__21.1177                
                GFX Firmware Status: normal                       
                                                                  
                PCI BDF Address: 0000:02:00.0                     
                PCI Slot: N/A                                     
                PCIe Generation: N/A                              
                PCIe Max Link Width: N/A                          
                PCIe Max Bandwidth: N/A                           
                                                                  
                Memory Physical Size: 24480.00 MiB                
                Max Mem Alloc Size: 23256.00 MiB                  
                ECC State: disabled                               
                Number of Memory Channels: 6                      
                Memory Bus Width: 192                             
                Max Hardware Contexts: 65536                      
                Max Command Queue Priority: 0                     
                                                                  
                Number of EUs: 160                                
                Number of Tiles: 1                                
                Number of Slices: 5                               
                Number of Sub Slices per Slice: 4                 
                Number of Threads per EU: 8                       
                Physical EU SIMD Width: 16                        
                Number of Media Engines: 2                        
                Number of Media Enhancement Engines: 2   
Mmmm… tasty but more error-prone VRAM!

But What About SYCL?

As I mentioned earlier, Unsloth Studio doesn’t ship a version of llama.cpp with SYCL enabled. So we’ll do that manually, and point it to the binary we create.

beaker@SAL9000:~> git clone https://github.com/ggml-org/llama.cpp.git
Cloning into 'llama.cpp'...
remote: Enumerating objects: 121486, done.
remote: Counting objects: 100% (91/91), done.
remote: Compressing objects: 100% (58/58), done.
remote: Total 121486 (delta 42), reused 53 (delta 31), pack-reused 121395 (from 2)
Receiving objects: 100% (121486/121486), 426.53 MiB | 74.14 MiB/s, done.
Resolving deltas: 100% (85737/85737), done.

beaker@SAL9000:~> cd llama.cpp

beaker@SAL9000:~/llama.cpp> cmake -B build -DGGML_SYCL=ON -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx -DGGML_SYCL_F16=ON
beaker@SAL9000:~/llama.cpp> cmake --build build --config Release -j -v

beaker@SAL9000:~/llama.cpp> ./build/bin/llama-ls-sycl-device
Found 2 SYCL devices:
|  |                   |                                       |       |Max    |        |Max  |Global |                     |
|  |                   |                                       |       |compute|Max work|sub  |mem    |                     |
|ID|        Device Type|                                   Name|Version|units  |group   |group|size   |       Driver version|
|--|-------------------|---------------------------------------|-------|-------|--------|-----|-------|---------------------|
| 0| [level_zero:gpu:0]|             Intel Arc Pro B60 Graphics|   20.1|    160|    1024|   32| 25669M|           1.15.39122|
| 1| [level_zero:gpu:1]|             Intel Arc Pro B60 Graphics|   20.1|    160|    1024|   32| 25669M|           1.15.39122|
SYCL Optimization Feature:
|ID|        Device Type|Reorder|
|--|-------------------|-------|
| 0| [level_zero:gpu:0]|      Y|
| 1| [level_zero:gpu:1]|      Y|

Now restart Unsloth Studio and navigate to Settings -> System -> GGUF inference engine. In the “Custom llama.cpp folder” box, type in the location of your newly created llama.cpp binary (folder navigation doesn’t work). This is my example:

Now, restart again.

NOTE: If you try loading a model now and get Failed to load model: llama-server could not start: the system library libsvml.so is missing, it’s not actually missing… it’s an environment problem. Studio launches llama-server by copying its own process environment wholesale, so if whatever terminal/session Studio itself is running in never sourced the oneAPI env (the .bashrc block from earlier only fires for interactive shells – it won’t help a systemd unit, cron job, or a tmux/screen session that predates that edit), the child process can’t find libsvml.so and friends under /opt/intel/oneapi/compiler/2026.1/lib.

Quick check before you launch Studio:
echo $LD_LIBRARY_PATH
If that’s empty, stop Studio, open a fresh terminal (or source ~/.bashrc), confirm the path shows up, then relaunch:
unsloth studio stop
echo $LD_LIBRARY_PATH
unsloth studio -p 8888 -H 0.0.0.0

Wait, Why Is “Compute Backend” Empty Now?

So you pointed Studio at your shiny hand-rolled SYCL binary, GPUs light up, inference actually runs on the cards, and then you open Settings and the “Compute backend” dropdown is just… nothing. Empty. Not even a CPU option.

Turns out this dropdown was never for us. I went digging through Studio’s backend code (routes/llama.py) and found the whole picker is hardcoded to exactly four values: cpu, cuda, rocm, vulkan. Not a sycl in sight. That’s because this thing isn’t “pick which backend runs my inference” – it’s “pick which of Unsloth’s own prebuilt downloads to install,” and Unsloth doesn’t build a SYCL prebuilt (we covered why earlier – Vulkan’s their catch-all for anything that isn’t Nvidia or AMD).

The instant you set a Custom llama.cpp folder, Studio quietly reclassifies your install as a local_link – their term for “the user pointed me at their own build, I don’t manage this anymore” (llama_cpp_update.py, if you want to go read it yourself). And a local_link install makes the backend-switcher shut itself off on purpose: no options, nothing to switch, because it genuinely has no idea what’s living in your directory and isn’t going to pretend otherwise.

So an empty dropdown here isn’t broken. It’s Studio politely getting out of your way. The only check that actually matters is xpu-smi stats -d 0 lighting up during inference. If that’s happening, you’re done and can ignore the dropdown forever.

Stats

So is it worth it to get SYCL working instead of Vulkan for these GPUs?

Yes. On my system, at least.

Qwen3.8-27B-GGUF UD-Q6_K_XL

  • Vulkan averaged 11.2 tok/s
  • SYCL averaged 19.4 tok/s

Still slow, but not as painful.

Things I Broke So You Don’t Have To (Landmines & Guardrails)

Everything above gets you a working SYCL build wired into Studio. This section is what I learned keeping it alive afterward – the parts where Studio’s SYCL support runs out of road, and the actual working config on the other side of an evening of crashes.

The Auto-Fit Blind Spot

You’ll notice GPU Layers is locked to Auto in the model load settings (you can’t type a number in). This is the same root cause as the empty Compute Backend dropdown earlier: Studio can only compute an automatic VRAM “fit” for CUDA/ROCm/Vulkan (there’s a dedicated free-memory probe for Vulkan in its code; there’s no SYCL equivalent). Without knowing your GPUs’ free memory, it can’t confirm a fit. So it won’t let you touch manual placement, and instead hands the model to llama.cpp’s own --fit on with no explicit device pin, which decided to run this dense a model entirely on CPU rather than guess.

There’s a separate free-text field for extra/raw arguments in the load settings, independent of the locked GPU Layers control. Whatever you put there gets appended after Studio’s own flags, so it wins (llama.cpp is last-flag-wins). This is what forced GPU offload in my scenario:

-ngl -1 --fit off --device SYCL0,SYCL1

The OOM I Walked Into

Forcing full offload this way removes a safety net you don’t see until it’s gone: Studio’s --fit logic normally keeps some layers on CPU host RAM when a config wouldn’t fit in VRAM (a “tensor spill” fallback). --fit off disables that entirely… it’s all-GPU-or-crash with no graceful degradation.

My first real config – full 262144 context, --parallel 4, --kv-unified (one shared KV cache across all 4 slots), full forced offload – ran fine for a while and then died 14 minutes into generation:

level_zero backend failed with error: 39 (UR_RESULT_ERROR_OUT_OF_DEVICE_MEMORY)

The KV cache had grown past what two 24GB cards could hold alongside the model weights. Retrying with the same settings later died even earlier (during model load this time), allocating the KV cache before generation even started.

Cutting context in half and dropping parallel slots to 1 fixed it for good:

-c 131072 --parallel 1

(no --kv-unified needed once there’s only one slot). That survived a 48K-token prompt and 3600+ generated tokens at a steady 15-16 tok/s, with --spec-type draft-mtp --spec-draft-n-max 3 (MTP speculative decoding) layered on top without issue – worth adding once your base config is already stable, not before, since speculative decoding needs its own slice of VRAM too.

Guardrails for Your Own Tuning

  • A clean model load proves nothing. My “fixed” config loaded fine and then OOM’d 14 minutes into real generation. Test with an actually long generation (2000+ tokens) before trusting a config change.
  • Watch VRAM headroom while it runs, not just at startup:
    sudo xpu-smi stats -d 0
    sudo xpu-smi stats -d 1

    GPU Memory Used climbing steadily toward the 24GB ceiling as generation continues is your early warning, before it becomes a crash.
  • Start conservative, then push. --parallel 1, no --kv-unified, and a context size well under your theoretical max is a safer baseline to tune up from than starting maxed out and cutting back after a crash. I’m the only user, so messing with --parallel >1 is of no benefit anyway (unless we’re discussing rare and unusual usage patterns).

Helpful Links

  • openSUSE Tumbleweed
    • Get openSUSE Tumbleweed
    • openSUSE Wiki / Portal:Tumbleweed
  • Intel GPU Driver / Level Zero
    • Intel dgpu-docs: Choosing an Installation Path
    • intel/compute-runtime (NEO) / Level Zero & OpenCL driver source
    • Level Zero Specification docs
  • oneAPI / SYCL / DPC++
    • Intel oneAPI Toolkits overview
    • intel/xpumanager / XPU Manager / xpu-smi source + releases
    • XPU-SMI Linux documentation
  • Unsloth Studio
    • Fine-tuning LLMs on Intel GPUs with Unsloth
    • unslothai/unsloth GitHub
    • Unsloth Documentation
    • PR #4384: –with-llama-cpp-dir / Custom llama.cpp folder (https://github.com/unslothai/unsloth/pull/4384)
    • Issue #4379: feature request that led to it (https://github.com/unslothai/unsloth/issues/4379)
  • llama.cpp / SYCL backend
    • ggml-org/llama.cpp
    • llama.cpp SYCL backend build docs
  • Proxmox / PCIe Passthrough
    • Proxmox VE Wiki: PCIe Passthrough
AI / ML, Linux Tags:battlemage, gpu, intel arc, llama.cpp, llm, oneapi, opensuse, proxmox, sycl, tumbleweed, unsloth, xpu-smi

Post navigation

Previous Post: Configuring a Passive Tap / Monitor Port: Mellanox SX1024 (Onyx) Network Switch
Next Post: AMD Instinct MI100 (CDNA / Vega 20) GPU on openSUSE Leap

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Copyright © 1999-2026 Procyon Labs