Views
No views yet
CompiledModel GPU delegate
(no CPU fallback). It emits the dense patch tokens; a top-3 PCA of those tokens
mapped to RGB gives the classic "what the backbone sees" overlay — semantically
similar patches (object parts vs background) share a color, so the object pops out
with no labels or segmentation.vit_small_patch14_dinov2 in timm) — 12 blocks,
dim 384, 6 heads, patch 14. Fixed 448×448 input → 32×32 = 1024 patch tokens.
[1, 3, 448, 448] NCHW, RGB, ImageNet-normalized.[1, 1024, 384] patch tokens (32×32 grid, cls token dropped).[1, heads, N, d] (≤4D) with a manual softmax(qkᵀ/√d)·v; the delegate rejects
the native 5D head-split reshape.ls1/ls2) baked into the following projection weights.0.5x(1+tanh(0.79788(x+0.044715x³)))) — near-exact and
delegate-friendly; the sigmoid-GELU approximation drifts to feature corr 0.968
over 12 blocks, tanh → 0.99999.GATHER_ND).1val model = CompiledModel.create(context.assets, "dinov2_s_fp16.tflite",
2 CompiledModel.Options(Accelerator.GPU), null)
3val inputs = model.createInputBuffers()
4val outputs = model.createOutputBuffers()
5
6inputs[0].writeFloat(imageNchw) // [1,3,448,448] ImageNet-normalized
7model.run(inputs, outputs)
8val tokens = outputs[0].readFloat() // [1024*384] patch tokens -> PCA host-side1import numpy as np
2from ai_edge_litert.compiled_model import CompiledModel
3
4model = CompiledModel.from_file("dinov2_s_fp16.tflite")
5inputs = model.create_input_buffers(0)
6outputs = model.create_output_buffers(0)
7inputs[0].write(np.ascontiguousarray(image, np.float32)) # [1,3,448,448]
8model.run_by_index(0, inputs, outputs)
9tokens = outputs[0].read(1024 * 384, np.float32).reshape(1024, 384)
10
11x = tokens - tokens.mean(0)
12_, _, vt = np.linalg.svd(x, full_matrices=False)
13rgb = x @ vt[:3].T # [1024,3] -> normalize -> 32x32 RGBbenchmark_model tool — 10 warm-up runs then 50 timed runs, reported as the tool's mean.| Runtime | Backend | Graph on GPU | Latency |
|---|---|---|---|
LiteRT CompiledModel (LITERT_CL) | GPU | 864 / 864 | ~8 ms |
TFLite benchmark_model (TfLiteGpuDelegateV2) | GPU (OpenCL) | 864 / 864 | did not run |
TFLite benchmark_model | CPU (XNNPACK, 4 threads) | — | 1093.3 ms |
LITERT_CL figure is the one recorded when this model shipped, taken through LiteRT's own CompiledModel accelerator — the path the Kotlin sample app and the LiteRT API use. The TfLiteGpuDelegateV2 figure is the classic TFLite OpenCL delegate, measured with a tool anyone can download and re-run. They agree on how much of the graph the GPU takes; they disagree on speed, and the classic delegate is the slower of the two here. Read the TfLiteGpuDelegateV2 row as a reproducible floor, not as this model's speed on LiteRT.dinov2_s_erf_fp16.tflite is the same model with the MLP GELU emitted as the
builtin GELU op (exact erf — the activation the official DINOv2 uses), features
matching the original file at corr 0.99999:| file | NPU (Hexagon v81) | GPU (Adreno) |
|---|---|---|
dinov2_s_fp16.tflite (tanh-GELU) | 85.9 ms | 54.7 ms |
dinov2_s_erf_fp16.tflite (GELU op) | 41.9 ms | 55.2 ms |
dinov2_s_fp16.tflite for Mali.CompiledModel 2.2.0, on-device JIT compile (first load
compiles in ~2-3 min and caches; later loads 0.2-0.4 s), one accelerator per process,
warm-up then N=50 timed runs, median reported, every row at thermal status NONE.
JIT matches the earlier ahead-of-time row (85.9 ms JIT vs 86.0 ms AOT). Latencies were
taken on the fp32 build of the same graph; storing the weights as fp16 (these files)
measured within run-to-run noise on this model (fp32-fold test: 85.9 -> 83.3/89.2 ms).
The runtime libraries the NPU needs are in the NPU recipe; GPU wiring is in the GPU recipe.