Repository navigation
Conversation
…(tools/vision gains -DSTRATA_VISION_SYCL=ON and no source change; the encoder gets its launcher; setup and docs/INTEL.md stop declining --vision) strata-vision is the image encoder, and it is not a Strata kernel: it is a thin front end over llama.cpp's mtmd and the model's mmproj GGUF, and tools/mtmd/clip.cpp selects its backend by device *type*, so with GGML_SYCL=ON the CLIP graph lands on the Arc with no source change. The engine's half of the path is already in the port (--vision, the GENI request, the per-cell M-RoPE table and the SVE1 file), so what was missing is a build option and a wiring step - which is what this is, on one Intel card. tools/vision/CMakeLists.txt gains STRATA_VISION_SYCL beside STRATA_VISION_CUDA, and the GPU backends are one list there. sycl/serve/strata-vision-sycl.sh is the encoder's launcher, in the shape of the port's own launcher for the engine, because serve/server.py execs the config's vision.exe directly and a binary built against oneAPI does not resolve libsycl.so.9, oneMKL or UMF from the loader's default path. sycl/tools/build.sh builds the encoder beside the engine, sycl/setup_intel.py answers --vision with it (gpu, or the same binary on the CPU), tools/test_setup_intel_vision.py holds the setup branch and the launcher to that, and docs/INTEL.md's comparison table and "Not done" section stop saying images are missing on the port. Measured on an Arc A770 16 GB (Alchemist, compute capability 12.55), xe, Linux 7.2.6, oneAPI 2026.1 (JIT), Ryzen 9 3950X, 64 GB RAM, against llama.cpp 207bdab: the encoder builds (239 targets, 0 errors) and writes the engine's SVE1 record for a 1862x1094 screenshot as 720 rows on a 40x18 grid at n_embd 2560; the Arc encodes it in 1.06 s (the CPU 5.02 s) and a 512x512 picture in 0.21 s, after a one-time 18.6 s warm-up. Two producers, one binary: the Intel one against the CPU one, mean absolute difference 4.0e-04 per float (1862x1094: per-row cosine mean 0.999711, min 0.970711, 4 of 720 rows below 0.99; 512x512: mean 0.999685, min 0.971744, 1 of 256; header, grid and width identical) - close, not bit-exact. The Intel producer is byte-deterministic (two runs, identical files), and a fresh image request through the serving path answers correctly about the picture (the page title and the sidebar's "Designed by" off a real web page screenshot). Windows: Linux only as shipped - the launcher is a shell script and sycl_vision_encoder() answers "the SYCL port runs on Linux only" there. docs/INTEL.md says so.
Owner
|
Thanks for the pull request. We're resetting the tracker for 0.2.0-beta. There are more than 1,300 open issues and pull requests, too many for us to review properly, so we're closing everything that isn't being worked on right now. Closed here does not mean rejected. To reopen it takes about two minutes:
The rules are in CONTRIBUTING.md. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Title
Issue: none; this adds the image encoder to the Intel port (related to #1545, #1606, the Arc A770 setup work
this was measured on, and #2229, which covers the CPU half of the same wiring).
Summary
On
main, images are the one feature the CUDA engine has that the Intel port does not. The engine's half of thepath is already ported (
--vision, theGENIrequest, the per-cell M-RoPE table, theSVE1file); what ismissing is the program that turns a picture into those rows.
That program is
strata-vision, the encoder intools/vision. It is a thin front end over llama.cpp'smtmdand the model's
mmprojGGUF, with no kernel of Strata's own, andtools/mtmd/clip.cppselects its backend bydevice type, so llama.cpp's SYCL backend runs the CLIP graph on the Arc with no source change to the tool.
What was missing was a build option and a wiring step.
This change adds both, demonstrated end to end on an Arc A770 on
xe:tools/vision/CMakeLists.txtgainsSTRATA_VISION_SYCL, the encoder gets the launcher a oneAPI binary needs,sycl/tools/build.shbuilds itbeside the engine, and
sycl/setup_intel.pystops answering--visionwithnone.docs/INTEL.md'scomparison table and its "Not done" section said images were missing on the port; the port's row is now
yes.What changed
Six files, +374/-7, all under
tools/,sycl/anddocs/. Nothing else is touched.tools/vision/CMakeLists.txt(+25/-1):option(STRATA_VISION_SYCL ...)for the Intel GPU, the matchingset(GGML_SYCL ... FORCE)beside the existingGGML_CUDAline, and oneif(STRATA_VISION_SYCL)block thatrequires
MKL_DIR(ggml-sycl's CMake doesfind_package(MKL REQUIRED)for the INTEL target) and prints oneSTATUSline. The GPU backends are one list (STRATA_VISION_GPU), refused when more than one is set. Theoption defaults OFF, so a build that does not pass it configures exactly as before.
sycl/serve/strata-vision-sycl.sh(new, 58 lines): the encoder's launcher, in the shape ofstrata-sycl.sh,the engine's own. A header names its two variables (
STRATA_VISION_BIN,STRATA_ONEAPI_ROOT); theLD_LIBRARY_PATHis composed from the oneAPI install it finds, with no hard-coded paths; anlddpreflightmakes a missing runtime fail with a named fix instead of the loader's message; and
exec "$bin" "$@"passesevery argument the server sends through unchanged.
sycl/setup_intel.py(+83/-3):sycl_vision_encoder()(discovers the built encoder the waysycl_engine()discovers the engine),
vision_intel()(yes/gpuplace the CLIP graph on the Arc,cpuruns the samebinary without
--gpu; anything else, or no encoder, leaves images off with a message),build_engine_sycl()(stages the encoder where the config can name it), and
to_sycl(), which keeps the config'svisionsection,names the launcher, and raises
--vram-reserve-mibto the encoder's own need.sycl/tools/build.sh(+46): no targets builds the encoder beside the engine,strata-visionbuilds it alone,stratastill builds the engine alone. Missing a llama.cpp checkout or oneMKL it says so and the engine stillbuilds.
docs/INTEL.md(+21/-3): theimagesrow of the comparison table, a short "Images on the SYCL port" section(what the encoder is, what to build, the
--visionwiring, what the first image costs), and the "Not done"entry rewritten so it no longer claims images are missing on the port. The section carries no measurement of
this work (no card, no encode times, no comparison against the CPU producer, no end-to-end claim); the numbers
are below, where a reviewer looks for them.
tools/test_setup_intel_vision.py(new, 11 tests): off stays off;yes/gpuneed a built encoder;cpuisthe same binary without
--gpu; the config'svisionsection survivesto_sycl()and names the launcher;and the launcher exists, is executable, keeps the encoder's arguments, and finds the oneAPI install from the
icpxonPATHor fromSTRATA_ONEAPI_ROOT, with the real launcher run against a tree laid out like aninstall.
How it was checked (Arc A770 16 GB, Alchemist, compute capability 12.55, xe, Linux 7.2.6, oneAPI 2026.1 JIT, Ryzen 9 3950X, 64 GB RAM)
Model
Qwen3.8-Flash-Next-Uncensored-IQ3_XXSwith its ownmmproj(F16,projection_dim2560). Encoder builtagainst llama.cpp
207bdab. Every number below was measured on this branch's own binary, on this card.The build.
cmake -S tools/vision -B build-vision-sycl -G Ninja -DCMAKE_BUILD_TYPE=Release -DLLAMA_DIR=<checkout> -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx -DSTRATA_VISION_SYCL=ON -DMKL_DIR=<oneMKL cmake dir>then--target strata-vision: 239 targets, 0 errors. The same configure runfour ways:
-DSTRATA_VISION_SYCL=ON -DMKL_DIR=…GGML_SYCL=ON,GGML_SYCL_F16=OFF,GGML_SYCL_DNN=ON(oneDNN is not installed, so it is inert),GGML_CUDA=OFF-DSTRATA_VISION_CUDA=ON -DSTRATA_VISION_SYCL=ONSTRATA_VISION_CUDA;STRATA_VISION_SYCL are exclusive; a build has one GPU backend-DSTRATA_VISION_SYCL=ONwith noMKL_DIRGGML_SYCL=OFF, unchanged from todayWhat it encodes. Against this model's
mmproj:720 rows on a 40x18 raster grid,
n_embd=2560, oneSVE1record, for a real 1862x1094 screenshot. 256 rows on16x16 for a 512x512 picture.
nx*ny == nand the width the engine insists on.Two producers, one binary. The encoder is both producers (with
--gputhe CLIP graph is on the Arc,without it on the CPU), which removes the usual confound in a CPU-versus-GPU comparison. Compared record by
record with a local comparator (it reads two
SVE1files and reports the per-row cosine and the max and meanabsolute difference; it is a measuring instrument, so it is not in the tree):
Numerically close, not bit-exact. Two controls: the Intel producer is byte-deterministic (two runs,
identical files), and turning flash attention off on the CPU backend alone moves the same rows by 1.0e-02 (max
abs), about two thirds of the 1.5e-02 that the same picture's CPU-and-GPU pair differs by, so the residual is
arithmetic ordering rather than preprocessing. A wrong resize, patch raster order or merge order gives rows that
are unrelated (cosine near zero), not rows that agree to three decimal places.
Encode time, on the Arc (this branch's binary, same A770):
READY(one 2048x2048 image at the 1024-token cap)The warm-up is almost all one-time JIT compilation of the CLIP graph, not the picture. No performance claim is
made: the encoder is not on the critical path (one encode per picture, cached by the image's hash for later
turns), and nothing about the text model's speed changes.
End to end.
--visionreaches the engine, the encoder starts before it (so its device buffers are allocatedbefore the engine sizes its expert cache), and a fresh OpenAI image request about the real screenshot returns
the right two facts about it:
The request ran against a server whose
vision.exeis this branch's launcher and whose encoder is this branch'sown build.
The launcher's preflight, four ways. With no oneAPI install reachable (no
LD_LIBRARY_PATH, noicpxonPATH, no/opt/intel/oneapi) it exits 1 with the one fix to apply. The capture isevidence/fresh/launcher-preflight-four-ways-runtime-root.txt, run on this commit; the threelauncher-preflight-both-ways*files beside it are the earlier revisions, kept as they were taken and labelled(the revision before the last review pass, the three-commit tip, the run before the launcher was renamed):
It preflights clean and execs the encoder in the other three cases: with
STRATA_ONEAPI_ROOTset to the oneAPItree; with nothing set but an install at Intel's own default
/opt/intel/oneapi; and with theicpxonPATHand the loader path otherwise empty, the route that takes the root from the compiler's own location. An unknown
argument reaches the encoder's own parser (
unknown argument --bogus, exit 2, device untouched), which provesresolution without using the card. On the card the encoder runs to
READY 2560andOKrecords.Extra Notes
xeonly: not Battlemage or a B-series, not an A750 oni915, not a two-card box.ONEAPI_DEVICE_SELECTORis the device switch, moot on one Intel card.toolchain from the port's container overlay; at run time the launcher finds oneAPI from
icpxonPATH, fromSTRATA_ONEAPI_ROOT, or from Intel's own default/opt/intel/oneapi.rows as the picture and answers about it correctly, and a token that diverges against llama.cpp is not excluded.
sycl/serve/strata-sycl.shis the engine's launcher and runsthe engine inside the port's dev image, so it cannot start the encoder.
serve/server.pystarts the config'svision.exeitself, as a host process, where the container's oneAPI runtime is not on the loader path;strata-vision-sycl.shis the launcher that supplies it, named the waystrata-sycl.shis, the binary itstarts then the backend that binary was built for.
yes/gpuwith awarning; this one adds the GPU path and the setup wiring around it, so both change
sycl/setup_intel.py.Whichever lands first, the other needs a small rebase. sycl: enable vision (--vision cpu) on intel #2229 also remaps the embeddings path for the container
deployment (
sycl/serve/server_intel.py,install_embeddings_path), which this change does not close.mtmdstack at thepinned commit, which is why the encoder cannot be built by the port's own CMake. The encoder is built against
llama.cpp
207bdabhere while the port pins3cf03257(the engine'sCMakeLists.txtGIT_TAG, the revisionrecorded in
third_party/ggml/VERSION.txt), so a llama.cpp bump has to move both builds and re-run thecomparison. Everything else added is opt-in:
--visionis off unless setup is asked for images, and noexisting path changes shape if the option is not passed.
.cpp(strata_vision.cppis byte-identical to
main), no debug output, no scratch scripts, no shared helper, no measuring instruments.The launcher composes its own runtime rather than adding a second mechanism beside
strata-sycl.sh.sycl/; this change touchestools/vision/CMakeLists.txtanddocs/INTEL.mdas well, because the encoder and its documentation are notper-vendor files. Nothing in
sycl/is regenerated fromdpctoutput, so nothing here is at risk fromsycl/tools/normalize.sh.This change was developed with AI assistance and reviewed and verified by a human before submission.