Skip to content

fix(litertlm): pin the vision encoder to the CPU backend on iOS - #413

Open
yjinjo wants to merge 1 commit into
DenisovAV:mainfrom
yjinjo:fix/vision-encoder-cpu-backend
Open

fix(litertlm): pin the vision encoder to the CPU backend on iOS#413
yjinjo wants to merge 1 commit into
DenisovAV:mainfrom
yjinjo:fix/vision-encoder-cpu-backend

Conversation

@yjinjo

@yjinjo yjinjo commented Aug 9, 2026

Copy link
Copy Markdown

Passing PreferredBackend.gpu also routes the vision encoder to Metal, where it cannot be prepared:

ERROR: Node number 41 (STABLEHLO_COMPOSITE) failed to prepare.
Failed to create conversation: INTERNAL:
  [runtime/executor/vision_litert_compiled_model_executor.cc:275]

Reproduced on an iPhone 17 Pro Max (iOS 26.6) with gemma-4-E2B-it.litertlm, supportImage: true, maxTokens: 2048. In debug builds the failure is silent and looks like a hang; only a profile build surfaces the error.

The .litertlm file already ships section_backend_constraint: cpu for vision_adapter and audio_encoder, so mixed backends are the intended configuration -- the vision encoder is simply missing that constraint. The audio backend here is already hardcoded to CPU for the same reason; this applies the same treatment to vision.

Measured on the same device (profile build, image + Korean prompt), time to first token:

all CPU                     3799 ms cold / 3727 ms warm
GPU LLM + CPU vision        6013 ms first ever (Metal shader
                            compile), 3487 ms cold after restart,
                            1499-1636 ms warm

A follow-up could expose visionBackend as a parameter instead of hardcoding it, once the Metal delegate gains STABLEHLO_COMPOSITE support.

Passing `PreferredBackend.gpu` also routes the vision encoder to Metal,
where it cannot be prepared:

    ERROR: Node number 41 (STABLEHLO_COMPOSITE) failed to prepare.
    Failed to create conversation: INTERNAL:
      [runtime/executor/vision_litert_compiled_model_executor.cc:275]

Reproduced on an iPhone 17 Pro Max (iOS 26.6) with
gemma-4-E2B-it.litertlm, supportImage: true, maxTokens: 2048.
In debug builds the failure is silent and looks like a hang; only a
profile build surfaces the error.

The .litertlm file already ships `section_backend_constraint: cpu` for
vision_adapter and audio_encoder, so mixed backends are the intended
configuration -- the vision encoder is simply missing that constraint.
The audio backend here is already hardcoded to CPU for the same reason;
this applies the same treatment to vision.

Measured on the same device (profile build, image + Korean prompt),
time to first token:

    all CPU                     3799 ms cold / 3727 ms warm
    GPU LLM + CPU vision        6013 ms first ever (Metal shader
                                compile), 3487 ms cold after restart,
                                1499-1636 ms warm

A follow-up could expose `visionBackend` as a parameter instead of
hardcoding it, once the Metal delegate gains STABLEHLO_COMPOSITE
support.
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