Skip to content

Intel GPU backend, shared graph cache, and checkpoint hardening (0.2.0) - #18

Open
khanhnd61-vr wants to merge 34 commits into
mainfrom
sycl
Open

Intel GPU backend, shared graph cache, and checkpoint hardening (0.2.0)#18
khanhnd61-vr wants to merge 34 commits into
mainfrom
sycl

Conversation

@khanhnd61-vr

@khanhnd61-vr khanhnd61-vr commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Adds an Intel GPU backend, collapses the per-arch backend selection that made
adding one painful, then extends the same treatment to the compute graph. Tagged
as 0.2.0.

Intel GPU via SYCL

src/backend.h is the new shared ladder. Every arch used to open-code the same
accelerator-then-CPU sequence, so a new backend meant editing a dozen files; they
now call vla::backend_init. Exactly one accelerator is compiled in, picked by
the CMake flag (GGML_CUDA / GGML_SYCL / GGML_METAL), and configure fails if
two are on. BitVLA keeps its own CPU init: it pins its ggml graph to the CPU and
offloads through its own ternary CUDA kernels.

VLA_DEVICE selects the ordinal on both multi-device backends. The SYCL path
range-checks it, because ggml_backend_sycl_init guards the index with an
assert that a Release build compiles out.

Intel Arc A380 (6 GB, Xe-HPG) against the CPU backend on an AMD Ryzen 5 5500,
8 threads:

Model input CPU Arc A380 speedup
SmolVLA 512 1,920 ms 630 ms 3.0x
Evo-1 448 7,695 ms 1,176 ms 6.5x
VLA-Adapter 224 2,994 ms 517 ms 5.8x

Two SYCL workarounds. GGML_SYCL_ENABLE_VMM=0 is defaulted at backend init:
ggml-sycl's VMM pool hands out pointers oneDNN cannot wrap in a dnnl::memory,
which aborts the GEMM for any non-F32 src0. It is only a default; setting it
explicitly wins. GGML_SYCL_ENABLE_DNN=0 also clears the crash but costs ~8%.
Setup and the memory ceiling are in docs/backend/sycl.md.

Shared graph cache

Only GR00T N1.7 kept its compute graph between predict calls; the other archs
rebuilt theirs every time and reused just the arena. vla::graph_cache in
src/models/scratch_ctx.h holds the context, allocator, graph, shape key and
input handles, so an arch supplies only its key and a build lambda. N1.7 moves
onto it and eight more archs gain it. A stable graph is also what lets ggml-cuda
capture and replay.

Measured on an RTX 5090 by alternating before/after binaries per model, several
rounds: 3-10% on pi0, pi0.5, GR00T N1.5/N1.6, VLA-Adapter and VLA-JEPA, neutral
elsewhere. A single sequential sweep across all 11 models is not usable for this
comparison; the models at the tail drift by 50% or more between runs.

Hardening

Five paths where a crafted checkpoint could overrun a host buffer: the smolvla
safetensors reader trusted data_offsets against a shape-derived buffer; bitvla
and gr00tn1d6 trusted patch-count keys the image grid contradicts; vla_adapter
trusted head_blocks past the layer count; the Qwen3-VL position resample
clamped only the upper interpolation index. Each is now a load-time check or a
clamp, verified by loading hand-patched GGUFs.

Two reachable without a crafted file: a peer that announced a multipart frame and
went quiet held either server's loop forever, and the hf download command took
its cache path from VLA_CACHE or HOME unescaped.

Also fixes the red CI. ctest registers six tests and the workflow built two, so
the other four reported not run.

Numerics

Every change is bit-identical across all 11 archs, checked with
vla_predict_check per CONTRIBUTING.md. One exception, stated in the changelog:
bumping llama.cpp to b10331 moves GR00T N1.5 and N1.6 by up to 4.6e-4 on actions
peaking near 0.87, from an upstream ggml kernel change on the SigLIP tower the two
share. The other nine are unaffected.

Distribution

vla-cli --text "pick up the bowl" tokenizes with the tokenizer the architecture
was trained on, so the quickstart no longer needs raw token ids. Release builds
linux-aarch64-cpu on a native arm64 runner for Jetson-class boards. The README
gains the LIBERO success rates that were sitting in eval/reports, labelled with
their hardware and commit.

anindex added 6 commits August 9, 2026 17:05
ctest registers six tests but the workflow named only two, so the other four
reported Not Run and the job exited 8. Building the default target also keeps
the next test that gets added from breaking it again.
A crafted checkpoint could overrun host buffers in five places. The smolvla
safetensors reader trusted data_offsets against a shape-derived buffer, bitvla
and gr00tn1d6 trusted patch-count keys that the image grid contradicts,
vla_adapter trusted head_blocks past the layer count, and the qwen3-vl position
resample only clamped the upper interpolation index.

Each is now a load-time check or a clamp. While here, smolvla, evo1 and bitvla
treat a missing state vector as zeros like the other eight archs instead of
dereferencing it.

All eleven checkpoints load unchanged and predict_check output is identical.
Both servers drained multipart frames with a blocking recv, so one client that
announced a frame and went quiet held the loop forever and shutdown never ran.
A 5s receive timeout bounds it and the drain now reports the stall instead of
replying into a socket that is still mid-message.

Also reject a cache path containing a quote and a repo id starting with a
slash: both reach the hf download shell command through VLA_CACHE or HOME.
Backend::is_cuda and is_gpu were copied into every arch and never read back.
Anything that needs the device type can ask ggml_backend_get_device.
vla_model_load leaked the whole engine if the handle allocation threw. The sycl
guide named GGML_SYCL_DISABLE_DNN, which does not exist; ggml reads
GGML_SYCL_ENABLE_DNN. The chat example linked a file that was never written.
Numerics: GR00T N1.5 and N1.6 move by up to 4.6e-4 on actions peaking near 0.87
(mean 6e-5), from an upstream ggml kernel change on the SigLIP tower path the
two share. The other nine archs are bit-identical. Also drops GGML_CUDA_GRAPHS
from the Dockerfile, which llama.cpp already defaults on.
anindex added 5 commits August 9, 2026 18:47
Only gr00tn1d7 kept its compute graph between predict calls; the rest rebuilt
theirs every time and reused just the arena. graph_cache in scratch_ctx.h holds
the context, allocator, graph, shape key and input handles, so an arch supplies
only its key and a build lambda.

gr00tn1d7 moves onto it and evo1, pi0, pi05, gr00tn1d5, gr00tn1d6, vla_adapter,
openvla_oft and vla_jepa gain it. A stable graph is also what lets ggml-cuda
capture and replay. Dump modes still rebuild, since they add graph outputs.

All eleven archs verified bit-identical with vla_predict_check.
sinusoidal_time_emb was copied into pi0, pi05 and smolvla, and the causal mask
loop into five archs; both move to dit_common.h. dual_tower derives the patch
count from the conv output instead of assuming 256.

test_config_guard now calls config_is_sane rather than reimplementing it, so a
change to the real guard can fail the test. It links vla_core for that, which
takes it out of the standalone sanitizer job.
The quickstart needed raw token ids, which meant setting up the python eval
client before the first command would run. --text calls
scripts/tokenize_prompt.py with the tokenizer the arch was trained on and feeds
the ids straight in; --tokens still works. VLA_PYTHON picks the interpreter and
VLA_TOKENIZE_SCRIPT the script, so a release tarball can carry its own.

Release also builds linux-aarch64-cpu on a native arm64 runner. Jetson is the
deployment target and only x86_64 and macOS had binaries. CUDA on aarch64 still
has to be built on the device.
Latency re-measured on the 5090 at the graph-cache code, best of three sweeps.
Also surfaces the LIBERO success rates that were sitting in eval/reports, with
their hardware and commit stated: latency alone does not say the policy works.
@anindex anindex changed the title Support sycl backend for Intel GPU Intel GPU backend, shared graph cache, and checkpoint hardening (0.2.0) Aug 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants