Skip to content

vla_adapter: fused DINOv2 + SigLIP towers and Qwen2 LM on SYCL - #56

Open
sandlbn wants to merge 2 commits into
VinRobotics:mainfrom
sandlbn:vla-adapter-sycl-fused
Open

sandlbn wants to merge 2 commits into
VinRobotics:mainfrom
sandlbn:vla-adapter-sycl-fused

Conversation

@sandlbn

@sandlbn sandlbn commented Oct 25, 2026

Copy link
Copy Markdown
Contributor

Depends on the SYCL fused-nodes PR. On SYCL with BF16 weights and view-taking flash attention (--flash-attn 0 or VLA_ADAPTER_NO_FUSE=1 keep the per-op F32 graph):

  • Towers. DualTower::enable_fused runs both towers as EncStack's fused blocks with the erf GELU. DINOv2's LayerScale is folded into its proj / fc2 weights. Every view goes through each tower in one pass, and the projector is three fused GEMMs. The per-op graph ran each view's towers separately with explicit attention. OpenVLA-OFT uses the same DualTower and could call enable_fused too; that is not enabled or measured here.
  • LM. The Qwen2 layers use modules/fused_lm.h. Each layer's F32 output still feeds its Bridge-Attention block.

Results

Core Ultra 7 356H (Panther Lake), 224 px, vla-bench p50:

views per-op F32 this PR vision
1 351 ms 124 ms 188 → 42 ms
2 753 ms 209 ms 375 → 72 ms

Actions vs the F32 graph (fixed inputs), max / mean: 5.4e-3 / 1.2e-3 (1 view), 3.7e-3 / 7.3e-4 (2 views), on actions up to 0.66.

LIBERO-object, 10 tasks x 10 episodes per arm, same binary:

success Wilson 95% median ms / request
per-op F32 (VLA_ADAPTER_NO_FUSE=1) 99/100 95-100% 789
this PR 100/100 96-100% 232

Verified

  • Builds clean under -Wall -Wextra (first-party code)
  • ctest passes
  • Numeric output unchanged (vla_predict_check diff), or the change is
    meant to move it and a LIBERO sweep is below

Archs and backends tested:

Linux x86 / PTL

layers/fused_ew.h, with CPU references and SYCL kernels:
- fused_rms: RMSNorm into F32 / BF16 rows (fused_rms_q8 wrote only q8 blobs)
- fused_swiglu: the GLU node with SiLU, into BF16 rows or a q8 blob
- FUSED_GELU_ERF: an exact-GELU epilogue for fused_linear and qlinear
  (oneDNN eltwise_gelu_erf); the old bool argument still means tanh
- fused_lnorm without affine (null weight and bias)
- fused_rope_kv_table: RoPE from per-token cos/sin tables (rope_2d), with a
  BF16 output so a batch of views can be read in place by the attention

modules/fused_lm.h: a Qwen2 / Llama decoder layer as 8 fused nodes.
modules/encoder: EncCfg::gelu_erf, and fold_layer_scale for folding
LayerScale into resident BF16 weights.

tests/test_fused_sycl_ops checks every new node against the CPU reference.
pi0.5's actions are bit-identical to before (default and W8A8).
On SYCL with BF16 weights and view-taking flash attention, DualTower runs
both towers as EncStack's fused blocks (DINOv2's LayerScale folded into its
weights), every view in one pass, the projector as three fused GEMMs; the
Qwen2 LM layers use modules/fused_lm.h. --flash-attn 0 or
VLA_ADAPTER_NO_FUSE=1 keep the per-op F32 graph.

Core Ultra 7 356H, 224 px, vla-bench p50: 1 view 351 -> 124 ms, 2 views
753 -> 209 ms. LIBERO-object x100: 100/100 (per-op F32: 99/100).
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.

1 participant