Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
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
26 changes: 17 additions & 9 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,23 @@ Notable changes to vla.cpp. Format loosely follows [Keep a Changelog](https://ke
- **Hexagon NPU on the Qualcomm Dragonwing IQ-10 (Linux).**
`scripts/build_linux_hexagon.sh` cross-builds vla.cpp with `GGML_HEXAGON=ON`
in Qualcomm's toolchain container, `vla-server` included. On the IQ-10 (v81,
llama.cpp `b11223`) SmolVLA, π0.5, Evo-1 and GR00T N1.5 / N1.6 / N1.7 run
within 2.9e-3 of the CPU build on fixed inputs and serve through
`eval/client`. Concats the NPU refuses on buffers above 4 GB of DSP address
space and matmuls of a 2D weight against a batch, which it computes wrong
(GR00T N1.6 with two views), run on the CPU, and GR00T N1.7's LM leaves
flash attention (F16 scores on the HMX) unless `--flash-attn` is given.
GR00T N1.5 and N1.6 are above the bar on a served LIBERO observation, as the
CPU is at F16. See `docs/backend/hexagon.md` for the build, the skel install
and the numbers.
llama.cpp `b11223`) SmolVLA, π0, π0.5, Evo-1, GR00T N1.5 / N1.6 / N1.7,
VLA-JEPA, VLA-Adapter, OpenVLA-OFT, Octo-Small and TurboVLA run within 2.9e-3
of the CPU build on fixed inputs and serve through `eval/client`. Concats the
NPU refuses on buffers above 4 GB of DSP address space, copies that read a
weight (also answered `NO_SUPPORT`; VLA-Adapter), matmuls of a 2D weight
against a batch, which it computes wrong (GR00T N1.6 with two views), and
repeats of a computed tensor, which can read stale cache lines (TurboVLA), run
on the CPU, and GR00T N1.7's LM leaves flash attention (F16 scores on the
HMX) unless `--flash-attn` is given. Three matmuls that the HMX does not take
move onto it: SigLIP's 4304-wide MLP is zero-padded to 4320 at load, π0.5's
SigLIP takes flash attention, and Evo-1's LM attention takes F16 K/V. GR00T N1.5, N1.6,
π0.5 and Evo-1 run 27-40% faster, within the bar on fixed inputs. π0.5's VLM
and action expert take flash attention too, and the experts' KV concats run as
row copies that stay on the NPU (π0, π0.5, SmolVLA). GR00T N1.5, N1.6 and
VLA-JEPA are above the bar on a served LIBERO observation, as the CPU is at
F16. See `docs/backend/hexagon.md` for the build, the skel install and the
numbers.
- **ROCm/HIP backend for VLA inference.** `-DGGML_HIP=ON` selects ggml's HIP
backend without compiling vla.cpp's CUDA-only kernels. On Linux `gfx1200`
(Radeon RX 9060 XT) with ROCm 7.14 and llama.cpp `b11223`, every arch except
Expand Down
112 changes: 81 additions & 31 deletions docs/backend/hexagon.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ to take once it ran.

> **Status: running on Windows on Arm and on a Dragonwing IQ-10 under Linux.**
> vla.cpp builds with `GGML_HEXAGON=ON` and runs eleven checkpoints on a
> Snapdragon X laptop's v73 NPU and six on an IQ-10's v81 NPU under Linux, each
> checked against a CPU reference. The laptop build, its measurements and the
> upstream bugs found along the way are in
> Snapdragon X laptop's v73 NPU and twelve on an IQ-10's v81 NPU under Linux,
> each checked against a CPU reference. The laptop build, its measurements and
> the upstream bugs found along the way are in
> [hexagon-windows.md](hexagon-windows.md); the Linux board is in [Linux
> (IQ-10)](#linux-iq-10). What follows is the backend in general: the parts that
> hold on any Snapdragon part, and the IQ-9 and multi-NPU notes from before
Expand Down Expand Up @@ -94,7 +94,10 @@ changed all three conclusions:
it.
- **`GELU_ERF` is still missing.** It now runs on the CPU (next point) in every
DINOv2 and SigLIP-so400m tower, and costs what that implies: Evo-1 spends more
on copies than the NPU saves.
on copies than the NPU saves. An HTP kernel was written and checked on the
IQ-10 (b11223): more accurate than the CPU's (relative error 1.5e-6 against
5.1e-5), and Evo-1 7% faster. It was left out: GR00T N1.7 sits close to the
bar, and the kernel moved its fixed-input chunk from 2.0e-3 to 3.0e-3.
- **Absent is no longer fatal.** `src/backend_fallback.cpp` wraps the NPU in a
backend that runs whatever it rejects on the CPU, without touching an arch.
That also covers ops refused for shape rather than type: softmax rows that are
Expand All @@ -109,6 +112,7 @@ these, and they compute something else:
| `ADD`/`MUL`/... | `src1` broadcast over one dim but not a higher one | Refused, runs on the CPU |
| `IM2COL` | Wrong unless kernel = stride > 1 and no padding | Refused, runs on the CPU |
| `CPY` F32→F16 | Reads back wrong on the host | Copies feeding a CPU op run on the CPU |
| `REPEAT` | Reads stale cache lines of a source written by DMA earlier in the same op batch | Refused unless the source is a weight, runs on the CPU |
| fused `MUL_MAT+ADD`, `RMS_NORM+MUL` | ~10x the error of the unfused ops | `GGML_HEXAGON_OPFUSION=0` by default |

Each one flips the gripper channel, or comes close, on some checkpoint. The
Expand All @@ -117,11 +121,21 @@ was right: a missing op fails at load, and these only show in the actions.
[hexagon-windows.md](hexagon-windows.md#hexagon-issues-found-and-worked-around)
has the numbers and how each was bisected. They belong upstream.

One more op is claimed and then refused at run time. On buffers mapped above
Two more ops are claimed and then refused at run time. On buffers mapped above
4 GB of DSP address space, which the IQ-10 under Linux hands out, the NPU runs
`CONCAT` only as the dim-1 contiguous DMA copy and answers any other concat with
`NO_SUPPORT`, and the host aborts on the first predict. The wrapper sends those
concats to the CPU.
concats to the CPU. A `CPY` that reads a weight gets the same answer
(VLA-Adapter casts its F16 action queries to F32 in the graph), and also runs on
the CPU.

The experts' KV concats (π0, π0.5, SmolVLA) were such concats: along the token
dim of contiguous [head dim, heads, tokens] tensors, once per layer per denoise
step. Appending along that dim appends whole rows, so on Hexagon
`concat_dim2()` in `src/backend.h` does them as a dim-1 concat of the
[head dim x heads, tokens] views, which writes the same bytes and stays on the
NPU: π0.5 1379 to 1133 ms, SmolVLA 810 to 638 ms, outputs unchanged. π0 takes
the same path.

Flash attention on the HMX (v81) keeps scores and probabilities in F16. That is
a precision limit rather than a wrong op, but in GR00T N1.7's LM it moves the
Expand All @@ -133,6 +147,28 @@ of 1, activations above 1) is claimed and comes out wrong. GR00T N1.6's SigLIP2
tower takes two camera views that way: its action chunk lands 0.16 from the CPU
reference. The wrapper runs those matmuls on the CPU: 1.9e-3, and 25% faster.

The matrix unit (HMX) takes a matmul only when its inner dim K and its output
dim N are multiples of 32, and with a batch only an F16 src0. Anything else runs
on the vector units, at about 1/20 of the speed. `GGML_HEXAGON_PROFILE=1` on the
IQ-10 showed three such matmuls dominating, and vla.cpp now avoids them in
Hexagon builds:

- **SigLIP-so400m's MLP is 4304 wide**: 440 ms of GR00T N1.5's 565 ms tower.
The loader zero-pads fc1, its bias and fc2 to 4320 (`WeightLoader::pad`,
`gemm_width()` in `src/backend.h`), which leaves the output unchanged.
- **π0.5's attention ran explicit scores** in SigLIP (head dim 72, F32 x F32),
the VLM and the action expert, because its flash attention was tied to SYCL's
view-taking kernel. The VLM's and the expert's single KV head also sent their
matmuls to the CPU (the batched `MUL_MAT` rule above). All three now take the
plain flash attention on Hexagon (`use_flash_attention()` in `pi05.cpp`).
- **Evo-1's LM attention multiplied F32 K and V against 14 query heads.** K and
V now go to F16 (`fa_kv()`); the scores still accumulate in F32.

What is left on the vector units: GR00T's DiT attention (head dim 48) and Evo-1's
DiT cross-attention (head dim 112, 1025 keys), whose shapes the HMX does not
take, and Evo-1's InternViT attention, which stays on the CPU because F16 K/V
there measured 3.9e-2.

## What changed in `vla.cpp`

The shape of the diff was predicted correctly, apart from the scheduler:
Expand Down Expand Up @@ -280,43 +316,57 @@ export LD_LIBRARY_PATH=$PWD/pkg/lib
`vla_predict_check` at the Hexagon defaults, against the same binary with
`VLA_DEVICE=cpu --weight-dtype f32 --flash-attn 0`. A Hexagon build turns flash
attention on by default even on the CPU, so the reference asks for the explicit
path that other builds run:

| Model | max\|Δ\| |
|---|--:|
| SmolVLA | 7.2e-4 |
| π0.5 | 2.7e-4 |
| Evo-1 | 4.1e-4 |
| GR00T N1.5 | 1.7e-3 |
| GR00T N1.6 | 1.4e-3 |
| GR00T N1.7 | 2.0e-3 |
path that other builds run. Views are the ones the LIBERO client sends, so they
differ from the benchmark's for VLA-JEPA, VLA-Adapter, OpenVLA-OFT and Octo:

GR00T N1.6 here takes one view; with two it is 1.9e-3. The other archs have
not been run on the board yet.
| Model | Views | max\|Δ\| |
|---|--:|--:|
| SmolVLA | 2 | 7.2e-4 |
| π0 | 2 | 1.2e-3 |
| π0.5 | 2 | 4.8e-4 |
| Evo-1 | 1 | 5.5e-4 |
| GR00T N1.5 | 1 | 2.4e-3 |
| GR00T N1.6 | 1 | 1.4e-3 |
| GR00T N1.7 | 1 | 2.0e-3 |
| VLA-JEPA | 2 | 2.8e-3 |
| VLA-Adapter | 2 | 4.2e-4 |
| OpenVLA-OFT | 2 | 3.5e-4 |
| Octo-Small | 1 | 4.1e-4 |
| TurboVLA | 2 | 3.1e-4 |

GR00T N1.6 with two views is 1.9e-3. At the benchmark's single view VLA-JEPA is
1.9e-3, VLA-Adapter 4.8e-4 and OpenVLA-OFT 2.2e-4.

### Serving

`vla-server` on the board, driven from the host by
`eval/client/vla_cpp_client.py` and the adapters `run_sim_client_direct.py`
uses, on one fixed LIBERO observation (two views, the task prompt, a fixed
robot state) with fixed noise. The same request goes to a Hexagon server and to
a CPU server with `--weight-dtype f32 --flash-attn 0`. Every model returns a
finite chunk, the same chunk for a repeated request, an error reply to a
malformed or an invalid request, and keeps serving afterwards.
uses, on one fixed LIBERO observation (two views, the task prompt, a fixed robot
state), with fixed noise for the archs that draw it. The same request goes to a
Hexagon server and to a CPU server with `--weight-dtype f32 --flash-attn 0`.
Every model returns a finite chunk, the same chunk for a repeated request, an
error reply to a malformed or an invalid request, and keeps serving afterwards.

| Model | max\|Δ\| vs CPU F32 | CPU F16 vs CPU F32 |
|---|--:|--:|
| SmolVLA | 1.3e-3 | |
| π0.5 | 4.3e-4 | |
| Evo-1 | 4.3e-4 | |
| GR00T N1.5 | 8.3e-3 | 4.3e-2 |
| π0.5 | 3.5e-4 | |
| Evo-1 | 1.1e-3 | |
| GR00T N1.5 | 1.1e-2 | 4.3e-2 |
| GR00T N1.6 | 1.3e-2 | 1.1e-2 |
| GR00T N1.7 | 2.5e-3 | |

GR00T N1.5 and N1.6 are above the bar on this input, by about what the CPU
itself gives with F16 weights: they are sensitive to 16-bit precision rather
than miscomputed. Running them with F32 weights on the NPU has not been tried
yet.
| π0 | 5.8e-4 | |
| VLA-JEPA | 6.7e-3 | 2.1e-2 |
| VLA-Adapter | 4.5e-4 | |
| OpenVLA-OFT | 5.0e-4 | |
| Octo-Small | 9.3e-5 | |
| TurboVLA | 2.2e-4 | |

GR00T N1.5, N1.6 and VLA-JEPA are above the bar on this input, and so is the CPU
itself with F16 weights: N1.5 and VLA-JEPA land closer to the reference than the
CPU at F16, N1.6 slightly further (1.3e-2 against 1.1e-2). They are sensitive to
16-bit precision rather than miscomputed. Running them with F32 weights on the
NPU has not been tried yet.

## IQ-10, imagined

Expand Down
4 changes: 2 additions & 2 deletions docs/benchmark/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ AGX Orin row ran at `e6653e8`, on the bit-exact CUDA path
ran at `d0e5d00`, PR #35 merged with main `f464653` (same llama.cpp pin), with
fixed-input checks against the CPU build in
[backend/rocm.md](../backend/rocm.md). The Qualcomm Dragonwing IQ-10 row ran at
`e8dfa34` (PR #69, same llama.cpp pin). Each report
`1cab1c3` (same llama.cpp pin). Each report
lists the device, the build, each model's configuration, latency and peak memory
at the defaults, and the fastest runtime flags for that device.

Expand All @@ -36,7 +36,7 @@ means the model does not fit or fails there; each report says which and why.
| [Intel Arc B390 iGPU (OpenVINO)](core-ultra-x7-358h.md) | N/A | 28.5 | 116.3 | 170.2 | 106.0 | 122.8 | 131.4 | N/A | 213.1 | 620.5 | 232.5 | 1262.5 | 566.0 |
| [Intel Arc A380 (SYCL)](arc-a380.md) | 60.5 | 103.5 | 355.9 | 408.9 | 472.0 | 646.0 | 615.3 | N/A | 734.5 | 921.9 | 945.6 | - | 1047.3 |
| [Snapdragon X Hexagon NPU](snapdragon-x-hexagon.md) | 239.7 | 2280.8 | 821.0 | 4072.1 | 2755.7 | 2940.0 | 1400.2 | N/A | 1239.3 | 5730.0 | 9321.7 | - | 7208.6 |
| [Qualcomm Dragonwing IQ-10 Hexagon NPU](qualcomm-iq10.md) | n/r | n/r | n/r | n/r | 1020.9 | 1110.3 | 747.5 | N/A | 810.3 | n/r | 2914.6 | n/r | 3519.4 |
| [Qualcomm Dragonwing IQ-10 Hexagon NPU](qualcomm-iq10.md) | 121.6 | 428.1 | 440.2 | 1733.6 | 613.7 | 705.8 | 747.0 | N/A | 631.0 | 1124.4 | 1117.4 | 4097.7 | 2579.1 |
| [Intel AI Boost NPU (OpenVINO)](core-ultra-x7-358h.md) | N/A | 23.5 | 90.7 | 126.7 | 134.0 | 161.1 | 144.9 | N/A | 161.3 | 438.3 | 430.2 | 405.8 | 256.3 |
| [Intel Core i7-14700F (CPU)](core-i7-14700f.md) | 39.8 | 195.1 | 825.5 | 1140.6 | 1913.8 | 1627.9 | 1453.4 | N/A | 1689.2 | 6455.7 | 6068.1 | 9869.0 | 4159.6 |
| [Intel Core i9-14900HX (CPU)](core-i9-14900hx.md) | 67.0 | 314.7 | 1227.2 | 1659.3 | 1935.4 | 1688.9 | 1505.5 | N/A | 1822.6 | 6182.1 | 5735.0 | 9126.4 | 4118.2 |
Expand Down
66 changes: 41 additions & 25 deletions docs/benchmark/qualcomm-iq10.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ through vla.cpp's fallback wrapper.
| Power | CPU governor `performance` |
| OS | Ubuntu 24.04.4 LTS, kernel 6.6.110 |
| Toolchain | `ghcr.io/snapdragon-toolchain/arm64-linux:v0.7`: clang 21.1.8, Hexagon SDK 6.6.0.0 (tools 19.0.07) |
| Commit | `e8dfa34` (PR #69, on top of #68) |
| Commit | `1cab1c3` |
| llama.cpp | `b11223` |
| Date | 2026-11-02 11:02 to 11:48 (UTC+07) |
| Date | 2026-11-04 11:52 to 12:30 (UTC+07) |
| Build | `scripts/build_linux_hexagon.sh` (servers included); the HTP skel processed for the board and installed in `/vendor/dsp/cdsp0..3` |
| Runtime flags | defaults; the fastest flags per model are in the second table |
| Method | 3 warmups + 20 timed reps per process, 3 processes. The process with the lowest mean is reported, and memory is the peak over all three. |
Expand Down Expand Up @@ -65,12 +65,18 @@ vision stage separately.

| Model | Views | Input | min ms | mean ms | p50 ms | p90 ms | vision ms | Peak RSS MiB | System RAM MiB |
|---|--:|--:|--:|--:|--:|--:|--:|--:|--:|
| GR00T N1.7 | 1 | 256 | 747.5 | 754.7 | 753.0 | 762.7 | 196.1 | 191 | 5083 |
| SmolVLA | 2 | 512 | 810.3 | 818.6 | 820.5 | 822.6 | 283.0 | 146 | 1187 |
| GR00T N1.5 | 1 | 224 | 1020.9 | 1024.2 | 1024.2 | 1027.0 | 563.2 | 162 | 3650 |
| GR00T N1.6 | 1 | 224 | 1110.3 | 1114.5 | 1113.6 | 1118.5 | 559.8 | 147 | 4687 |
| π0.5 | 2 | 224 | 2914.6 | 2942.6 | 2934.4 | 2967.2 | 1429.6 | 285 | 5517 |
| Evo-1 | 1 | 448 | 3519.4 | 3572.4 | 3576.7 | 3588.2 | 854.5 | 319 | 1579 |
| Octo-Small | 2 | 256 + 128 | 121.6 | 123.0 | 122.3 | 125.8 | 20.5 | 253 | 804 |
| TurboVLA | 2 | 256 | 428.1 | 433.0 | 431.6 | 436.8 | - | 438 | 1327 |
| VLA-JEPA | 1 | 256 | 440.2 | 446.3 | 444.7 | 450.2 | 195.2 | 185 | 3971 |
| GR00T N1.5 | 1 | 224 | 613.7 | 615.7 | 615.7 | 618.0 | 148.3 | 162 | 3636 |
| SmolVLA | 2 | 512 | 631.0 | 632.4 | 631.7 | 634.6 | 281.8 | 146 | 1190 |
| GR00T N1.6 | 1 | 224 | 705.8 | 708.5 | 708.0 | 710.7 | 145.0 | 146 | 4869 |
| GR00T N1.7 | 1 | 256 | 747.0 | 756.0 | 755.0 | 764.5 | 197.2 | 191 | 5090 |
| π0.5 | 2 | 224 | 1117.4 | 1121.0 | 1120.8 | 1123.3 | 292.5 | 285 | 5790 |
| π0 | 2 | 224 | 1124.4 | 1128.7 | 1128.6 | 1130.5 | 293.0 | 285 | 5534 |
| VLA-Adapter | 1 | 224 | 1733.6 | 1752.3 | 1749.5 | 1765.6 | 1187.2 | 872 | 3566 |
| Evo-1 | 1 | 448 | 2579.1 | 2595.5 | 2592.1 | 2611.9 | 854.0 | 319 | 1551 |
| OpenVLA-OFT | 1 | 224 | 4097.7 | 4107.8 | 4107.8 | 4114.2 | 1187.3 | 844 | 15327 |

### Fastest configuration

Expand All @@ -94,32 +100,42 @@ rates measured at the defaults therefore do not carry over to these rows.

| Model | Fastest flags | min ms | mean ms | p50 ms | p90 ms | vision ms | Peak RSS MiB | System RAM MiB | vs defaults |
|---|---|--:|--:|--:|--:|--:|--:|--:|--:|
| GR00T N1.7 | *(defaults)* | 747.5 | 754.7 | 753.0 | 762.7 | 196.1 | 191 | 5083 | - |
| SmolVLA | *(defaults)* | 810.3 | 818.6 | 820.5 | 822.6 | 283.0 | 146 | 1187 | - |
| GR00T N1.5 | *(defaults)* | 1020.9 | 1024.2 | 1024.2 | 1027.0 | 563.2 | 162 | 3650 | - |
| GR00T N1.6 | *(defaults)* | 1110.3 | 1114.5 | 1113.6 | 1118.5 | 559.8 | 147 | 4687 | - |
| π0.5 | *(defaults)* | 2914.6 | 2942.6 | 2934.4 | 2967.2 | 1429.6 | 285 | 5517 | - |
| Evo-1 | *(defaults)* | 3519.4 | 3572.4 | 3576.7 | 3588.2 | 854.5 | 319 | 1579 | - |
| Octo-Small | *(defaults)* | 121.6 | 123.0 | 122.3 | 125.8 | 20.5 | 253 | 804 | - |
| TurboVLA | *(defaults)* | 428.1 | 433.0 | 431.6 | 436.8 | - | 438 | 1327 | - |
| VLA-JEPA | *(defaults)* | 440.2 | 446.3 | 444.7 | 450.2 | 195.2 | 185 | 3971 | - |
| GR00T N1.5 | *(defaults)* | 613.7 | 615.7 | 615.7 | 618.0 | 148.3 | 162 | 3636 | - |
| SmolVLA | *(defaults)* | 631.0 | 632.4 | 631.7 | 634.6 | 281.8 | 146 | 1190 | - |
| GR00T N1.6 | *(defaults)* | 705.8 | 708.5 | 708.0 | 710.7 | 145.0 | 146 | 4869 | - |
| GR00T N1.7 | *(defaults)* | 747.0 | 756.0 | 755.0 | 764.5 | 197.2 | 191 | 5090 | - |
| π0.5 | *(defaults)* | 1117.4 | 1121.0 | 1120.8 | 1123.3 | 292.5 | 285 | 5790 | - |
| π0 | *(defaults)* | 1124.4 | 1128.7 | 1128.6 | 1130.5 | 293.0 | 285 | 5534 | - |
| VLA-Adapter | *(defaults)* | 1733.6 | 1752.3 | 1749.5 | 1765.6 | 1187.2 | 872 | 3566 | - |
| Evo-1 | *(defaults)* | 2579.1 | 2595.5 | 2592.1 | 2611.9 | 854.0 | 319 | 1551 | - |
| OpenVLA-OFT | *(defaults)* | 4097.7 | 4107.8 | 4107.8 | 4114.2 | 1187.3 | 844 | 15327 | - |

<details><summary>Screen means (ms) per flag set</summary>

| Model | defaults | `--flash-attn` | `--mm-prec default` | `--flash-attn --mm-prec default` | `--flash-attn 0` |
|---|--:|--:|--:|--:|--:|
| GR00T N1.7 | 768.7 | 748.5 | 761.3 | 744.5 | 1086.6 |
| SmolVLA | 823.1 | 818.9 | 819.5 | 818.5 | 3018.8 |
| GR00T N1.5 | 1026.1 | 1023.0 | 1025.3 | 1026.1 | 1501.2 |
| GR00T N1.6 | 1114.4 | 1115.1 | 1114.4 | 1113.3 | 1290.3 |
| π0.5 | 2939.0 | 2956.9 | 2959.0 | 2962.7 | 2959.6 |
| Evo-1 | 3583.7 | 3593.9 | 3591.8 | 3582.6 | 5828.5 |
| Octo-Small | 125.3 | 128.8 | 124.4 | 123.5 | 124.6 |
| TurboVLA | 438.8 | 436.5 | 439.3 | 438.2 | 535.1 |
| VLA-JEPA | 446.7 | 445.8 | 444.8 | 445.2 | 817.8 |
| GR00T N1.5 | 615.8 | 619.3 | 615.3 | 618.4 | 1096.5 |
| SmolVLA | 632.1 | 633.0 | 632.5 | 632.6 | 2834.8 |
| GR00T N1.6 | 714.2 | 712.1 | 718.7 | 714.9 | 885.7 |
| GR00T N1.7 | 765.2 | 742.0 | 761.5 | 743.6 | 1081.0 |
| π0.5 | 1121.1 | 1121.9 | 1120.5 | 1121.4 | 2062.9 |
| π0 | 1129.8 | 1128.8 | 1131.8 | 1128.5 | 2090.5 |
| VLA-Adapter | 1766.1 | 1760.1 | 1756.1 | 1757.2 | 1767.1 |
| Evo-1 | 2613.0 | 2613.7 | 2617.3 | 2617.9 | 4840.1 |
| OpenVLA-OFT | 4110.3 | 4101.9 | 4101.7 | 4108.2 | 4107.9 |

</details>

## Not run

- **BitVLA**: N/A off CUDA. The only published GGUF is int2-packed, and only
CUDA builds load it.
- **π0, VLA-JEPA, VLA-Adapter, OpenVLA-OFT, Octo-Small, TurboVLA**: not run in
this round; their GGUFs were not on the board.

## Notes

Expand All @@ -132,9 +148,9 @@ its SigLIP2 tower hits the batched `MUL_MAT` the wrapper sends to the CPU; see
[backend/hexagon.md](../backend/hexagon.md#op-coverage-measured).

These rows time the defaults; they do not vouch for accuracy. On a served LIBERO
observation, GR00T N1.5 and N1.6 land above the 2.9e-3 fidelity bar, about as
far off as the CPU at F16; see
[backend/hexagon.md](../backend/hexagon.md#serving).
observation, GR00T N1.5, N1.6 and VLA-JEPA land above the 2.9e-3 fidelity bar:
N1.5 and VLA-JEPA closer to the reference than the CPU at F16, N1.6 slightly
further; see [backend/hexagon.md](../backend/hexagon.md#serving).

## Reproducing

Expand Down
Loading
Loading