From a432e652c33968dc41b52e0f7d5664a8f1db80ca Mon Sep 17 00:00:00 2001 From: BadStorm Date: Thu, 9 Jul 2026 22:59:46 +0200 Subject: [PATCH] Add ardeno fix --- .gitattributes | 1 + containers/llamacpp/build-mesa.sh | 49 ++++++++--- ...ubgroups_26.2.0-devel+subgroups1_arm64.deb | 3 + .../llamacpp/llamacpp-opencl.Containerfile | 75 +++++++++------- containers/llamacpp/opencl-mesa-rusticl.patch | 88 +++++++++++++++++++ 5 files changed, 173 insertions(+), 43 deletions(-) create mode 100644 containers/llamacpp/deb/mesa-freedreno-subgroups_26.2.0-devel+subgroups1_arm64.deb create mode 100644 containers/llamacpp/opencl-mesa-rusticl.patch diff --git a/.gitattributes b/.gitattributes index 36802d6..ad61f37 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1 +1,2 @@ containers/odoo/deb/*.deb filter=lfs diff=lfs merge=lfs -text +containers/llamacpp/deb/*.deb filter=lfs diff=lfs merge=lfs -text diff --git a/containers/llamacpp/build-mesa.sh b/containers/llamacpp/build-mesa.sh index bd16ddd..8e9c069 100644 --- a/containers/llamacpp/build-mesa.sh +++ b/containers/llamacpp/build-mesa.sh @@ -22,12 +22,23 @@ sudo apt-get update sudo apt-get build-dep -y mesa || { echo "build-dep su pacchetto 'mesa' fallito o non disponibile, installo un set minimo esplicito." sudo apt-get install -y \ - git meson ninja-build pkg-config python3-mako python3-pip \ - libdrm-dev libx11-dev libxext-dev libxfixes-dev libxcb1-dev \ + git meson ninja-build pkg-config pkgconf python3 python3-mako python3-pip \ + python3-ply python3-pycparser python3-yaml python3-setuptools \ + libdrm-dev libx11-dev libx11-xcb-dev libxext-dev libxfixes-dev libxcb1-dev \ libxcb-glx0-dev libxxf86vm-dev libxrandr-dev libwayland-dev \ - wayland-protocols llvm-dev clang libclc-dev spirv-tools \ - libspirv-tools-dev rustc cargo libelf-dev libzstd-dev \ - libexpat1-dev bindgen cbindgen dpkg-dev debhelper devscripts + libwayland-egl-backend-dev libxcb-randr0-dev libxcb-shm0-dev \ + libxcb-dri2-0-dev libxcb-dri3-dev libxcb-present-dev \ + libxcb-sync-dev libxcb-xfixes0-dev libxshmfence-dev \ + x11proto-dev linux-libc-dev libsensors-dev \ + libva-dev libvdpau-dev libvulkan-dev libglvnd-core-dev \ + wayland-protocols llvm-dev llvm-19-dev clang \ + libclang-19-dev libclang-cpp19-dev libclc-19-dev libclc-19 \ + spirv-tools glslang-tools llvm-spirv-19 libllvmspirvlib-19-dev \ + flatbuffers-compiler libflatbuffers-dev libxtensor-dev \ + byacc bison flex zlib1g-dev libelf-dev libzstd-dev libexpat1-dev \ + rustc cargo rustfmt bindgen cbindgen \ + librust-paste-dev librust-syn-dev \ + valgrind dpkg-dev debhelper devscripts } echo @@ -49,9 +60,25 @@ else fi if [ -z "${MESA_SRC:-}" ]; then - CLONE_DIR="/tmp/mesa-$(date +%Y%m%d-%H%M%S)" - echo "=== Clono ${CLONE_URL} in ${CLONE_DIR} ===" - git clone "${CLONE_URL}" "${CLONE_DIR}" + CLONE_DIR="/tmp/mesa-src" + + if [ -d "${CLONE_DIR}/.git" ]; then + EXISTING_URL="$(git -C "${CLONE_DIR}" remote get-url origin 2>/dev/null || echo "")" + if [ "${EXISTING_URL}" = "${CLONE_URL}" ]; then + echo "=== Checkout gia' presente in ${CLONE_DIR}, aggiorno allineandolo a origin/main ===" + git -C "${CLONE_DIR}" fetch origin main + git -C "${CLONE_DIR}" checkout -B main origin/main + git -C "${CLONE_DIR}" reset --hard origin/main + else + echo "=== ${CLONE_DIR} esiste ma punta a un remote diverso, rifaccio il clone ===" + rm -rf "${CLONE_DIR}" + git clone "${CLONE_URL}" "${CLONE_DIR}" + fi + else + echo "=== Clono ${CLONE_URL} in ${CLONE_DIR} ===" + git clone "${CLONE_URL}" "${CLONE_DIR}" + fi + MESA_SRC="${CLONE_DIR}" fi @@ -68,7 +95,8 @@ echo echo "=== Verifica commit fix subgroup presente ===" mkdir -p "${DEB_OUT_DIR}" cd "${MESA_SRC}" -if git log --oneline | grep -q "185c89084ab7\|Expose subgroup ops"; then +SUBGROUP_COMMIT="185c89084ab7a84722b75af6a6026b56945ed44e" +if git merge-base --is-ancestor "${SUBGROUP_COMMIT}" HEAD 2>/dev/null; then echo "OK: commit fix subgroup trovato nella history." else echo "ATTENZIONE: non trovo il commit atteso nella history di questo checkout." >&2 @@ -83,11 +111,11 @@ echo "=== Build Mesa (meson/ninja) ===" rm -rf "${BUILD_DIR}" meson setup "${BUILD_DIR}" "${MESA_SRC}" \ -Dprefix=/usr \ + -Dsysconfdir=/etc \ -Dgallium-drivers=freedreno \ -Dvulkan-drivers= \ -Dgallium-rusticl=true \ -Dgallium-rusticl-enable-drivers=freedreno \ - -Dopencl-spirv=true \ -Dbuildtype=release \ 2>&1 | tee -a "${LOG_FILE}" @@ -120,6 +148,7 @@ else rm -rf "${PKG_ROOT}" mkdir -p "${PKG_DIR}/DEBIAN" cp -a "${DESTDIR}/usr" "${PKG_DIR}/" + [ -d "${DESTDIR}/etc" ] && cp -a "${DESTDIR}/etc" "${PKG_DIR}/" cat > "${PKG_DIR}/DEBIAN/control" << EOF Package: ${PKG_NAME} diff --git a/containers/llamacpp/deb/mesa-freedreno-subgroups_26.2.0-devel+subgroups1_arm64.deb b/containers/llamacpp/deb/mesa-freedreno-subgroups_26.2.0-devel+subgroups1_arm64.deb new file mode 100644 index 0000000..8422c4f --- /dev/null +++ b/containers/llamacpp/deb/mesa-freedreno-subgroups_26.2.0-devel+subgroups1_arm64.deb @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c03ad2ed9b1781b578bb659c5dbee13ae4a919d63bfb78587b4f797d8e2b0262 +size 10970816 diff --git a/containers/llamacpp/llamacpp-opencl.Containerfile b/containers/llamacpp/llamacpp-opencl.Containerfile index 7dc19ff..607350b 100644 --- a/containers/llamacpp/llamacpp-opencl.Containerfile +++ b/containers/llamacpp/llamacpp-opencl.Containerfile @@ -3,23 +3,29 @@ ### ### 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 debian:13-slim USER root EXPOSE 8090 -# Copia il/i pacchetto/i .deb con la Mesa patchata (fix subgroup Freedreno, -# commit 185c89084ab7, non presente in alcuna release Debian/backports). -# Generati da build-mesa.sh nella sottocartella ./deb accanto a questo file. +# Mesa patchata (fix subgroup Freedreno a6xx, commit 185c89084ab7, non in +# alcuna release Debian/backports). Generata da build-mesa.sh in ./deb. 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 \ - # Installa la Mesa patchata locale (fornisce mesa-opencl-icd / mesa-libgallium - # equivalenti, con il fix subgroup). Se il .deb ha dipendenze non risolte, - # il secondo apt-get -f install le completa dai repo standard. - && (dpkg -i /tmp/mesa-deb/*.deb || true) \ + 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]" \ @@ -34,38 +40,41 @@ RUN apt-get update \ WORKDIR /build RUN git clone --depth 1 https://github.com/ggml-org/llama.cpp -# --- PATCH: riconosci device Rusticl/Freedreno (es. "FD690") come Adreno --- -# Il backend OpenCL controlla dev_ctx->device_name cercando le stringhe -# "Adreno" o "Qualcomm" (vedi ggml_opencl_is_device_supported in -# ggml/src/ggml-opencl/ggml-opencl.cpp). Il driver Mesa/Rusticl riporta pero' -# il device come "FD690" (Freedreno + numero modello), non "Adreno 690", quindi -# il controllo fallisce e il device viene scartato con "unsupported GPU". -# Questa patch resta necessaria SEMPRE, indipendentemente dalla versione Mesa, -# perche' riguarda solo il nome con cui Rusticl si presenta, non le capability -# del device. Aggiungiamo il pattern "FD6" (copre la serie Adreno 6xx via -# Freedreno) alla condizione che marca il device come GPU_FAMILY::ADRENO. -# -# NOTA: la patch precedente che bypassava il controllo "does not support -# subgroups" NON e' piu' necessaria ne' presente qui: con la Mesa patchata -# (vedi deb/ - fix upstream "freedreno/a6xx: Expose subgroup ops") il device -# dichiara realmente cl_khr_subgroups, quindi il controllo originale del -# codice passa senza bisogno di bypass. Se in futuro si torna a una Mesa -# senza quel fix, il controllo tornera' a scartare il device correttamente -# (comportamento voluto: meglio un fallback esplicito che un bypass silente). -RUN cd llama.cpp \ - && grep -n 'strstr(dev_ctx->device_name.c_str(), "Adreno")' ggml/src/ggml-opencl/ggml-opencl.cpp \ - && sed -i \ - 's/strstr(dev_ctx->device_name.c_str(), "Adreno") ||/strstr(dev_ctx->device_name.c_str(), "Adreno") ||\n strstr(dev_ctx->device_name.c_str(), "FD6") ||/' \ - ggml/src/ggml-opencl/ggml-opencl.cpp \ - && grep -n -A5 'strstr(dev_ctx->device_name.c_str(), "Adreno")' ggml/src/ggml-opencl/ggml-opencl.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 +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=ON \ + -DGGML_OPENCL_USE_ADRENO_KERNELS=OFF \ -DBUILD_SHARED_LIBS=ON \ && cmake --build . --config Release -j$(nproc) diff --git a/containers/llamacpp/opencl-mesa-rusticl.patch b/containers/llamacpp/opencl-mesa-rusticl.patch new file mode 100644 index 0000000..3bb0801 --- /dev/null +++ b/containers/llamacpp/opencl-mesa-rusticl.patch @@ -0,0 +1,88 @@ +diff --git a/ggml/src/ggml-opencl/ggml-opencl.cpp b/ggml/src/ggml-opencl/ggml-opencl.cpp +index 5c96b9a9f..90ce16da8 100644 +--- a/ggml/src/ggml-opencl/ggml-opencl.cpp ++++ b/ggml/src/ggml-opencl/ggml-opencl.cpp +@@ -1160,7 +1160,8 @@ static void load_cl_kernels_argsort(ggml_backend_opencl_context *backend_ctx) { + std::string("CL") + std::to_string(backend_ctx->opencl_c_version.major) + "." + std::to_string(backend_ctx->opencl_c_version.minor); + std::string compile_opts = std::string("-cl-std=") + opencl_c_std + + " -cl-mad-enable -cl-unsafe-math-optimizations" +- " -cl-finite-math-only -cl-fast-relaxed-math"; ++ " -cl-finite-math-only -cl-fast-relaxed-math" ++ " -D cl_qcom_reqd_sub_group_size"; + + // argsort + if (!backend_ctx->kernels_loaded_argsort) { +@@ -1203,7 +1204,8 @@ static void load_cl_kernels(ggml_backend_opencl_context *backend_ctx) { + std::string("CL") + std::to_string(backend_ctx->opencl_c_version.major) + "." + std::to_string(backend_ctx->opencl_c_version.minor); + std::string compile_opts = std::string("-cl-std=") + opencl_c_std + + " -cl-mad-enable -cl-unsafe-math-optimizations" +- " -cl-finite-math-only -cl-fast-relaxed-math"; ++ " -cl-finite-math-only -cl-fast-relaxed-math" ++ " -D cl_qcom_reqd_sub_group_size"; + + if (backend_ctx->adreno_use_large_buffer) { + compile_opts += " -qcom-enable-large-buffer "; +@@ -5343,6 +5345,7 @@ static bool ggml_opencl_is_device_supported(ggml_backend_dev_t dev) { + GGML_ASSERT(dev_ctx->device); + + if (strstr(dev_ctx->device_name.c_str(), "Adreno") || ++ strstr(dev_ctx->device_name.c_str(), "FD6") || + strstr(dev_ctx->device_name.c_str(), "Qualcomm") || + strstr(dev_ctx->device_version.c_str(), "Adreno")) { + dev_ctx->gpu_family = GPU_FAMILY::ADRENO; +@@ -5394,7 +5397,8 @@ static bool ggml_opencl_is_device_supported(ggml_backend_dev_t dev) { + // If OpenCL 3.0 is supported, then check for cl_khr_subgroups, which becomes + // optional in OpenCL 3.0 (cl_khr_subgroup is mandatory in OpenCL 2.x) + if (opencl_c_version.major == 3 && strstr(ext_buffer, "cl_khr_subgroups") == NULL && +- strstr(ext_buffer, "cl_intel_subgroups") == NULL) { ++ strstr(ext_buffer, "cl_intel_subgroups") == NULL && ++ strstr(ext_buffer, "cl_khr_subgroup_ballot") == NULL) { + GGML_LOG_WARN("ggml_opencl: device does not support subgroups (cl_khr_subgroups or cl_intel_subgroups) " + "(note that subgroups is an optional feature in OpenCL 3.0)\n"); + return false; +diff --git a/ggml/src/ggml-opencl/kernels/mul_mm_q4_k_f32_l4_lm.cl b/ggml/src/ggml-opencl/kernels/mul_mm_q4_k_f32_l4_lm.cl +index 2235b1ae8..dc191b1d2 100644 +--- a/ggml/src/ggml-opencl/kernels/mul_mm_q4_k_f32_l4_lm.cl ++++ b/ggml/src/ggml-opencl/kernels/mul_mm_q4_k_f32_l4_lm.cl +@@ -90,7 +90,7 @@ kernel void kernel_mul_mm_q4_k_f32_l4_lm( + int is = 2 * n + b; + int qsi = n * 32 + (iqs % 16) * 2; + +- char * scales = src0_s + ib * 12; ++ global uchar * scales = src0_s + ib * 12; + + int scidx0 = (is < 4) ? is : (is + 4); + int scidx1 = (is < 4) ? is : (is - 4); +diff --git a/ggml/src/ggml-opencl/kernels/mul_mv_f16_f32_l4.cl b/ggml/src/ggml-opencl/kernels/mul_mv_f16_f32_l4.cl +index da2e14ae9..b293c73d6 100644 +--- a/ggml/src/ggml-opencl/kernels/mul_mv_f16_f32_l4.cl ++++ b/ggml/src/ggml-opencl/kernels/mul_mv_f16_f32_l4.cl +@@ -180,10 +180,12 @@ kernel void kernel_mul_mat_f16_f32_l4_dr( + // Kernels for decoding, Adreno only for now + #define MUL_MAT_F16_F32_L4_DR_LS_R2_MAX 8 + +-#ifdef ADRENO_GPU ++#if defined(ADRENO_GPU) && defined(cl_qcom_subgroup_shuffle) + #pragma OPENCL EXTENSION cl_qcom_subgroup_shuffle : enable + #define sub_group_shuffle_xor(val, mask) qcom_sub_group_shuffle_xor((val), (mask), CLK_SUB_GROUP_SHUFFLE_WIDTH_WAVE_SIZE_QCOM, 0.0f) ++#endif + ++#ifdef ADRENO_GPU + REQD_SUBGROUP_SIZE_64 + kernel void kernel_mul_mat_f16_f32_l4_dr_ls( + global char * src0, +diff --git a/ggml/src/ggml-opencl/kernels/mul_mv_q4_k_f32.cl b/ggml/src/ggml-opencl/kernels/mul_mv_q4_k_f32.cl +index 71ab98982..64cff077f 100644 +--- a/ggml/src/ggml-opencl/kernels/mul_mv_q4_k_f32.cl ++++ b/ggml/src/ggml-opencl/kernels/mul_mv_q4_k_f32.cl +@@ -151,8 +151,8 @@ kernel void kernel_mul_mv_q4_K_f32( + acc2.s3 += yh[i+9] * (q2[i/2] & 0xF000); + } + +- float dall = dh[0]; +- float dmin = dh[1]; ++ float dall = vload_half(0, dh); ++ float dmin = vload_half(1, dh); + sumf[row] += dall * ((acc1.s0 + 1.f/256.f * acc1.s1) * sc8[0] + + (acc1.s2 + 1.f/256.f * acc1.s3) * sc8[1] * 1.f/16.f + + (acc2.s0 + 1.f/256.f * acc2.s1) * sc8[4] +