Files
bdi_podman_serverconf/containers/llamacpp/llamacpp-opencl.Containerfile
T

110 строки
5.5 KiB
Docker

### LLaMACpp Builder Container with OpenCL for Qualcomm Adreno GPUs
### Build from source with GGML_OPENCL=ON since no official Linux OpenCL release exists
###
### BUILD: podman build -t llamacpp:opencl-arm64 -f llamacpp-opencl.Containerfile .
### Export: podman save -o /home/badstorm/llamacpp-opencl-arm64.tar localhost/llamacpp:opencl-arm64
###
### ATTENZIONE: i modelli quantizzati IQ2_* / IQ3_* NON sono supportati dal
### backend OpenCL di llama.cpp (nessun kernel mul_mv_iq2_*/iq3_* esiste in
### ggml/src/ggml-opencl/kernels/), indipendentemente dalle patch qui sotto.
### Q2_K/Q3_K invece SONO supportati (riusano i kernel Q4_K).
FROM ubuntu:26.04
USER root
EXPOSE 8090
# Mesa 26.2.0-rc3 buildata da noi (build-mesa.sh in ./deb): su Debian experimental e' solo amd64/i386, niente arm64 ancora
COPY deb/*.deb /tmp/mesa-deb/
RUN apt-get update \
&& apt-get install -y curl tar grep sed git ffmpeg nano python3-pip python3 python3-wheel \
ocl-icd-libopencl1 ocl-icd-opencl-dev opencl-headers clinfo \
libclang-cpp19 libllvmspirvlib19.1 libclc-19 \
cmake ninja-build build-essential pkg-config libcurl4-openssl-dev \
# --force-overwrite: il .deb Mesa patchato non dichiara Replaces/Conflicts
# verso i pacchetti mesa stock che alcune dipendenze (es. ffmpeg) portano.
&& dpkg -i --force-overwrite /tmp/mesa-deb/*.deb \
&& apt-get install -y -f \
&& test -f /etc/OpenCL/vendors/rusticl.icd \
&& rm -rf /tmp/mesa-deb \
&& pip install --break-system-packages --upgrade setuptools \
&& pip install --break-system-packages -U "huggingface_hub[cli]" \
&& if [ -f requirements.txt ]; then pip install --break-system-packages -r requirements.txt; fi \
&& apt autoremove -y \
&& apt clean -y \
&& rm -rf /tmp/* /var/tmp/* \
&& rm -rf /var/lib/apt/lists/* \
&& find /var/cache/apt/archives /var/lib/apt/lists -not -name lock -type f -delete \
&& find /var/cache -type f -delete
WORKDIR /build
RUN git clone --depth 1 https://github.com/ggml-org/llama.cpp
# Patch per far compilare/girare il backend OpenCL su Mesa/rusticl invece del
# driver Adreno proprietario per cui e' stato scritto originariamente. Vedi
# FIX.md accanto a questo file per l'analisi completa di ogni singola patch
# (perche' serve, come e' stata verificata su hardware reale). In sintesi:
# 1. riconosce "FD6*" (nome device Rusticl/Freedreno) come famiglia Adreno
# 2. accetta cl_khr_subgroup_ballot come prova di supporto subgroup, dato
# che rusticl non espone mai la stringa legacy cl_khr_subgroups
# 3. forza la macro -D cl_qcom_reqd_sub_group_size in compilazione, per
# attivare i rami di codice kernel che assumono hardware Adreno reale
# (subgroup size 64), assenti in un ramo "generico"
# 4. mul_mv_q4_k_f32.cl: vload_half() al posto del dereference diretto di
# un puntatore half (Mesa lo rifiuta, il driver Adreno lo tollera)
# 5. mul_mm_q4_k_f32_l4_lm.cl: address space esplicito su un puntatore
# locale (bug upstream, non specifico di Mesa - il file gemello
# mul_mm_q5_k_f32_l4_lm.cl non ha il problema)
# 6. mul_mv_f16_f32_l4.cl: la macro sub_group_shuffle_xor->qcom_* scattava
# con la sola macro del punto 3, ma richiede una diversa estensione
# proprietaria (cl_qcom_subgroup_shuffle) che Mesa non implementa
# 7. clampa local_work_size anche contro CL_DEVICE_MAX_WORK_ITEM_SIZES
# (1024 su questo device, non solo il limite di prodotto CL_DEVICE_
# MAX_WORK_GROUP_SIZE=2048) in 9 punti di dispatch - senza questo,
# QUALSIASI modello con n_embd (o dimensione analoga) sopra 1024
# falliva con CL_INVALID_WORK_ITEM_SIZE (es. Qwen2.5-1.5B, n_embd=1536)
COPY opencl-mesa-rusticl.patch /tmp/
RUN cd llama.cpp && git apply /tmp/opencl-mesa-rusticl.patch \
&& rm -f /tmp/opencl-mesa-rusticl.patch
# GGML_OPENCL_USE_ADRENO_KERNELS=OFF: i kernel "Adreno-optimized" (_flat,
# _noshuffle, _moe/_ns) sono scritti per il driver proprietario e in parte
# non compilano affatto su Mesa (estensioni vettoriali/builtin proprietari
# senza fix possibile, vedi FIX.md). Con OFF il C++ che li compilerebbe/
# userebbe resta escluso a compile-time: il routing MoE passa comunque dai
# kernel standard mul_mv_id_*, non gated da questo flag.
RUN cd llama.cpp \
&& mkdir build && cd build \
&& cmake .. -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DGGML_OPENCL=ON \
-DGGML_OPENCL_EMBED_KERNELS=ON \
-DGGML_OPENCL_USE_ADRENO_KERNELS=OFF \
-DBUILD_SHARED_LIBS=ON \
&& cmake --build . --config Release -j$(nproc)
# Copy the built binaries and libraries into /app, matching the layout the runtime expects
RUN mkdir -p /app \
&& find /build/llama.cpp/build/bin -maxdepth 1 -type f -exec cp {} /app/ \; \
&& find /build/llama.cpp/build -maxdepth 3 -iname "*.so*" -exec cp -P {} /app/ \; \
&& find /app -maxdepth 1 -type f -exec chmod +x {} \; \
&& rm -rf /build
WORKDIR /app
ENV PATH=/app:$PATH
ENV LD_LIBRARY_PATH=/app:$LD_LIBRARY_PATH
ENV HF_XET_HIGH_PERFORMANCE=1
ENV LLAMA_ARG_HOST=0.0.0.0
ENV LLAMA_ARG_PORT=8090
ENV LLAMA_ARG_HF_REPO=unsloth/Qwen3.5-35B-A3B-GGUF:Q2_K_XL
ENV LLAMA_ARG_LOAD_MODE=none
ENV LLAMA_ARG_CTX_SIZE=128000
# Adreno-specific: make sure Rusticl/OpenCL device is picked correctly
ENV GGML_OPENCL_PLATFORM=0
ENV GGML_OPENCL_DEVICE=0
# NECESSARIA: senza questa, Rusticl carica la piattaforma OpenCL ma con 0
# device (il driver Freedreno non viene attivato). Con questa variabile
# clinfo/ggml_opencl vedono correttamente il device Adreno (es. FD690).
ENV RUSTICL_ENABLE=freedreno
ENTRYPOINT ["/app/llama-server"]
CMD ["--no-warmup"]