mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-09-07 16:37:57 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e71b80510c | ||
|
|
ccc3646c63 | ||
|
|
c0b1871bc7 | ||
|
|
160bd031b2 | ||
|
|
dbeb37548e | ||
|
|
7a333e7240 | ||
|
|
0c963452ea | ||
|
|
4735997382 | ||
|
|
d23c47f2a9 | ||
|
|
73ab7599b5 | ||
|
|
0cae43063c | ||
|
|
1173700b9c | ||
|
|
5202104b59 | ||
|
|
9a7570587c | ||
|
|
b74f590eaf | ||
|
|
992cb503cd | ||
|
|
9ac8c408a3 | ||
|
|
2092353c8b | ||
|
|
8fe90e1fbf | ||
|
|
465e49b9ce | ||
|
|
5fdfa62829 | ||
|
|
3ad1ba7336 | ||
|
|
d03efa5d53 | ||
|
|
73a43d1f69 | ||
|
|
9e0e220594 | ||
|
|
0afb805b19 | ||
|
|
7620399f58 | ||
|
|
c457e3bf7f | ||
|
|
971595d669 | ||
|
|
74a7c897f0 | ||
|
|
6a1a922d26 | ||
|
|
4d9176092d | ||
|
|
cd8cdf397d | ||
|
|
427291b5b3 | ||
|
|
85d5703a3b | ||
|
|
1548a240e3 | ||
|
|
4acf4a4cb8 | ||
|
|
8b4b3558f1 | ||
|
|
1863ac0333 | ||
|
|
49c0dc82b8 |
@@ -31,7 +31,7 @@
|
||||
]
|
||||
&& blas.meta.available,
|
||||
useCuda ? config.cudaSupport,
|
||||
useMetalKit ? stdenv.isAarch64 && stdenv.isDarwin,
|
||||
useMetalKit ? stdenv.hostPlatform.isAarch64 && stdenv.hostPlatform.isDarwin,
|
||||
# Increases the runtime closure size by ~700M
|
||||
useMpi ? false,
|
||||
useRocm ? config.rocmSupport,
|
||||
@@ -92,7 +92,7 @@ let
|
||||
|
||||
cudaBuildInputs = with cudaPackages; [
|
||||
cuda_cudart
|
||||
cuda_cccl # <nv/target>
|
||||
cccl # <nv/target>
|
||||
libcublas
|
||||
];
|
||||
|
||||
@@ -166,7 +166,7 @@ effectiveStdenv.mkDerivation (finalAttrs: {
|
||||
# `xcrun` is used find the path of the Metal compiler, which is varible
|
||||
# and not on $PATH
|
||||
# see https://github.com/ggml-org/llama.cpp/pull/6118 for discussion
|
||||
__noChroot = effectiveStdenv.isDarwin && useMetalKit && precompileMetalShaders;
|
||||
__noChroot = effectiveStdenv.hostPlatform.isDarwin && useMetalKit && precompileMetalShaders;
|
||||
|
||||
nativeBuildInputs =
|
||||
[
|
||||
@@ -181,10 +181,10 @@ effectiveStdenv.mkDerivation (finalAttrs: {
|
||||
autoAddDriverRunpath
|
||||
]
|
||||
++ optionals (effectiveStdenv.hostPlatform.isGnu && enableStatic) [ glibc.static ]
|
||||
++ optionals (effectiveStdenv.isDarwin && useMetalKit && precompileMetalShaders) [ xcrunHost ];
|
||||
++ optionals (effectiveStdenv.hostPlatform.isDarwin && useMetalKit && precompileMetalShaders) [ xcrunHost ];
|
||||
|
||||
buildInputs =
|
||||
optionals effectiveStdenv.isDarwin darwinBuildInputs
|
||||
optionals effectiveStdenv.hostPlatform.isDarwin darwinBuildInputs
|
||||
++ optionals useCuda cudaBuildInputs
|
||||
++ optionals useMpi [ mpi ]
|
||||
++ optionals useRocm rocmBuildInputs
|
||||
@@ -245,7 +245,7 @@ effectiveStdenv.mkDerivation (finalAttrs: {
|
||||
|
||||
# Configurations that are known to result in build failures. Can be
|
||||
# overridden by importing Nixpkgs with `allowBroken = true`.
|
||||
broken = (useMetalKit && !effectiveStdenv.isDarwin);
|
||||
broken = (useMetalKit && !effectiveStdenv.hostPlatform.isDarwin);
|
||||
|
||||
description = "Inference of LLaMA model in pure C/C++${descriptionSuffix}";
|
||||
homepage = "https://github.com/ggml-org/llama.cpp/";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
blank_issues_enabled: true
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Got an idea?
|
||||
url: https://github.com/ggml-org/llama.cpp/discussions/categories/ideas
|
||||
|
||||
@@ -50,8 +50,16 @@ jobs:
|
||||
uses: ggml-org/ccache-action@v1.2.24
|
||||
with:
|
||||
key: apple-arm64
|
||||
evict-old-files: 1d
|
||||
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
save: false
|
||||
|
||||
- name: ccache-buckets-restore
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CI }}
|
||||
with:
|
||||
key: apple-arm64
|
||||
folder: llama.cpp
|
||||
hf_bucket: ggml-org/cache
|
||||
|
||||
- name: Build
|
||||
id: cmake_build
|
||||
@@ -67,6 +75,18 @@ jobs:
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=13.3
|
||||
time cmake --build build --config Release -j $(sysctl -n hw.logicalcpu)
|
||||
|
||||
- name: ccache-buckets-save
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CACHE_OUTPUT }}
|
||||
with:
|
||||
key: apple-arm64
|
||||
folder: llama.cpp
|
||||
evict-old-files: 1d
|
||||
hf_bucket: ggml-org/cache
|
||||
save: true
|
||||
|
||||
- name: Check for leaks
|
||||
run: |
|
||||
cmd=(./build/bin/test-thread-safety -hf ggml-org/gemma-3-270m-qat-GGUF -ngl 99 -p "$(printf 'hello %.0s' {1..128})" -n 16 -c 512 -ub 32 -np 2 -t 2 -lv 1)
|
||||
@@ -80,16 +100,6 @@ jobs:
|
||||
cd build
|
||||
ctest -L main -E "test-llama-archs" --verbose --timeout 900
|
||||
|
||||
- name: ccache-clear
|
||||
uses: ./.github/actions/ccache-clear
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
key: apple-arm64
|
||||
older: 5m
|
||||
min: 1
|
||||
dry-run: ${{ github.event_name != 'push' || github.ref != 'refs/heads/master' }}
|
||||
|
||||
macos-latest-x64:
|
||||
runs-on: macos-15-intel
|
||||
|
||||
@@ -102,8 +112,16 @@ jobs:
|
||||
uses: ggml-org/ccache-action@v1.2.24
|
||||
with:
|
||||
key: apple-x64
|
||||
evict-old-files: 1d
|
||||
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
save: false
|
||||
|
||||
- name: ccache-buckets-restore
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CI }}
|
||||
with:
|
||||
key: apple-x64
|
||||
folder: llama.cpp
|
||||
hf_bucket: ggml-org/cache
|
||||
|
||||
- name: Build
|
||||
id: cmake_build
|
||||
@@ -120,22 +138,24 @@ jobs:
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=13.3
|
||||
time cmake --build build --config Release -j $(sysctl -n hw.logicalcpu)
|
||||
|
||||
- name: ccache-buckets-save
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CACHE_OUTPUT }}
|
||||
with:
|
||||
key: apple-x64
|
||||
folder: llama.cpp
|
||||
evict-old-files: 1d
|
||||
hf_bucket: ggml-org/cache
|
||||
save: true
|
||||
|
||||
- name: Test
|
||||
id: cmake_test
|
||||
run: |
|
||||
cd build
|
||||
ctest -L main --verbose --timeout 900
|
||||
|
||||
- name: ccache-clear
|
||||
uses: ./.github/actions/ccache-clear
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
key: apple-x64
|
||||
older: 5m
|
||||
min: 1
|
||||
dry-run: ${{ github.event_name != 'push' || github.ref != 'refs/heads/master' }}
|
||||
|
||||
macos-latest-ios-xcode:
|
||||
runs-on: macos-latest
|
||||
|
||||
|
||||
@@ -65,8 +65,7 @@ jobs:
|
||||
uses: ggml-org/ccache-action@v1.2.24
|
||||
with:
|
||||
key: cpu-${{ matrix.os }}
|
||||
evict-old-files: 1d
|
||||
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
save: false
|
||||
|
||||
- name: Build Dependencies
|
||||
id: build_depends
|
||||
@@ -91,6 +90,15 @@ jobs:
|
||||
python3 -m pip install --upgrade pip setuptools
|
||||
pip3 install ./gguf-py
|
||||
|
||||
- name: ccache-buckets-restore
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CI }}
|
||||
with:
|
||||
key: cpu-${{ matrix.os }}
|
||||
folder: llama.cpp
|
||||
hf_bucket: ggml-org/cache
|
||||
|
||||
- name: Build
|
||||
id: cmake_build
|
||||
run: |
|
||||
@@ -100,6 +108,18 @@ jobs:
|
||||
-DGGML_RPC=ON
|
||||
time cmake --build build --config Release -j $(nproc)
|
||||
|
||||
- name: ccache-buckets-save
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CACHE_OUTPUT }}
|
||||
with:
|
||||
key: cpu-${{ matrix.os }}
|
||||
folder: llama.cpp
|
||||
evict-old-files: 1d
|
||||
hf_bucket: ggml-org/cache
|
||||
save: true
|
||||
|
||||
- name: Test
|
||||
id: cmake_test
|
||||
run: |
|
||||
@@ -117,18 +137,6 @@ jobs:
|
||||
./bin/llama-convert-llama2c-to-ggml --copy-vocab-from-model ./tok512.bin --llama2c-model stories260K.bin --llama2c-output-model stories260K.gguf
|
||||
./bin/llama-completion -m stories260K.gguf -p "One day, Lily met a Shoggoth" -n 500 -c 256
|
||||
|
||||
# note: real deletion only on push to master (same condition as the ccache save),
|
||||
# dry-run otherwise (the token is read-only on PRs from forks)
|
||||
- name: ccache-clear
|
||||
uses: ./.github/actions/ccache-clear
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
key: cpu-${{ matrix.os }}
|
||||
older: 5m
|
||||
min: 1
|
||||
dry-run: ${{ github.event_name != 'push' || github.ref != 'refs/heads/master' }}
|
||||
|
||||
windows:
|
||||
name: windows / ${{ matrix.build }}
|
||||
runs-on: windows-2025
|
||||
|
||||
@@ -61,7 +61,7 @@ jobs:
|
||||
- name: ccache-buckets-restore
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CACHE_OUTPUT }}
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CI }}
|
||||
with:
|
||||
key: cuda-ubuntu-24.04-cuda
|
||||
folder: llama.cpp
|
||||
@@ -116,7 +116,7 @@ jobs:
|
||||
- name: ccache-buckets-restore
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CACHE_OUTPUT }}
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CI }}
|
||||
with:
|
||||
key: cuda-ubuntu-22.04-hip
|
||||
folder: llama.cpp
|
||||
@@ -167,7 +167,7 @@ jobs:
|
||||
- name: ccache-buckets-restore
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CACHE_OUTPUT }}
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CI }}
|
||||
with:
|
||||
key: cuda-ubuntu-22.04-musa
|
||||
folder: llama.cpp
|
||||
|
||||
@@ -78,8 +78,16 @@ jobs:
|
||||
uses: ggml-org/ccache-action@v1.2.24
|
||||
with:
|
||||
key: sycl-ubuntu-24-${{ matrix.build }}
|
||||
evict-old-files: 1d
|
||||
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
save: false
|
||||
|
||||
- name: ccache-buckets-restore
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CI }}
|
||||
with:
|
||||
key: sycl-ubuntu-24-${{ matrix.build }}
|
||||
folder: llama.cpp
|
||||
hf_bucket: ggml-org/cache
|
||||
|
||||
- name: Build
|
||||
id: cmake_build
|
||||
@@ -96,15 +104,17 @@ jobs:
|
||||
-DGGML_SYCL_F16=${{ matrix.fp16 }}
|
||||
time cmake --build build --config Release -j $(nproc)
|
||||
|
||||
- name: ccache-clear
|
||||
uses: ./.github/actions/ccache-clear
|
||||
- name: ccache-buckets-save
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CACHE_OUTPUT }}
|
||||
with:
|
||||
key: sycl-ubuntu-24-${{ matrix.build }}
|
||||
older: 5m
|
||||
min: 1
|
||||
dry-run: ${{ github.event_name != 'push' || github.ref != 'refs/heads/master' }}
|
||||
folder: llama.cpp
|
||||
evict-old-files: 1d
|
||||
hf_bucket: ggml-org/cache
|
||||
save: true
|
||||
|
||||
windows-latest-sycl:
|
||||
runs-on: windows-2022
|
||||
|
||||
@@ -57,8 +57,16 @@ jobs:
|
||||
with:
|
||||
key: vulkan-ubuntu-24.04-arm
|
||||
variant: ccache
|
||||
evict-old-files: 1d
|
||||
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
save: false
|
||||
|
||||
- name: ccache-buckets-restore
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CI }}
|
||||
with:
|
||||
key: vulkan-ubuntu-24.04-arm
|
||||
folder: llama.cpp
|
||||
hf_bucket: ggml-org/cache
|
||||
|
||||
- name: Configure
|
||||
id: cmake_configure
|
||||
@@ -73,15 +81,17 @@ jobs:
|
||||
run: |
|
||||
time cmake --build build -j $(nproc)
|
||||
|
||||
- name: ccache-clear
|
||||
uses: ./.github/actions/ccache-clear
|
||||
- name: ccache-buckets-save
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CACHE_OUTPUT }}
|
||||
with:
|
||||
key: vulkan-ubuntu-24.04-arm
|
||||
older: 5m
|
||||
min: 1
|
||||
dry-run: ${{ github.event_name != 'push' || github.ref != 'refs/heads/master' }}
|
||||
folder: llama.cpp
|
||||
evict-old-files: 1d
|
||||
hf_bucket: ggml-org/cache
|
||||
save: true
|
||||
|
||||
ubuntu-llvmpipe:
|
||||
runs-on: ubuntu-24.04
|
||||
@@ -115,8 +125,16 @@ jobs:
|
||||
uses: ggml-org/ccache-action@v1.2.24
|
||||
with:
|
||||
key: vulkan-ubuntu-24.04-llvmpipe
|
||||
evict-old-files: 1d
|
||||
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
save: false
|
||||
|
||||
- name: ccache-buckets-restore
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CI }}
|
||||
with:
|
||||
key: vulkan-ubuntu-24.04-llvmpipe
|
||||
folder: llama.cpp
|
||||
hf_bucket: ggml-org/cache
|
||||
|
||||
- name: Build
|
||||
id: cmake_build
|
||||
@@ -127,6 +145,18 @@ jobs:
|
||||
-DGGML_VULKAN=ON
|
||||
cmake --build build --config Release -j $(nproc)
|
||||
|
||||
- name: ccache-buckets-save
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CACHE_OUTPUT }}
|
||||
with:
|
||||
key: vulkan-ubuntu-24.04-llvmpipe
|
||||
folder: llama.cpp
|
||||
evict-old-files: 1d
|
||||
hf_bucket: ggml-org/cache
|
||||
save: true
|
||||
|
||||
- name: Test
|
||||
id: cmake_test
|
||||
run: |
|
||||
@@ -138,16 +168,6 @@ jobs:
|
||||
# test-backend-ops is too slow on llvmpipe, skip it
|
||||
ctest -L main -E test-backend-ops --verbose --timeout 900
|
||||
|
||||
- name: ccache-clear
|
||||
uses: ./.github/actions/ccache-clear
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
key: vulkan-ubuntu-24.04-llvmpipe
|
||||
older: 5m
|
||||
min: 1
|
||||
dry-run: ${{ github.event_name != 'push' || github.ref != 'refs/heads/master' }}
|
||||
|
||||
windows:
|
||||
runs-on: windows-2025
|
||||
|
||||
|
||||
@@ -57,8 +57,7 @@ jobs:
|
||||
uses: ggml-org/ccache-action@v1.2.24
|
||||
with:
|
||||
key: webgpu-ubuntu-24.04-arm-wasm
|
||||
evict-old-files: 1d
|
||||
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
save: false
|
||||
|
||||
- name: Install Emscripten
|
||||
run: |
|
||||
@@ -76,6 +75,15 @@ jobs:
|
||||
"https://github.com/google/dawn/releases/download/${DAWN_TAG}/${EMDAWN_PKG}"
|
||||
unzip emdawn.zip
|
||||
|
||||
- name: ccache-buckets-restore
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CI }}
|
||||
with:
|
||||
key: webgpu-ubuntu-24.04-arm-wasm
|
||||
folder: llama.cpp
|
||||
hf_bucket: ggml-org/cache
|
||||
|
||||
- name: Build WASM WebGPU
|
||||
run: |
|
||||
source emsdk/emsdk_env.sh
|
||||
@@ -89,12 +97,14 @@ jobs:
|
||||
|
||||
time cmake --build build-wasm --config Release --target test-backend-ops -j $(nproc)
|
||||
|
||||
- name: ccache-clear
|
||||
uses: ./.github/actions/ccache-clear
|
||||
- name: ccache-buckets-save
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CACHE_OUTPUT }}
|
||||
with:
|
||||
key: webgpu-ubuntu-24.04-arm-wasm
|
||||
older: 5m
|
||||
min: 1
|
||||
dry-run: ${{ github.event_name != 'push' || github.ref != 'refs/heads/master' }}
|
||||
folder: llama.cpp
|
||||
evict-old-files: 1d
|
||||
hf_bucket: ggml-org/cache
|
||||
save: true
|
||||
|
||||
@@ -72,8 +72,7 @@ jobs:
|
||||
uses: ggml-org/ccache-action@v1.2.24
|
||||
with:
|
||||
key: webgpu-macos-latest
|
||||
evict-old-files: 1d
|
||||
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
save: false
|
||||
|
||||
- name: Dawn Dependency
|
||||
id: dawn-depends
|
||||
@@ -88,6 +87,15 @@ jobs:
|
||||
mkdir dawn
|
||||
tar -xvf artifact.tar.gz -C dawn --strip-components=1
|
||||
|
||||
- name: ccache-buckets-restore
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CI }}
|
||||
with:
|
||||
key: webgpu-macos-latest
|
||||
folder: llama.cpp
|
||||
hf_bucket: ggml-org/cache
|
||||
|
||||
- name: Build
|
||||
id: cmake_build
|
||||
run: |
|
||||
@@ -95,22 +103,24 @@ jobs:
|
||||
cmake -B build -G "Ninja" -DCMAKE_BUILD_TYPE=Release -DGGML_WEBGPU=ON -DGGML_METAL=OFF -DGGML_BLAS=OFF
|
||||
time cmake --build build --config Release -j $(sysctl -n hw.logicalcpu)
|
||||
|
||||
- name: ccache-buckets-save
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CACHE_OUTPUT }}
|
||||
with:
|
||||
key: webgpu-macos-latest
|
||||
folder: llama.cpp
|
||||
evict-old-files: 1d
|
||||
hf_bucket: ggml-org/cache
|
||||
save: true
|
||||
|
||||
- name: Test
|
||||
id: cmake_test
|
||||
run: |
|
||||
cd build
|
||||
ctest -L main --verbose --timeout 900
|
||||
|
||||
- name: ccache-clear
|
||||
uses: ./.github/actions/ccache-clear
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
key: webgpu-macos-latest
|
||||
older: 5m
|
||||
min: 1
|
||||
dry-run: ${{ github.event_name != 'push' || github.ref != 'refs/heads/master' }}
|
||||
|
||||
ubuntu:
|
||||
runs-on: ubuntu-24.04
|
||||
|
||||
@@ -123,8 +133,7 @@ jobs:
|
||||
uses: ggml-org/ccache-action@v1.2.24
|
||||
with:
|
||||
key: webgpu-ubuntu-24.04
|
||||
evict-old-files: 1d
|
||||
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
save: false
|
||||
|
||||
- name: Dependencies
|
||||
id: depends
|
||||
@@ -148,6 +157,15 @@ jobs:
|
||||
mkdir dawn
|
||||
tar -xvf artifact.tar.gz -C dawn --strip-components=1
|
||||
|
||||
- name: ccache-buckets-restore
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CI }}
|
||||
with:
|
||||
key: webgpu-ubuntu-24.04
|
||||
folder: llama.cpp
|
||||
hf_bucket: ggml-org/cache
|
||||
|
||||
- name: Build
|
||||
id: cmake_build
|
||||
run: |
|
||||
@@ -156,6 +174,18 @@ jobs:
|
||||
-DGGML_WEBGPU=ON
|
||||
time cmake --build build --config Release -j $(nproc)
|
||||
|
||||
- name: ccache-buckets-save
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CACHE_OUTPUT }}
|
||||
with:
|
||||
key: webgpu-ubuntu-24.04
|
||||
folder: llama.cpp
|
||||
evict-old-files: 1d
|
||||
hf_bucket: ggml-org/cache
|
||||
save: true
|
||||
|
||||
- name: Test
|
||||
id: cmake_test
|
||||
run: |
|
||||
@@ -163,13 +193,3 @@ jobs:
|
||||
# This is using llvmpipe and runs slower than other backends
|
||||
# test-backend-ops is too slow on llvmpipe, skip it
|
||||
ctest -L main -E test-backend-ops --verbose --timeout 900
|
||||
|
||||
- name: ccache-clear
|
||||
uses: ./.github/actions/ccache-clear
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
key: webgpu-ubuntu-24.04
|
||||
older: 5m
|
||||
min: 1
|
||||
dry-run: ${{ github.event_name != 'push' || github.ref != 'refs/heads/master' }}
|
||||
|
||||
@@ -49,14 +49,22 @@ jobs:
|
||||
id: depends
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y build-essential git cmake rocblas-dev hipblas-dev libssl-dev python3
|
||||
sudo apt-get install -y build-essential git cmake rocblas-dev hipblas-dev libssl-dev python3 python3-venv python3-pip jq
|
||||
|
||||
- name: ccache
|
||||
uses: ggml-org/ccache-action@v1.2.24
|
||||
with:
|
||||
key: hip-quality-check-ubuntu-22.04
|
||||
evict-old-files: 1d
|
||||
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
save: false
|
||||
|
||||
- name: ccache-buckets-restore
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CI }}
|
||||
with:
|
||||
key: hip-quality-check-ubuntu-22.04
|
||||
folder: llama.cpp
|
||||
hf_bucket: ggml-org/cache
|
||||
|
||||
- name: Build with Werror
|
||||
id: cmake_build
|
||||
@@ -85,12 +93,14 @@ jobs:
|
||||
make -j $(nproc) 2>&1 | tee metrics.log | grep -v 'Rpass-analysis=kernel-resource-usage\|remark:\|^$'
|
||||
python3 ../scripts/hip/gcn-cdna-vgpr-check.py metrics.log
|
||||
|
||||
- name: ccache-clear
|
||||
uses: ./.github/actions/ccache-clear
|
||||
- name: ccache-buckets-save
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CACHE_OUTPUT }}
|
||||
with:
|
||||
key: hip-quality-check-ubuntu-22.04
|
||||
older: 5m
|
||||
min: 1
|
||||
dry-run: ${{ github.event_name != 'push' || github.ref != 'refs/heads/master' }}
|
||||
folder: llama.cpp
|
||||
evict-old-files: 1d
|
||||
hf_bucket: ggml-org/cache
|
||||
save: true
|
||||
|
||||
@@ -19,6 +19,7 @@ env:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
make-release:
|
||||
@@ -113,6 +114,29 @@ jobs:
|
||||
data: await fs.readFileSync('./nightly-tag.txt')
|
||||
});
|
||||
|
||||
- name: Re-tag container images with release version
|
||||
if: ${{ github.event.inputs.dry_run == 'false' && steps.desc.outputs.nightly_tag != '' }}
|
||||
env:
|
||||
GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }}
|
||||
run: |
|
||||
VERSION="${{ steps.checks.outputs.version }}"
|
||||
NIGHTLY_TAG="${{ steps.desc.outputs.nightly_tag }}"
|
||||
REPO_OWNER="${GITHUB_REPOSITORY_OWNER,,}"
|
||||
IMAGE_REPO="ghcr.io/${REPO_OWNER}/${{ github.event.repository.name }}"
|
||||
|
||||
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u "${{ github.actor }}" --password-stdin
|
||||
|
||||
VARIANTS=("" "-cuda" "-cuda13" "-vulkan" "-rocm" "-intel" "-musa" "-openvino")
|
||||
TYPES=("full" "light" "server")
|
||||
for type in "${TYPES[@]}"; do
|
||||
for variant in "${VARIANTS[@]}"; do
|
||||
src="${IMAGE_REPO}:${type}${variant}-${NIGHTLY_TAG}"
|
||||
dst="${IMAGE_REPO}:${type}${variant}-${VERSION}"
|
||||
echo "Tagging ${src} -> ${dst}"
|
||||
docker buildx imagetools create --tag "${dst}" "${src}"
|
||||
done
|
||||
done
|
||||
|
||||
- name: Dry run summary
|
||||
if: ${{ github.event.inputs.dry_run == 'true' }}
|
||||
run: |
|
||||
|
||||
@@ -83,8 +83,16 @@ jobs:
|
||||
uses: ggml-org/ccache-action@v1.2.24
|
||||
with:
|
||||
key: server-ubuntu-24.04-arm
|
||||
evict-old-files: 1d
|
||||
save: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
save: false
|
||||
|
||||
- name: ccache-buckets-restore
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CI }}
|
||||
with:
|
||||
key: server-ubuntu-24.04-arm
|
||||
folder: llama.cpp
|
||||
hf_bucket: ggml-org/cache
|
||||
|
||||
- name: Build
|
||||
id: cmake_build
|
||||
@@ -93,6 +101,18 @@ jobs:
|
||||
-DGGML_SCHED_NO_REALLOC=ON
|
||||
cmake --build build --config Release -j $(nproc) --target llama-server
|
||||
|
||||
- name: ccache-buckets-save
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }}
|
||||
uses: ./.github/actions/ccache-buckets
|
||||
env:
|
||||
HF_TOKEN: ${{ secrets.HF_TOKEN_CACHE_OUTPUT }}
|
||||
with:
|
||||
key: server-ubuntu-24.04-arm
|
||||
folder: llama.cpp
|
||||
evict-old-files: 1d
|
||||
hf_bucket: ggml-org/cache
|
||||
save: true
|
||||
|
||||
- name: Python setup
|
||||
id: setup_python
|
||||
uses: actions/setup-python@v6
|
||||
@@ -128,16 +148,6 @@ jobs:
|
||||
export LLAMA_ARG_BACKEND_SAMPLING=1
|
||||
SLOW_TESTS=1 ./tests.sh
|
||||
|
||||
- name: ccache-clear
|
||||
uses: ./.github/actions/ccache-clear
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
with:
|
||||
key: server-ubuntu-24.04-arm
|
||||
older: 5m
|
||||
min: 1
|
||||
dry-run: ${{ github.event_name != 'push' || github.ref != 'refs/heads/master' }}
|
||||
|
||||
windows:
|
||||
runs-on: windows-2025
|
||||
|
||||
|
||||
@@ -3901,6 +3901,14 @@ common_params_context common_params_parser_init(common_params & params, llama_ex
|
||||
common_log_set_file(common_log_main(), value.c_str());
|
||||
}
|
||||
).set_env("LLAMA_ARG_LOG_FILE"));
|
||||
add_opt(common_arg(
|
||||
{"--log-jsonl"},
|
||||
{"--no-log-jsonl"},
|
||||
"Log as JSONL (one JSON object per line) to stdout, this also disables colored logging (default: disabled)",
|
||||
[](common_params &, bool value) {
|
||||
common_log_set_jsonl(common_log_main(), value);
|
||||
}
|
||||
).set_env("LLAMA_ARG_LOG_JSONL"));
|
||||
add_opt(common_arg(
|
||||
{"--log-prompts-dir"}, "PATH",
|
||||
"Log prompts to directory (auto-created if not present; only used for debugging, default: disabled)",
|
||||
|
||||
@@ -117,6 +117,7 @@ caps caps_get(jinja::program & prog) {
|
||||
|
||||
JJ_DEBUG("%s\n", ">>> Running capability check: typed content");
|
||||
|
||||
bool checks_for_string = false;
|
||||
static const std::string content_marker = "STRING_MARKER";
|
||||
|
||||
// case: typed content support
|
||||
@@ -136,6 +137,10 @@ caps caps_get(jinja::program & prog) {
|
||||
[&](context &, bool success, value & messages, value &, const std::string & rendered) {
|
||||
auto & content = messages->at(0)->at("content");
|
||||
caps_print_stats(content, "messages[0].content");
|
||||
if (has_op(content, "test_is_string")) {
|
||||
// checked if content is string
|
||||
checks_for_string = true;
|
||||
}
|
||||
bool used_as_array = has_op(content, "selectattr") || has_op(content, "array_access");
|
||||
if (used_as_array) {
|
||||
// accessed as an array
|
||||
@@ -151,6 +156,33 @@ caps caps_get(jinja::program & prog) {
|
||||
}
|
||||
);
|
||||
|
||||
if (checks_for_string) {
|
||||
caps_try_execute(
|
||||
prog,
|
||||
[&]() {
|
||||
// messages
|
||||
return json::array({
|
||||
{
|
||||
{"role", "user"},
|
||||
{"content", json::array({
|
||||
})}
|
||||
}
|
||||
});
|
||||
},
|
||||
nullptr, // ctx_fn
|
||||
nullptr, // tools_fn
|
||||
[&](context &, bool success, value & messages, value &, const std::string &) {
|
||||
auto & content = messages->at(0)->at("content");
|
||||
caps_print_stats(content, "messages[0].content");
|
||||
bool used_as_array = has_op(content, "selectattr") || has_op(content, "array_access");
|
||||
if (used_as_array && success) {
|
||||
// accessed as an array
|
||||
result.supports_typed_content = true;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
JJ_DEBUG("%s\n", ">>> Running capability check: system prompt");
|
||||
|
||||
// case: system prompt support
|
||||
|
||||
@@ -412,12 +412,18 @@ value test_expression::execute_impl(context & ctx) {
|
||||
throw std::runtime_error("Invalid test expression");
|
||||
}
|
||||
|
||||
auto it = builtins.find("test_is_" + test_id);
|
||||
JJ_DEBUG("Test expression %s '%s' %s (using function 'test_is_%s')", operand->type().c_str(), test_id.c_str(), negate ? "(negate)" : "", test_id.c_str());
|
||||
const std::string test_name = "test_is_" + test_id;
|
||||
auto it = builtins.find(test_name);
|
||||
JJ_DEBUG("Test expression %s '%s' %s (using function '%s')", operand->type().c_str(), test_id.c_str(), negate ? "(negate)" : "", test_name.c_str());
|
||||
if (it == builtins.end()) {
|
||||
throw std::runtime_error("Unknown test '" + test_id + "'");
|
||||
}
|
||||
|
||||
if (ctx.is_get_stats) {
|
||||
value_t::stats_t::mark_used(input);
|
||||
input->stats.ops.insert(test_name);
|
||||
}
|
||||
|
||||
auto res = it->second(args);
|
||||
|
||||
if (negate) {
|
||||
|
||||
+39
-1
@@ -1,5 +1,6 @@
|
||||
#include "common.h"
|
||||
#include "log.h"
|
||||
#include "json.h"
|
||||
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
@@ -66,6 +67,17 @@ static const char* g_col[] = {
|
||||
"",
|
||||
};
|
||||
|
||||
static const char * level_str(enum ggml_log_level level) {
|
||||
switch (level) {
|
||||
case GGML_LOG_LEVEL_DEBUG: return "debug";
|
||||
case GGML_LOG_LEVEL_INFO: return "info";
|
||||
case GGML_LOG_LEVEL_WARN: return "warn";
|
||||
case GGML_LOG_LEVEL_ERROR: return "error";
|
||||
case GGML_LOG_LEVEL_CONT: return "cont";
|
||||
default: return "none";
|
||||
}
|
||||
}
|
||||
|
||||
struct common_log_entry {
|
||||
enum ggml_log_level level {GGML_LOG_LEVEL_INFO};
|
||||
|
||||
@@ -74,6 +86,7 @@ struct common_log_entry {
|
||||
int64_t timestamp { 0 };
|
||||
bool is_end { false }; // signals the worker thread to stop
|
||||
bool prefix { false };
|
||||
bool jsonl { false };
|
||||
|
||||
common_log_entry(size_t size = 256) : msg(size) { }
|
||||
|
||||
@@ -88,11 +101,23 @@ struct common_log_entry {
|
||||
|
||||
fcur = stdout;
|
||||
|
||||
if (level != GGML_LOG_LEVEL_NONE) {
|
||||
if (level != GGML_LOG_LEVEL_NONE && !jsonl) {
|
||||
fcur = stderr;
|
||||
}
|
||||
}
|
||||
|
||||
if (jsonl) {
|
||||
common_json obj = {
|
||||
{"type", "log"},
|
||||
{"time", timestamp},
|
||||
{"level", level_str(level)},
|
||||
{"msg", msg.data()},
|
||||
};
|
||||
fprintf(fcur, "%s\n", obj.dump_safe().c_str());
|
||||
fflush(fcur);
|
||||
return;
|
||||
}
|
||||
|
||||
if (level != GGML_LOG_LEVEL_NONE && level != GGML_LOG_LEVEL_CONT && prefix) {
|
||||
if (timestamp) {
|
||||
// [M.s.ms.us]
|
||||
@@ -131,6 +156,7 @@ struct common_log {
|
||||
file = nullptr;
|
||||
prefix = false;
|
||||
timestamps = false;
|
||||
jsonl = false;
|
||||
running = false;
|
||||
t_start = t_us();
|
||||
|
||||
@@ -158,6 +184,7 @@ private:
|
||||
|
||||
bool prefix;
|
||||
bool timestamps;
|
||||
bool jsonl;
|
||||
bool running;
|
||||
|
||||
int64_t t_start;
|
||||
@@ -246,6 +273,7 @@ public:
|
||||
entry.is_end = false;
|
||||
entry.level = level;
|
||||
entry.prefix = prefix;
|
||||
entry.jsonl = jsonl;
|
||||
entry.timestamp = 0;
|
||||
if (timestamps) {
|
||||
entry.timestamp = t_us() - t_start;
|
||||
@@ -360,6 +388,12 @@ public:
|
||||
|
||||
this->timestamps = timestamps;
|
||||
}
|
||||
|
||||
void set_jsonl(bool jsonl) {
|
||||
std::lock_guard<std::mutex> lock(mtx);
|
||||
|
||||
this->jsonl = jsonl;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
@@ -433,6 +467,10 @@ void common_log_set_timestamps(struct common_log * log, bool timestamps) {
|
||||
log->set_timestamps(timestamps);
|
||||
}
|
||||
|
||||
void common_log_set_jsonl(struct common_log * log, bool jsonl) {
|
||||
log->set_jsonl(jsonl);
|
||||
}
|
||||
|
||||
void common_log_flush(struct common_log * log) {
|
||||
log->pause();
|
||||
log->resume();
|
||||
|
||||
@@ -91,6 +91,7 @@ void common_log_set_file (struct common_log * log, const char * file); // n
|
||||
void common_log_set_colors (struct common_log * log, log_colors colors); // not thread-safe
|
||||
void common_log_set_prefix (struct common_log * log, bool prefix); // whether to output prefix to each log
|
||||
void common_log_set_timestamps(struct common_log * log, bool timestamps); // whether to output timestamps in the prefix
|
||||
void common_log_set_jsonl (struct common_log * log, bool jsonl); // print each log as a JSON object on one line, not thread-safe
|
||||
void common_log_flush (struct common_log * log); // flush all pending log messages
|
||||
|
||||
// helper macros for logging
|
||||
|
||||
@@ -124,6 +124,7 @@ TEXT_MODEL_MAP: dict[str, str] = {
|
||||
"HunYuanMoEV1ForCausalLM": "hunyuan",
|
||||
"HunYuanVLForConditionalGeneration": "hunyuan",
|
||||
"HYV3ForCausalLM": "hunyuan",
|
||||
"HYV4ForCausalLM": "hy_v4",
|
||||
"IQuestCoderForCausalLM": "llama",
|
||||
"InternLM2ForCausalLM": "internlm",
|
||||
"InternLM3ForCausalLM": "internlm",
|
||||
@@ -254,6 +255,7 @@ TEXT_MODEL_MAP: dict[str, str] = {
|
||||
"SeedOssForCausalLM": "olmo",
|
||||
"SmallThinkerForCausalLM": "smallthinker",
|
||||
"SmolLM3ForCausalLM": "llama",
|
||||
"Spark2_5ForCausalLM": "spark2_5",
|
||||
"SolarOpenForCausalLM": "glm",
|
||||
"StableLMEpochForCausalLM": "stablelm",
|
||||
"StableLmForCausalLM": "stablelm",
|
||||
|
||||
+97
-1
@@ -130,7 +130,8 @@ class ModelBase:
|
||||
sentence_transformers_dense_modules: bool = False,
|
||||
target_model_dir: Path | None = None,
|
||||
fuse_gate_up_exps: bool = False,
|
||||
fp8_as_q8: bool = False):
|
||||
fp8_as_q8: bool = False,
|
||||
fuse_qkv: bool = False):
|
||||
if type(self) is ModelBase or \
|
||||
type(self) is TextModel or \
|
||||
type(self) is MmprojModel:
|
||||
@@ -153,6 +154,15 @@ class ModelBase:
|
||||
self.fuse_gate_up_exps = fuse_gate_up_exps
|
||||
self._gate_exp_buffer: dict[int, Tensor] = {}
|
||||
self._up_exp_buffer: dict[int, Tensor] = {}
|
||||
self.fuse_qkv = fuse_qkv
|
||||
self._q_buffer: dict[int, Tensor] = {}
|
||||
self._k_buffer: dict[int, Tensor] = {}
|
||||
self._v_buffer: dict[int, Tensor] = {}
|
||||
self._q_bias_buffer: dict[int, Tensor] = {}
|
||||
self._k_bias_buffer: dict[int, Tensor] = {}
|
||||
self._v_bias_buffer: dict[int, Tensor] = {}
|
||||
self._fusable_qkv_weight_layers: set[int] = set()
|
||||
self._fusable_qkv_bias_layers: set[int] = set()
|
||||
self.hparams = ModelBase.load_hparams(self.dir_model, self.is_mistral_format) if hparams is None else hparams
|
||||
self.model_tensors = self.index_tensors(remote_hf_model_id=remote_hf_model_id)
|
||||
self.metadata_override = metadata_override
|
||||
@@ -617,6 +627,43 @@ class ModelBase:
|
||||
raise ValueError(f"Can not map tensor {name!r}")
|
||||
return new_name
|
||||
|
||||
def prepare_qkv_fusion(self) -> None:
|
||||
self._fusable_qkv_weight_layers.clear()
|
||||
self._fusable_qkv_bias_layers.clear()
|
||||
if not self.fuse_qkv or gguf.MODEL_TENSOR.ATTN_QKV not in gguf.MODEL_TENSORS[self.model_arch]:
|
||||
return
|
||||
|
||||
qkv_types = {
|
||||
gguf.MODEL_TENSOR.ATTN_Q,
|
||||
gguf.MODEL_TENSOR.ATTN_K,
|
||||
gguf.MODEL_TENSOR.ATTN_V,
|
||||
}
|
||||
weights: dict[int, set[gguf.MODEL_TENSOR]] = {}
|
||||
biases: dict[int, set[gguf.MODEL_TENSOR]] = {}
|
||||
|
||||
for name in self.model_tensors:
|
||||
mapped = self.tensor_map.get_type_and_name(name, try_suffixes=(".weight", ".bias"))
|
||||
if mapped is None:
|
||||
continue
|
||||
tensor_type, new_name = mapped
|
||||
if tensor_type not in qkv_types:
|
||||
continue
|
||||
|
||||
bid = next((int(part) for part in new_name.split(".") if part.isdecimal()), None)
|
||||
if bid is None:
|
||||
continue
|
||||
if new_name.endswith(".weight"):
|
||||
weights.setdefault(bid, set()).add(tensor_type)
|
||||
elif new_name.endswith(".bias"):
|
||||
biases.setdefault(bid, set()).add(tensor_type)
|
||||
|
||||
for bid, weight_types in weights.items():
|
||||
bias_types = biases.get(bid, set())
|
||||
if weight_types == qkv_types and (not bias_types or bias_types == qkv_types):
|
||||
self._fusable_qkv_weight_layers.add(bid)
|
||||
if bias_types:
|
||||
self._fusable_qkv_bias_layers.add(bid)
|
||||
|
||||
def set_gguf_parameters(self):
|
||||
raise NotImplementedError("set_gguf_parameters() must be implemented in subclasses")
|
||||
|
||||
@@ -645,6 +692,40 @@ class ModelBase:
|
||||
self.match_model_tensor_name(new_name, gguf.MODEL_TENSOR.FFN_UP_EXP, bid):
|
||||
return []
|
||||
|
||||
# Handle Q/K/V tensor fusion if enabled
|
||||
qkv_bid = next((int(part) for part in new_name.split(".") if part.isdecimal()), None) if self.fuse_qkv else None
|
||||
if qkv_bid is not None:
|
||||
is_bias = new_name.endswith('.bias')
|
||||
suffix = '.bias' if is_bias else '.weight'
|
||||
fusable_layers = self._fusable_qkv_bias_layers if is_bias else self._fusable_qkv_weight_layers
|
||||
if qkv_bid not in fusable_layers:
|
||||
return [(new_name, data_torch)]
|
||||
|
||||
buf_q = self._q_bias_buffer if is_bias else self._q_buffer
|
||||
buf_k = self._k_bias_buffer if is_bias else self._k_buffer
|
||||
buf_v = self._v_bias_buffer if is_bias else self._v_buffer
|
||||
|
||||
if self.match_model_tensor_name(new_name, gguf.MODEL_TENSOR.ATTN_Q, qkv_bid, suffix):
|
||||
buf_q[qkv_bid] = data_torch
|
||||
elif self.match_model_tensor_name(new_name, gguf.MODEL_TENSOR.ATTN_K, qkv_bid, suffix):
|
||||
buf_k[qkv_bid] = data_torch
|
||||
elif self.match_model_tensor_name(new_name, gguf.MODEL_TENSOR.ATTN_V, qkv_bid, suffix):
|
||||
buf_v[qkv_bid] = data_torch
|
||||
|
||||
if qkv_bid in buf_q and qkv_bid in buf_k and qkv_bid in buf_v:
|
||||
q_data = buf_q.pop(qkv_bid)
|
||||
k_data = buf_k.pop(qkv_bid)
|
||||
v_data = buf_v.pop(qkv_bid)
|
||||
fused_data = torch.cat([q_data, k_data, v_data], dim=0)
|
||||
fused_name = self.format_tensor_name(gguf.MODEL_TENSOR.ATTN_QKV, qkv_bid, suffix=suffix)
|
||||
logger.info(f"Fused Q, K, V {suffix[1:]} into QKV for layer {qkv_bid}")
|
||||
return [(fused_name, fused_data)]
|
||||
|
||||
if self.match_model_tensor_name(new_name, gguf.MODEL_TENSOR.ATTN_Q, qkv_bid, suffix) or \
|
||||
self.match_model_tensor_name(new_name, gguf.MODEL_TENSOR.ATTN_K, qkv_bid, suffix) or \
|
||||
self.match_model_tensor_name(new_name, gguf.MODEL_TENSOR.ATTN_V, qkv_bid, suffix):
|
||||
return []
|
||||
|
||||
return [(new_name, data_torch)]
|
||||
|
||||
def tensor_force_quant(self, name: str, new_name: str, bid: int | None, n_dims: int) -> gguf.GGMLQuantizationType | bool:
|
||||
@@ -899,6 +980,8 @@ class ModelBase:
|
||||
|
||||
self.dequant_model()
|
||||
|
||||
self.prepare_qkv_fusion()
|
||||
|
||||
# Handle empty tensor_map for models with block_count=0 (like MobileNetV5)
|
||||
if self.tensor_map.mapping:
|
||||
max_name_len = max(len(s) for _, s in self.tensor_map.mapping.values()) + len(".weight,")
|
||||
@@ -1027,6 +1110,13 @@ class ModelBase:
|
||||
|
||||
self.gguf_writer.add_tensor(new_name, data, raw_dtype=data_qtype)
|
||||
|
||||
qkv_buffers = (
|
||||
self._q_buffer, self._k_buffer, self._v_buffer,
|
||||
self._q_bias_buffer, self._k_bias_buffer, self._v_bias_buffer,
|
||||
)
|
||||
if any(qkv_buffers):
|
||||
raise ValueError("QKV fusion did not consume all buffered tensors")
|
||||
|
||||
def set_type(self):
|
||||
self.gguf_writer.add_type(gguf.GGUFType.MODEL)
|
||||
|
||||
@@ -1507,6 +1597,9 @@ class TextModel(ModelBase):
|
||||
if chkhsh == "bba3b3366b646dbdded5dbc42d59598b849371afc42f7beafa914afaa5b70aa6":
|
||||
# ref: https://huggingface.co/tencent/Hunyuan-4B-Instruct
|
||||
res = "hunyuan-dense"
|
||||
if chkhsh == "e6ddf9c6686791c12d698d34c31ab9be1fea9af5a3d9a6909783ab382198ae1c":
|
||||
# ref: https://huggingface.co/tencent/Hy4-preview
|
||||
res = "hy_v4"
|
||||
if chkhsh == "a6b57017d60e6edb4d88ecc2845188e0eb333a70357e45dcc9b53964a73bbae6":
|
||||
# ref: https://huggingface.co/tiiuae/Falcon-H1-0.5B-Base
|
||||
res = "falcon-h1"
|
||||
@@ -1540,6 +1633,9 @@ class TextModel(ModelBase):
|
||||
if chkhsh == "9e454714343b69b99b71795c1d27a68c2a1d15dab111f4d353109f966af29da7":
|
||||
# ref: https://huggingface.co/LiquidAI/LFM2.5-8B-A1B
|
||||
res = "lfm2"
|
||||
if chkhsh == "0a766d034107bc736a3f2dc4968fd62e54a3570f1454443e0c5a4cc6bd7941ed":
|
||||
# ref: https://huggingface.co/XHToken/Spark-X2.5-1.7B
|
||||
res = "spark2_5"
|
||||
if chkhsh == "0ef9807a4087ebef797fc749390439009c3b9eda9ad1a097abbe738f486c01e5":
|
||||
# ref: https://huggingface.co/meta-llama/Meta-Llama-3-8B
|
||||
res = "llama-bpe"
|
||||
|
||||
@@ -0,0 +1,244 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import Iterable
|
||||
|
||||
import torch
|
||||
|
||||
from .base import ModelBase, gguf, logger
|
||||
from .deepseek import DeepseekV2Model
|
||||
|
||||
|
||||
def split_gate_up(weight: torch.Tensor, moe_intermediate_size: int):
|
||||
"""Split a fused stacked gate_up expert tensor into (gate, up).
|
||||
|
||||
weight: [n_expert, 2*moe_intermediate_size, hidden] (gate first, up second).
|
||||
Returns (gate, up) each [n_expert, moe_intermediate_size, hidden].
|
||||
"""
|
||||
assert weight.shape[1] == 2 * moe_intermediate_size, f"{weight.shape[1]} != 2*{moe_intermediate_size}"
|
||||
gate = weight[:, :moe_intermediate_size, :].contiguous()
|
||||
up = weight[:, moe_intermediate_size:, :].contiguous()
|
||||
return gate, up
|
||||
|
||||
|
||||
@ModelBase.register("HYV4ForCausalLM")
|
||||
@ModelBase.example("tencent/Hy4-preview")
|
||||
class HYV4Model(DeepseekV2Model):
|
||||
"""HY_V4: DeepSeek-V3 style MLA + MoE with iHC, a gated MLA output and a learnable sink.
|
||||
|
||||
Reuses DeepseekV2Model for the vocab and the MLA metadata, but overrides the tensor mapping
|
||||
because HY_V4 ships pre-stacked / fused experts plus extra iHC, gate and sink tensors. The
|
||||
rope rows are mapped straight through (no permute) - the graph rotates consecutive pairs.
|
||||
|
||||
DSA is supported: indexer weights are exported for the layers marked "full" in indexer_types.
|
||||
"shared" layers reuse the top-k of the last preceding full layer at inference time, so they
|
||||
carry no indexer weights.
|
||||
|
||||
MTP (num_nextn_predict_layers) is dropped, so the GGUF cannot be used for speculative
|
||||
decoding. The reference only runs the MTP layers while training or while speculating, so they
|
||||
cannot change single-token logits.
|
||||
"""
|
||||
|
||||
model_arch = gguf.MODEL_ARCH.HY_V4
|
||||
|
||||
merge_expert = False
|
||||
|
||||
# tensors a "full" indexer layer must carry
|
||||
INDEXER_SUFFIXES = frozenset({
|
||||
"self_attn.indexer.wq_b.weight",
|
||||
"self_attn.indexer.wk.weight",
|
||||
"self_attn.indexer.k_norm.weight",
|
||||
"self_attn.indexer.k_norm.bias",
|
||||
"self_attn.indexer.weights_proj.weight",
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def filter_tensors(cls, item):
|
||||
# drop MTP here, not in modify_tensors, so the weights are never read
|
||||
if item[0].startswith("model.mtp_layers."):
|
||||
return None
|
||||
return super().filter_tensors(item)
|
||||
|
||||
def _check_indexer_hparams(self):
|
||||
for key in ("index_n_heads", "index_head_dim", "index_topk"):
|
||||
if key not in self.hparams:
|
||||
raise ValueError(f"HY_V4 has DSA layers but no {key}")
|
||||
|
||||
def indexer_is_full(self) -> list[bool] | None:
|
||||
"""Per-layer indexer ownership, or None when the checkpoint has no DSA.
|
||||
|
||||
indexer_types entries are "full" (owns an indexer) or "shared" (reuses the preceding
|
||||
full layer's top-k). Missing indexer_types with sparse layers means every sparse layer
|
||||
owns one.
|
||||
"""
|
||||
hparams = self.hparams
|
||||
n_layer = hparams["num_hidden_layers"]
|
||||
indexer_types = hparams.get("indexer_types")
|
||||
|
||||
# the reference drives DSA off indexer_types alone; layer_types is only a fallback for
|
||||
# checkpoints predating it (it was renamed to deepseek_sparse_attention upstream)
|
||||
if indexer_types is None:
|
||||
layer_types = hparams.get("layer_types") or []
|
||||
sparse = {"sparse_attention", "deepseek_sparse_attention"}
|
||||
if not any(t in sparse for t in layer_types):
|
||||
return None
|
||||
if len(layer_types) < n_layer:
|
||||
raise ValueError(f"HY_V4 layer_types has {len(layer_types)} entries, need {n_layer}")
|
||||
self._check_indexer_hparams()
|
||||
return [t in sparse for t in layer_types[:n_layer]]
|
||||
|
||||
self._check_indexer_hparams()
|
||||
|
||||
if len(indexer_types) < n_layer:
|
||||
raise ValueError(f"HY_V4 indexer_types has {len(indexer_types)} entries, need {n_layer}")
|
||||
unknown = {t for t in indexer_types[:n_layer]} - {"full", "shared"}
|
||||
if unknown:
|
||||
raise ValueError(f"HY_V4 unknown indexer_types values: {sorted(unknown)}")
|
||||
is_full = [t == "full" for t in indexer_types[:n_layer]]
|
||||
if is_full and not is_full[0]:
|
||||
raise ValueError("HY_V4 layer 0 must be indexer_types 'full' (nothing precedes it to share)")
|
||||
return is_full
|
||||
|
||||
def set_gguf_parameters(self):
|
||||
hparams = self.hparams
|
||||
|
||||
# HY4 has n_group == topk_group == 1 (no group routing). Drop the keys so the base does
|
||||
# not emit expert_group_count/used; llama.cpp then takes the ungrouped MoE path.
|
||||
if hparams.get("n_group") == 1 and hparams.get("topk_group") == 1:
|
||||
hparams.pop("n_group", None)
|
||||
hparams.pop("topk_group", None)
|
||||
|
||||
# HY_V4 config expresses dense/sparse layers via mlp_layer_types, but DeepseekV2Model
|
||||
# needs first_k_dense_replace. Derive it as the contiguous leading "dense" block
|
||||
# (the real config.json also carries first_k_dense_replace; prefer it when present,
|
||||
# but assert the two agree so a mismatch fails loudly).
|
||||
mlp_types = hparams.get("mlp_layer_types")
|
||||
explicit = hparams.get("first_k_dense_replace")
|
||||
derived = None
|
||||
if mlp_types is not None:
|
||||
lead = 0
|
||||
for t in mlp_types:
|
||||
if t == "dense":
|
||||
lead += 1
|
||||
else:
|
||||
break
|
||||
if any(t == "dense" for t in mlp_types[lead:]):
|
||||
raise NotImplementedError("HY_V4 converter expects a contiguous leading dense block")
|
||||
derived = lead
|
||||
if explicit is not None and derived is not None and explicit != derived:
|
||||
raise ValueError(
|
||||
f"HY_V4 first_k_dense_replace ({explicit}) disagrees with mlp_layer_types "
|
||||
f"leading-dense count ({derived})"
|
||||
)
|
||||
if explicit is None:
|
||||
if derived is None:
|
||||
raise ValueError("HY_V4 needs first_k_dense_replace or mlp_layer_types to place dense layers")
|
||||
hparams["first_k_dense_replace"] = derived
|
||||
|
||||
# reuse DeepseekV2 MLA + MoE metadata (forces num_key_value_heads=1, writes q/kv lora,
|
||||
# key/value lengths, expert counts, weights scale/norm, rope dims, etc.)
|
||||
super().set_gguf_parameters()
|
||||
|
||||
# HY4 uses DeepSeek-V3 sigmoid routing with e_score_correction_bias. The config has no
|
||||
# scoring_func key, so the base does not write a gating func; set it explicitly.
|
||||
self.gguf_writer.add_expert_gating_func(gguf.ExpertGatingFuncType.SIGMOID)
|
||||
|
||||
# routed-expert SwiGLU logits clamp (only routed experts; shared/dense are not clamped,
|
||||
# so swiglu_clamp_shexp is intentionally not written). 0.0 disables the clamp.
|
||||
swiglu_limit = float(hparams.get("swiglu_limit", 0.0) or 0.0)
|
||||
if swiglu_limit > 0.0:
|
||||
self.gguf_writer.add_swiglu_clamp_exp([swiglu_limit] * self.block_count)
|
||||
|
||||
# iHC (independent Hyper-Connections)
|
||||
self.gguf_writer.add_hyper_connection_count(hparams["hc_mult"])
|
||||
self.gguf_writer.add_hyper_connection_epsilon(hparams["hc_eps"])
|
||||
self.gguf_writer.add_hyper_connection_magnitude(hparams["hc_magnitude"])
|
||||
|
||||
# is_full is written explicitly; the graph must not infer it from tensor presence
|
||||
is_full = self.indexer_is_full()
|
||||
if is_full is not None:
|
||||
self.gguf_writer.add_indexer_head_count(hparams["index_n_heads"])
|
||||
self.gguf_writer.add_indexer_key_length(hparams["index_head_dim"])
|
||||
self.gguf_writer.add_indexer_top_k(hparams["index_topk"])
|
||||
self.gguf_writer.add_indexer_types(is_full)
|
||||
logger.info(
|
||||
"HY_V4 DSA: %d/%d layers own an indexer (top_k=%d, n_heads=%d, head_dim=%d)",
|
||||
sum(is_full), len(is_full), hparams["index_topk"],
|
||||
hparams["index_n_heads"], hparams["index_head_dim"],
|
||||
)
|
||||
|
||||
if hparams.get("num_nextn_predict_layers", 0):
|
||||
logger.warning(
|
||||
"HY_V4: dropping %d MTP (nextn) layer(s) - the reference runs them only under "
|
||||
"training / speculative decoding. This GGUF cannot be used for speculative decoding.",
|
||||
hparams["num_nextn_predict_layers"],
|
||||
)
|
||||
|
||||
def prepare_tensors(self):
|
||||
# Hy4-preview for some reason has num_key_value_heads equal to 8, so override it here
|
||||
# without this conversion/deepseek.py fails on assert
|
||||
self.hparams["num_key_value_heads"] = self.hparams["num_attention_heads"]
|
||||
|
||||
# validate before the base materializes tensors, so a mismatch fails early
|
||||
is_full = self.indexer_is_full()
|
||||
if is_full is not None:
|
||||
present: dict[int, set[str]] = {}
|
||||
for name in self.model_tensors:
|
||||
m = re.match(r"model\.layers\.(\d+)\.(self_attn\.indexer\..+)$", name)
|
||||
if m:
|
||||
present.setdefault(int(m.group(1)), set()).add(m.group(2))
|
||||
for il, expect_full in enumerate(is_full):
|
||||
seen = present.get(il, set())
|
||||
if expect_full and seen != self.INDEXER_SUFFIXES:
|
||||
raise ValueError(
|
||||
f"HY_V4 layer {il} is indexer_types 'full' but is missing indexer tensors: "
|
||||
f"{sorted(self.INDEXER_SUFFIXES - seen)}"
|
||||
)
|
||||
if not expect_full and seen:
|
||||
raise ValueError(
|
||||
f"HY_V4 layer {il} is indexer_types 'shared' but carries indexer tensors: "
|
||||
f"{sorted(seen)}"
|
||||
)
|
||||
|
||||
super().prepare_tensors()
|
||||
|
||||
def tensor_force_quant(self, name, new_name, bid, n_dims):
|
||||
# iHC mixing matrices are 2D .weight tensors that the reference keeps in fp32
|
||||
# (_keep_in_fp32_modules_strict). 1D tensors (hc_base/scale, attn_sinks,
|
||||
# e_score_correction_bias) and the router (FFN_GATE_INP) are already forced F32 by the
|
||||
# base rules. Force the HC *_fn matrices here.
|
||||
if new_name.endswith(("hc_attn_fn.weight", "hc_ffn_fn.weight", "output_hc_fn.weight")):
|
||||
return gguf.GGMLQuantizationType.F32
|
||||
# indexer k_norm is fp32 in the reference; the base rules already cover
|
||||
# *_norm.weight and INDEXER_PROJ, but not this bias
|
||||
if self.match_model_tensor_name(new_name, gguf.MODEL_TENSOR.INDEXER_K_NORM, bid, suffix=".bias"):
|
||||
return gguf.GGMLQuantizationType.F32
|
||||
# enable_lm_head_fp32: mirror the reference fp32 LM-head matmul by keeping output F32.
|
||||
if new_name == "output.weight" and self.hparams.get("enable_lm_head_fp32", False):
|
||||
return gguf.GGMLQuantizationType.F32
|
||||
return super().tensor_force_quant(name, new_name, bid, n_dims)
|
||||
|
||||
def modify_tensors(self, data_torch: torch.Tensor, name: str, bid: int | None) -> Iterable[tuple[str, torch.Tensor]]:
|
||||
hparams = self.hparams
|
||||
moe_inter = hparams["moe_intermediate_size"]
|
||||
|
||||
tn = self.format_tensor_name
|
||||
|
||||
# fused stacked experts: split gate_up into gate/up
|
||||
if name.endswith("mlp.experts.gate_up_proj"):
|
||||
gate, up = split_gate_up(data_torch, moe_inter)
|
||||
yield from super().modify_tensors(gate, tn(gguf.MODEL_TENSOR.FFN_GATE_EXP, bid), bid)
|
||||
yield from super().modify_tensors(up, tn(gguf.MODEL_TENSOR.FFN_UP_EXP, bid), bid)
|
||||
return
|
||||
|
||||
# add .weight suffixes
|
||||
if name.endswith("mlp.experts.down_proj") or name.endswith(".self_attn.learnable_sink_param"):
|
||||
name += ".weight"
|
||||
|
||||
if re.search(r"\.hc_head\.hc_head_(?:fn|base|scale)$", name):
|
||||
name += ".weight"
|
||||
|
||||
if re.search(r"\.hc_(?:attn|mlp)_layer\.hc_pre\.hc_(?:fn|base|scale)$", name):
|
||||
name += ".weight"
|
||||
|
||||
yield from super().modify_tensors(data_torch, name, bid)
|
||||
@@ -379,6 +379,13 @@ class Qwen3NextModel(_QwenMtpMixin, Qwen2MoeModel):
|
||||
self.gguf_writer.add_ssm_group_count(self.hparams["linear_num_key_heads"])
|
||||
self.gguf_writer.add_ssm_time_step_rank(self.hparams["linear_num_value_heads"])
|
||||
self.gguf_writer.add_ssm_inner_size(self.hparams["linear_value_head_dim"] * self.hparams["linear_num_value_heads"])
|
||||
if (layer_types := self.hparams.get("layer_types")) is not None:
|
||||
n_layer = self.hparams["num_hidden_layers"]
|
||||
if len(layer_types) != n_layer:
|
||||
raise ValueError(f"layer_types has {len(layer_types)} entries, expected num_hidden_layers ({n_layer})")
|
||||
recurrent = [t == "linear_attention" for t in layer_types]
|
||||
recurrent += [False] * (self.block_count - n_layer)
|
||||
self.gguf_writer.add_recurrent_layers(recurrent)
|
||||
self.gguf_writer.add_full_attention_interval(self.hparams.get("full_attention_interval", 4))
|
||||
if (rope_dim := self.hparams.get("head_dim")) is None:
|
||||
rope_dim = self.hparams["hidden_size"] // self.hparams["num_attention_heads"]
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Iterable
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from torch import Tensor
|
||||
|
||||
from .base import ModelBase, TextModel, gguf
|
||||
|
||||
|
||||
@ModelBase.register("Spark2_5ForCausalLM")
|
||||
@ModelBase.example("XHToken/Spark-X2.5-1.7B")
|
||||
class Spark2_5Model(TextModel):
|
||||
model_arch = gguf.MODEL_ARCH.SPARK2_5
|
||||
|
||||
def set_gguf_parameters(self) -> None:
|
||||
super().set_gguf_parameters()
|
||||
|
||||
hparams = self.hparams
|
||||
layer_types = hparams["layer_types"]
|
||||
if len(layer_types) != self.block_count:
|
||||
raise ValueError(
|
||||
f"Spark2_5 layer_types length {len(layer_types)} != num_hidden_layers {self.block_count}"
|
||||
)
|
||||
if any(layer_type not in ("sliding_attention", "full_attention") for layer_type in layer_types):
|
||||
raise ValueError(f"Spark2_5 has unsupported layer_types: {layer_types}")
|
||||
if hparams.get("gate_attn_act_mode") != "sigmoid" or hparams.get("headwise_attn_output_gate") is not True:
|
||||
raise ValueError("Spark2_5 conversion requires head-wise sigmoid attention gates")
|
||||
if hparams.get("hidden_act") != "gelu":
|
||||
raise ValueError(f"Spark2_5 conversion requires GELU, got {hparams.get('hidden_act')!r}")
|
||||
|
||||
self.gguf_writer.add_vocab_size(hparams["vocab_size"])
|
||||
self.gguf_writer.add_sliding_window(hparams["sliding_window"])
|
||||
self.gguf_writer.add_sliding_window_pattern(
|
||||
[layer_type == "sliding_attention" for layer_type in layer_types]
|
||||
)
|
||||
|
||||
head_dim = hparams["head_dim"]
|
||||
full_rope = self.rope_parameters["full_attention"]
|
||||
swa_rope = self.rope_parameters["sliding_attention"]
|
||||
self.gguf_writer.add_rope_dimension_count(
|
||||
int(head_dim * float(full_rope["partial_rotary_factor"]))
|
||||
)
|
||||
self.gguf_writer.add_rope_dimension_count_swa(
|
||||
int(head_dim * float(swa_rope["partial_rotary_factor"]))
|
||||
)
|
||||
|
||||
def modify_tensors(self, data_torch: Tensor, name: str, bid: int | None) -> Iterable[tuple[str, Tensor]]:
|
||||
if name.endswith(".self_attn.q_k_v_proj.weight"):
|
||||
if bid is None:
|
||||
raise ValueError(f"Spark2_5 fused QKV tensor has no block id: {name}")
|
||||
yield self.format_tensor_name(gguf.MODEL_TENSOR.ATTN_QKV, bid), data_torch
|
||||
return
|
||||
|
||||
if name.endswith(".self_attn.g_proj.weight"):
|
||||
if bid is None:
|
||||
raise ValueError(f"Spark2_5 attention gate tensor has no block id: {name}")
|
||||
expected = self.hparams["num_attention_heads"]
|
||||
if data_torch.shape[0] != expected:
|
||||
raise ValueError(
|
||||
f"Spark2_5 layer {bid} attention gate width {data_torch.shape[0]} != head count {expected}"
|
||||
)
|
||||
|
||||
yield from super().modify_tensors(data_torch, name, bid)
|
||||
@@ -157,6 +157,10 @@ def parse_args() -> argparse.Namespace:
|
||||
help="Store tensors dequantized from FP8 as Q8_0 instead of BF16/F16.",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--fuse-qkv", action="store_true",
|
||||
help="Fuse separate Q, K, V weight tensors into a single QKV tensor.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"--target-model-dir", type=str, default=None,
|
||||
help=(
|
||||
@@ -290,6 +294,7 @@ def main() -> None:
|
||||
target_model_dir=Path(args.target_model_dir) if args.target_model_dir else None,
|
||||
fuse_gate_up_exps=args.fuse_gate_up_exps,
|
||||
fp8_as_q8=args.fp8_as_q8,
|
||||
fuse_qkv=args.fuse_qkv,
|
||||
)
|
||||
|
||||
if args.vocab_only:
|
||||
|
||||
@@ -176,6 +176,7 @@ pre_computed_hashes = [
|
||||
{"name": "minerva-7b", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/sapienzanlp/Minerva-7B-base-v1.0", "chkhsh": "1431a23e583c97432bc230bff598d103ddb5a1f89960c8f1d1051aaa944d0b35"},
|
||||
{"name": "hunyuan", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/tencent/Hunyuan-A13B-Instruct", "chkhsh": "7e57df22b1fe23a7b1e1c7f3dc4e3f96d43a4eb0836d0c6bdc3436d7b2f1c664"},
|
||||
{"name": "hunyuan-dense", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/tencent/Hunyuan-4B-Instruct", "chkhsh": "bba3b3366b646dbdded5dbc42d59598b849371afc42f7beafa914afaa5b70aa6"},
|
||||
{"name": "hy_v4", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/tencent/Hy4-preview", "chkhsh": "e6ddf9c6686791c12d698d34c31ab9be1fea9af5a3d9a6909783ab382198ae1c"},
|
||||
# falcon-h1 series uses 4 different tokenizers across model sizes (0.5b - 34b), hence we need to define 4 different hashes
|
||||
{"name": "falcon-h1", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/tiiuae/Falcon-H1-0.5B-Base", "chkhsh": "a6b57017d60e6edb4d88ecc2845188e0eb333a70357e45dcc9b53964a73bbae6"},
|
||||
{"name": "falcon-h1", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/tiiuae/Falcon-H1-1B-Base", "chkhsh": "60476e1243776c4fb1b993dbd7a5f15ac22f83c80afdf425fa5ae01c8d44ef86"},
|
||||
@@ -190,6 +191,7 @@ pre_computed_hashes = [
|
||||
{"name": "gpt-2", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/evilfreelancer/ruGPT3XL", "chkhsh": "0fe1cf6eda062318a1af7270f3331a85c539a01778ff948e24388e949c5282f4"},
|
||||
# lfm2 variants
|
||||
{"name": "lfm2", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/LiquidAI/LFM2.5-8B-A1B", "chkhsh": "9e454714343b69b99b71795c1d27a68c2a1d15dab111f4d353109f966af29da7"},
|
||||
{"name": "spark2_5", "tokt": TOKENIZER_TYPE.BPE, "repo": "https://huggingface.co/XHToken/Spark-X2.5-1.7B", "chkhsh": "0a766d034107bc736a3f2dc4968fd62e54a3570f1454443e0c5a4cc6bd7941ed"},
|
||||
]
|
||||
|
||||
|
||||
|
||||
@@ -514,6 +514,7 @@ The following templates have active tests in `tests/test-chat.cpp`:
|
||||
| Mistral Small 3.2 | JSON_NATIVE | `[TOOL_CALLS]func[ARGS]{...}` with call ID |
|
||||
| Devstral | JSON_NATIVE | `[TOOL_CALLS]func[ARGS]{...}` without call ID |
|
||||
| StepFun 3.5 Flash | TAG_WITH_TAGGED | `<function=X><parameter=Y>` format |
|
||||
| Spark2.5 | TAG_WITH_TAGGED | `<tool_call>name<arg_key>...<arg_value>...` format |
|
||||
|
||||
## Adding Support for New Templates
|
||||
|
||||
|
||||
@@ -805,6 +805,8 @@ User can use the device management in [docs/multi-gpu.md](https://github.com/ggm
|
||||
| GGML_SYCL_ENABLE_VMM | 0 or 1 (default) | Enable the virtual-memory device pool. |
|
||||
| GGML_SYCL_ENABLE_MKL_FA | 1 (default) or 0 | Enable oneMKL GEMM flash attention for XMX-accelerated prompt processing with quantized KV cache. Automatically activates during prefill (prompt processing) when all conditions are met: (1) flash-attn enabled (`-fa` or `--flash-attn on`), (2) KV cache quantized (`--cache-type-k q8_0 --cache-type-v q8_0` or other `*_0/*_1` types), (3) batch size ≥ 1024 (`--batch-size 1024`), (4) prompt length ≥ 1024 tokens. Set to 0 to force the TILE kernel for A/B testing. Example minimum command: `llama-cli -m model.gguf -fa -ngl 99 --cache-type-k q8_0 --cache-type-v q8_0 --batch-size 1024 -p "your prompt"` |
|
||||
| GGML_SYCL_MKL_FA_DEBUG | 0 (default) or 1 | Enable per-call diagnostic logging for MKL flash attention: GEMM/softmax timings, interleaved-head detection, and buffer memory usage. |
|
||||
| GGML_SYCL_MEMTRACE | 0 (default), 1, 2 | Enable record and output memory allocation diagnostics. Requires `-lv 4`. <br>0 - Disable<br>1 - Basic memory info, including current and peak allocations, as well allocations from other sources, around 50 lines per model load.<br>2 - More verbose, logging around 900 specific allocations and deallocations. |
|
||||
| GGML_SYCL_MEMTRACE_STEP | 64 (default) or positive integer | With GGML_SYCL_MEMTRACE=1, the minimum growth in memory usage to trigger another log record. |
|
||||
| GGML_SYCL_MKL_FA_DIAG | 0 (default) or 1 | Enable output fingerprinting for MKL flash attention. Dumps the first 64 float output values for the first 6 FA calls with n_kv ≥ 1024, labeled with kernel type (MKL/TILE/VEC) for cross-kernel comparison. |
|
||||
| GGML_SYCL_ENABLE_FUSION | 0 or 1 (default) | Enable fused-kernel dispatch in graph compute. Unsupported types and layouts fall back to the standalone op kernels. See `ggml_sycl_can_fuse()`. |
|
||||
| GGML_SYCL_ENABLE_ESIMD | 0 or 1 (default)| Enable ESIMD kernels when available. |
|
||||
|
||||
@@ -2,8 +2,9 @@
|
||||
#include <cstdio>
|
||||
|
||||
int main(void) {
|
||||
printf("[test-cmake] version: %s, build: %d (%s)\n",
|
||||
printf("[test-cmake] llama.cpp version: %s, build: %d (%s)\n",
|
||||
llama_version(), LLAMA_BUILD_NUMBER, LLAMA_BUILD_COMMIT);
|
||||
printf("[test-cmake] ggml version: %s, commit: %s\n", ggml_version(), ggml_commit());
|
||||
printf("[test-cmake] Initializing backend...\n");
|
||||
llama_backend_init();
|
||||
printf("[test-cmake] Backend initialized.\n");
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
}:
|
||||
{
|
||||
# For standardised reproducible formatting with `nix fmt`
|
||||
formatter = pkgs.nixfmt-rfc-style;
|
||||
formatter = pkgs.nixfmt;
|
||||
|
||||
# Unlike `.#packages`, legacyPackages may contain values of
|
||||
# arbitrary types (including nested attrsets) and may even throw
|
||||
@@ -156,7 +156,7 @@
|
||||
windows = config.legacyPackages.llamaPackagesWindows.llama-cpp;
|
||||
python-scripts = config.legacyPackages.llamaPackages.python-scripts;
|
||||
}
|
||||
// lib.optionalAttrs pkgs.stdenv.isLinux {
|
||||
// lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux {
|
||||
cuda = config.legacyPackages.llamaPackagesCuda.llama-cpp;
|
||||
|
||||
mpi-cpu = config.packages.default.override { useMpi = true; };
|
||||
|
||||
@@ -849,7 +849,7 @@ static void ggml_backend_sched_split_inputs_grow(struct ggml_backend_sched_split
|
||||
int new_cap = GGML_SCHED_MAX_SPLIT_INPUTS;
|
||||
if (split->inputs_capacity > 0) {
|
||||
new_cap = 2*split->inputs_capacity;
|
||||
GGML_LOG_WARN("%s: increasing split inputs capacity from %d to %d\n", __func__, split->inputs_capacity, new_cap);
|
||||
GGML_LOG_DEBUG("%s: increasing split inputs capacity from %d to %d\n", __func__, split->inputs_capacity, new_cap);
|
||||
}
|
||||
auto * pnew = (struct ggml_tensor **) realloc((void *) split->inputs, new_cap * sizeof(struct ggml_tensor *));
|
||||
if (pnew == NULL) {
|
||||
@@ -864,7 +864,7 @@ static void ggml_backend_sched_graph_inputs_grow(ggml_backend_sched_t sched) {
|
||||
int new_cap = GGML_SCHED_MAX_SPLIT_INPUTS;
|
||||
if (sched->graph_inputs_capacity > 0) {
|
||||
new_cap = 2*sched->graph_inputs_capacity;
|
||||
GGML_LOG_WARN("%s: increasing graph inputs capacity from %d to %d\n", __func__, sched->graph_inputs_capacity, new_cap);
|
||||
GGML_LOG_DEBUG("%s: increasing graph inputs capacity from %d to %d\n", __func__, sched->graph_inputs_capacity, new_cap);
|
||||
}
|
||||
auto * pnew = (struct ggml_tensor **) realloc((void *) sched->graph_inputs, new_cap * sizeof(struct ggml_tensor *));
|
||||
if (pnew == NULL) {
|
||||
@@ -1338,17 +1338,6 @@ void ggml_backend_sched_split_graph(ggml_backend_sched_t sched, struct ggml_cgra
|
||||
break;
|
||||
}
|
||||
}
|
||||
// check if the split has too many inputs
|
||||
// FIXME: count the number of inputs instead of only checking when full
|
||||
if (split->n_inputs >= split->inputs_capacity) {
|
||||
const size_t id = hash_id(src);
|
||||
int src_backend_id = sched->hv_tensor_backend_ids[id];
|
||||
bool supported = ggml_backend_sched_buffer_supported(sched, src, cur_backend_id);
|
||||
if (src_backend_id != cur_backend_id && tensor_id_copy(id, cur_backend_id, 0) == NULL && !supported) {
|
||||
need_new_split = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,8 @@
|
||||
#define GGML_CUDA_CC_GCN4 (GGML_CUDA_CC_OFFSET_AMD + 0x803) // Tonga, Fiji, Polaris, minimum for fast fp16
|
||||
#define GGML_CUDA_CC_VEGA (GGML_CUDA_CC_OFFSET_AMD + 0x900) // Vega56/64, minimum for fp16 dual issue
|
||||
#define GGML_CUDA_CC_VEGA20 (GGML_CUDA_CC_OFFSET_AMD + 0x906) // MI50/Radeon VII, minimum for dp4a
|
||||
#define GGML_CUDA_CC_GFX909 (GGML_CUDA_CC_OFFSET_AMD + 0x909) // GCN APU
|
||||
#define GGML_CUDA_CC_GFX90C (GGML_CUDA_CC_OFFSET_AMD + 0x90c) // GCN APU
|
||||
#define GGML_CUDA_CC_CDNA1 (GGML_CUDA_CC_OFFSET_AMD + 0x908) // MI100, minimum for MFMA, acc registers
|
||||
#define GGML_CUDA_CC_CDNA2 (GGML_CUDA_CC_OFFSET_AMD + 0x90a) // MI210 (gfx90a), minimum acc register renaming
|
||||
#define GGML_CUDA_CC_CDNA3 (GGML_CUDA_CC_OFFSET_AMD + 0x942) // MI300
|
||||
@@ -89,12 +91,13 @@
|
||||
#define GGML_CUDA_CC_IS_RDNA3_5(cc) (cc >= GGML_CUDA_CC_RDNA3_5 && cc < GGML_CUDA_CC_RDNA4)
|
||||
#define GGML_CUDA_CC_IS_RDNA3(cc) (GGML_CUDA_CC_IS_RDNA3_0(cc) || GGML_CUDA_CC_IS_RDNA3_5(cc))
|
||||
#define GGML_CUDA_CC_IS_RDNA4(cc) (cc >= GGML_CUDA_CC_RDNA4)
|
||||
#define GGML_CUDA_CC_IS_GCN(cc) (cc > GGML_CUDA_CC_OFFSET_AMD && cc < GGML_CUDA_CC_CDNA1)
|
||||
#define GGML_CUDA_CC_IS_CDNA(cc) (cc >= GGML_CUDA_CC_CDNA1 && cc < GGML_CUDA_CC_RDNA1)
|
||||
#define GGML_CUDA_CC_IS_CDNA1(cc) (cc >= GGML_CUDA_CC_CDNA1 && cc < GGML_CUDA_CC_CDNA2)
|
||||
#define GGML_CUDA_CC_IS_CDNA2(cc) (cc >= GGML_CUDA_CC_CDNA2 && cc < GGML_CUDA_CC_CDNA3)
|
||||
#define GGML_CUDA_CC_IS_CDNA3(cc) (cc >= GGML_CUDA_CC_CDNA3 && cc < GGML_CUDA_CC_CDNA4)
|
||||
#define GGML_CUDA_CC_IS_CDNA4(cc) (cc >= GGML_CUDA_CC_CDNA4 && cc < GGML_CUDA_CC_RDNA1)
|
||||
#define GGML_CUDA_CC_IS_GCN_APU(cc) ((cc) == GGML_CUDA_CC_GFX909 || (cc) == GGML_CUDA_CC_GFX90C)
|
||||
#define GGML_CUDA_CC_IS_GCN(cc) ((cc > GGML_CUDA_CC_OFFSET_AMD && cc < GGML_CUDA_CC_CDNA1) || GGML_CUDA_CC_IS_GCN_APU(cc))
|
||||
#define GGML_CUDA_CC_IS_CDNA(cc) (!GGML_CUDA_CC_IS_GCN_APU(cc) && cc >= GGML_CUDA_CC_CDNA1 && cc < GGML_CUDA_CC_RDNA1)
|
||||
#define GGML_CUDA_CC_IS_CDNA1(cc) (GGML_CUDA_CC_IS_CDNA(cc) && cc >= GGML_CUDA_CC_CDNA1 && cc < GGML_CUDA_CC_CDNA2)
|
||||
#define GGML_CUDA_CC_IS_CDNA2(cc) (GGML_CUDA_CC_IS_CDNA(cc) && cc >= GGML_CUDA_CC_CDNA2 && cc < GGML_CUDA_CC_CDNA3)
|
||||
#define GGML_CUDA_CC_IS_CDNA3(cc) (GGML_CUDA_CC_IS_CDNA(cc) && cc >= GGML_CUDA_CC_CDNA3 && cc < GGML_CUDA_CC_CDNA4)
|
||||
#define GGML_CUDA_CC_IS_CDNA4(cc) (GGML_CUDA_CC_IS_CDNA(cc) && cc >= GGML_CUDA_CC_CDNA4 && cc < GGML_CUDA_CC_RDNA1)
|
||||
|
||||
// Moore Threads
|
||||
#define MUSART_HMASK 40300 // MUSA rc4.3, min. ver. for half2 -> uint mask comparisons
|
||||
@@ -121,6 +124,12 @@
|
||||
# define GGML_CUDA_USE_PDL
|
||||
#endif // !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA) && (CUDART_VERSION >= 12030 || (!(defined(_MSC_VER) && !defined(__clang__)) && CUDART_VERSION >= 11080))
|
||||
|
||||
static __device__ __forceinline__ void ggml_cuda_syncwarp() {
|
||||
#ifndef GGML_USE_HIP
|
||||
__syncwarp();
|
||||
#endif // GGML_USE_HIP
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ void ggml_cuda_pdl_sync() {
|
||||
#if defined(GGML_CUDA_USE_PDL) && defined(__CUDA_ARCH__) && __CUDA_ARCH__ >= GGML_CUDA_CC_HOPPER
|
||||
cudaGridDependencySynchronize();
|
||||
@@ -970,6 +979,7 @@ template<>
|
||||
struct ggml_cuda_type_traits<GGML_TYPE_F16> {
|
||||
static constexpr int qk = 1;
|
||||
static constexpr int qr = 1;
|
||||
static constexpr int bs = sizeof(ggml_half);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -977,6 +987,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_Q1_0> {
|
||||
static constexpr int qk = QK1_0;
|
||||
static constexpr int qr = QR1_0;
|
||||
static constexpr int qi = QI1_0;
|
||||
static constexpr int bs = sizeof(block_q1_0);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -984,6 +995,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_Q2_0> {
|
||||
static constexpr int qk = QK2_0;
|
||||
static constexpr int qr = QR2_0;
|
||||
static constexpr int qi = QI2_0;
|
||||
static constexpr int bs = sizeof(block_q2_0);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -991,6 +1003,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_Q4_0> {
|
||||
static constexpr int qk = QK4_0;
|
||||
static constexpr int qr = QR4_0;
|
||||
static constexpr int qi = QI4_0;
|
||||
static constexpr int bs = sizeof(block_q4_0);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -998,6 +1011,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_Q4_1> {
|
||||
static constexpr int qk = QK4_1;
|
||||
static constexpr int qr = QR4_1;
|
||||
static constexpr int qi = QI4_1;
|
||||
static constexpr int bs = sizeof(block_q4_1);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1005,6 +1019,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_Q5_0> {
|
||||
static constexpr int qk = QK5_0;
|
||||
static constexpr int qr = QR5_0;
|
||||
static constexpr int qi = QI5_0;
|
||||
static constexpr int bs = sizeof(block_q5_0);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1012,6 +1027,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_Q5_1> {
|
||||
static constexpr int qk = QK5_1;
|
||||
static constexpr int qr = QR5_1;
|
||||
static constexpr int qi = QI5_1;
|
||||
static constexpr int bs = sizeof(block_q5_1);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1019,6 +1035,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_Q8_0> {
|
||||
static constexpr int qk = QK8_0;
|
||||
static constexpr int qr = QR8_0;
|
||||
static constexpr int qi = QI8_0;
|
||||
static constexpr int bs = sizeof(block_q8_0);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1026,6 +1043,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_MXFP4> {
|
||||
static constexpr int qk = QK_MXFP4;
|
||||
static constexpr int qr = QR_MXFP4;
|
||||
static constexpr int qi = QI_MXFP4;
|
||||
static constexpr int bs = sizeof(block_mxfp4);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1033,6 +1051,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_NVFP4> {
|
||||
static constexpr int qk = QK_NVFP4;
|
||||
static constexpr int qr = QR_NVFP4;
|
||||
static constexpr int qi = QI_NVFP4;
|
||||
static constexpr int bs = sizeof(block_nvfp4);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1040,6 +1059,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_Q2_K> {
|
||||
static constexpr int qk = QK_K;
|
||||
static constexpr int qr = QR2_K;
|
||||
static constexpr int qi = QI2_K;
|
||||
static constexpr int bs = sizeof(block_q2_K);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1047,6 +1067,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_Q3_K> {
|
||||
static constexpr int qk = QK_K;
|
||||
static constexpr int qr = QR3_K;
|
||||
static constexpr int qi = QI3_K;
|
||||
static constexpr int bs = sizeof(block_q3_K);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1054,6 +1075,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_Q4_K> {
|
||||
static constexpr int qk = QK_K;
|
||||
static constexpr int qr = QR4_K;
|
||||
static constexpr int qi = QI4_K;
|
||||
static constexpr int bs = sizeof(block_q4_K);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1061,6 +1083,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_Q5_K> {
|
||||
static constexpr int qk = QK_K;
|
||||
static constexpr int qr = QR5_K;
|
||||
static constexpr int qi = QI5_K;
|
||||
static constexpr int bs = sizeof(block_q5_K);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1068,6 +1091,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_Q6_K> {
|
||||
static constexpr int qk = QK_K;
|
||||
static constexpr int qr = QR6_K;
|
||||
static constexpr int qi = QI6_K;
|
||||
static constexpr int bs = sizeof(block_q6_K);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1075,6 +1099,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_IQ2_XXS> {
|
||||
static constexpr int qk = QK_K;
|
||||
static constexpr int qr = QR2_XXS;
|
||||
static constexpr int qi = QI2_XXS;
|
||||
static constexpr int bs = sizeof(block_iq2_xxs);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1082,6 +1107,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_IQ2_XS> {
|
||||
static constexpr int qk = QK_K;
|
||||
static constexpr int qr = QR2_XS;
|
||||
static constexpr int qi = QI2_XS;
|
||||
static constexpr int bs = sizeof(block_iq2_xs);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1089,6 +1115,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_IQ2_S> {
|
||||
static constexpr int qk = QK_K;
|
||||
static constexpr int qr = QR2_S;
|
||||
static constexpr int qi = QI2_S;
|
||||
static constexpr int bs = sizeof(block_iq2_s);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1096,6 +1123,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_IQ3_XXS> {
|
||||
static constexpr int qk = QK_K;
|
||||
static constexpr int qr = QR3_XXS;
|
||||
static constexpr int qi = QI3_XXS;
|
||||
static constexpr int bs = sizeof(block_iq3_xxs);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1103,6 +1131,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_IQ1_S> {
|
||||
static constexpr int qk = QK_K;
|
||||
static constexpr int qr = QR1_S;
|
||||
static constexpr int qi = QI1_S;
|
||||
static constexpr int bs = sizeof(block_iq1_s);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1110,6 +1139,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_IQ1_M> {
|
||||
static constexpr int qk = QK_K;
|
||||
static constexpr int qr = QR1_M;
|
||||
static constexpr int qi = QI1_M;
|
||||
static constexpr int bs = sizeof(block_iq1_m);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1117,6 +1147,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_IQ4_NL> {
|
||||
static constexpr int qk = QK4_NL;
|
||||
static constexpr int qr = QR4_NL;
|
||||
static constexpr int qi = QI4_NL;
|
||||
static constexpr int bs = sizeof(block_iq4_nl);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1124,6 +1155,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_IQ4_XS> {
|
||||
static constexpr int qk = QK_K;
|
||||
static constexpr int qr = QR4_XS;
|
||||
static constexpr int qi = QI4_XS;
|
||||
static constexpr int bs = sizeof(block_iq4_xs);
|
||||
};
|
||||
|
||||
template<>
|
||||
@@ -1131,6 +1163,7 @@ struct ggml_cuda_type_traits<GGML_TYPE_IQ3_S> {
|
||||
static constexpr int qk = QK_K;
|
||||
static constexpr int qr = QR3_S;
|
||||
static constexpr int qi = QI3_S;
|
||||
static constexpr int bs = sizeof(block_iq3_s);
|
||||
};
|
||||
|
||||
//////////////////////
|
||||
|
||||
@@ -1545,77 +1545,77 @@ static __device__ __forceinline__ void flash_attn_ext_f16_process_tile(
|
||||
}
|
||||
}
|
||||
|
||||
if (np > 1 && threadIdx.y % np == 0) {
|
||||
// Combine the meta data for parallel warps via shared memory.
|
||||
// Warps with threadIdx.y % np != 0 must NOT return early.
|
||||
// All threads must return simultaneously to avoid race conditions with work on the next tile.
|
||||
|
||||
if (np > 1) {
|
||||
constexpr int nmeta = np*cols_per_warp >= warp_size ? np*cols_per_warp/warp_size : 1;
|
||||
|
||||
float KQ_cmn;
|
||||
float KQ_cms[nmeta];
|
||||
float KQ_crs;
|
||||
|
||||
const int jc_meta = threadIdx.y*cols_per_warp + (np*cols_per_warp < warp_size ? threadIdx.x % (np*cols_per_warp) : threadIdx.x);
|
||||
float2 * const meta_ptr = ((float2 *) tile_Q) + jc_meta*(tile_stride/2) + nbatch_combine/2;
|
||||
float2 meta[nmeta];
|
||||
#pragma unroll
|
||||
for (int imeta = 0; imeta < nmeta; ++imeta) {
|
||||
meta[imeta] = meta_ptr[imeta * warp_size * tile_stride/2];
|
||||
}
|
||||
|
||||
float KQ_cmn = meta[0].x; // KQ combine max new, max between all parallel warps.
|
||||
if (threadIdx.y % np == 0) {
|
||||
// Combine the meta data for parallel warps via shared memory.
|
||||
float2 meta[nmeta];
|
||||
#pragma unroll
|
||||
for (int imeta = 1; imeta < nmeta; ++imeta) {
|
||||
KQ_cmn = fmaxf(KQ_cmn, meta[imeta].x);
|
||||
}
|
||||
#pragma unroll
|
||||
for (int offset = np*cols_per_warp/2; offset >= cols_per_warp; offset >>= 1) {
|
||||
if (offset < warp_size) {
|
||||
KQ_cmn = fmaxf(KQ_cmn, __shfl_xor_sync(0xFFFFFFFF, KQ_cmn, offset, warp_size));
|
||||
for (int imeta = 0; imeta < nmeta; ++imeta) {
|
||||
meta[imeta] = meta_ptr[imeta * warp_size * tile_stride/2];
|
||||
}
|
||||
}
|
||||
|
||||
float KQ_cms[nmeta]; // KQ combine max scale per warp.
|
||||
KQ_cmn = meta[0].x; // KQ combine max new, max between all parallel warps.
|
||||
#pragma unroll
|
||||
for (int imeta = 0; imeta < nmeta; ++imeta) {
|
||||
KQ_cms[imeta] = expf(meta[imeta].x - KQ_cmn);
|
||||
}
|
||||
for (int imeta = 1; imeta < nmeta; ++imeta) {
|
||||
KQ_cmn = fmaxf(KQ_cmn, meta[imeta].x);
|
||||
}
|
||||
#pragma unroll
|
||||
for (int offset = np*cols_per_warp/2; offset >= cols_per_warp; offset >>= 1) {
|
||||
if (offset < warp_size) {
|
||||
KQ_cmn = fmaxf(KQ_cmn, __shfl_xor_sync(0xFFFFFFFF, KQ_cmn, offset, warp_size));
|
||||
}
|
||||
}
|
||||
|
||||
float KQ_crs = KQ_cms[0]*meta[0].y; // KQ combine rowsum, scaled sum of all parallel warps.
|
||||
#pragma unroll
|
||||
for (int imeta = 1; imeta < nmeta; ++imeta) {
|
||||
KQ_crs += KQ_cms[imeta]*meta[imeta].y;
|
||||
}
|
||||
for (int imeta = 0; imeta < nmeta; ++imeta) {
|
||||
KQ_cms[imeta] = expf(meta[imeta].x - KQ_cmn);
|
||||
}
|
||||
|
||||
KQ_crs = KQ_cms[0]*meta[0].y; // KQ combine rowsum, scaled sum of all parallel warps.
|
||||
#pragma unroll
|
||||
for (int offset = np*cols_per_warp/2; offset >= cols_per_warp; offset >>= 1) {
|
||||
if (offset < warp_size) {
|
||||
KQ_crs += __shfl_xor_sync(0xFFFFFFFF, KQ_crs, offset, warp_size);
|
||||
for (int imeta = 1; imeta < nmeta; ++imeta) {
|
||||
KQ_crs += KQ_cms[imeta]*meta[imeta].y;
|
||||
}
|
||||
#pragma unroll
|
||||
for (int offset = np*cols_per_warp/2; offset >= cols_per_warp; offset >>= 1) {
|
||||
if (offset < warp_size) {
|
||||
KQ_crs += __shfl_xor_sync(0xFFFFFFFF, KQ_crs, offset, warp_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__syncthreads();
|
||||
|
||||
// Write back combined meta data:
|
||||
if (threadIdx.y % np == 0) {
|
||||
// Write back combined meta data:
|
||||
#pragma unroll
|
||||
for (int imeta = 0; imeta < nmeta; ++imeta) {
|
||||
if (np*cols_per_warp >= warp_size || threadIdx.x < np*cols_per_warp) {
|
||||
// Combined KQ max scale + rowsum.
|
||||
meta_ptr[imeta * warp_size * tile_stride/2] = make_float2(KQ_cms[imeta], KQ_crs);
|
||||
for (int imeta = 0; imeta < nmeta; ++imeta) {
|
||||
if (np*cols_per_warp >= warp_size || threadIdx.x < np*cols_per_warp) {
|
||||
// Combined KQ max scale + rowsum.
|
||||
meta_ptr[imeta * warp_size * tile_stride/2] = make_float2(KQ_cms[imeta], KQ_crs);
|
||||
}
|
||||
}
|
||||
|
||||
// Combined KQ max + rowsum.
|
||||
static_assert(cols_per_warp <= warp_size);
|
||||
if (needs_fixup && (cols_per_warp == warp_size || threadIdx.x < cols_per_warp)) {
|
||||
float2 * dstk_fixup_meta = dstk_fixup + blockIdx.x*ncols;
|
||||
dstk_fixup_meta[(threadIdx.y/np)*cols_per_warp + threadIdx.x] = make_float2(KQ_cmn, KQ_crs);
|
||||
}
|
||||
if (is_fixup && (cols_per_warp == warp_size || threadIdx.x < cols_per_warp)) {
|
||||
float2 * dstk_fixup_meta = dstk_fixup + (gridDim.x + blockIdx.x)*ncols;
|
||||
dstk_fixup_meta[(threadIdx.y/np)*cols_per_warp + threadIdx.x] = make_float2(KQ_cmn, KQ_crs);
|
||||
}
|
||||
}
|
||||
|
||||
// Combined KQ max + rowsum.
|
||||
static_assert(cols_per_warp <= warp_size);
|
||||
if (needs_fixup && (cols_per_warp == warp_size || threadIdx.x < cols_per_warp)) {
|
||||
float2 * dstk_fixup_meta = dstk_fixup + blockIdx.x*ncols;
|
||||
dstk_fixup_meta[(threadIdx.y/np)*cols_per_warp + threadIdx.x] = make_float2(KQ_cmn, KQ_crs);
|
||||
}
|
||||
if (is_fixup && (cols_per_warp == warp_size || threadIdx.x < cols_per_warp)) {
|
||||
float2 * dstk_fixup_meta = dstk_fixup + (gridDim.x + blockIdx.x)*ncols;
|
||||
dstk_fixup_meta[(threadIdx.y/np)*cols_per_warp + threadIdx.x] = make_float2(KQ_cmn, KQ_crs);
|
||||
}
|
||||
} else if (np > 1) {
|
||||
// Warps with threadIdx.y % np == 0 execute a __syncthreads() in the if branch.
|
||||
// Therefore, all other warps also need to execute a __syncthreads().
|
||||
// Otherwise the points at which warps synchronize with each other would become misaligned.
|
||||
__syncthreads();
|
||||
}
|
||||
|
||||
#pragma unroll
|
||||
|
||||
@@ -317,9 +317,7 @@ static __global__ void flash_attn_ext_vec(
|
||||
#endif // V_DOT2_F32_F16_AVAILABLE
|
||||
}
|
||||
|
||||
#ifndef GGML_USE_HIP
|
||||
__syncwarp();
|
||||
#endif // GGML_USE_HIP
|
||||
ggml_cuda_syncwarp();
|
||||
|
||||
#pragma unroll
|
||||
for (int k0 = 0; k0 < WARP_SIZE; k0 += V_cols_per_iter) {
|
||||
|
||||
@@ -212,6 +212,7 @@ static int ggml_cuda_parse_id(char devName[]) {
|
||||
}
|
||||
archNum += archMajor * 0x100;
|
||||
archNum += archMinor;
|
||||
|
||||
return archNum;
|
||||
}
|
||||
#endif // defined(GGML_USE_HIP)
|
||||
|
||||
@@ -143,6 +143,7 @@ static __global__ void mul_mat_f(
|
||||
if (threadIdx.x == 0) {
|
||||
slot_map[j] = -1;
|
||||
}
|
||||
ggml_cuda_syncwarp();
|
||||
|
||||
if (col_base + j >= ncols_dst_total) {
|
||||
continue;
|
||||
@@ -171,10 +172,12 @@ static __global__ void mul_mat_f(
|
||||
tile_A A[ntA][warp_size / tile_A::J];
|
||||
#pragma unroll
|
||||
for (int itA = 0; itA < ntA; ++itA) {
|
||||
ggml_cuda_syncwarp();
|
||||
#pragma unroll
|
||||
for (int i = 0; i < tile_A::I; ++i) {
|
||||
tile_xy[i*tile_k_padded + threadIdx.x] = x[(itA*tile_A::I + i)*stride_row + col];
|
||||
}
|
||||
ggml_cuda_syncwarp();
|
||||
#pragma unroll
|
||||
for (int k0 = 0; k0 < warp_size; k0 += tile_A::J) {
|
||||
load_ldmatrix(A[itA][k0/tile_A::J], tile_xy + k0, tile_k_padded);
|
||||
@@ -183,6 +186,7 @@ static __global__ void mul_mat_f(
|
||||
|
||||
#pragma unroll
|
||||
for (int itB = 0; itB < ntB; ++itB) {
|
||||
ggml_cuda_syncwarp();
|
||||
if constexpr (std::is_same_v<T, float>) {
|
||||
#pragma unroll
|
||||
for (int j0 = 0; j0 < tile_B::I; ++j0) {
|
||||
@@ -212,6 +216,7 @@ static __global__ void mul_mat_f(
|
||||
} else {
|
||||
static_assert(std::is_same_v<T, void>, "unsupported type");
|
||||
}
|
||||
ggml_cuda_syncwarp();
|
||||
#pragma unroll
|
||||
for (int k0 = 0; k0 < warp_size; k0 += tile_B::J) {
|
||||
tile_B B;
|
||||
@@ -229,6 +234,8 @@ static __global__ void mul_mat_f(
|
||||
|
||||
if (nwarps > 1) {
|
||||
__syncthreads();
|
||||
} else {
|
||||
ggml_cuda_syncwarp();
|
||||
}
|
||||
#pragma unroll
|
||||
for (int itB = 0; itB < ntB; ++itB) {
|
||||
@@ -245,6 +252,8 @@ static __global__ void mul_mat_f(
|
||||
|
||||
if (nwarps > 1) {
|
||||
__syncthreads();
|
||||
} else {
|
||||
ggml_cuda_syncwarp();
|
||||
}
|
||||
|
||||
#pragma unroll
|
||||
@@ -382,10 +391,12 @@ static __global__ void mul_mat_f_ids(
|
||||
tile_A A[ntA][warp_size / tile_A::J];
|
||||
#pragma unroll
|
||||
for (int itA = 0; itA < ntA; ++itA) {
|
||||
ggml_cuda_syncwarp();
|
||||
#pragma unroll
|
||||
for (int i = 0; i < tile_A::I; ++i) {
|
||||
tile_xy[i*tile_k_padded + threadIdx.x] = x[(itA*tile_A::I + i)*stride_row + col];
|
||||
}
|
||||
ggml_cuda_syncwarp();
|
||||
#pragma unroll
|
||||
for (int k0 = 0; k0 < warp_size; k0 += tile_A::J) {
|
||||
load_ldmatrix(A[itA][k0/tile_A::J], tile_xy + k0, tile_k_padded);
|
||||
@@ -419,6 +430,7 @@ static __global__ void mul_mat_f_ids(
|
||||
int next_buf = 1;
|
||||
#pragma unroll
|
||||
for (int itB = 0; itB < ntB; ++itB) {
|
||||
ggml_cuda_syncwarp();
|
||||
#pragma unroll
|
||||
for (int j0 = 0; j0 < tile_B::I; ++j0) {
|
||||
tile_xy[j0*tile_k_padded + threadIdx.x] = vals_buf[curr_buf][j0];
|
||||
@@ -428,6 +440,7 @@ static __global__ void mul_mat_f_ids(
|
||||
gather_tile(itB + 1, vals_buf[next_buf]);
|
||||
}
|
||||
|
||||
ggml_cuda_syncwarp();
|
||||
#pragma unroll
|
||||
for (int k0 = 0; k0 < warp_size; k0 += tile_B::J) {
|
||||
tile_B B;
|
||||
@@ -472,6 +485,7 @@ static __global__ void mul_mat_f_ids(
|
||||
int next_buf = 1;
|
||||
#pragma unroll
|
||||
for (int itB = 0; itB < ntB; ++itB) {
|
||||
ggml_cuda_syncwarp();
|
||||
#pragma unroll
|
||||
for (int j0 = 0; j0 < tile_B::I; ++j0) {
|
||||
const float2 tmp = vals_buf[curr_buf][j0];
|
||||
@@ -482,6 +496,7 @@ static __global__ void mul_mat_f_ids(
|
||||
gather_tile(itB + 1, vals_buf[next_buf]);
|
||||
}
|
||||
|
||||
ggml_cuda_syncwarp();
|
||||
#pragma unroll
|
||||
for (int k0 = 0; k0 < warp_size; k0 += tile_B::J) {
|
||||
tile_B B;
|
||||
@@ -507,6 +522,8 @@ static __global__ void mul_mat_f_ids(
|
||||
|
||||
if (nwarps > 1) {
|
||||
__syncthreads();
|
||||
} else {
|
||||
ggml_cuda_syncwarp();
|
||||
}
|
||||
#pragma unroll
|
||||
for (int itB = 0; itB < ntB; ++itB) {
|
||||
@@ -523,6 +540,8 @@ static __global__ void mul_mat_f_ids(
|
||||
|
||||
if (nwarps > 1) {
|
||||
__syncthreads();
|
||||
} else {
|
||||
ggml_cuda_syncwarp();
|
||||
}
|
||||
|
||||
#pragma unroll
|
||||
|
||||
@@ -101,6 +101,7 @@ static __global__ void mm_ids_helper(
|
||||
}
|
||||
}
|
||||
nex_prev = warp_reduce_sum<warp_size>(nex_prev);
|
||||
ggml_cuda_syncwarp();
|
||||
|
||||
for (int itc = threadIdx.x; itc < it_compact; itc += warp_size) {
|
||||
const mm_ids_helper_store store_it = store[itc];
|
||||
|
||||
@@ -375,10 +375,10 @@ bool ggml_cuda_should_use_mmq(enum ggml_type type, int cc, int64_t ne11, int64_t
|
||||
return true;
|
||||
}
|
||||
|
||||
// gfx900 (Vega 10) lacks native dp4a, loses to dequant + hipBLAS
|
||||
// gfx900 (Vega 10), gfx909, and gfx90c lack native dp4a, losing to dequant + hipBLAS
|
||||
// for dense matrices; keep MMQ only for MoE, where the
|
||||
// hipBLAS path is much slower.
|
||||
if (cc == GGML_CUDA_CC_VEGA) {
|
||||
if (cc == GGML_CUDA_CC_VEGA || GGML_CUDA_CC_IS_GCN_APU(cc)) {
|
||||
return n_experts > 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,35 @@
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
// only enabled on DGX Spark, where it is a gain on every type below. On the higher-bandwidth parts the kernel
|
||||
// has little exposed latency left to hide and the extra requests cost more than they save.
|
||||
// For perf data, see https://github.com/ggml-org/llama.cpp/pull/26705#issuecomment-5569335031
|
||||
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ == GGML_CUDA_CC_DGX_SPARK
|
||||
// returns true only for those quants that benefit from prefetch and false otherwise
|
||||
static constexpr __host__ __device__ bool mmvq_should_prefetch(ggml_type type) {
|
||||
switch (type) {
|
||||
case GGML_TYPE_Q4_0:
|
||||
case GGML_TYPE_Q5_0:
|
||||
case GGML_TYPE_Q8_0:
|
||||
case GGML_TYPE_MXFP4:
|
||||
case GGML_TYPE_Q3_K:
|
||||
case GGML_TYPE_Q4_K:
|
||||
case GGML_TYPE_Q5_K:
|
||||
case GGML_TYPE_Q6_K:
|
||||
case GGML_TYPE_IQ1_M:
|
||||
case GGML_TYPE_IQ4_NL:
|
||||
case GGML_TYPE_IQ4_XS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static __device__ __forceinline__ void mmvq_prefetch_l2(const void * p) {
|
||||
asm volatile("prefetch.global.L2 [%0];" :: "l"(p));
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef float (*vec_dot_q_cuda_t)(const void * __restrict__ vbq, const block_q8_1 * __restrict__ bq8_1, const int & kbx, const int & iqs);
|
||||
|
||||
static constexpr __device__ vec_dot_q_cuda_t get_vec_dot_q_cuda(ggml_type type) {
|
||||
@@ -298,9 +327,6 @@ bool ggml_cuda_should_use_mmvq(enum ggml_type type, int cc, int64_t ne11) {
|
||||
return ne11 <= 4;
|
||||
case GGML_TYPE_Q3_K:
|
||||
return ne11 <= 6;
|
||||
case GGML_TYPE_Q4_K:
|
||||
case GGML_TYPE_Q5_K:
|
||||
return ne11 <= 7;
|
||||
default:
|
||||
return ne11 <= MMVQ_MAX_BATCH_SIZE;
|
||||
}
|
||||
@@ -310,8 +336,9 @@ bool ggml_cuda_should_use_mmvq(enum ggml_type type, int cc, int64_t ne11) {
|
||||
case GGML_TYPE_Q2_K:
|
||||
case GGML_TYPE_Q3_K:
|
||||
case GGML_TYPE_Q4_K:
|
||||
case GGML_TYPE_Q5_K:
|
||||
return ne11 <= 5;
|
||||
case GGML_TYPE_Q5_K:
|
||||
return ne11 <= 6;
|
||||
case GGML_TYPE_Q6_K:
|
||||
return ne11 <= 7;
|
||||
default:
|
||||
@@ -675,6 +702,26 @@ static __global__ void mul_mat_vec_q(
|
||||
// x block quant index when casting the quants to int
|
||||
const int kqs = vdr * (tid % (qi/vdr));
|
||||
|
||||
#if defined(__CUDA_ARCH__) && __CUDA_ARCH__ == GGML_CUDA_CC_DGX_SPARK
|
||||
// start the next iterations' weight loads early
|
||||
if constexpr (mmvq_should_prefetch(type)) {
|
||||
constexpr int pf_dist = 2; // loop iterations, not blocks
|
||||
const int kbx_pf = kbx + pf_dist*blocks_per_iter;
|
||||
if (kbx_pf < blocks_per_row_x) {
|
||||
#pragma unroll
|
||||
for (int i = 0; i < rows_per_cuda_block; ++i) {
|
||||
const size_t off = (size_t)(kbx_offset + i*stride_row_x + kbx_pf) * ggml_cuda_type_traits<type>::bs;
|
||||
mmvq_prefetch_l2((const char *) vx + off);
|
||||
if constexpr (has_fusion) {
|
||||
if (use_gate) {
|
||||
mmvq_prefetch_l2((const char *) vgate + off);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma unroll
|
||||
for (int j = 0; j < ncols_dst; ++j) {
|
||||
#pragma unroll
|
||||
|
||||
@@ -936,16 +936,20 @@ static __device__ __forceinline__ float vec_dot_q4_K_q8_1(
|
||||
v[0] = q4[0];
|
||||
v[1] = q4[4];
|
||||
|
||||
// branchless so nvcc can hoist this out of the ncols_dst loop
|
||||
const uint16_t * scales = (const uint16_t *)bq4_K->scales;
|
||||
const int j = bq8_offset/2;
|
||||
const int jm = j & 1;
|
||||
|
||||
const uint32_t s0 = scales[jm + 0];
|
||||
const uint32_t s2 = scales[jm + 2];
|
||||
const uint32_t s4 = scales[jm + 4];
|
||||
|
||||
const uint32_t hi = (uint32_t) -(int32_t) (j >= 2);
|
||||
|
||||
uint16_t aux[2];
|
||||
const int j = bq8_offset/2;
|
||||
if (j < 2) {
|
||||
aux[0] = scales[j+0] & 0x3f3f;
|
||||
aux[1] = scales[j+2] & 0x3f3f;
|
||||
} else {
|
||||
aux[0] = ((scales[j+2] >> 0) & 0x0f0f) | ((scales[j-2] & 0xc0c0) >> 2);
|
||||
aux[1] = ((scales[j+2] >> 4) & 0x0f0f) | ((scales[j-0] & 0xc0c0) >> 2);
|
||||
}
|
||||
aux[0] = (uint16_t) (((s0 & 0x3f3f) & ~hi) | ((((s4 >> 0) & 0x0f0f) | ((s0 & 0xc0c0) >> 2)) & hi));
|
||||
aux[1] = (uint16_t) (((s2 & 0x3f3f) & ~hi) | ((((s4 >> 4) & 0x0f0f) | ((s2 & 0xc0c0) >> 2)) & hi));
|
||||
const uint8_t * sc = (const uint8_t *)aux;
|
||||
const uint8_t * m = sc + 2;
|
||||
|
||||
@@ -981,16 +985,21 @@ static __device__ __forceinline__ float vec_dot_q5_K_q8_1(
|
||||
vh[0] = qh[0] >> bq8_offset;
|
||||
vh[1] = qh[4] >> bq8_offset;
|
||||
|
||||
// same as q4_K
|
||||
const uint16_t * scales = (const uint16_t *)bq5_K->scales;
|
||||
const int j = bq8_offset/2;
|
||||
const int jm = j & 1;
|
||||
|
||||
const uint32_t s0 = scales[jm + 0];
|
||||
const uint32_t s2 = scales[jm + 2];
|
||||
const uint32_t s4 = scales[jm + 4];
|
||||
|
||||
const uint32_t hi = (uint32_t) -(int32_t) (j >= 2);
|
||||
|
||||
uint16_t aux[2];
|
||||
const int j = bq8_offset/2;
|
||||
if (j < 2) {
|
||||
aux[0] = scales[j+0] & 0x3f3f;
|
||||
aux[1] = scales[j+2] & 0x3f3f;
|
||||
} else {
|
||||
aux[0] = ((scales[j+2] >> 0) & 0x0f0f) | ((scales[j-2] & 0xc0c0) >> 2);
|
||||
aux[1] = ((scales[j+2] >> 4) & 0x0f0f) | ((scales[j-0] & 0xc0c0) >> 2);
|
||||
}
|
||||
aux[0] = (uint16_t) (((s0 & 0x3f3f) & ~hi) | ((((s4 >> 0) & 0x0f0f) | ((s0 & 0xc0c0) >> 2)) & hi));
|
||||
aux[1] = (uint16_t) (((s2 & 0x3f3f) & ~hi) | ((((s4 >> 4) & 0x0f0f) | ((s2 & 0xc0c0) >> 2)) & hi));
|
||||
|
||||
const uint8_t * sc = (const uint8_t *)aux;
|
||||
const uint8_t * m = sc + 2;
|
||||
|
||||
|
||||
Vendored
+2
-2
@@ -176,9 +176,9 @@
|
||||
|
||||
#define __CUDA_ARCH__ 1300
|
||||
|
||||
#if defined(__gfx900__) || defined(__gfx906__)
|
||||
#if defined(__gfx900__) || defined(__gfx906__) || defined(__gfx909__) || defined(__gfx90c__)
|
||||
#define GCN5
|
||||
#endif // defined(__gfx900__) || defined(__gfx906__)
|
||||
#endif // defined(__gfx900__) || defined(__gfx906__) || defined(__gfx909__) || defined(__gfx90c__)
|
||||
|
||||
#if defined(__gfx803__)
|
||||
#define GCN4
|
||||
|
||||
@@ -111,6 +111,7 @@ ggml_metal_t ggml_metal_init(ggml_metal_device_t dev) {
|
||||
id<MTLCommandQueue> queue = ggml_metal_device_get_queue(dev);
|
||||
if (queue == nil) {
|
||||
GGML_LOG_ERROR("%s: error: failed to create command queue\n", __func__);
|
||||
free(res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -1486,7 +1486,9 @@ static bool ggml_metal_supports_mul_mat_op(
|
||||
const struct ggml_tensor * op,
|
||||
bool src0_f16_has_mv,
|
||||
bool mm_path) {
|
||||
if (!has_simdgroup_reduction || op->src[0]->type == GGML_TYPE_NVFP4) {
|
||||
if (!has_simdgroup_reduction ||
|
||||
op->src[0]->type == GGML_TYPE_NVFP4 ||
|
||||
op->src[0]->type == GGML_TYPE_TQ1_0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1887,7 +1889,8 @@ bool ggml_metal_device_supports_op(ggml_metal_device_t dev, const struct ggml_te
|
||||
};
|
||||
}
|
||||
case GGML_OP_GET_ROWS:
|
||||
return op->src[0]->type != GGML_TYPE_NVFP4;
|
||||
return op->src[0]->type != GGML_TYPE_NVFP4 &&
|
||||
op->src[0]->type != GGML_TYPE_TQ1_0;
|
||||
case GGML_OP_SET_ROWS:
|
||||
{
|
||||
if (op->src[0]->type == GGML_TYPE_F16) {
|
||||
|
||||
@@ -1248,6 +1248,153 @@ constexpr fa_vec_entry_t fa_vec_tuned_table[] = {
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_F16, 512, 512, 2, 0 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_F16, 512, 512, 2, 1 }, { 4, 1 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_F16, 512, 512, 2, 2 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 32, 32, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 32, 32, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 32, 32, 2, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 32, 32, 2, 4 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 32, 32, 3, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 32, 32, 3, 3 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 64, 64, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 64, 64, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 64, 64, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 64, 64, 2, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 64, 64, 3, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 96, 96, 1, 3 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 96, 96, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 96, 96, 2, 3 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 96, 96, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 96, 96, 3, 3 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 128, 128, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 128, 128, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 128, 128, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 192, 192, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 192, 192, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 192, 128, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 192, 128, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 256, 256, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 256, 256, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 320, 256, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 320, 256, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 512, 512, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 512, 512, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 576, 512, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_0, 576, 512, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 32, 32, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 32, 32, 1, 3 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 32, 32, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 32, 32, 2, 3 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 32, 32, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 32, 32, 3, 3 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 32, 32, 3, 4 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 64, 64, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 64, 64, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 64, 64, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 64, 64, 2, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 64, 64, 2, 4 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 64, 64, 3, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 96, 96, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 96, 96, 2, 3 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 96, 96, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 96, 96, 3, 3 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 128, 128, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 128, 128, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 128, 128, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 128, 128, 1, 4 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 128, 128, 2, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 128, 128, 3, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 192, 192, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 192, 192, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 192, 192, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 192, 192, 2, 3 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 192, 128, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 192, 128, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 256, 256, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 256, 256, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 320, 256, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 320, 256, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 512, 512, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 512, 512, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 576, 512, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q4_1, 576, 512, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 32, 32, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 32, 32, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 32, 32, 1, 4 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 32, 32, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 32, 32, 2, 4 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 32, 32, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 64, 64, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 64, 64, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 64, 64, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 64, 64, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 64, 64, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 96, 96, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 96, 96, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 96, 96, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 96, 96, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 128, 128, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 128, 128, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 192, 192, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 192, 192, 1, 2 }, { 1, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 192, 192, 1, 4 }, { 1, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 192, 192, 2, 2 }, { 1, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 192, 192, 3, 2 }, { 1, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 192, 128, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 192, 128, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 192, 128, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 192, 128, 2, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 192, 128, 2, 3 }, { 4, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 192, 128, 3, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 192, 128, 3, 3 }, { 4, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 256, 256, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 256, 256, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 256, 256, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 256, 256, 2, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 256, 256, 3, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 320, 256, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 320, 256, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 512, 512, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 512, 512, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 576, 512, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_0, 576, 512, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 32, 32, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 32, 32, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 32, 32, 1, 4 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 32, 32, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 32, 32, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 64, 64, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 64, 64, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 64, 64, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 64, 64, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 64, 64, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 96, 96, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 96, 96, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 96, 96, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 96, 96, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 128, 128, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 128, 128, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 128, 128, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 128, 128, 2, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 192, 192, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 192, 192, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 192, 192, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 192, 192, 2, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 192, 192, 3, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 192, 128, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 192, 128, -1, 1 }, { 4, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 192, 128, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 192, 128, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 192, 128, 1, 4 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 192, 128, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 192, 128, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 192, 128, 3, 4 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 256, 256, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 256, 256, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 320, 256, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 320, 256, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 512, 512, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 512, 512, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 576, 512, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q5_1, 576, 512, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q8_0, 32, 32, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q8_0, 32, 32, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M2_MAX, GGML_TYPE_Q8_0, 32, 32, 2, 2 }, { 4, 4 } },
|
||||
@@ -1525,6 +1672,178 @@ constexpr fa_vec_entry_t fa_vec_tuned_table[] = {
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_F16, 576, 512, 2, 1 }, { 4, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_F16, 576, 512, 2, 2 }, { 4, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_F16, 576, 512, 3, 1 }, { 4, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 32, 32, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 32, 32, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 32, 32, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 32, 32, 2, 4 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 32, 32, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 64, 64, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 64, 64, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 64, 64, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 64, 64, 1, 4 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 64, 64, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 64, 64, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 64, 64, 3, 4 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 96, 96, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 96, 96, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 96, 96, 2, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 128, 128, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 128, 128, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 128, 128, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 128, 128, 2, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 128, 128, 3, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 192, 192, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 192, 192, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 192, 192, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 192, 192, 2, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 192, 192, 3, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 192, 192, 3, 2 }, { 1, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 192, 192, 3, 3 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 192, 128, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 192, 128, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 192, 128, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 192, 128, 2, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 256, 256, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 256, 256, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 320, 256, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 320, 256, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 320, 256, 3, 4 }, { 1, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 512, 512, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 512, 512, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 576, 512, 2, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 576, 512, 3, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 576, 512, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_0, 576, 512, 1, 4 }, { 1, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 32, 32, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 32, 32, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 32, 32, 1, 4 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 32, 32, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 32, 32, 2, 4 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 32, 32, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 64, 64, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 64, 64, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 64, 64, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 64, 64, 1, 4 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 64, 64, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 64, 64, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 96, 96, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 96, 96, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 96, 96, 1, 3 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 96, 96, 2, 2 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 128, 128, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 128, 128, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 128, 128, 1, 2 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 128, 128, 2, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 128, 128, 3, 1 }, { 2, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 128, 128, 3, 2 }, { 2, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 128, 128, 3, 3 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 192, 192, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 192, 192, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 192, 192, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 192, 192, 2, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 192, 192, 3, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 192, 128, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 192, 128, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 256, 256, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 256, 256, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 320, 256, 2, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 320, 256, 3, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 320, 256, 1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 320, 256, 2, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 320, 256, 3, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 320, 256, 3, 3 }, { 2, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 512, 512, 2, 0 }, { 4, 1 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 512, 512, 2, 4 }, { 4, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 512, 512, 3, 1 }, { 4, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 512, 512, 3, 2 }, { 4, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 576, 512, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 576, 512, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q4_1, 576, 512, 1, 4 }, { 1, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 32, 32, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 32, 32, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 32, 32, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 32, 32, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 64, 64, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 64, 64, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 64, 64, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 64, 64, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 64, 64, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 96, 96, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 96, 96, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 96, 96, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 96, 96, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 128, 128, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 128, 128, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 128, 128, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 128, 128, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 128, 128, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 192, 192, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 192, 192, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 192, 128, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 192, 128, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 192, 128, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 192, 128, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 192, 128, 2, 4 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 192, 128, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 256, 256, -1, 0 }, { 1, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 256, 256, -1, 1 }, { 2, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 256, 256, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 256, 256, 2, 2 }, { 1, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 256, 256, 3, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 320, 256, 1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 320, 256, -1, 1 }, { 2, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 320, 256, 2, 2 }, { 1, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 320, 256, 3, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 512, 512, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 512, 512, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 512, 512, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 576, 512, 2, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 576, 512, 3, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 576, 512, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 576, 512, 1, 1 }, { 1, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_0, 576, 512, 1, 4 }, { 1, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 32, 32, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 32, 32, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 32, 32, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 32, 32, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 64, 64, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 64, 64, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 64, 64, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 64, 64, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 64, 64, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 96, 96, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 96, 96, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 96, 96, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 96, 96, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 128, 128, 3, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 128, 128, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 128, 128, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 128, 128, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 128, 128, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 192, 192, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 192, 192, -1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 192, 128, 1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 192, 128, 2, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 192, 128, -1, 1 }, { 4, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 192, 128, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 192, 128, 1, 4 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 192, 128, 2, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 192, 128, 3, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 256, 256, -1, 0 }, { 1, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 256, 256, -1, 1 }, { 2, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 256, 256, 3, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 320, 256, 3, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 320, 256, -1, 1 }, { 2, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 320, 256, 1, 2 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 320, 256, 2, 2 }, { 1, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 320, 256, 3, 2 }, { 1, 2 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 512, 512, -1, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 512, 512, -1, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 576, 512, 2, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 576, 512, 3, 0 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 576, 512, 2, 4 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 576, 512, 3, 1 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q5_1, 576, 512, 3, 3 }, { 1, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q8_0, 32, 32, -1, 1 }, { 4, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q8_0, 32, 32, 1, 1 }, { 2, 4 } },
|
||||
{ { GGML_METAL_DEVICE_M3, GGML_TYPE_Q8_0, 32, 32, 2, 1 }, { 2, 4 } },
|
||||
|
||||
@@ -222,6 +222,7 @@ set(GGML_OPENCL_KERNELS
|
||||
exp
|
||||
expm1
|
||||
abs
|
||||
unary_ext
|
||||
softplus
|
||||
pad
|
||||
repeat
|
||||
@@ -238,7 +239,7 @@ set(GGML_OPENCL_KERNELS
|
||||
)
|
||||
|
||||
if (GGML_OPENCL_USE_ADRENO_KERNELS)
|
||||
list(APPEND GGML_OPENCL_KERNELS gemm_xmem_f16_f32_os8)
|
||||
list(APPEND GGML_OPENCL_KERNELS gemm_xmem_f16_f32_os8 sdpa_xmem_f32_f16_os8)
|
||||
endif ()
|
||||
|
||||
foreach (K ${GGML_OPENCL_KERNELS})
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,56 +1,66 @@
|
||||
kernel void kernel_concat_f32(
|
||||
global const char * src0,
|
||||
ulong offset0,
|
||||
global const char * src1,
|
||||
ulong offset1,
|
||||
global char * dst,
|
||||
ulong offsetd,
|
||||
int ne00,
|
||||
int ne01,
|
||||
int ne02,
|
||||
int ne03,
|
||||
ulong nb00,
|
||||
ulong nb01,
|
||||
ulong nb02,
|
||||
ulong nb03,
|
||||
ulong nb10,
|
||||
ulong nb11,
|
||||
ulong nb12,
|
||||
ulong nb13,
|
||||
int ne0,
|
||||
ulong nb0,
|
||||
ulong nb1,
|
||||
ulong nb2,
|
||||
ulong nb3,
|
||||
int dim
|
||||
) {
|
||||
src0 = src0 + offset0;
|
||||
src1 = src1 + offset1;
|
||||
dst = dst + offsetd;
|
||||
// concat is a pure copy, so the kernels are keyed by element byte size
|
||||
// (1/2/4/8) rather than logical type, matching the CUDA backend.
|
||||
|
||||
const int i3 = get_group_id(2);
|
||||
const int i2 = get_group_id(1);
|
||||
const int i1 = get_group_id(0);
|
||||
|
||||
int o[4] = {0, 0, 0, 0};
|
||||
o[dim] = dim == 0 ? ne00 : (dim == 1 ? ne01 : (dim == 2 ? ne02 : ne03));
|
||||
|
||||
global const float * x;
|
||||
|
||||
for (int i0 = get_local_id(0); i0 < ne0; i0 += get_local_size(0)) {
|
||||
if (i0 < ne00 && i1 < ne01 && i2 < ne02 && i3 < ne03) {
|
||||
x = (global const float *)(src0 + (i3 )*nb03 + (i2 )*nb02 + (i1 )*nb01 + (i0 )*nb00);
|
||||
} else {
|
||||
x = (global const float *)(src1 + (i3 - o[3])*nb13 + (i2 - o[2])*nb12 + (i1 - o[1])*nb11 + (i0 - o[0])*nb10);
|
||||
}
|
||||
|
||||
global float * y = (global float *)(dst + i3*nb3 + i2*nb2 + i1*nb1 + i0*nb0);
|
||||
|
||||
*y = *x;
|
||||
}
|
||||
#define KERNEL_CONCAT(SUFFIX, T) \
|
||||
kernel void kernel_concat_##SUFFIX( \
|
||||
global const char * src0, \
|
||||
ulong offset0, \
|
||||
global const char * src1, \
|
||||
ulong offset1, \
|
||||
global char * dst, \
|
||||
ulong offsetd, \
|
||||
int ne00, \
|
||||
int ne01, \
|
||||
int ne02, \
|
||||
int ne03, \
|
||||
ulong nb00, \
|
||||
ulong nb01, \
|
||||
ulong nb02, \
|
||||
ulong nb03, \
|
||||
ulong nb10, \
|
||||
ulong nb11, \
|
||||
ulong nb12, \
|
||||
ulong nb13, \
|
||||
int ne0, \
|
||||
ulong nb0, \
|
||||
ulong nb1, \
|
||||
ulong nb2, \
|
||||
ulong nb3, \
|
||||
int dim \
|
||||
) { \
|
||||
src0 = src0 + offset0; \
|
||||
src1 = src1 + offset1; \
|
||||
dst = dst + offsetd; \
|
||||
\
|
||||
const int i3 = get_group_id(2); \
|
||||
const int i2 = get_group_id(1); \
|
||||
const int i1 = get_group_id(0); \
|
||||
\
|
||||
int o[4] = {0, 0, 0, 0}; \
|
||||
o[dim] = dim == 0 ? ne00 : (dim == 1 ? ne01 : (dim == 2 ? ne02 : ne03)); \
|
||||
\
|
||||
global const T * x; \
|
||||
\
|
||||
for (int i0 = get_local_id(0); i0 < ne0; i0 += get_local_size(0)) { \
|
||||
if (i0 < ne00 && i1 < ne01 && i2 < ne02 && i3 < ne03) { \
|
||||
x = (global const T *)(src0 + (i3 )*nb03 + (i2 )*nb02 + (i1 )*nb01 + (i0 )*nb00); \
|
||||
} else { \
|
||||
x = (global const T *)(src1 + (i3 - o[3])*nb13 + (i2 - o[2])*nb12 + (i1 - o[1])*nb11 + (i0 - o[0])*nb10); \
|
||||
} \
|
||||
\
|
||||
global T * y = (global T *)(dst + i3*nb3 + i2*nb2 + i1*nb1 + i0*nb0); \
|
||||
\
|
||||
*y = *x; \
|
||||
} \
|
||||
}
|
||||
|
||||
kernel void kernel_concat_f32_pack(
|
||||
KERNEL_CONCAT(b1, char)
|
||||
KERNEL_CONCAT(b2, short)
|
||||
KERNEL_CONCAT(b4, int)
|
||||
KERNEL_CONCAT(b8, long)
|
||||
|
||||
// packed variant for the common dim==0, small-ne0 case (4-byte elements only).
|
||||
kernel void kernel_concat_b4_pack(
|
||||
global const char * src0,
|
||||
ulong offset0,
|
||||
global const char * src1,
|
||||
@@ -104,14 +114,14 @@ kernel void kernel_concat_f32_pack(
|
||||
o[dim] = dim == 0 ? ne00 : (dim == 1 ? ne01 : (dim == 2 ? ne02 : ne03));
|
||||
|
||||
for (int i0 = lane; i0 < ne0; i0 += tpr) {
|
||||
global const float * x;
|
||||
global const int * x;
|
||||
if (i0 < ne00 && i1 < ne01 && i2 < ne02 && i3 < ne03) {
|
||||
x = (global const float *)(src0 + (i3 )*nb03 + (i2 )*nb02 + (i1 )*nb01 + (i0 )*nb00);
|
||||
x = (global const int *)(src0 + (i3 )*nb03 + (i2 )*nb02 + (i1 )*nb01 + (i0 )*nb00);
|
||||
} else {
|
||||
x = (global const float *)(src1 + (i3 - o[3])*nb13 + (i2 - o[2])*nb12 + (i1 - o[1])*nb11 + (i0 - o[0])*nb10);
|
||||
x = (global const int *)(src1 + (i3 - o[3])*nb13 + (i2 - o[2])*nb12 + (i1 - o[1])*nb11 + (i0 - o[0])*nb10);
|
||||
}
|
||||
|
||||
global float * y = (global float *)(dst + i3*nb3 + i2*nb2 + i1*nb1 + i0*nb0);
|
||||
global int * y = (global int *)(dst + i3*nb3 + i2*nb2 + i1*nb1 + i0*nb0);
|
||||
|
||||
*y = *x;
|
||||
}
|
||||
|
||||
@@ -286,3 +286,28 @@ kernel void kernel_cpy_i32_i32(
|
||||
dst_data[i00] = src[0];
|
||||
}
|
||||
}
|
||||
|
||||
// Contiguous f32 copy, one work item per float4 over the whole tensor. The kernels above map
|
||||
// one workgroup to each row, which leaves a tensor with few long rows on a single compute unit.
|
||||
// vload4/vstore4 rather than a float4 cast: these buffers carry an arbitrary 4-byte view offset.
|
||||
kernel void kernel_cpy_f32_f32_flat(
|
||||
global float * src0,
|
||||
ulong offset0,
|
||||
global float * dst,
|
||||
ulong offsetd,
|
||||
ulong ne,
|
||||
ulong n4
|
||||
) {
|
||||
src0 = (global float*)((global char*)src0 + offset0);
|
||||
dst = (global float*)((global char*)dst + offsetd);
|
||||
|
||||
const ulong i = get_global_id(0);
|
||||
|
||||
if (i < n4) {
|
||||
vstore4(vload4(i, src0), i, dst);
|
||||
} else if (i == n4) {
|
||||
for (ulong t = n4 * 4; t < ne; ++t) {
|
||||
dst[t] = src0[t];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,871 @@
|
||||
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
|
||||
#pragma OPENCL EXTENSION cl_qcom_subgroup_uniform_load : enable
|
||||
#pragma OPENCL EXTENSION cl_qcom_subgroup_constant_load : enable
|
||||
|
||||
#define bool2 uchar2
|
||||
#define bool3 uchar3
|
||||
#define bool4 uchar4
|
||||
|
||||
__constant sampler_t smp_none = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_NONE | CLK_FILTER_NEAREST;
|
||||
__constant sampler_t smp_zero = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP | CLK_FILTER_NEAREST;
|
||||
|
||||
__kernel void adreno_xmem_attn_q_f32_to_img_scaled(const global void * src_void,
|
||||
ulong src_offset,
|
||||
write_only image2d_t dst_image2d,
|
||||
const float scale,
|
||||
const int d_head,
|
||||
const int n_q,
|
||||
const int n_head,
|
||||
const int n_head_kv,
|
||||
const int n_batch,
|
||||
const ulong src_nb1,
|
||||
const ulong src_nb2,
|
||||
const ulong src_nb3) {
|
||||
const int x = get_global_id(0);
|
||||
const int flat_h = get_global_id(1);
|
||||
const int d = get_global_id(2);
|
||||
|
||||
const int heads_total = n_head * n_batch;
|
||||
const int kpack = d_head / 4;
|
||||
|
||||
if (x >= n_q || flat_h >= heads_total || d >= kpack) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int batch = flat_h / n_head;
|
||||
const int head = flat_h % n_head;
|
||||
const int gqa = n_head / n_head_kv;
|
||||
const int head_kv = head / gqa;
|
||||
const int head_group = head - head_kv * gqa;
|
||||
const int compact_h = batch * n_head_kv + head_kv;
|
||||
const int compact_x = head_group * n_q + x;
|
||||
const int c = d * 4;
|
||||
|
||||
const global char * src_base = (const global char *) src_void + src_offset;
|
||||
const global float * row_ptr = (const global float *) (src_base + batch * src_nb3 + head * src_nb2 + x * src_nb1);
|
||||
|
||||
half4 out = (half4) (0.0h);
|
||||
out.x = convert_half(row_ptr[c + 0] * scale);
|
||||
if (c + 1 < d_head) {
|
||||
out.y = convert_half(row_ptr[c + 1] * scale);
|
||||
}
|
||||
if (c + 2 < d_head) {
|
||||
out.z = convert_half(row_ptr[c + 2] * scale);
|
||||
}
|
||||
if (c + 3 < d_head) {
|
||||
out.w = convert_half(row_ptr[c + 3] * scale);
|
||||
}
|
||||
|
||||
write_imageh(dst_image2d, (int2) (compact_x, compact_h * kpack + d), out);
|
||||
}
|
||||
|
||||
__kernel void adreno_xmem_attn_kv_f32_to_img_gqa(const global void * src_void,
|
||||
ulong src_offset,
|
||||
write_only image2d_t dst_image2d,
|
||||
const int d_head,
|
||||
const int n_kv,
|
||||
const int n_kv_padded,
|
||||
const int n_head_kv,
|
||||
const int n_batch,
|
||||
const ulong src_nb1,
|
||||
const ulong src_nb2,
|
||||
const ulong src_nb3) {
|
||||
const int x = get_global_id(0);
|
||||
const int flat_h = get_global_id(1);
|
||||
const int d = get_global_id(2);
|
||||
|
||||
const int kv_heads_total = n_head_kv * n_batch;
|
||||
const int kpack = d_head / 4;
|
||||
|
||||
if (x >= n_kv_padded || flat_h >= kv_heads_total || d >= kpack) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int batch = flat_h / n_head_kv;
|
||||
const int head_kv = flat_h % n_head_kv;
|
||||
const int c = d * 4;
|
||||
|
||||
half4 out = (half4) (0.0h);
|
||||
if (x < n_kv) {
|
||||
const global char * src_base = (const global char *) src_void + src_offset;
|
||||
const global float * row_ptr =
|
||||
(const global float *) (src_base + batch * src_nb3 + head_kv * src_nb2 + x * src_nb1);
|
||||
out.x = convert_half(row_ptr[c + 0]);
|
||||
if (c + 1 < d_head) {
|
||||
out.y = convert_half(row_ptr[c + 1]);
|
||||
}
|
||||
if (c + 2 < d_head) {
|
||||
out.z = convert_half(row_ptr[c + 2]);
|
||||
}
|
||||
if (c + 3 < d_head) {
|
||||
out.w = convert_half(row_ptr[c + 3]);
|
||||
}
|
||||
}
|
||||
|
||||
write_imageh(dst_image2d, (int2) (x, flat_h * kpack + d), out);
|
||||
}
|
||||
|
||||
__kernel void adreno_xmem_attn_kv_f16_to_img_gqa(const global void * src_void,
|
||||
ulong src_offset,
|
||||
write_only image2d_t dst_image2d,
|
||||
const int d_head,
|
||||
const int n_kv,
|
||||
const int n_kv_padded,
|
||||
const int n_head_kv,
|
||||
const int n_batch,
|
||||
const ulong src_nb1,
|
||||
const ulong src_nb2,
|
||||
const ulong src_nb3) {
|
||||
const int x = get_global_id(0);
|
||||
const int flat_h = get_global_id(1);
|
||||
const int d = get_global_id(2);
|
||||
|
||||
const int kv_heads_total = n_head_kv * n_batch;
|
||||
const int kpack = d_head / 4;
|
||||
|
||||
if (x >= n_kv_padded || flat_h >= kv_heads_total || d >= kpack) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int batch = flat_h / n_head_kv;
|
||||
const int head_kv = flat_h % n_head_kv;
|
||||
const int c = d * 4;
|
||||
|
||||
half4 out = (half4) (0.0h);
|
||||
if (x < n_kv) {
|
||||
const global char * src_base = (const global char *) src_void + src_offset;
|
||||
const global half * row_ptr =
|
||||
(const global half *) (src_base + batch * src_nb3 + head_kv * src_nb2 + x * src_nb1);
|
||||
out.x = row_ptr[c + 0];
|
||||
if (c + 1 < d_head) {
|
||||
out.y = row_ptr[c + 1];
|
||||
}
|
||||
if (c + 2 < d_head) {
|
||||
out.z = row_ptr[c + 2];
|
||||
}
|
||||
if (c + 3 < d_head) {
|
||||
out.w = row_ptr[c + 3];
|
||||
}
|
||||
}
|
||||
|
||||
write_imageh(dst_image2d, (int2) (x, flat_h * kpack + d), out);
|
||||
}
|
||||
|
||||
__kernel void adreno_xmem_attn_img_to_f32(global void * dst_void,
|
||||
ulong dst_offset,
|
||||
read_only image2d_t src_image2d,
|
||||
const int d_head,
|
||||
const int n_q,
|
||||
const int n_head,
|
||||
const int n_head_kv,
|
||||
const int n_batch,
|
||||
const ulong dst_nb1,
|
||||
const ulong dst_nb2,
|
||||
const ulong dst_nb3) {
|
||||
const int x = get_global_id(0);
|
||||
const int flat_h = get_global_id(1);
|
||||
const int d = get_global_id(2);
|
||||
|
||||
const int heads_total = n_head * n_batch;
|
||||
const int kpack = d_head / 4;
|
||||
|
||||
if (x >= n_q || flat_h >= heads_total || d >= kpack) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int batch = flat_h / n_head;
|
||||
const int head = flat_h % n_head;
|
||||
const int gqa = n_head / n_head_kv;
|
||||
const int head_kv = head / gqa;
|
||||
const int head_group = head - head_kv * gqa;
|
||||
const int compact_h = batch * n_head_kv + head_kv;
|
||||
const int compact_x = head_group * n_q + x;
|
||||
const int c = d * 4;
|
||||
|
||||
global char * dst_base = (global char *) dst_void + dst_offset;
|
||||
global float * row_ptr = (global float *) (dst_base + batch * dst_nb3 + x * dst_nb2 + head * dst_nb1);
|
||||
|
||||
const half4 in_value = read_imageh(src_image2d, smp_zero, (int2) (compact_x, compact_h * kpack + d));
|
||||
row_ptr[c + 0] = convert_float(in_value.x);
|
||||
if (c + 1 < d_head) {
|
||||
row_ptr[c + 1] = convert_float(in_value.y);
|
||||
}
|
||||
if (c + 2 < d_head) {
|
||||
row_ptr[c + 2] = convert_float(in_value.z);
|
||||
}
|
||||
if (c + 3 < d_head) {
|
||||
row_ptr[c + 3] = convert_float(in_value.w);
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void adreno_xmem_attn_k_gather(global half4 * dst_tensor_buffer,
|
||||
read_only image2d_t src_tensor_image2d,
|
||||
const int4 shared_int4_0,
|
||||
const int4 shared_int4_1) {
|
||||
int X = get_global_id(0);
|
||||
int Y = get_global_id(1);
|
||||
int S = get_global_id(2);
|
||||
if (X >= shared_int4_0.w || Y >= shared_int4_0.y || S >= shared_int4_0.z) {
|
||||
return;
|
||||
}
|
||||
half temps[4];
|
||||
temps[0] = (half) (0.f);
|
||||
temps[1] = (half) (0.f);
|
||||
temps[2] = (half) (0.f);
|
||||
temps[3] = (half) (0.f);
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
int dst_channel = S * 4 + i;
|
||||
if (dst_channel < shared_int4_0.x) {
|
||||
int s_y = Y;
|
||||
int s_x = dst_channel;
|
||||
int s_c = X;
|
||||
{
|
||||
int slice_coord_TMP = (s_c) / 4;
|
||||
int sub_ch_coord_TMP = (s_c) % 4;
|
||||
half4 src_TMP = read_imageh(src_tensor_image2d, smp_zero,
|
||||
(int2) ((s_x), ((s_y) *shared_int4_1.x + (slice_coord_TMP))));
|
||||
temps[i] = (half[4]){ src_TMP.x, src_TMP.y, src_TMP.z, src_TMP.w }[sub_ch_coord_TMP];
|
||||
};
|
||||
}
|
||||
}
|
||||
half4 result;
|
||||
result.x = temps[0];
|
||||
result.y = temps[1];
|
||||
result.z = temps[2];
|
||||
result.w = temps[3];
|
||||
dst_tensor_buffer[(((S) *shared_int4_0.y + (Y)) * shared_int4_0.w + (X))] = result;
|
||||
}
|
||||
|
||||
__kernel void adreno_xmem_attn_pack_k(global half4 * dst_tensor_buffer,
|
||||
read_only image1d_buffer_t src_image_buffer,
|
||||
const int4 shared_int4_0,
|
||||
const int4 shared_int4_1,
|
||||
const int4 shared_int4_2) {
|
||||
int linear_index = get_global_id(0);
|
||||
if (linear_index >= shared_int4_0.y) {
|
||||
return;
|
||||
}
|
||||
if (get_global_id(1) != 0) {
|
||||
return;
|
||||
}
|
||||
if (get_global_id(2) != 0) {
|
||||
return;
|
||||
}
|
||||
int dst_o_sp_i_ogroup = linear_index;
|
||||
int dst_ogroup = dst_o_sp_i_ogroup % shared_int4_0.x;
|
||||
int dst_o_sp_i = dst_o_sp_i_ogroup / shared_int4_0.x;
|
||||
int dst_i = dst_o_sp_i % shared_int4_0.z;
|
||||
int dst_o_sp = dst_o_sp_i / shared_int4_0.z;
|
||||
int dst_sp = dst_o_sp % shared_int4_1.x;
|
||||
int dst_o = dst_o_sp / shared_int4_1.x;
|
||||
int i_slice = dst_i;
|
||||
int o_slice = dst_o * shared_int4_0.x + dst_ogroup;
|
||||
int spatial_linear = dst_sp;
|
||||
int W = spatial_linear % shared_int4_1.y;
|
||||
int H = spatial_linear / shared_int4_1.y;
|
||||
half4 w0 = (half4) (0);
|
||||
half4 w1 = (half4) (0);
|
||||
half4 w2 = (half4) (0);
|
||||
half4 w3 = (half4) (0);
|
||||
|
||||
if (i_slice * 4 < shared_int4_0.w && o_slice < shared_int4_1.w) {
|
||||
w0 = read_imageh(src_image_buffer, (((o_slice) *shared_int4_1.z + (W)) * shared_int4_2.x + (i_slice * 4)));
|
||||
}
|
||||
if (i_slice * 4 + 1 < shared_int4_0.w && o_slice < shared_int4_1.w) {
|
||||
w1 = read_imageh(src_image_buffer, (((o_slice) *shared_int4_1.z + (W)) * shared_int4_2.x + (i_slice * 4 + 1)));
|
||||
}
|
||||
if (i_slice * 4 + 2 < shared_int4_0.w && o_slice < shared_int4_1.w) {
|
||||
w2 = read_imageh(src_image_buffer, (((o_slice) *shared_int4_1.z + (W)) * shared_int4_2.x + (i_slice * 4 + 2)));
|
||||
}
|
||||
if (i_slice * 4 + 3 < shared_int4_0.w && o_slice < shared_int4_1.w) {
|
||||
w3 = read_imageh(src_image_buffer, (((o_slice) *shared_int4_1.z + (W)) * shared_int4_2.x + (i_slice * 4 + 3)));
|
||||
}
|
||||
half4 r0 = w0;
|
||||
half4 r1 = w1;
|
||||
half4 r2 = w2;
|
||||
half4 r3 = w3;
|
||||
dst_tensor_buffer[linear_index * 4 + 0] = r0;
|
||||
dst_tensor_buffer[linear_index * 4 + 1] = r1;
|
||||
dst_tensor_buffer[linear_index * 4 + 2] = r2;
|
||||
dst_tensor_buffer[linear_index * 4 + 3] = r3;
|
||||
}
|
||||
|
||||
__attribute__((qcom_max_concurrent_subgroups(12))) __kernel void adreno_xmem_attn_qk_gemm(
|
||||
global half4 * dst_tensor_buffer,
|
||||
constant half8 * weights_buffer __attribute__((sub_group_uniform)),
|
||||
constant half8 * xmem_buffer __attribute__((max_constant_size((6144)))),
|
||||
read_only image2d_t src_tensor_image2d,
|
||||
const int4 shared_int4_0,
|
||||
const int4 shared_int4_1,
|
||||
const int4 shared_int4_2) {
|
||||
int X = get_group_id(1) * get_local_size(0) + get_local_id(0);
|
||||
int Y = get_group_id(2) * get_local_size(1) + get_local_id(1);
|
||||
int Z = get_group_id(0) * get_local_size(2) + get_local_id(2);
|
||||
if (X >= shared_int4_0.z || Y >= shared_int4_0.x) {
|
||||
return;
|
||||
}
|
||||
if (Z * 8 >= shared_int4_0.y) {
|
||||
return;
|
||||
}
|
||||
|
||||
half4 r0 = (half4) (0.f);
|
||||
half4 r1 = (half4) (0.f);
|
||||
half4 r2 = (half4) (0.f);
|
||||
half4 r3 = (half4) (0.f);
|
||||
half4 r4 = (half4) (0.f);
|
||||
half4 r5 = (half4) (0.f);
|
||||
half4 r6 = (half4) (0.f);
|
||||
half4 r7 = (half4) (0.f);
|
||||
int x_coord = mad24(X, shared_int4_2.y, shared_int4_1.y);
|
||||
int y_coord = mad24(Y, shared_int4_2.z, shared_int4_1.z);
|
||||
int coord_x, coord_y, coord_s;
|
||||
int f_offset = (Z * shared_int4_1.w + Y) * shared_int4_1.x * 32;
|
||||
|
||||
int subgroup_id = (int) ((0x1F & qcom_get_physical_sub_group_id()));
|
||||
subgroup_id = subgroup_id % 12;
|
||||
int c_offset = mul24(subgroup_id, shared_int4_0.w);
|
||||
__constant half16 * weights_cache = (__constant half16 *) &xmem_buffer[c_offset];
|
||||
coord_y = Y;
|
||||
coord_x = X;
|
||||
coord_s = 0;
|
||||
do {
|
||||
half4 src0 =
|
||||
read_imageh(src_tensor_image2d, smp_zero, (int2) ((coord_x), ((coord_y) *shared_int4_2.x + (coord_s))));
|
||||
coord_s++;
|
||||
half4 src1 =
|
||||
read_imageh(src_tensor_image2d, smp_zero, (int2) ((coord_x), ((coord_y) *shared_int4_2.x + (coord_s))));
|
||||
coord_s++;
|
||||
qcom_sub_group_constant_load8(xmem_buffer, weights_buffer, c_offset, f_offset >> 1, 32);
|
||||
f_offset += 64;
|
||||
qcom_sub_group_sync(QCOM_CLK_CONST_LOAD_SYNC);
|
||||
r0 += src0.x * weights_cache[0].s0123;
|
||||
r0 += src0.y * weights_cache[0].s4567;
|
||||
r0 += src0.z * weights_cache[0].s89ab;
|
||||
r0 += src0.w * weights_cache[0].scdef;
|
||||
r1 += src0.x * weights_cache[1].s0123;
|
||||
r1 += src0.y * weights_cache[1].s4567;
|
||||
r1 += src0.z * weights_cache[1].s89ab;
|
||||
r1 += src0.w * weights_cache[1].scdef;
|
||||
r2 += src0.x * weights_cache[2].s0123;
|
||||
r2 += src0.y * weights_cache[2].s4567;
|
||||
r2 += src0.z * weights_cache[2].s89ab;
|
||||
r2 += src0.w * weights_cache[2].scdef;
|
||||
r3 += src0.x * weights_cache[3].s0123;
|
||||
r3 += src0.y * weights_cache[3].s4567;
|
||||
r3 += src0.z * weights_cache[3].s89ab;
|
||||
r3 += src0.w * weights_cache[3].scdef;
|
||||
r4 += src0.x * weights_cache[4].s0123;
|
||||
r4 += src0.y * weights_cache[4].s4567;
|
||||
r4 += src0.z * weights_cache[4].s89ab;
|
||||
r4 += src0.w * weights_cache[4].scdef;
|
||||
r5 += src0.x * weights_cache[5].s0123;
|
||||
r5 += src0.y * weights_cache[5].s4567;
|
||||
r5 += src0.z * weights_cache[5].s89ab;
|
||||
r5 += src0.w * weights_cache[5].scdef;
|
||||
r6 += src0.x * weights_cache[6].s0123;
|
||||
r6 += src0.y * weights_cache[6].s4567;
|
||||
r6 += src0.z * weights_cache[6].s89ab;
|
||||
r6 += src0.w * weights_cache[6].scdef;
|
||||
r7 += src0.x * weights_cache[7].s0123;
|
||||
r7 += src0.y * weights_cache[7].s4567;
|
||||
r7 += src0.z * weights_cache[7].s89ab;
|
||||
r7 += src0.w * weights_cache[7].scdef;
|
||||
r0 += src1.x * weights_cache[8].s0123;
|
||||
r0 += src1.y * weights_cache[8].s4567;
|
||||
r0 += src1.z * weights_cache[8].s89ab;
|
||||
r0 += src1.w * weights_cache[8].scdef;
|
||||
r1 += src1.x * weights_cache[9].s0123;
|
||||
r1 += src1.y * weights_cache[9].s4567;
|
||||
r1 += src1.z * weights_cache[9].s89ab;
|
||||
r1 += src1.w * weights_cache[9].scdef;
|
||||
r2 += src1.x * weights_cache[10].s0123;
|
||||
r2 += src1.y * weights_cache[10].s4567;
|
||||
r2 += src1.z * weights_cache[10].s89ab;
|
||||
r2 += src1.w * weights_cache[10].scdef;
|
||||
r3 += src1.x * weights_cache[11].s0123;
|
||||
r3 += src1.y * weights_cache[11].s4567;
|
||||
r3 += src1.z * weights_cache[11].s89ab;
|
||||
r3 += src1.w * weights_cache[11].scdef;
|
||||
r4 += src1.x * weights_cache[12].s0123;
|
||||
r4 += src1.y * weights_cache[12].s4567;
|
||||
r4 += src1.z * weights_cache[12].s89ab;
|
||||
r4 += src1.w * weights_cache[12].scdef;
|
||||
r5 += src1.x * weights_cache[13].s0123;
|
||||
r5 += src1.y * weights_cache[13].s4567;
|
||||
r5 += src1.z * weights_cache[13].s89ab;
|
||||
r5 += src1.w * weights_cache[13].scdef;
|
||||
r6 += src1.x * weights_cache[14].s0123;
|
||||
r6 += src1.y * weights_cache[14].s4567;
|
||||
r6 += src1.z * weights_cache[14].s89ab;
|
||||
r6 += src1.w * weights_cache[14].scdef;
|
||||
r7 += src1.x * weights_cache[15].s0123;
|
||||
r7 += src1.y * weights_cache[15].s4567;
|
||||
r7 += src1.z * weights_cache[15].s89ab;
|
||||
r7 += src1.w * weights_cache[15].scdef;
|
||||
} while (coord_s < shared_int4_2.x);
|
||||
|
||||
coord_s = mul24(Z, 8);
|
||||
coord_x = X;
|
||||
coord_y = Y;
|
||||
if (coord_s < shared_int4_0.y) {
|
||||
half4 res = convert_half4(r0);
|
||||
if (coord_s < 0) {
|
||||
res += read_imageh(src_tensor_image2d, smp_zero, (int2) ((0), ((0) * shared_int4_2.x + (0))));
|
||||
}
|
||||
dst_tensor_buffer[(((coord_s) *shared_int4_0.x + (coord_y)) * shared_int4_0.z + (coord_x))] = res;
|
||||
coord_s++;
|
||||
}
|
||||
if (coord_s < shared_int4_0.y) {
|
||||
half4 res = convert_half4(r1);
|
||||
if (coord_s < 0) {
|
||||
res += read_imageh(src_tensor_image2d, smp_zero, (int2) ((0), ((0) * shared_int4_2.x + (0))));
|
||||
}
|
||||
dst_tensor_buffer[(((coord_s) *shared_int4_0.x + (coord_y)) * shared_int4_0.z + (coord_x))] = res;
|
||||
coord_s++;
|
||||
}
|
||||
if (coord_s < shared_int4_0.y) {
|
||||
half4 res = convert_half4(r2);
|
||||
if (coord_s < 0) {
|
||||
res += read_imageh(src_tensor_image2d, smp_zero, (int2) ((0), ((0) * shared_int4_2.x + (0))));
|
||||
}
|
||||
dst_tensor_buffer[(((coord_s) *shared_int4_0.x + (coord_y)) * shared_int4_0.z + (coord_x))] = res;
|
||||
coord_s++;
|
||||
}
|
||||
if (coord_s < shared_int4_0.y) {
|
||||
half4 res = convert_half4(r3);
|
||||
if (coord_s < 0) {
|
||||
res += read_imageh(src_tensor_image2d, smp_zero, (int2) ((0), ((0) * shared_int4_2.x + (0))));
|
||||
}
|
||||
dst_tensor_buffer[(((coord_s) *shared_int4_0.x + (coord_y)) * shared_int4_0.z + (coord_x))] = res;
|
||||
coord_s++;
|
||||
}
|
||||
if (coord_s < shared_int4_0.y) {
|
||||
half4 res = convert_half4(r4);
|
||||
if (coord_s < 0) {
|
||||
res += read_imageh(src_tensor_image2d, smp_zero, (int2) ((0), ((0) * shared_int4_2.x + (0))));
|
||||
}
|
||||
dst_tensor_buffer[(((coord_s) *shared_int4_0.x + (coord_y)) * shared_int4_0.z + (coord_x))] = res;
|
||||
coord_s++;
|
||||
}
|
||||
if (coord_s < shared_int4_0.y) {
|
||||
half4 res = convert_half4(r5);
|
||||
if (coord_s < 0) {
|
||||
res += read_imageh(src_tensor_image2d, smp_zero, (int2) ((0), ((0) * shared_int4_2.x + (0))));
|
||||
}
|
||||
dst_tensor_buffer[(((coord_s) *shared_int4_0.x + (coord_y)) * shared_int4_0.z + (coord_x))] = res;
|
||||
coord_s++;
|
||||
}
|
||||
if (coord_s < shared_int4_0.y) {
|
||||
half4 res = convert_half4(r6);
|
||||
if (coord_s < 0) {
|
||||
res += read_imageh(src_tensor_image2d, smp_zero, (int2) ((0), ((0) * shared_int4_2.x + (0))));
|
||||
}
|
||||
dst_tensor_buffer[(((coord_s) *shared_int4_0.x + (coord_y)) * shared_int4_0.z + (coord_x))] = res;
|
||||
coord_s++;
|
||||
}
|
||||
if (coord_s < shared_int4_0.y) {
|
||||
half4 res = convert_half4(r7);
|
||||
if (coord_s < 0) {
|
||||
res += read_imageh(src_tensor_image2d, smp_zero, (int2) ((0), ((0) * shared_int4_2.x + (0))));
|
||||
}
|
||||
dst_tensor_buffer[(((coord_s) *shared_int4_0.x + (coord_y)) * shared_int4_0.z + (coord_x))] = res;
|
||||
coord_s++;
|
||||
}
|
||||
}
|
||||
|
||||
__kernel void adreno_xmem_attn_softmax_reduce_basic(read_only image1d_buffer_t src_tensor_image_buffer,
|
||||
write_only image2d_t dst_tensor_image2d,
|
||||
const int4 shared_int4_0,
|
||||
const int4 shared_int4_1) {
|
||||
int X = get_global_id(0);
|
||||
int Y = get_global_id(1);
|
||||
if (X >= shared_int4_0.z || Y >= shared_int4_0.x) {
|
||||
return;
|
||||
}
|
||||
float sum = 0.0f;
|
||||
int end_channel = shared_int4_0.w;
|
||||
int end_slice = (end_channel + 3) / 4;
|
||||
int start_channel = 0;
|
||||
int start_slice = start_channel / 4;
|
||||
bool need_per_channels_check = start_channel % 4 != 0 || end_channel % 4 != 0;
|
||||
float maximum;
|
||||
{
|
||||
int slice_coord_TMP = (start_channel) / 4;
|
||||
int sub_ch_coord_TMP = (start_channel) % 4;
|
||||
float4 src_TMP = convert_float4(
|
||||
read_imageh(src_tensor_image_buffer, ((slice_coord_TMP) *shared_int4_1.x + (Y)) * shared_int4_1.y + (X)));
|
||||
maximum = (float[4]){ src_TMP.x, src_TMP.y, src_TMP.z, src_TMP.w }[sub_ch_coord_TMP];
|
||||
};
|
||||
for (int d = start_slice; d < end_slice; d += 1) {
|
||||
float4 mask_dot = (float4) (1.f);
|
||||
float4 src =
|
||||
convert_float4(read_imageh(src_tensor_image_buffer, ((d) *shared_int4_1.x + (Y)) * shared_int4_1.y + (X)));
|
||||
if (need_per_channels_check && (d == start_slice || d == end_slice - 1)) {
|
||||
if (d * 4 + 0 < start_channel || d * 4 + 0 >= end_channel) {
|
||||
mask_dot.x = 0.f;
|
||||
src.x = maximum;
|
||||
}
|
||||
if (d * 4 + 1 < start_channel || d * 4 + 1 >= end_channel) {
|
||||
mask_dot.y = 0.f;
|
||||
src.y = maximum;
|
||||
}
|
||||
if (d * 4 + 2 < start_channel || d * 4 + 2 >= end_channel) {
|
||||
mask_dot.z = 0.f;
|
||||
src.z = maximum;
|
||||
}
|
||||
if (d * 4 + 3 < start_channel || d * 4 + 3 >= end_channel) {
|
||||
mask_dot.w = 0.f;
|
||||
src.w = maximum;
|
||||
}
|
||||
}
|
||||
float new_max = max(src.x, src.y);
|
||||
new_max = max(new_max, src.z);
|
||||
new_max = max(new_max, src.w);
|
||||
new_max = max(new_max, maximum);
|
||||
float scale = native_exp(maximum - new_max);
|
||||
maximum = new_max;
|
||||
sum *= scale;
|
||||
float4 exp_res = native_exp(src - maximum);
|
||||
sum += dot(mask_dot, exp_res);
|
||||
}
|
||||
if (!isfinite(maximum) || sum == 0.0f) {
|
||||
write_imageh(dst_tensor_image2d, (int2) (X, Y), (half4) (0.0h));
|
||||
return;
|
||||
}
|
||||
write_imageh(dst_tensor_image2d, (int2) (X, Y),
|
||||
(half4) (convert_half(1.0f / sum), convert_half(maximum), 0.0h, 0.0h));
|
||||
}
|
||||
|
||||
__kernel void adreno_xmem_attn_softmax_apply_basic(global half4 * dst_tensor_buffer,
|
||||
read_only image1d_buffer_t src_tensor_image_buffer,
|
||||
read_only image2d_t src_tensor_1_image2d,
|
||||
const int4 shared_int4_0,
|
||||
const int4 shared_int4_1) {
|
||||
int X = get_global_id(0);
|
||||
int Y = get_global_id(1);
|
||||
int Z = get_global_id(2);
|
||||
if (X >= shared_int4_0.z || Y >= shared_int4_0.x || Z >= shared_int4_0.y) {
|
||||
return;
|
||||
}
|
||||
half4 src = read_imageh(src_tensor_image_buffer, ((Z) *shared_int4_1.x + (Y)) * shared_int4_1.y + (X));
|
||||
{
|
||||
half4 src_final;
|
||||
{
|
||||
{
|
||||
half4 exp_val = read_imageh(src_tensor_1_image2d, smp_zero, (int2) (X, Y));
|
||||
src_final = exp(src - exp_val.y) * exp_val.x;
|
||||
const int k = Z * 4;
|
||||
const int n_kv = shared_int4_1.z;
|
||||
if (k + 0 >= n_kv) {
|
||||
src_final.x = 0.0h;
|
||||
}
|
||||
if (k + 1 >= n_kv) {
|
||||
src_final.y = 0.0h;
|
||||
}
|
||||
if (k + 2 >= n_kv) {
|
||||
src_final.z = 0.0h;
|
||||
}
|
||||
if (k + 3 >= n_kv) {
|
||||
src_final.w = 0.0h;
|
||||
}
|
||||
}
|
||||
}
|
||||
dst_tensor_buffer[(((Z) *shared_int4_0.x + (Y)) * shared_int4_0.z + (X))] = src_final;
|
||||
};
|
||||
}
|
||||
|
||||
__kernel void adreno_xmem_attn_mask_scores(global half4 * dst_score_tensor_buffer,
|
||||
read_only image1d_buffer_t src_score_image_buffer,
|
||||
const global half * mask,
|
||||
const ulong mask_offset,
|
||||
const int q_width,
|
||||
const int n_q,
|
||||
const int n_kv,
|
||||
const int n_kv_padded,
|
||||
const int kv_heads_total,
|
||||
const int n_head,
|
||||
const int n_head_kv,
|
||||
const ulong mask_nb1,
|
||||
const ulong mask_nb2,
|
||||
const ulong mask_nb3,
|
||||
const int mask_ne2,
|
||||
const int mask_ne3) {
|
||||
const int X = get_global_id(0);
|
||||
const int Y = get_global_id(1);
|
||||
const int Z = get_global_id(2);
|
||||
const int npack = n_kv_padded / 4;
|
||||
if (X >= q_width || Y >= kv_heads_total || Z >= npack) {
|
||||
return;
|
||||
}
|
||||
|
||||
const int gqa = n_head / n_head_kv;
|
||||
const int head_kv = Y % n_head_kv;
|
||||
const int batch = Y / n_head_kv;
|
||||
const int head_group = X / n_q;
|
||||
const int q = X - head_group * n_q;
|
||||
const int head = head_kv * gqa + head_group;
|
||||
const int mask_head_idx = head % mask_ne2;
|
||||
const int mask_batch_idx = batch % mask_ne3;
|
||||
const global char * mask_base = (const global char *) mask + mask_offset;
|
||||
const global half * mask_row = (const global half *) (mask_base + mask_batch_idx * mask_nb3 +
|
||||
mask_head_idx * mask_nb2 + q * mask_nb1);
|
||||
|
||||
const half4 score = read_imageh(src_score_image_buffer, ((Z * kv_heads_total + Y) * q_width + X));
|
||||
float vals[4] = {
|
||||
convert_float(score.x),
|
||||
convert_float(score.y),
|
||||
convert_float(score.z),
|
||||
convert_float(score.w),
|
||||
};
|
||||
|
||||
for (int lane = 0; lane < 4; ++lane) {
|
||||
const int k_idx = Z * 4 + lane;
|
||||
if (k_idx >= n_kv) {
|
||||
vals[lane] = -INFINITY;
|
||||
} else {
|
||||
vals[lane] += convert_float(mask_row[k_idx]);
|
||||
}
|
||||
}
|
||||
|
||||
dst_score_tensor_buffer[((Z * kv_heads_total + Y) * q_width + X)] =
|
||||
(half4) (convert_half(vals[0]), convert_half(vals[1]), convert_half(vals[2]), convert_half(vals[3]));
|
||||
}
|
||||
|
||||
__kernel void adreno_xmem_attn_pack_v(global half4 * dst_tensor_buffer,
|
||||
read_only image2d_t src_image2d,
|
||||
const int4 shared_int4_0,
|
||||
const int4 shared_int4_1) {
|
||||
int linear_index = get_global_id(0);
|
||||
if (linear_index >= shared_int4_0.y) {
|
||||
return;
|
||||
}
|
||||
if (get_global_id(1) != 0) {
|
||||
return;
|
||||
}
|
||||
if (get_global_id(2) != 0) {
|
||||
return;
|
||||
}
|
||||
int dst_o_sp_i_ogroup = linear_index;
|
||||
int dst_ogroup = dst_o_sp_i_ogroup % shared_int4_0.x;
|
||||
int dst_o_sp_i = dst_o_sp_i_ogroup / shared_int4_0.x;
|
||||
int dst_i = dst_o_sp_i % shared_int4_0.z;
|
||||
int dst_o_sp = dst_o_sp_i / shared_int4_0.z;
|
||||
int dst_sp = dst_o_sp % shared_int4_1.x;
|
||||
int dst_o = dst_o_sp / shared_int4_1.x;
|
||||
int i_slice = dst_i;
|
||||
int o_slice = dst_o * shared_int4_0.x + dst_ogroup;
|
||||
int spatial_linear = dst_sp;
|
||||
int W = spatial_linear % shared_int4_1.y;
|
||||
int H = spatial_linear / shared_int4_1.y;
|
||||
half4 w0 = (half4) (0);
|
||||
half4 w1 = (half4) (0);
|
||||
half4 w2 = (half4) (0);
|
||||
half4 w3 = (half4) (0);
|
||||
|
||||
if (i_slice * 4 < shared_int4_0.w && o_slice < shared_int4_1.z) {
|
||||
w0 = read_imageh(src_image2d, smp_zero, (int2) ((i_slice * 4), ((W) *shared_int4_1.z + (o_slice))));
|
||||
}
|
||||
if (i_slice * 4 + 1 < shared_int4_0.w && o_slice < shared_int4_1.z) {
|
||||
w1 = read_imageh(src_image2d, smp_zero, (int2) ((i_slice * 4 + 1), ((W) *shared_int4_1.z + (o_slice))));
|
||||
}
|
||||
if (i_slice * 4 + 2 < shared_int4_0.w && o_slice < shared_int4_1.z) {
|
||||
w2 = read_imageh(src_image2d, smp_zero, (int2) ((i_slice * 4 + 2), ((W) *shared_int4_1.z + (o_slice))));
|
||||
}
|
||||
if (i_slice * 4 + 3 < shared_int4_0.w && o_slice < shared_int4_1.z) {
|
||||
w3 = read_imageh(src_image2d, smp_zero, (int2) ((i_slice * 4 + 3), ((W) *shared_int4_1.z + (o_slice))));
|
||||
}
|
||||
half4 r0 = w0;
|
||||
half4 r1 = w1;
|
||||
half4 r2 = w2;
|
||||
half4 r3 = w3;
|
||||
dst_tensor_buffer[linear_index * 4 + 0] = r0;
|
||||
dst_tensor_buffer[linear_index * 4 + 1] = r1;
|
||||
dst_tensor_buffer[linear_index * 4 + 2] = r2;
|
||||
dst_tensor_buffer[linear_index * 4 + 3] = r3;
|
||||
}
|
||||
|
||||
__attribute__((qcom_max_concurrent_subgroups(12))) __kernel void adreno_xmem_attn_pv_gemm(
|
||||
constant half8 * weights_buffer __attribute__((sub_group_uniform)),
|
||||
constant half8 * xmem_buffer __attribute__((max_constant_size((6144)))),
|
||||
read_only image1d_buffer_t src_tensor_image_buffer,
|
||||
write_only image2d_t dst_tensor_image2d,
|
||||
const int4 shared_int4_0,
|
||||
const int4 shared_int4_1,
|
||||
const int4 shared_int4_2,
|
||||
const int4 shared_int4_3) {
|
||||
int X = get_group_id(1) * get_local_size(0) + get_local_id(0);
|
||||
int Y = get_group_id(2) * get_local_size(1) + get_local_id(1);
|
||||
int Z = get_group_id(0) * get_local_size(2) + get_local_id(2);
|
||||
if (X >= shared_int4_0.z || Y >= shared_int4_0.x) {
|
||||
return;
|
||||
}
|
||||
if (Z * 8 >= shared_int4_0.y) {
|
||||
return;
|
||||
}
|
||||
|
||||
half4 r0 = (half4) (0.f);
|
||||
half4 r1 = (half4) (0.f);
|
||||
half4 r2 = (half4) (0.f);
|
||||
half4 r3 = (half4) (0.f);
|
||||
half4 r4 = (half4) (0.f);
|
||||
half4 r5 = (half4) (0.f);
|
||||
half4 r6 = (half4) (0.f);
|
||||
half4 r7 = (half4) (0.f);
|
||||
int x_coord = mad24(X, shared_int4_2.w, shared_int4_1.y);
|
||||
int y_coord = mad24(Y, shared_int4_3.x, shared_int4_1.z);
|
||||
int coord_x, coord_y, coord_s;
|
||||
int f_offset = (Z * shared_int4_1.w + Y) * shared_int4_1.x * 32;
|
||||
|
||||
int subgroup_id = (int) ((0x1F & qcom_get_physical_sub_group_id()));
|
||||
subgroup_id = subgroup_id % 12;
|
||||
int c_offset = mul24(subgroup_id, shared_int4_0.w);
|
||||
__constant half16 * weights_cache = (__constant half16 *) &xmem_buffer[c_offset];
|
||||
coord_y = Y;
|
||||
coord_x = X;
|
||||
int addr = (((0) * shared_int4_1.w + (coord_y)) * shared_int4_2.z + (coord_x));
|
||||
int dz = shared_int4_2.x;
|
||||
coord_s = 0;
|
||||
do {
|
||||
half4 src0 = read_imageh(src_tensor_image_buffer, addr);
|
||||
addr += dz;
|
||||
coord_s++;
|
||||
half4 src1 = read_imageh(src_tensor_image_buffer, addr);
|
||||
addr += dz;
|
||||
coord_s++;
|
||||
qcom_sub_group_constant_load8(xmem_buffer, weights_buffer, c_offset, f_offset >> 1, 32);
|
||||
f_offset += 64;
|
||||
qcom_sub_group_sync(QCOM_CLK_CONST_LOAD_SYNC);
|
||||
r0 += src0.x * weights_cache[0].s0123;
|
||||
r0 += src0.y * weights_cache[0].s4567;
|
||||
r0 += src0.z * weights_cache[0].s89ab;
|
||||
r0 += src0.w * weights_cache[0].scdef;
|
||||
r1 += src0.x * weights_cache[1].s0123;
|
||||
r1 += src0.y * weights_cache[1].s4567;
|
||||
r1 += src0.z * weights_cache[1].s89ab;
|
||||
r1 += src0.w * weights_cache[1].scdef;
|
||||
r2 += src0.x * weights_cache[2].s0123;
|
||||
r2 += src0.y * weights_cache[2].s4567;
|
||||
r2 += src0.z * weights_cache[2].s89ab;
|
||||
r2 += src0.w * weights_cache[2].scdef;
|
||||
r3 += src0.x * weights_cache[3].s0123;
|
||||
r3 += src0.y * weights_cache[3].s4567;
|
||||
r3 += src0.z * weights_cache[3].s89ab;
|
||||
r3 += src0.w * weights_cache[3].scdef;
|
||||
r4 += src0.x * weights_cache[4].s0123;
|
||||
r4 += src0.y * weights_cache[4].s4567;
|
||||
r4 += src0.z * weights_cache[4].s89ab;
|
||||
r4 += src0.w * weights_cache[4].scdef;
|
||||
r5 += src0.x * weights_cache[5].s0123;
|
||||
r5 += src0.y * weights_cache[5].s4567;
|
||||
r5 += src0.z * weights_cache[5].s89ab;
|
||||
r5 += src0.w * weights_cache[5].scdef;
|
||||
r6 += src0.x * weights_cache[6].s0123;
|
||||
r6 += src0.y * weights_cache[6].s4567;
|
||||
r6 += src0.z * weights_cache[6].s89ab;
|
||||
r6 += src0.w * weights_cache[6].scdef;
|
||||
r7 += src0.x * weights_cache[7].s0123;
|
||||
r7 += src0.y * weights_cache[7].s4567;
|
||||
r7 += src0.z * weights_cache[7].s89ab;
|
||||
r7 += src0.w * weights_cache[7].scdef;
|
||||
r0 += src1.x * weights_cache[8].s0123;
|
||||
r0 += src1.y * weights_cache[8].s4567;
|
||||
r0 += src1.z * weights_cache[8].s89ab;
|
||||
r0 += src1.w * weights_cache[8].scdef;
|
||||
r1 += src1.x * weights_cache[9].s0123;
|
||||
r1 += src1.y * weights_cache[9].s4567;
|
||||
r1 += src1.z * weights_cache[9].s89ab;
|
||||
r1 += src1.w * weights_cache[9].scdef;
|
||||
r2 += src1.x * weights_cache[10].s0123;
|
||||
r2 += src1.y * weights_cache[10].s4567;
|
||||
r2 += src1.z * weights_cache[10].s89ab;
|
||||
r2 += src1.w * weights_cache[10].scdef;
|
||||
r3 += src1.x * weights_cache[11].s0123;
|
||||
r3 += src1.y * weights_cache[11].s4567;
|
||||
r3 += src1.z * weights_cache[11].s89ab;
|
||||
r3 += src1.w * weights_cache[11].scdef;
|
||||
r4 += src1.x * weights_cache[12].s0123;
|
||||
r4 += src1.y * weights_cache[12].s4567;
|
||||
r4 += src1.z * weights_cache[12].s89ab;
|
||||
r4 += src1.w * weights_cache[12].scdef;
|
||||
r5 += src1.x * weights_cache[13].s0123;
|
||||
r5 += src1.y * weights_cache[13].s4567;
|
||||
r5 += src1.z * weights_cache[13].s89ab;
|
||||
r5 += src1.w * weights_cache[13].scdef;
|
||||
r6 += src1.x * weights_cache[14].s0123;
|
||||
r6 += src1.y * weights_cache[14].s4567;
|
||||
r6 += src1.z * weights_cache[14].s89ab;
|
||||
r6 += src1.w * weights_cache[14].scdef;
|
||||
r7 += src1.x * weights_cache[15].s0123;
|
||||
r7 += src1.y * weights_cache[15].s4567;
|
||||
r7 += src1.z * weights_cache[15].s89ab;
|
||||
r7 += src1.w * weights_cache[15].scdef;
|
||||
} while (coord_s < shared_int4_2.y);
|
||||
|
||||
coord_s = mul24(Z, 8);
|
||||
coord_x = X;
|
||||
coord_y = Y;
|
||||
if (coord_s < shared_int4_0.y) {
|
||||
half4 res = convert_half4(r0);
|
||||
if (coord_s < 0) {
|
||||
res += read_imageh(src_tensor_image_buffer, ((0) * shared_int4_1.w + (0)) * shared_int4_2.z + (0));
|
||||
}
|
||||
write_imageh(dst_tensor_image2d, (int2) ((coord_x), ((coord_y) *shared_int4_0.y + (coord_s))), res);
|
||||
coord_s++;
|
||||
}
|
||||
if (coord_s < shared_int4_0.y) {
|
||||
half4 res = convert_half4(r1);
|
||||
if (coord_s < 0) {
|
||||
res += read_imageh(src_tensor_image_buffer, ((0) * shared_int4_1.w + (0)) * shared_int4_2.z + (0));
|
||||
}
|
||||
write_imageh(dst_tensor_image2d, (int2) ((coord_x), ((coord_y) *shared_int4_0.y + (coord_s))), res);
|
||||
coord_s++;
|
||||
}
|
||||
if (coord_s < shared_int4_0.y) {
|
||||
half4 res = convert_half4(r2);
|
||||
if (coord_s < 0) {
|
||||
res += read_imageh(src_tensor_image_buffer, ((0) * shared_int4_1.w + (0)) * shared_int4_2.z + (0));
|
||||
}
|
||||
write_imageh(dst_tensor_image2d, (int2) ((coord_x), ((coord_y) *shared_int4_0.y + (coord_s))), res);
|
||||
coord_s++;
|
||||
}
|
||||
if (coord_s < shared_int4_0.y) {
|
||||
half4 res = convert_half4(r3);
|
||||
if (coord_s < 0) {
|
||||
res += read_imageh(src_tensor_image_buffer, ((0) * shared_int4_1.w + (0)) * shared_int4_2.z + (0));
|
||||
}
|
||||
write_imageh(dst_tensor_image2d, (int2) ((coord_x), ((coord_y) *shared_int4_0.y + (coord_s))), res);
|
||||
coord_s++;
|
||||
}
|
||||
if (coord_s < shared_int4_0.y) {
|
||||
half4 res = convert_half4(r4);
|
||||
if (coord_s < 0) {
|
||||
res += read_imageh(src_tensor_image_buffer, ((0) * shared_int4_1.w + (0)) * shared_int4_2.z + (0));
|
||||
}
|
||||
write_imageh(dst_tensor_image2d, (int2) ((coord_x), ((coord_y) *shared_int4_0.y + (coord_s))), res);
|
||||
coord_s++;
|
||||
}
|
||||
if (coord_s < shared_int4_0.y) {
|
||||
half4 res = convert_half4(r5);
|
||||
if (coord_s < 0) {
|
||||
res += read_imageh(src_tensor_image_buffer, ((0) * shared_int4_1.w + (0)) * shared_int4_2.z + (0));
|
||||
}
|
||||
write_imageh(dst_tensor_image2d, (int2) ((coord_x), ((coord_y) *shared_int4_0.y + (coord_s))), res);
|
||||
coord_s++;
|
||||
}
|
||||
if (coord_s < shared_int4_0.y) {
|
||||
half4 res = convert_half4(r6);
|
||||
if (coord_s < 0) {
|
||||
res += read_imageh(src_tensor_image_buffer, ((0) * shared_int4_1.w + (0)) * shared_int4_2.z + (0));
|
||||
}
|
||||
write_imageh(dst_tensor_image2d, (int2) ((coord_x), ((coord_y) *shared_int4_0.y + (coord_s))), res);
|
||||
coord_s++;
|
||||
}
|
||||
if (coord_s < shared_int4_0.y) {
|
||||
half4 res = convert_half4(r7);
|
||||
if (coord_s < 0) {
|
||||
res += read_imageh(src_tensor_image_buffer, ((0) * shared_int4_1.w + (0)) * shared_int4_2.z + (0));
|
||||
}
|
||||
write_imageh(dst_tensor_image2d, (int2) ((coord_x), ((coord_y) *shared_int4_0.y + (coord_s))), res);
|
||||
coord_s++;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Extended elementwise unary ops, same variant shape as abs.cl:
|
||||
// f32, f32_4 (vec4), f16, f16_4 (vec4), f32_nc, f16_nc (stride-addressed).
|
||||
//
|
||||
// sgn, step, elu, hardswish, hardsigmoid, floor, ceil, round, trunc.
|
||||
//
|
||||
// Semantics match the ggml CPU reference (ggml.c). Values are computed in float
|
||||
// (the f16 variants read/write half and convert), so the conditional ops match
|
||||
// the CPU bit-for-bit within tolerance. SEXPR is the scalar form, VEXPR the
|
||||
// float4 form (vector ternaries need select()).
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#define UNARY_EXT(NAME, SEXPR, VEXPR) \
|
||||
kernel void kernel_##NAME##_f32( \
|
||||
global const float * src0, ulong offset0, \
|
||||
global float * dst, ulong offsetd) { \
|
||||
src0 = (global float*)((global char*)src0 + offset0); \
|
||||
dst = (global float*)((global char*)dst + offsetd); \
|
||||
float x = src0[get_global_id(0)]; \
|
||||
dst[get_global_id(0)] = (SEXPR); \
|
||||
} \
|
||||
kernel void kernel_##NAME##_f32_4( \
|
||||
global const float4 * src0, ulong offset0, \
|
||||
global float4 * dst, ulong offsetd) { \
|
||||
src0 = (global float4*)((global char*)src0 + offset0); \
|
||||
dst = (global float4*)((global char*)dst + offsetd); \
|
||||
float4 x = src0[get_global_id(0)]; \
|
||||
dst[get_global_id(0)] = (VEXPR); \
|
||||
} \
|
||||
kernel void kernel_##NAME##_f16( \
|
||||
global const half * src0, ulong offset0, \
|
||||
global half * dst, ulong offsetd) { \
|
||||
src0 = (global half*)((global char*)src0 + offset0); \
|
||||
dst = (global half*)((global char*)dst + offsetd); \
|
||||
float x = src0[get_global_id(0)]; \
|
||||
dst[get_global_id(0)] = (SEXPR); \
|
||||
} \
|
||||
kernel void kernel_##NAME##_f16_4( \
|
||||
global const half4 * src0, ulong offset0, \
|
||||
global half4 * dst, ulong offsetd) { \
|
||||
src0 = (global half4*)((global char*)src0 + offset0); \
|
||||
dst = (global half4*)((global char*)dst + offsetd); \
|
||||
float4 x = convert_float4(src0[get_global_id(0)]); \
|
||||
dst[get_global_id(0)] = convert_half4(VEXPR); \
|
||||
} \
|
||||
kernel void kernel_##NAME##_f32_nc( \
|
||||
global const char * src0, ulong offset0, \
|
||||
global char * dst, ulong offsetd, \
|
||||
int ne00, ulong nb00, ulong nb01, ulong nb02, ulong nb03, \
|
||||
ulong nb0, ulong nb1, ulong nb2, ulong nb3) { \
|
||||
src0 = src0 + offset0; dst = dst + offsetd; \
|
||||
const int i3 = get_group_id(2); \
|
||||
const int i2 = get_group_id(1); \
|
||||
const int i1 = get_group_id(0); \
|
||||
for (int i0 = get_local_id(0); i0 < ne00; i0 += get_local_size(0)) { \
|
||||
float x = *(global const float *)(src0 + i3*nb03 + i2*nb02 + i1*nb01 + i0*nb00); \
|
||||
*(global float *)(dst + i3*nb3 + i2*nb2 + i1*nb1 + i0*nb0) = (SEXPR); \
|
||||
} \
|
||||
} \
|
||||
kernel void kernel_##NAME##_f16_nc( \
|
||||
global const char * src0, ulong offset0, \
|
||||
global char * dst, ulong offsetd, \
|
||||
int ne00, ulong nb00, ulong nb01, ulong nb02, ulong nb03, \
|
||||
ulong nb0, ulong nb1, ulong nb2, ulong nb3) { \
|
||||
src0 = src0 + offset0; dst = dst + offsetd; \
|
||||
const int i3 = get_group_id(2); \
|
||||
const int i2 = get_group_id(1); \
|
||||
const int i1 = get_group_id(0); \
|
||||
for (int i0 = get_local_id(0); i0 < ne00; i0 += get_local_size(0)) {\
|
||||
float x = *(global const half *)(src0 + i3*nb03 + i2*nb02 + i1*nb01 + i0*nb00); \
|
||||
*(global half *)(dst + i3*nb3 + i2*nb2 + i1*nb1 + i0*nb0) = (SEXPR); \
|
||||
} \
|
||||
}
|
||||
|
||||
UNARY_EXT(sgn, sign(x), sign(x))
|
||||
UNARY_EXT(step, x > 0.0f ? 1.0f : 0.0f, select((float4)0.0f, (float4)1.0f, x > 0.0f))
|
||||
UNARY_EXT(elu, x > 0.0f ? x : expm1(x), select(expm1(x), x, x > 0.0f))
|
||||
UNARY_EXT(hardswish, x * fmin(1.0f, fmax(0.0f, (x + 3.0f) / 6.0f)), x * fmin((float4)1.0f, fmax((float4)0.0f, (x + 3.0f) / 6.0f)))
|
||||
UNARY_EXT(hardsigmoid, fmin(1.0f, fmax(0.0f, (x + 3.0f) / 6.0f)), fmin((float4)1.0f, fmax((float4)0.0f, (x + 3.0f) / 6.0f)))
|
||||
UNARY_EXT(floor, floor(x), floor(x))
|
||||
UNARY_EXT(ceil, ceil(x), ceil(x))
|
||||
UNARY_EXT(round, round(x), round(x))
|
||||
UNARY_EXT(trunc, trunc(x), trunc(x))
|
||||
@@ -1091,6 +1091,10 @@ static ggml_openvino_op_support is_op_supported_case(const ggml_tensor * op) {
|
||||
if (op->ne[3] != 1) {
|
||||
return {false, "GET_ROWS/SET_ROWS with ne[3] != 1 (ne[3]=" + std::to_string(op->ne[3]) + ") is not supported"};
|
||||
}
|
||||
if (op->op == GGML_OP_GET_ROWS && ggml_is_quantized(op->src[0]->type) &&
|
||||
op->src[0]->view_src != nullptr && op->src[0]->view_offs != 0) {
|
||||
return {false, "GET_ROWS with a nonzero quantized src0 view offset is not supported"};
|
||||
}
|
||||
if (op->op == GGML_OP_GET_ROWS && ggml_openvino_get_device_name() == "GPU" &&
|
||||
op->src[0]->type == GGML_TYPE_BF16) {
|
||||
return {false, "GET_ROWS with BF16 src0 is not supported on GPU"};
|
||||
|
||||
@@ -94,7 +94,7 @@ static bool ggml_sycl_use_level_zero_device_alloc(sycl::queue &q) {
|
||||
|
||||
// Use Level Zero zeMemAllocDevice to avoid sycl::malloc_device triggering
|
||||
// DMA-buf/TTM system RAM staging in the xe kernel driver during multi-GPU inference.
|
||||
void * ggml_sycl_malloc_device(size_t size, sycl::queue &q) {
|
||||
void * ggml_sycl_malloc_device(size_t size, sycl::queue &q, ggml_sycl_mem_type type) {
|
||||
#ifdef GGML_SYCL_SUPPORT_LEVEL_ZERO_API
|
||||
if (ggml_sycl_use_level_zero_device_alloc(q)) {
|
||||
void *ptr = nullptr;
|
||||
@@ -117,16 +117,25 @@ void * ggml_sycl_malloc_device(size_t size, sycl::queue &q) {
|
||||
#endif
|
||||
ze_result_t r = zeMemAllocDevice(ze_ctx, &alloc_desc, size, 64, ze_dev, &ptr);
|
||||
if (r == ZE_RESULT_SUCCESS && ptr) {
|
||||
ggml_sycl_memtrace_add(type, ptr, size);
|
||||
return ptr;
|
||||
}
|
||||
ggml_sycl_memtrace_fail(type, size);
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
return sycl::malloc_device(size, q);
|
||||
void * ptr = sycl::malloc_device(size, q);
|
||||
if (ptr == nullptr) {
|
||||
ggml_sycl_memtrace_fail(type, size);
|
||||
return nullptr;
|
||||
}
|
||||
ggml_sycl_memtrace_add(type, ptr, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void ggml_sycl_free_device(void *ptr, sycl::queue &q) {
|
||||
if (!ptr) return;
|
||||
ggml_sycl_memtrace_del(ptr);
|
||||
#ifdef GGML_SYCL_SUPPORT_LEVEL_ZERO_API
|
||||
if (ggml_sycl_use_level_zero_device_alloc(q)) {
|
||||
auto ze_ctx = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(q.get_context());
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "type.hpp"
|
||||
#include "sycl_hw.hpp"
|
||||
#include "fattn-buffers.hpp"
|
||||
#include "memtrace.hpp"
|
||||
|
||||
namespace syclexp = sycl::ext::oneapi::experimental;
|
||||
|
||||
@@ -69,6 +70,8 @@ extern int g_ggml_sycl_dev2dev_memcpy;
|
||||
extern int g_ggml_sycl_fa_onednn;
|
||||
extern int g_ggml_sycl_fa_onednn_max_kv;
|
||||
extern int g_ggml_sycl_enable_mkl_fa;
|
||||
extern int g_ggml_sycl_memtrace;
|
||||
extern int g_ggml_sycl_memtrace_step;
|
||||
|
||||
|
||||
#define CHECK_TRY_ERROR(expr) \
|
||||
@@ -318,7 +321,8 @@ struct ggml_tensor_extra_gpu {
|
||||
};
|
||||
|
||||
extern int g_ggml_sycl_use_level_zero_api;
|
||||
void * ggml_sycl_malloc_device(size_t size, sycl::queue &q);
|
||||
void * ggml_sycl_malloc_device(size_t size, sycl::queue &q,
|
||||
ggml_sycl_mem_type type = GGML_SYCL_MEM_DIRECT);
|
||||
void ggml_sycl_free_device(void *ptr, sycl::queue &q);
|
||||
|
||||
void release_extra_gpu(ggml_tensor_extra_gpu * extra, std::vector<queue_ptr> streams={});
|
||||
|
||||
@@ -21,6 +21,7 @@ sycl::half * ggml_sycl_fattn_kv_buffers::kv_buffer::ensure_half(size_t n_elems)
|
||||
|
||||
if (ptr) {
|
||||
SYCL_CHECK(CHECK_TRY_ERROR(qptr->wait()));
|
||||
ggml_sycl_memtrace_del(ptr);
|
||||
SYCL_CHECK(CHECK_TRY_ERROR(sycl::free(ptr, *qptr)));
|
||||
ptr = nullptr;
|
||||
capacity = 0;
|
||||
@@ -38,11 +39,13 @@ sycl::half * ggml_sycl_fattn_kv_buffers::kv_buffer::ensure_half(size_t n_elems)
|
||||
|
||||
if (!dev_ptr) {
|
||||
GGML_LOG_ERROR("%s: can't allocate %lu Bytes of memory on device\n", __func__, cap);
|
||||
ggml_sycl_memtrace_fail(GGML_SYCL_MEM_FATTN_KV, cap);
|
||||
GGML_ABORT("fattn buffer alloc failed");
|
||||
}
|
||||
|
||||
ptr = static_cast<sycl::half *>(dev_ptr);
|
||||
capacity = cap;
|
||||
ggml_sycl_memtrace_add(GGML_SYCL_MEM_FATTN_KV, ptr, cap);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
@@ -51,6 +54,7 @@ ggml_sycl_fattn_kv_buffers::kv_buffer::~kv_buffer() {
|
||||
GGML_LOG_INFO("ggml_sycl_fattn_kv_buffer[%d]: %.2f MiB\n", device, capacity / 1024.0 / 1024.0);
|
||||
#endif
|
||||
if (ptr) {
|
||||
ggml_sycl_memtrace_del(ptr);
|
||||
SYCL_CHECK(CHECK_TRY_ERROR(sycl::free(ptr, *qptr)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,50 @@
|
||||
#include "fwht.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#define P 1.0f
|
||||
#define N -1.0f
|
||||
|
||||
// constant Hadamard matrix via Paley I construction
|
||||
static constexpr float H12[12][12] = {
|
||||
{ P, P, P, P, P, P, P, P, P, P, P, P },
|
||||
{ P, N, P, N, P, P, P, N, N, N, P, N },
|
||||
{ P, N, N, P, N, P, P, P, N, N, N, P },
|
||||
{ P, P, N, N, P, N, P, P, P, N, N, N },
|
||||
{ P, N, P, N, N, P, N, P, P, P, N, N },
|
||||
{ P, N, N, P, N, N, P, N, P, P, P, N },
|
||||
{ P, N, N, N, P, N, N, P, N, P, P, P },
|
||||
{ P, P, N, N, N, P, N, N, P, N, P, P },
|
||||
{ P, P, P, N, N, N, P, N, N, P, N, P },
|
||||
{ P, P, P, P, N, N, N, P, N, N, P, N },
|
||||
{ P, N, P, P, P, N, N, N, P, N, N, P },
|
||||
{ P, P, N, P, P, P, N, N, N, P, N, N }
|
||||
};
|
||||
|
||||
static constexpr float H20[20][20] = {
|
||||
{ P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P },
|
||||
{ P, N, P, N, N, P, P, P, P, N, P, N, P, N, N, N, N, P, P, N },
|
||||
{ P, N, N, P, N, N, P, P, P, P, N, P, N, P, N, N, N, N, P, P },
|
||||
{ P, P, N, N, P, N, N, P, P, P, P, N, P, N, P, N, N, N, N, P },
|
||||
{ P, P, P, N, N, P, N, N, P, P, P, P, N, P, N, P, N, N, N, N },
|
||||
{ P, N, P, P, N, N, P, N, N, P, P, P, P, N, P, N, P, N, N, N },
|
||||
{ P, N, N, P, P, N, N, P, N, N, P, P, P, P, N, P, N, P, N, N },
|
||||
{ P, N, N, N, P, P, N, N, P, N, N, P, P, P, P, N, P, N, P, N },
|
||||
{ P, N, N, N, N, P, P, N, N, P, N, N, P, P, P, P, N, P, N, P },
|
||||
{ P, P, N, N, N, N, P, P, N, N, P, N, N, P, P, P, P, N, P, N },
|
||||
{ P, N, P, N, N, N, N, P, P, N, N, P, N, N, P, P, P, P, N, P },
|
||||
{ P, P, N, P, N, N, N, N, P, P, N, N, P, N, N, P, P, P, P, N },
|
||||
{ P, N, P, N, P, N, N, N, N, P, P, N, N, P, N, N, P, P, P, P },
|
||||
{ P, P, N, P, N, P, N, N, N, N, P, P, N, N, P, N, N, P, P, P },
|
||||
{ P, P, P, N, P, N, P, N, N, N, N, P, P, N, N, P, N, N, P, P },
|
||||
{ P, P, P, P, N, P, N, P, N, N, N, N, P, P, N, N, P, N, N, P },
|
||||
{ P, P, P, P, P, N, P, N, P, N, N, N, N, P, P, N, N, P, N, N },
|
||||
{ P, N, P, P, P, P, N, P, N, P, N, N, N, N, P, P, N, N, P, N },
|
||||
{ P, N, N, P, P, P, P, N, P, N, P, N, N, N, N, P, P, N, N, P },
|
||||
{ P, P, N, N, P, P, P, P, N, P, N, P, N, N, N, N, P, P, N, N }
|
||||
};
|
||||
|
||||
#undef P
|
||||
#undef N
|
||||
|
||||
template <int N>
|
||||
static void fwht_kernel(const float * __restrict__ src, float * __restrict__ dst, const int64_t n_rows,
|
||||
@@ -80,6 +124,122 @@ static void launch_fwht(const float * src, float * dst, const int64_t n_rows, co
|
||||
});
|
||||
}
|
||||
|
||||
template <int N, int m>
|
||||
static void kronecker_kernel(const float * __restrict__ src,
|
||||
float * __restrict__ dst,
|
||||
const int64_t n_rows,
|
||||
const float scale,
|
||||
const sycl::nd_item<2> & item) {
|
||||
static_assert(m == 12 || m == 20, "block size has to be 12 or 20.");
|
||||
|
||||
const sycl::sub_group sg = item.get_sub_group();
|
||||
|
||||
const int64_t r = item.get_global_id(0);
|
||||
if (r >= n_rows) {
|
||||
return;
|
||||
}
|
||||
|
||||
src += r * N;
|
||||
dst += r * N;
|
||||
|
||||
constexpr int blocks_per_group = N / m;
|
||||
constexpr int el_w = blocks_per_group / WARP_SIZE;
|
||||
static_assert(el_w >= 1 && blocks_per_group % WARP_SIZE == 0, "blocks_per_group must be a multiple of WARP_SIZE");
|
||||
float reg[el_w * m];
|
||||
const int lane = sg.get_local_linear_id();
|
||||
|
||||
#pragma unroll
|
||||
for (int i = 0; i < el_w; ++i) {
|
||||
const int b_idx = i * WARP_SIZE + lane;
|
||||
|
||||
#pragma unroll
|
||||
for (int j = 0; j < m; ++j) {
|
||||
reg[i * m + j] = src[b_idx * m + j] * scale;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma unroll
|
||||
for (int b = 0; b < el_w; ++b) {
|
||||
float z[m] = { 0.0f };
|
||||
|
||||
#pragma unroll
|
||||
for (int i = 0; i < m; ++i) {
|
||||
#pragma unroll
|
||||
for (int j = 0; j < m; ++j) {
|
||||
const float h = (m == 12 ? H12[j][i] : H20[j][i]);
|
||||
z[i] += reg[b * m + j] * h;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma unroll
|
||||
for (int i = 0; i < m; ++i) {
|
||||
reg[b * m + i] = z[i];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma unroll
|
||||
for (int h = 1; h < WARP_SIZE; h *= 2) {
|
||||
#pragma unroll
|
||||
for (int j = 0; j < el_w; ++j) {
|
||||
#pragma unroll
|
||||
for (int k = 0; k < m; ++k) {
|
||||
const float val = reg[j * m + k];
|
||||
const float val2 = dpct::permute_sub_group_by_xor(sg, val, h, WARP_SIZE);
|
||||
|
||||
reg[j * m + k] = (lane & h) == 0 ? val + val2 : val2 - val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma unroll
|
||||
for (int h = WARP_SIZE; h < blocks_per_group; h *= 2) {
|
||||
const int step = h / WARP_SIZE;
|
||||
#pragma unroll
|
||||
for (int j = 0; j < el_w; j += 2 * step) {
|
||||
#pragma unroll
|
||||
for (int s = 0; s < step; ++s) {
|
||||
#pragma unroll
|
||||
for (int k = 0; k < m; ++k) {
|
||||
const float x = reg[(j + s) * m + k];
|
||||
const float y = reg[(j + s + step) * m + k];
|
||||
|
||||
reg[(j + s) * m + k] = x + y;
|
||||
reg[(j + s + step) * m + k] = x - y;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma unroll
|
||||
for (int i = 0; i < el_w; ++i) {
|
||||
const int b_idx = i * WARP_SIZE + lane;
|
||||
#pragma unroll
|
||||
for (int k = 0; k < m; ++k) {
|
||||
dst[b_idx * m + k] = reg[i * m + k];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <int N, int m>
|
||||
static void launch_kronecker(const float * src,
|
||||
float * dst,
|
||||
const int64_t n_rows,
|
||||
const float scale,
|
||||
dpct::queue_ptr stream) {
|
||||
constexpr int rows_per_block = 4;
|
||||
|
||||
const int64_t num_blocks = (n_rows + rows_per_block - 1) / rows_per_block;
|
||||
|
||||
// dim 1 is the fastest-varying, so a sub-group is exactly one row's WARP_SIZE lanes.
|
||||
const sycl::range<2> global(num_blocks * rows_per_block, WARP_SIZE);
|
||||
const sycl::range<2> local(rows_per_block, WARP_SIZE);
|
||||
|
||||
stream->parallel_for(sycl::nd_range<2>(global, local),
|
||||
[=](sycl::nd_item<2> item) [[sycl::reqd_sub_group_size(WARP_SIZE)]] {
|
||||
kronecker_kernel<N, m>(src, dst, n_rows, scale, item);
|
||||
});
|
||||
}
|
||||
|
||||
bool ggml_sycl_op_fwht(ggml_backend_sycl_context & ctx, const ggml_tensor * src, ggml_tensor * dst) {
|
||||
if (src->type != GGML_TYPE_F32 || dst->type != GGML_TYPE_F32) {
|
||||
return false;
|
||||
@@ -113,6 +273,18 @@ bool ggml_sycl_op_fwht(ggml_backend_sycl_context & ctx, const ggml_tensor * src,
|
||||
case 512:
|
||||
launch_fwht<512>(src_d, dst_d, rows, scale, stream);
|
||||
return true;
|
||||
case 384:
|
||||
launch_kronecker<384, 12>(src_d, dst_d, rows, scale, stream);
|
||||
return true;
|
||||
case 768:
|
||||
launch_kronecker<768, 12>(src_d, dst_d, rows, scale, stream);
|
||||
return true;
|
||||
case 640:
|
||||
launch_kronecker<640, 20>(src_d, dst_d, rows, scale, stream);
|
||||
return true;
|
||||
case 1280:
|
||||
launch_kronecker<1280, 20>(src_d, dst_d, rows, scale, stream);
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -97,6 +97,8 @@ int g_ggml_sycl_enable_dnn = 1;
|
||||
int g_ggml_sycl_fa_onednn = 1;
|
||||
int g_ggml_sycl_fa_onednn_max_kv = 0;
|
||||
int g_ggml_sycl_enable_mkl_fa = 1;
|
||||
int g_ggml_sycl_memtrace = 0;
|
||||
int g_ggml_sycl_memtrace_step = 64;
|
||||
int g_ggml_sycl_enable_vmm = 1;
|
||||
int g_ggml_sycl_enable_fusion = 1;
|
||||
int g_ggml_sycl_enable_esimd = 1;
|
||||
@@ -335,6 +337,8 @@ static void ggml_check_sycl() try {
|
||||
g_ggml_sycl_fa_onednn = ggml_sycl_get_env("GGML_SYCL_FA_ONEDNN", 1);
|
||||
g_ggml_sycl_fa_onednn_max_kv = ggml_sycl_get_env("GGML_SYCL_FA_ONEDNN_MAX_KV", 0);
|
||||
g_ggml_sycl_enable_mkl_fa = ggml_sycl_get_env("GGML_SYCL_ENABLE_MKL_FA", 1);
|
||||
g_ggml_sycl_memtrace = ggml_sycl_get_env("GGML_SYCL_MEMTRACE", 0);
|
||||
g_ggml_sycl_memtrace_step = ggml_sycl_get_env("GGML_SYCL_MEMTRACE_STEP", 64);
|
||||
g_ggml_sycl_enable_vmm = ggml_sycl_get_env("GGML_SYCL_ENABLE_VMM", 1);
|
||||
g_ggml_sycl_enable_fusion = ggml_sycl_get_env("GGML_SYCL_ENABLE_FUSION", 1);
|
||||
g_ggml_sycl_enable_esimd = ggml_sycl_get_env("GGML_SYCL_ENABLE_ESIMD", 1);
|
||||
@@ -421,6 +425,8 @@ static void ggml_check_sycl() try {
|
||||
#endif
|
||||
GGML_LOG_INFO(" GGML_SYCL_FA_ONEDNN_MAX_KV: %d\n", g_ggml_sycl_fa_onednn_max_kv);
|
||||
GGML_LOG_INFO(" GGML_SYCL_ENABLE_MKL_FA: %d\n", g_ggml_sycl_enable_mkl_fa);
|
||||
GGML_LOG_INFO(" GGML_SYCL_MEMTRACE: %d\n", g_ggml_sycl_memtrace);
|
||||
GGML_LOG_INFO(" GGML_SYCL_MEMTRACE_STEP: %d\n", g_ggml_sycl_memtrace_step);
|
||||
#ifdef SYCL_FLASH_ATTN
|
||||
GGML_LOG_INFO(" GGML_SYCL_ENABLE_FLASH_ATTN: %d\n", g_ggml_sycl_enable_flash_attention);
|
||||
#else
|
||||
@@ -964,7 +970,7 @@ ggml_backend_sycl_buffer_type_alloc_buffer(ggml_backend_buffer_type_t buft,
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
SYCL_CHECK(CHECK_TRY_ERROR(dev_ptr = (void *)ggml_sycl_malloc_device(size, *stream)));
|
||||
SYCL_CHECK(CHECK_TRY_ERROR(dev_ptr = (void *)ggml_sycl_malloc_device(size, *stream, GGML_SYCL_MEM_BUFFER)));
|
||||
if (!dev_ptr) {
|
||||
GGML_LOG_ERROR("%s: can't allocate %zu Bytes of memory on device\n", __func__, size);
|
||||
return nullptr;
|
||||
@@ -1217,7 +1223,7 @@ ggml_backend_sycl_split_buffer_init_tensor(ggml_backend_buffer_t buffer,
|
||||
ggml_sycl_set_device(i);
|
||||
const queue_ptr stream = ctx->streams[i];
|
||||
char * buf;
|
||||
SYCL_CHECK(CHECK_TRY_ERROR(buf = (char *)ggml_sycl_malloc_device(size, *stream)));
|
||||
SYCL_CHECK(CHECK_TRY_ERROR(buf = (char *)ggml_sycl_malloc_device(size, *stream, GGML_SYCL_MEM_BUFFER)));
|
||||
if (!buf) {
|
||||
char err_buf[1024];
|
||||
snprintf(err_buf, 1023, "%s: can't allocate %zu Bytes of memory on device\n", __func__, size);
|
||||
@@ -1697,7 +1703,7 @@ struct ggml_sycl_pool_leg : public ggml_sycl_pool {
|
||||
void * ptr;
|
||||
size_t look_ahead_size = (size_t) (1.05 * size);
|
||||
|
||||
SYCL_CHECK(CHECK_TRY_ERROR(ptr = (void *)ggml_sycl_malloc_device(look_ahead_size, *qptr)));
|
||||
SYCL_CHECK(CHECK_TRY_ERROR(ptr = (void *)ggml_sycl_malloc_device(look_ahead_size, *qptr, GGML_SYCL_MEM_POOL_LEG)));
|
||||
if (!ptr) {
|
||||
GGML_LOG_ERROR("%s: can't allocate %zu Bytes of memory on device/GPU\n", __func__, look_ahead_size);
|
||||
return nullptr;
|
||||
@@ -1786,6 +1792,13 @@ struct ggml_sycl_pool_vmm : public ggml_sycl_pool {
|
||||
|
||||
GGML_ASSERT(pool_size + reserve_size <= SYCL_POOL_VMM_MAX_SIZE);
|
||||
|
||||
if (ggml_sycl_memtrace_enabled()) {
|
||||
GGML_LOG_INFO(GGML_SYCL_MEMTRACE_TAG " pool_vmm[%d] committing %5zu MiB (pool %5zu -> %5zu MiB)\n",
|
||||
device, reserve_size / (1024 * 1024), pool_size / (1024 * 1024),
|
||||
(pool_size + reserve_size) / (1024 * 1024));
|
||||
ggml_sycl_memtrace_report("before pool_vmm commit");
|
||||
}
|
||||
|
||||
// allocate more physical memory
|
||||
std::optional<sycl::ext::oneapi::experimental::physical_mem> phys;
|
||||
SYCL_CHECK(CHECK_TRY_ERROR(phys.emplace(dev, ctx, reserve_size)));
|
||||
@@ -1811,6 +1824,7 @@ struct ggml_sycl_pool_vmm : public ggml_sycl_pool {
|
||||
|
||||
// add to the pool
|
||||
pool_size += reserve_size;
|
||||
ggml_sycl_memtrace_add(GGML_SYCL_MEM_POOL_VMM, map_ptr, reserve_size);
|
||||
|
||||
#ifdef DEBUG_SYCL_MALLOC
|
||||
GGML_LOG_INFO("sycl pool[%d]: size increased to %llu MB (reserved %llu MB)\n",
|
||||
@@ -4039,7 +4053,9 @@ static inline void * sycl_ext_malloc_device(dpct::queue_ptr stream, size_t size)
|
||||
bool use_async = g_ggml_sycl_use_async_mem_op;
|
||||
#if defined(GGML_SYCL_GRAPH) && SYCL_EXT_ONEAPI_ASYNC_MEMORY_ALLOC
|
||||
if (use_async) {
|
||||
return syclex::async_malloc(*stream, sycl::usm::alloc::device, size);
|
||||
void * ptr = syclex::async_malloc(*stream, sycl::usm::alloc::device, size);
|
||||
ggml_sycl_memtrace_add(GGML_SYCL_MEM_ASYNC, ptr, size);
|
||||
return ptr;
|
||||
}
|
||||
#else
|
||||
// If async allocation extension is not available, use_async should always be false.
|
||||
@@ -4052,6 +4068,7 @@ static inline void sycl_ext_free(dpct::queue_ptr stream, void * ptr) {
|
||||
bool use_async = g_ggml_sycl_use_async_mem_op;
|
||||
#if defined(GGML_SYCL_GRAPH) && SYCL_EXT_ONEAPI_ASYNC_MEMORY_ALLOC
|
||||
if (use_async) {
|
||||
ggml_sycl_memtrace_del(ptr);
|
||||
syclex::async_free(*stream, ptr);
|
||||
return;
|
||||
}
|
||||
@@ -4841,6 +4858,78 @@ static bool ggml_sycl_mul_mat_glu_mmvq_fused(ggml_backend_sycl_context & ctx, gg
|
||||
/*stride_col_dst=*/(int) glu->ne[0], stream);
|
||||
}
|
||||
|
||||
// Batch the run of consecutive L2_NORM siblings starting at node_idx into one launch.
|
||||
// Returns the number of extra graph nodes consumed, or 0 if the run is shorter than two
|
||||
// (the caller then runs the norm through the per-tensor kernel).
|
||||
static int ggml_sycl_l2_norm_batch_fused(ggml_backend_sycl_context & ctx, ggml_cgraph * cgraph, int node_idx) {
|
||||
const ggml_tensor * node = cgraph->nodes[node_idx];
|
||||
if (ggml_sycl_info().device_count != 1 || node->type != GGML_TYPE_F32 ||
|
||||
node->src[0]->type != GGML_TYPE_F32 || node->src[0]->ne[0] >= 1024) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
ggml_tensor * batch[GGML_SYCL_L2_BATCH_MAX];
|
||||
int count = 0;
|
||||
int last = node_idx;
|
||||
float eps0;
|
||||
memcpy(&eps0, node->op_params, sizeof(float));
|
||||
|
||||
// Conservative aliasing test: the batched norms run concurrently in one kernel,
|
||||
// so none may read what another writes, and none may write where another writes.
|
||||
auto overlaps = [](const ggml_tensor * a, const ggml_tensor * b) {
|
||||
const char * ab = (const char *) a->data;
|
||||
const char * bb = (const char *) b->data;
|
||||
return ab < bb + ggml_nbytes(b) && bb < ab + ggml_nbytes(a);
|
||||
};
|
||||
|
||||
for (int j = node_idx; j < cgraph->n_nodes && count < GGML_SYCL_L2_BATCH_MAX; ++j) {
|
||||
ggml_tensor * nj = cgraph->nodes[j];
|
||||
if (ggml_is_empty(nj) || nj->op == GGML_OP_RESHAPE || nj->op == GGML_OP_TRANSPOSE ||
|
||||
nj->op == GGML_OP_VIEW || nj->op == GGML_OP_PERMUTE || nj->op == GGML_OP_NONE ||
|
||||
(nj->flags & GGML_TENSOR_FLAG_COMPUTE) == 0) {
|
||||
continue; // not a launch; cannot break a run of adjacent norms
|
||||
}
|
||||
if (nj->op != GGML_OP_L2_NORM || nj->type != GGML_TYPE_F32 ||
|
||||
nj->src[0]->type != GGML_TYPE_F32 || !ggml_are_same_shape(nj, node) ||
|
||||
!ggml_are_same_shape(nj->src[0], node->src[0])) {
|
||||
break; // any other launch ends the run
|
||||
}
|
||||
bool same_nb = true;
|
||||
for (int d = 0; d < GGML_MAX_DIMS; ++d) {
|
||||
if (nj->nb[d] != node->nb[d] || nj->src[0]->nb[d] != node->src[0]->nb[d]) {
|
||||
same_nb = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!same_nb) {
|
||||
break; // one nb[] stride set is shared by the whole batch
|
||||
}
|
||||
float epsj;
|
||||
memcpy(&epsj, nj->op_params, sizeof(float));
|
||||
if (epsj != eps0) {
|
||||
break; // eps mismatch ends the run
|
||||
}
|
||||
bool indep = true;
|
||||
for (int k = 0; k < count; ++k) {
|
||||
if (overlaps(nj->src[0], batch[k]) || overlaps(nj, batch[k])) {
|
||||
indep = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!indep) {
|
||||
break; // an overlapping tensor would race inside one launch
|
||||
}
|
||||
batch[count++] = nj;
|
||||
last = j;
|
||||
}
|
||||
if (count < 2) {
|
||||
return 0; // a lone norm falls through to the per-tensor kernel
|
||||
}
|
||||
ggml_sycl_l2_norm_batch(ctx, batch, count);
|
||||
return last - node_idx;
|
||||
}
|
||||
|
||||
|
||||
__dpct_inline__ static void k_copy_src1_to_contiguous(
|
||||
const char *__restrict__ src1_original, char *__restrict__ src1_contiguous,
|
||||
const mmid_row_mapping *__restrict__ row_mapping,
|
||||
@@ -5643,6 +5732,7 @@ void ggml_backend_sycl_get_device_memory(int device, size_t * free, size_t * tot
|
||||
if (!res) {
|
||||
GGML_ABORT("[%s] failed to get device memory size", __func__);
|
||||
}
|
||||
ggml_sycl_memtrace_report_device("device memory query", device, *free, *total);
|
||||
} catch (const sycl::exception & exc) {
|
||||
std::cerr << exc.what() << "Exception caught at file:" << __FILE__ << ", line:" << __LINE__ << std::endl;
|
||||
std::exit(1);
|
||||
@@ -5890,6 +5980,17 @@ static void ggml_backend_sycl_graph_compute_impl(ggml_backend_sycl_context * syc
|
||||
continue;
|
||||
}
|
||||
|
||||
// Batch consecutive independent same-shape F32 L2_NORM siblings (the GDN q/k
|
||||
// norms) into one launch; sources are strided views of the fused qkv buffer, so
|
||||
// the scan skips the interleaved view nodes instead of breaking on them.
|
||||
if (node->op == GGML_OP_L2_NORM) {
|
||||
const int l2_batch_skip = ggml_sycl_l2_norm_batch_fused(*sycl_ctx, cgraph, i);
|
||||
if (l2_batch_skip > 0) {
|
||||
i += l2_batch_skip;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (node->op == GGML_OP_MUL_MAT && ggml_sycl_mul_mat_glu_mmvq_fused(*sycl_ctx, cgraph, i)) {
|
||||
i += 2;
|
||||
continue;
|
||||
@@ -6082,6 +6183,7 @@ static void ggml_backend_sycl_device_get_memory(ggml_backend_dev_t dev, size_t *
|
||||
if (!res) {
|
||||
GGML_ABORT("[%s] failed to get device memory size", __func__);
|
||||
}
|
||||
ggml_sycl_memtrace_report_device("device memory query (dev)", ctx->device, *free, *total);
|
||||
}
|
||||
|
||||
static enum ggml_backend_dev_type ggml_backend_sycl_device_get_type(ggml_backend_dev_t dev) {
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
#include "memtrace.hpp"
|
||||
|
||||
#include "common.hpp"
|
||||
#include "ggml-impl.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <mutex>
|
||||
#include <unordered_map>
|
||||
|
||||
constexpr size_t MIB = 1024 * 1024;
|
||||
|
||||
static const char * mem_type_name(ggml_sycl_mem_type type) {
|
||||
switch (type) {
|
||||
case GGML_SYCL_MEM_BUFFER: return "buffer";
|
||||
case GGML_SYCL_MEM_POOL_LEG: return "pool_leg";
|
||||
case GGML_SYCL_MEM_POOL_VMM: return "pool_vmm";
|
||||
case GGML_SYCL_MEM_ASYNC: return "async";
|
||||
case GGML_SYCL_MEM_FATTN_KV: return "fattn_kv";
|
||||
case GGML_SYCL_MEM_DIRECT: return "direct";
|
||||
default: GGML_ABORT("[%s] The type value %d is not supported\n", __func__, (int) type);
|
||||
}
|
||||
}
|
||||
|
||||
struct mem_tracker {
|
||||
std::mutex mutex;
|
||||
std::unordered_map<const void *, std::pair<ggml_sycl_mem_type, size_t>> live_by_ptr;
|
||||
size_t live[GGML_SYCL_MEM_TYPE_COUNT] = {};
|
||||
size_t peak[GGML_SYCL_MEM_TYPE_COUNT] = {};
|
||||
size_t total_live = 0;
|
||||
size_t total_peak = 0;
|
||||
size_t last_logged_peak = 0;
|
||||
};
|
||||
|
||||
static mem_tracker & get_tracker() {
|
||||
static mem_tracker t;
|
||||
return t;
|
||||
}
|
||||
|
||||
static size_t step_bytes() {
|
||||
const int mib = g_ggml_sycl_memtrace_step > 0 ? g_ggml_sycl_memtrace_step : 64;
|
||||
return (size_t) mib * MIB;
|
||||
}
|
||||
|
||||
static void report_sites_locked() {
|
||||
mem_tracker & t = get_tracker();
|
||||
for (int i = 0; i < GGML_SYCL_MEM_TYPE_COUNT; i++) {
|
||||
if (t.peak[i] == 0) {
|
||||
continue;
|
||||
}
|
||||
GGML_LOG_INFO(GGML_SYCL_MEMTRACE_TAG " %-9s allocated %5zu MiB, peak %5zu MiB\n",
|
||||
mem_type_name((ggml_sycl_mem_type) i), t.live[i] / MIB, t.peak[i] / MIB);
|
||||
}
|
||||
}
|
||||
|
||||
static void report_locked(const char * tag) {
|
||||
mem_tracker & t = get_tracker();
|
||||
|
||||
const size_t allocated = t.total_live / MIB;
|
||||
const size_t buffers = t.live[GGML_SYCL_MEM_BUFFER] / MIB;
|
||||
|
||||
GGML_LOG_INFO(GGML_SYCL_MEMTRACE_TAG " %s: allocated %5zu MiB (buffers %5zu + scratch %5zu),"
|
||||
" peak %5zu MiB\n",
|
||||
tag, allocated, buffers, allocated - buffers, t.total_peak / MIB);
|
||||
report_sites_locked();
|
||||
}
|
||||
|
||||
static void log_event_locked(const char * op, ggml_sycl_mem_type type, const void * ptr, size_t bytes) {
|
||||
GGML_LOG_INFO(GGML_SYCL_MEMTRACE_TAG " allocated %5zu MiB %-5s %-9s %9.3f MiB ptr=%p\n",
|
||||
get_tracker().total_live / MIB, op, mem_type_name(type),
|
||||
(double) bytes / MIB, ptr);
|
||||
}
|
||||
|
||||
bool ggml_sycl_memtrace_enabled() {
|
||||
return g_ggml_sycl_memtrace > 0;
|
||||
}
|
||||
|
||||
void ggml_sycl_memtrace_add(ggml_sycl_mem_type type, const void * ptr, size_t bytes) {
|
||||
if (!ggml_sycl_memtrace_enabled()) {
|
||||
return;
|
||||
}
|
||||
GGML_ASSERT(ptr != nullptr);
|
||||
GGML_ASSERT(bytes != 0);
|
||||
|
||||
mem_tracker & t = get_tracker();
|
||||
std::lock_guard<std::mutex> lock(t.mutex);
|
||||
|
||||
auto it = t.live_by_ptr.find(ptr);
|
||||
if (it != t.live_by_ptr.end()) {
|
||||
t.live[it->second.first] -= it->second.second;
|
||||
t.total_live -= it->second.second;
|
||||
}
|
||||
|
||||
t.live_by_ptr[ptr] = { type, bytes };
|
||||
t.live[type] += bytes;
|
||||
t.total_live += bytes;
|
||||
|
||||
if (t.live[type] > t.peak[type]) {
|
||||
t.peak[type] = t.live[type];
|
||||
}
|
||||
if (t.total_live > t.total_peak) {
|
||||
t.total_peak = t.total_live;
|
||||
}
|
||||
|
||||
if (g_ggml_sycl_memtrace >= 2) {
|
||||
log_event_locked("alloc", type, ptr, bytes);
|
||||
}
|
||||
|
||||
static const size_t step = step_bytes();
|
||||
if (t.total_peak >= t.last_logged_peak + step) {
|
||||
t.last_logged_peak = t.total_peak;
|
||||
char tag[96];
|
||||
std::snprintf(tag, sizeof(tag), "peak grew (+%zu MiB from %s)", bytes / MIB,
|
||||
mem_type_name(type));
|
||||
report_locked(tag);
|
||||
}
|
||||
}
|
||||
|
||||
void ggml_sycl_memtrace_del(const void * ptr) {
|
||||
if (!ggml_sycl_memtrace_enabled() || ptr == nullptr) {
|
||||
return;
|
||||
}
|
||||
mem_tracker & t = get_tracker();
|
||||
std::lock_guard<std::mutex> lock(t.mutex);
|
||||
|
||||
auto it = t.live_by_ptr.find(ptr);
|
||||
if (it == t.live_by_ptr.end()) {
|
||||
return;
|
||||
}
|
||||
const ggml_sycl_mem_type type = it->second.first;
|
||||
const size_t bytes = it->second.second;
|
||||
t.live[type] -= bytes;
|
||||
t.total_live -= bytes;
|
||||
t.live_by_ptr.erase(it);
|
||||
|
||||
if (g_ggml_sycl_memtrace >= 2) {
|
||||
log_event_locked("free", type, ptr, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
void ggml_sycl_memtrace_fail(ggml_sycl_mem_type type, size_t bytes) {
|
||||
GGML_LOG_ERROR(GGML_SYCL_MEMTRACE_TAG " alloc FAILED: %9.3f MiB %s\n",
|
||||
(double) bytes / MIB, mem_type_name(type));
|
||||
if (!ggml_sycl_memtrace_enabled()) {
|
||||
return;
|
||||
}
|
||||
mem_tracker & t = get_tracker();
|
||||
std::lock_guard<std::mutex> lock(t.mutex);
|
||||
report_locked("at allocation failure");
|
||||
}
|
||||
|
||||
void ggml_sycl_memtrace_report(const char * tag) {
|
||||
if (!ggml_sycl_memtrace_enabled()) {
|
||||
return;
|
||||
}
|
||||
mem_tracker & t = get_tracker();
|
||||
std::lock_guard<std::mutex> lock(t.mutex);
|
||||
report_locked(tag);
|
||||
}
|
||||
|
||||
static bool device_memory_is_dedicated(int device) {
|
||||
if (device < 0 || device >= ggml_sycl_info().device_count) {
|
||||
return false;
|
||||
}
|
||||
const sycl_device_info & info = ggml_sycl_info().devices[device];
|
||||
return info.l0_device_type_valid && info.l0_discrete_gpu;
|
||||
}
|
||||
|
||||
void ggml_sycl_memtrace_report_device(const char * tag, int device, size_t dev_free, size_t dev_total) {
|
||||
if (!ggml_sycl_memtrace_enabled()) {
|
||||
return;
|
||||
}
|
||||
mem_tracker & t = get_tracker();
|
||||
std::lock_guard<std::mutex> lock(t.mutex);
|
||||
|
||||
const size_t in_use = dev_total > dev_free ? dev_total - dev_free : 0;
|
||||
const size_t total = dev_total / MIB;
|
||||
const size_t freed = dev_free / MIB;
|
||||
const size_t allocated = t.total_live / MIB;
|
||||
const size_t buffers = t.live[GGML_SYCL_MEM_BUFFER] / MIB;
|
||||
const size_t peak = t.total_peak / MIB;
|
||||
|
||||
if (in_use >= t.total_live && device_memory_is_dedicated(device) && total >= freed + allocated) {
|
||||
GGML_LOG_INFO(GGML_SYCL_MEMTRACE_TAG " %s: total %5zu MiB = free %5zu + allocated %5zu"
|
||||
" (buffers %5zu + scratch %5zu) + other %5zu, peak %5zu MiB\n",
|
||||
tag, total, freed, allocated, buffers, allocated - buffers,
|
||||
total - freed - allocated, peak);
|
||||
} else {
|
||||
GGML_LOG_INFO(GGML_SYCL_MEMTRACE_TAG " %s: total %5zu MiB, free %5zu, in use %5zu;"
|
||||
" allocated %5zu (buffers %5zu + scratch %5zu), peak %5zu MiB\n",
|
||||
tag, total, freed, in_use / MIB, allocated, buffers,
|
||||
allocated - buffers, peak);
|
||||
}
|
||||
report_sites_locked();
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef GGML_SYCL_MEMTRACE_HPP
|
||||
#define GGML_SYCL_MEMTRACE_HPP
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#define GGML_SYCL_MEMTRACE_TAG "[SYCL-MEMTRACE]"
|
||||
|
||||
enum ggml_sycl_mem_type {
|
||||
GGML_SYCL_MEM_BUFFER = 0,
|
||||
GGML_SYCL_MEM_POOL_LEG,
|
||||
GGML_SYCL_MEM_POOL_VMM,
|
||||
GGML_SYCL_MEM_ASYNC,
|
||||
GGML_SYCL_MEM_FATTN_KV,
|
||||
GGML_SYCL_MEM_DIRECT,
|
||||
|
||||
GGML_SYCL_MEM_TYPE_COUNT,
|
||||
};
|
||||
|
||||
bool ggml_sycl_memtrace_enabled();
|
||||
|
||||
void ggml_sycl_memtrace_add(ggml_sycl_mem_type type, const void * ptr, size_t bytes);
|
||||
void ggml_sycl_memtrace_del(const void * ptr);
|
||||
|
||||
void ggml_sycl_memtrace_report(const char * tag);
|
||||
void ggml_sycl_memtrace_report_device(const char * tag, int device, size_t dev_free, size_t dev_total);
|
||||
void ggml_sycl_memtrace_fail(ggml_sycl_mem_type type, size_t bytes);
|
||||
|
||||
#endif // GGML_SYCL_MEMTRACE_HPP
|
||||
@@ -543,6 +543,62 @@ static void l2_norm_f32_sycl(const float * x,
|
||||
}
|
||||
}
|
||||
|
||||
// Batched L2 norm: N independent same-shape F32 tensors in one launch; the tensor
|
||||
// index is folded into grid dim0 and each row's reduction is identical to the
|
||||
// single-tensor kernel, so the result is bit-exact.
|
||||
struct l2_batch_ptrs {
|
||||
const float * src[GGML_SYCL_L2_BATCH_MAX];
|
||||
float * dst[GGML_SYCL_L2_BATCH_MAX];
|
||||
};
|
||||
|
||||
// One stride set shared by the whole batch: the caller only groups tensors whose nb[]
|
||||
// all match, so per-tensor state stays two pointers.
|
||||
struct l2_batch_strides {
|
||||
int ne1, ne2;
|
||||
int64_t ss0, ss1, ss2, ss3;
|
||||
int64_t ds0, ds1, ds2, ds3;
|
||||
};
|
||||
|
||||
template <int warp_size>
|
||||
static void l2_norm_f32_batch(l2_batch_ptrs p, l2_batch_strides st, const int ncols, const float eps,
|
||||
const sycl::nd_item<3> & item_ct1) {
|
||||
const int t = item_ct1.get_group(0); // tensor index
|
||||
const int r = item_ct1.get_group(2); // flattened row over ne1*ne2*ne3
|
||||
const int tid = item_ct1.get_local_id(2);
|
||||
|
||||
const int i1 = r % st.ne1;
|
||||
const int i2 = (r / st.ne1) % st.ne2;
|
||||
const int i3 = r / (st.ne1 * st.ne2);
|
||||
|
||||
const float * x = p.src[t] + i3 * st.ss3 + i2 * st.ss2 + i1 * st.ss1;
|
||||
float * dst = p.dst[t] + i3 * st.ds3 + i2 * st.ds2 + i1 * st.ds1;
|
||||
|
||||
float tmp = 0.0f;
|
||||
for (int col = tid; col < ncols; col += warp_size) {
|
||||
const float xi = x[col * st.ss0];
|
||||
tmp += xi * xi;
|
||||
}
|
||||
tmp = block_reduce<block_reduce_method::SUM, warp_size>(tmp, (float *) nullptr, warp_size);
|
||||
const float scale = sycl::rsqrt(sycl::fmax(tmp, eps * eps));
|
||||
for (int col = tid; col < ncols; col += warp_size) {
|
||||
dst[col * st.ds0] = scale * x[col * st.ss0];
|
||||
}
|
||||
}
|
||||
|
||||
template <int warp_size>
|
||||
static void l2_norm_f32_batch_sycl(l2_batch_ptrs p, l2_batch_strides st, const int n_tensors,
|
||||
const int ncols, const int nrows_total, const float eps,
|
||||
queue_ptr stream) {
|
||||
const dpct::dim3 blocks_num(nrows_total, 1, n_tensors);
|
||||
const dpct::dim3 block_dims(warp_size, 1, 1);
|
||||
stream->submit([&](sycl::handler & cgh) {
|
||||
cgh.parallel_for(sycl::nd_range<3>(blocks_num * block_dims, block_dims),
|
||||
[=](sycl::nd_item<3> item_ct1) [[sycl::reqd_sub_group_size(warp_size)]] {
|
||||
l2_norm_f32_batch<warp_size>(p, st, ncols, eps, item_ct1);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
void ggml_sycl_op_norm(ggml_backend_sycl_context& ctx, ggml_tensor* dst) {
|
||||
const ggml_tensor * src0 = dst->src[0];
|
||||
|
||||
@@ -961,3 +1017,30 @@ void ggml_sycl_op_l2_norm(ggml_backend_sycl_context& ctx, ggml_tensor* dst) {
|
||||
l2_norm_f32_sycl<WARP_SIZE>(src0_d, dst_d, ne00, ne01, ne02, ne03,
|
||||
ss0, ss1, ss2, ss3, ds0, ds1, ds2, ds3, eps, stream, ctx.device);
|
||||
}
|
||||
|
||||
// nodes[0..count) are independent, same-shape, same-eps, same-nb L2_NORM ops validated
|
||||
// by the caller; requires ncols < 1024 (the warp reduction path).
|
||||
void ggml_sycl_l2_norm_batch(ggml_backend_sycl_context & ctx, ggml_tensor ** nodes, int count) {
|
||||
const ggml_tensor * s0 = nodes[0]->src[0];
|
||||
const int ncols = (int) s0->ne[0];
|
||||
const int nrows_total = (int) ggml_nrows(s0);
|
||||
float eps;
|
||||
memcpy(&eps, nodes[0]->op_params, sizeof(float));
|
||||
GGML_ASSERT(eps >= 0.0f);
|
||||
|
||||
l2_batch_ptrs p{};
|
||||
for (int t = 0; t < count; ++t) {
|
||||
p.src[t] = (const float *) nodes[t]->src[0]->data;
|
||||
p.dst[t] = (float *) nodes[t]->data;
|
||||
}
|
||||
|
||||
const ggml_tensor * d0 = nodes[0];
|
||||
const size_t ts = ggml_type_size(GGML_TYPE_F32);
|
||||
l2_batch_strides st{};
|
||||
st.ne1 = (int) s0->ne[1];
|
||||
st.ne2 = (int) s0->ne[2];
|
||||
st.ss0 = s0->nb[0] / ts; st.ss1 = s0->nb[1] / ts; st.ss2 = s0->nb[2] / ts; st.ss3 = s0->nb[3] / ts;
|
||||
st.ds0 = d0->nb[0] / ts; st.ds1 = d0->nb[1] / ts; st.ds2 = d0->nb[2] / ts; st.ds3 = d0->nb[3] / ts;
|
||||
|
||||
l2_norm_f32_batch_sycl<WARP_SIZE>(p, st, count, ncols, nrows_total, eps, ctx.stream());
|
||||
}
|
||||
|
||||
@@ -29,4 +29,7 @@ void ggml_sycl_op_group_norm(ggml_backend_sycl_context& ctx, ggml_tensor* dst);
|
||||
|
||||
void ggml_sycl_op_l2_norm(ggml_backend_sycl_context& ctx, ggml_tensor* dst);
|
||||
|
||||
#define GGML_SYCL_L2_BATCH_MAX 8
|
||||
void ggml_sycl_l2_norm_batch(ggml_backend_sycl_context & ctx, ggml_tensor ** nodes, int count);
|
||||
|
||||
#endif // GGML_SYCL_NORM_HPP
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -608,6 +608,21 @@ vec2 get_dm(uint ib, uint a_offset) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(DATA_A_TQ1_0)
|
||||
float tq1_0_val(uint ib, uint e, uint a_offset) {
|
||||
const uint bidx = tq1_0_byte_of(e);
|
||||
const uint qbyte = uint(bidx < 48u ? data_a[a_offset + ib].qs[bidx]
|
||||
: data_a[a_offset + ib].qh[bidx - 48u]);
|
||||
return float(tq1_0_trit(qbyte, tq1_0_digit_of(e))) - 1.0;
|
||||
}
|
||||
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
||||
return vec2(tq1_0_val(ib, iqs, a_offset), tq1_0_val(ib, iqs + 1u, a_offset));
|
||||
}
|
||||
vec2 get_dm(uint ib, uint a_offset) {
|
||||
return vec2(float(data_a[a_offset + ib].d), 0);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(DATA_A_TQ2_0)
|
||||
vec2 dequantize(uint ib, uint iqs, uint a_offset) {
|
||||
// elem e -> byte qs[(e/128)*32 + e%32], bits 2*((e%128)/32); w = q - 1 (d applied via get_dm)
|
||||
|
||||
@@ -247,6 +247,19 @@ f16vec4 dequantFuncQ8_0_v(const in decodeBufQ8_0 bl, const in uint blockCoords[2
|
||||
return f16vec4(vec4(qi) * vec4(float(d)));
|
||||
}
|
||||
|
||||
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufTQ1_0 {
|
||||
block_tq1_0 block;
|
||||
};
|
||||
|
||||
float16_t dequantFuncTQ1_0(const in decodeBufTQ1_0 bl, const in uint blockCoords[2], const in uint coordInBlock[2])
|
||||
{
|
||||
const uint e = coordInBlock[1];
|
||||
const uint bidx = tq1_0_byte_of(e);
|
||||
const uint qbyte = uint(bidx < 48u ? bl.block.qs[bidx] : bl.block.qh[bidx - 48u]);
|
||||
const uint xi = tq1_0_trit(qbyte, tq1_0_digit_of(e));
|
||||
return bl.block.d * (float16_t(int(xi)) - float16_t(1.0));
|
||||
}
|
||||
|
||||
layout(buffer_reference, std430, buffer_reference_align = 2) buffer decodeBufTQ2_0 {
|
||||
block_tq2_0 block;
|
||||
};
|
||||
@@ -1406,6 +1419,8 @@ f16vec4 dequantFuncNVFP4_v(const in decodeBufNVFP4 bl, const in uint blockCoords
|
||||
#elif defined(DATA_A_Q8_0)
|
||||
#define dequantFuncA dequantFuncQ8_0
|
||||
#define dequantFuncA_v dequantFuncQ8_0_v
|
||||
#elif defined(DATA_A_TQ1_0)
|
||||
#define dequantFuncA dequantFuncTQ1_0
|
||||
#elif defined(DATA_A_TQ2_0)
|
||||
#define dequantFuncA dequantFuncTQ2_0
|
||||
#define dequantFuncA_v dequantFuncTQ2_0_v
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#version 450
|
||||
|
||||
#include "dequant_head.glsl"
|
||||
|
||||
layout (local_size_x = 256, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
layout (binding = 0) readonly buffer A {block_tq1_0 data_a[];};
|
||||
layout (binding = 1) writeonly buffer D {D_TYPE data_b[];};
|
||||
|
||||
void main() {
|
||||
const uint i = gl_GlobalInvocationID.x * 4;
|
||||
|
||||
if (i >= p.nel) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint ib = i / QUANT_K_TQ1_0;
|
||||
const float d = float(data_a[ib].d);
|
||||
|
||||
[[unroll]] for (uint j = 0; j < 4 && (i + j) < p.nel; ++j) {
|
||||
const uint e = (i + j) % QUANT_K_TQ1_0;
|
||||
const uint bidx = tq1_0_byte_of(e);
|
||||
const uint qbyte = uint(bidx < 48u ? data_a[ib].qs[bidx]
|
||||
: data_a[ib].qh[bidx - 48u]);
|
||||
const uint xi = tq1_0_trit(qbyte, tq1_0_digit_of(e));
|
||||
data_b[i + j] = D_TYPE(d * (float(xi) - 1.0f));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
#version 450
|
||||
|
||||
#extension GL_EXT_control_flow_attributes : require
|
||||
#extension GL_KHR_shader_subgroup_basic : require
|
||||
#extension GL_KHR_shader_subgroup_shuffle : require
|
||||
|
||||
// 16 lanes per token, indexed idst + hc*isrc: idst in bits 0..1, isrc in bits 2..3,
|
||||
// so subgroupShuffleXor by 1|2 reduces a row and by 4|8 a column.
|
||||
|
||||
layout(constant_id = 0) const uint SUBGROUP_SIZE = 32;
|
||||
|
||||
layout(local_size_x_id = 0, local_size_y = 4, local_size_z = 1) in;
|
||||
|
||||
layout(push_constant) uniform parameter
|
||||
{
|
||||
uint n_tokens;
|
||||
|
||||
uint nbm0; uint nbm1; // mixes
|
||||
uint nbs0; // scale
|
||||
uint nbb0; // base
|
||||
uint nbd0; uint nbd1; uint nbd2; // dst
|
||||
|
||||
uint m_offset;
|
||||
uint s_offset;
|
||||
uint b_offset;
|
||||
uint d_offset;
|
||||
|
||||
float eps;
|
||||
uint n_iter;
|
||||
};
|
||||
|
||||
layout(binding = 0, std430) readonly buffer M { float data_m[]; };
|
||||
layout(binding = 1, std430) readonly buffer S { float data_s[]; };
|
||||
layout(binding = 2, std430) readonly buffer B { float data_b[]; };
|
||||
layout(binding = 3, std430) writeonly buffer D { float data_d[]; };
|
||||
|
||||
const uint hc = 4;
|
||||
const uint comb_offset = 2 * hc;
|
||||
|
||||
const uint TOKENS_PER_SUBGROUP = SUBGROUP_SIZE / 16;
|
||||
|
||||
void main() {
|
||||
const uint lane = gl_SubgroupInvocationID;
|
||||
const uint blk = lane >> 4; // which 16-lane block, i.e. which token
|
||||
const uint idx = lane & 15; // idst + hc*isrc
|
||||
|
||||
const uint sg = gl_WorkGroupID.x * gl_WorkGroupSize.y + gl_SubgroupID;
|
||||
const uint it = sg * TOKENS_PER_SUBGROUP + blk;
|
||||
|
||||
// no early return, the shuffles need every lane; out-of-range blocks compute a discarded value
|
||||
const bool in_range = it < n_tokens;
|
||||
|
||||
const float scale_comb = data_s[s_offset + 2 * nbs0];
|
||||
|
||||
float v = 0.0f;
|
||||
if (in_range) {
|
||||
v = data_m[m_offset + (comb_offset + idx) * nbm0 + it * nbm1] * scale_comb
|
||||
+ data_b[b_offset + (comb_offset + idx) * nbb0];
|
||||
}
|
||||
|
||||
// Softmax across destinations: the four lanes sharing an isrc.
|
||||
float vmax = max(v, subgroupShuffleXor(v, 1));
|
||||
vmax = max(vmax, subgroupShuffleXor(vmax, 2));
|
||||
v = exp(v - vmax);
|
||||
|
||||
float sum = v + subgroupShuffleXor(v, 1);
|
||||
sum += subgroupShuffleXor(sum, 2);
|
||||
v = v / sum + eps;
|
||||
|
||||
// Normalize columns: equal destination indices are four lanes apart.
|
||||
sum = v + subgroupShuffleXor(v, 4);
|
||||
sum += subgroupShuffleXor(sum, 8);
|
||||
v /= sum + eps;
|
||||
|
||||
for (uint i = 1; i < n_iter; ++i) {
|
||||
sum = v + subgroupShuffleXor(v, 1);
|
||||
sum += subgroupShuffleXor(sum, 2);
|
||||
v /= sum + eps;
|
||||
|
||||
sum = v + subgroupShuffleXor(v, 4);
|
||||
sum += subgroupShuffleXor(sum, 8);
|
||||
v /= sum + eps;
|
||||
}
|
||||
|
||||
if (in_range) {
|
||||
const uint idst = idx & 3;
|
||||
const uint isrc = idx >> 2;
|
||||
data_d[d_offset + idst * nbd0 + isrc * nbd1 + it * nbd2] = v;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
#version 450
|
||||
|
||||
#extension GL_EXT_control_flow_attributes : require
|
||||
|
||||
// Fan one stream back out to hc streams and add the combination-weighted
|
||||
// residuals:
|
||||
//
|
||||
// dst[i0, idst, it] = x[i0, it]*post[idst, it]
|
||||
// + sum_isrc residual[i0, isrc, it]*comb[idst, isrc, it]
|
||||
|
||||
layout(constant_id = 0) const uint BLOCK_SIZE = 256;
|
||||
|
||||
layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
layout(push_constant) uniform parameter
|
||||
{
|
||||
uint n_embd;
|
||||
uint n_tokens;
|
||||
|
||||
uint nbx0; uint nbx1; // x
|
||||
uint nbr0; uint nbr1; uint nbr2; // residual
|
||||
uint nbp0; uint nbp1; // post
|
||||
uint nbc0; uint nbc1; uint nbc2; // comb
|
||||
uint nbd0; uint nbd1; uint nbd2; // dst
|
||||
|
||||
uint x_offset;
|
||||
uint r_offset;
|
||||
uint p_offset;
|
||||
uint c_offset;
|
||||
uint d_offset;
|
||||
};
|
||||
|
||||
layout(binding = 0, std430) readonly buffer X { float data_x[]; };
|
||||
layout(binding = 1, std430) readonly buffer R { float data_r[]; };
|
||||
layout(binding = 2, std430) readonly buffer P { float data_p[]; };
|
||||
layout(binding = 3, std430) readonly buffer C { float data_c[]; };
|
||||
layout(binding = 4, std430) writeonly buffer D { float data_d[]; };
|
||||
|
||||
const uint hc = 4;
|
||||
|
||||
shared float post_s[hc];
|
||||
shared float comb_s[hc * hc];
|
||||
|
||||
void main() {
|
||||
const uint tid = gl_LocalInvocationID.x;
|
||||
const uint it = gl_WorkGroupID.y;
|
||||
|
||||
if (tid < hc) {
|
||||
post_s[tid] = data_p[p_offset + tid * nbp0 + it * nbp1];
|
||||
}
|
||||
if (tid < hc * hc) {
|
||||
const uint idst = tid & 3;
|
||||
const uint isrc = tid >> 2;
|
||||
comb_s[tid] = data_c[c_offset + idst * nbc0 + isrc * nbc1 + it * nbc2];
|
||||
}
|
||||
barrier();
|
||||
|
||||
// After the barrier, so every invocation reaches it.
|
||||
const uint i0 = gl_WorkGroupID.x * BLOCK_SIZE + tid;
|
||||
if (i0 >= n_embd) {
|
||||
return;
|
||||
}
|
||||
|
||||
const float xv = data_x[x_offset + i0 * nbx0 + it * nbx1];
|
||||
|
||||
const uint rb = r_offset + i0 * nbr0 + it * nbr2;
|
||||
|
||||
float r[hc];
|
||||
[[unroll]]
|
||||
for (uint isrc = 0; isrc < hc; ++isrc) {
|
||||
r[isrc] = data_r[rb + isrc * nbr1];
|
||||
}
|
||||
|
||||
[[unroll]]
|
||||
for (uint idst = 0; idst < hc; ++idst) {
|
||||
float result = xv * post_s[idst];
|
||||
[[unroll]]
|
||||
for (uint isrc = 0; isrc < hc; ++isrc) {
|
||||
result = fma(r[isrc], comb_s[idst + hc * isrc], result);
|
||||
}
|
||||
data_d[d_offset + i0 * nbd0 + idst * nbd1 + it * nbd2] = result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
#version 450
|
||||
|
||||
#extension GL_EXT_control_flow_attributes : require
|
||||
|
||||
// Collapse the hc residual streams of a token into one, weighted per stream:
|
||||
//
|
||||
// dst[i0, it] = sum_ih x[i0, ih, it] * weights[ih, it]
|
||||
|
||||
layout(constant_id = 0) const uint BLOCK_SIZE = 256;
|
||||
|
||||
layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
layout(push_constant) uniform parameter
|
||||
{
|
||||
uint n_embd;
|
||||
uint n_tokens;
|
||||
|
||||
uint nbx0; uint nbx1; uint nbx2; // x
|
||||
uint nbw0; uint nbw1; // weights
|
||||
uint nbd0; uint nbd1; // dst
|
||||
|
||||
uint x_offset;
|
||||
uint w_offset;
|
||||
uint d_offset;
|
||||
};
|
||||
|
||||
layout(binding = 0, std430) readonly buffer X { float data_x[]; };
|
||||
layout(binding = 1, std430) readonly buffer W { float data_w[]; };
|
||||
layout(binding = 2, std430) writeonly buffer D { float data_d[]; };
|
||||
|
||||
const uint hc = 4;
|
||||
|
||||
shared float w[hc];
|
||||
|
||||
void main() {
|
||||
const uint tid = gl_LocalInvocationID.x;
|
||||
const uint it = gl_WorkGroupID.y;
|
||||
|
||||
if (tid < hc) {
|
||||
w[tid] = data_w[w_offset + tid * nbw0 + it * nbw1];
|
||||
}
|
||||
barrier();
|
||||
|
||||
// After the barrier, so every invocation reaches it.
|
||||
const uint i0 = gl_WorkGroupID.x * BLOCK_SIZE + tid;
|
||||
if (i0 >= n_embd) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint xb = x_offset + i0 * nbx0 + it * nbx2;
|
||||
|
||||
float result = 0.0f;
|
||||
[[unroll]]
|
||||
for (uint ih = 0; ih < hc; ++ih) {
|
||||
result = fma(data_x[xb + ih * nbx1], w[ih], result);
|
||||
}
|
||||
|
||||
data_d[d_offset + i0 * nbd0 + it * nbd1] = result;
|
||||
}
|
||||
@@ -27,10 +27,10 @@ void main() {
|
||||
const uint i11 = gid_z / p.ne12;
|
||||
const uint i12 = gid_z % p.ne12;
|
||||
|
||||
const uint i01 = data_b[i10*p.nb10 + i11*p.nb11 + i12*p.nb12];
|
||||
const uint i01 = data_b[get_boffset() + i10*p.nb10 + i11*p.nb11 + i12*p.nb12];
|
||||
|
||||
const uint a_offset = i01*p.nb01 + i11*p.nb02 + i12*p.nb03;
|
||||
const uint d_offset = i10*p.nb21 + i11*p.nb22 + i12*p.nb23;
|
||||
const uint a_offset = get_aoffset() + i01*p.nb01 + i11*p.nb02 + i12*p.nb03;
|
||||
const uint d_offset = get_doffset() + i10*p.nb21 + i11*p.nb22 + i12*p.nb23;
|
||||
|
||||
const uint ib = a_offset + i00/QUANT_K; // block index
|
||||
const uint iqs = (i00%QUANT_K)/QUANT_R; // quant index
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
#version 450
|
||||
#extension GL_EXT_shader_explicit_arithmetic_types : require
|
||||
|
||||
#include "mul_mat_vec_base.glsl"
|
||||
|
||||
layout(local_size_x_id = 0, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
FLOAT_TYPE temp[NUM_COLS][NUM_ROWS];
|
||||
|
||||
// Walks the packed bytes directly (byte m, digit t) rather than via
|
||||
// tq1_0_byte_of()/tq1_0_digit_of(): one byte per thread, expanded in place.
|
||||
void compute_outputs(const uint32_t first_row, const uint32_t num_rows) {
|
||||
uint a_offset, b_offset, d_offset;
|
||||
get_offsets(a_offset, b_offset, d_offset);
|
||||
|
||||
const uint num_blocks_per_row = p.ncols / QUANT_K;
|
||||
const uint tid = gl_LocalInvocationID.x;
|
||||
|
||||
[[unroll]] for (uint j = 0; j < NUM_COLS; ++j) {
|
||||
[[unroll]] for (uint i = 0; i < NUM_ROWS; ++i) {
|
||||
temp[j][i] = FLOAT_TYPE(0);
|
||||
}
|
||||
}
|
||||
|
||||
for (uint nrow = 0; nrow < num_rows; ++nrow) {
|
||||
const uint ib0 = a_offset + (first_row + nrow) * num_blocks_per_row;
|
||||
for (uint jcol = 0; jcol < NUM_COLS; ++jcol) {
|
||||
const uint b_base = (jcol * p.batch_stride_b);
|
||||
for (uint i = tid/8; i < num_blocks_per_row; i += gl_WorkGroupSize.x/8) {
|
||||
const FLOAT_TYPE d = float(data_a[ib0 + i].d);
|
||||
|
||||
// First qs chunk: 32 bytes (5*32 elements)
|
||||
[[unroll]] for (uint m = tid%8; m < 32; m += 8) {
|
||||
const uint q_byte = uint(data_a[ib0 + i].qs[m]);
|
||||
[[unroll]] for (uint t = 0; t < 5; ++t) {
|
||||
const uint xi = tq1_0_trit(q_byte, t);
|
||||
const FLOAT_TYPE dequant_val = FLOAT_TYPE(d * (float(xi) - 1.0f));
|
||||
const uint elem = t * 32u + m;
|
||||
const uint b_idx = i * QUANT_K + elem;
|
||||
temp[jcol][nrow] += dequant_val * FLOAT_TYPE(data_b[b_base + b_offset + b_idx]);
|
||||
}
|
||||
}
|
||||
|
||||
// Second qs chunk: 16 bytes (5*16 elements)
|
||||
[[unroll]] for (uint m = tid%8; m < 16; m += 8) {
|
||||
const uint q_byte = uint(data_a[ib0 + i].qs[32u + m]);
|
||||
[[unroll]] for (uint t = 0; t < 5; ++t) {
|
||||
const uint xi = tq1_0_trit(q_byte, t);
|
||||
const FLOAT_TYPE dequant_val = FLOAT_TYPE(d * (float(xi) - 1.0f));
|
||||
const uint elem = 160u + t * 16u + m;
|
||||
const uint b_idx = i * QUANT_K + elem;
|
||||
temp[jcol][nrow] += dequant_val * FLOAT_TYPE(data_b[b_base + b_offset + b_idx]);
|
||||
}
|
||||
}
|
||||
|
||||
// qh bytes: 4 bytes (4*4 elements)
|
||||
[[unroll]] for (uint j = tid%8; j < 4; j += 8) {
|
||||
const uint qh_byte = uint(data_a[ib0 + i].qh[j]);
|
||||
[[unroll]] for (uint t = 0; t < 4; ++t) {
|
||||
const uint xi = tq1_0_trit(qh_byte, t);
|
||||
const FLOAT_TYPE dequant_val = FLOAT_TYPE(d * (float(xi) - 1.0f));
|
||||
const uint elem = 240u + t * 4u + j;
|
||||
const uint b_idx = i * QUANT_K + elem;
|
||||
temp[jcol][nrow] += dequant_val * FLOAT_TYPE(data_b[b_base + b_offset + b_idx]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
reduce_result(temp, d_offset, first_row, num_rows, tid);
|
||||
}
|
||||
|
||||
void main() {
|
||||
const uint first_row = NUM_ROWS * (gl_WorkGroupID.x + gl_NumWorkGroups.x * gl_WorkGroupID.z);
|
||||
|
||||
if (first_row + NUM_ROWS <= p.stride_d) {
|
||||
compute_outputs(first_row, NUM_ROWS);
|
||||
} else {
|
||||
if (first_row >= p.stride_d) {
|
||||
return;
|
||||
}
|
||||
compute_outputs(first_row, p.stride_d - first_row);
|
||||
}
|
||||
}
|
||||
@@ -197,6 +197,24 @@ void load_a_to_shmem(const uint pos_a, const uint row, const uint col, const uin
|
||||
const uint k_pair = row * LOAD_VEC_A / 2;
|
||||
store_a(col, k_pair, FLOAT_TYPEV2(v.xy));
|
||||
store_a(col, k_pair + 1, FLOAT_TYPEV2(v.zw));
|
||||
#elif defined(DATA_A_TQ1_0)
|
||||
const uint idx = pos_a + col * p.stride_a / LOAD_VEC_A + row;
|
||||
|
||||
const uint ib = idx / 128; // 2 values per idx
|
||||
const uint iqs = (idx % 128) * 2; // element 0,2,4..254
|
||||
|
||||
const float d = float(data_a[ib].d);
|
||||
vec2 v;
|
||||
for (uint kk = 0u; kk < 2u; ++kk) {
|
||||
const uint e = iqs + kk;
|
||||
const uint bidx = tq1_0_byte_of(e);
|
||||
const uint qbyte = uint(bidx < 48u ? data_a[ib].qs[bidx]
|
||||
: data_a[ib].qh[bidx - 48u]);
|
||||
v[kk] = d * (float(tq1_0_trit(qbyte, tq1_0_digit_of(e))) - 1.0);
|
||||
}
|
||||
|
||||
const uint k_pair = row * LOAD_VEC_A / 2;
|
||||
store_a(col, k_pair, FLOAT_TYPEV2(v.xy));
|
||||
#elif defined(DATA_A_TQ2_0)
|
||||
const uint idx = pos_a + col * p.stride_a / LOAD_VEC_A + row;
|
||||
|
||||
|
||||
@@ -27,12 +27,24 @@ layout (binding = 6) readonly buffer R_I {uvec2 rope_data_i[];}; // indices for
|
||||
#define GGML_ROPE_TYPE_MROPE 8
|
||||
#define GGML_ROPE_TYPE_VISION 24
|
||||
|
||||
#elif RMS_NORM_ADD_FUSION
|
||||
|
||||
layout (binding = 3) readonly buffer C {float data_c[];};
|
||||
layout (binding = 4) readonly buffer E {float data_e[];};
|
||||
|
||||
#elif RMS_NORM_SET_ROWS_FUSION
|
||||
|
||||
layout (binding = 3) readonly buffer I {uvec2 data_i[];};
|
||||
|
||||
#endif
|
||||
|
||||
#extension GL_EXT_control_flow_attributes : enable
|
||||
#define BLOCK_SIZE 512
|
||||
|
||||
layout (constant_id = 1) const bool do_multiply = false;
|
||||
#if RMS_NORM_ADD_FUSION
|
||||
layout (constant_id = 2) const bool do_post_multiply = false;
|
||||
#endif
|
||||
|
||||
layout(local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
@@ -57,6 +69,8 @@ void rms_norm(uint num_iters) {
|
||||
#if RMS_NORM_ROPE_FUSION
|
||||
// Per-row offset in shared memory
|
||||
uint32_t d_offset = 0;
|
||||
#elif RMS_NORM_SET_ROWS_FUSION
|
||||
uint32_t d_offset = data_i[channel].x*p.nb21 + row*ncols + get_doffset();
|
||||
#else
|
||||
uint32_t d_offset = ((samp*nchannels + channel)*nrows + row)*ncols + get_doffset();
|
||||
#endif
|
||||
@@ -91,14 +105,28 @@ void rms_norm(uint num_iters) {
|
||||
if (col >= ncols) {
|
||||
continue;
|
||||
}
|
||||
data_d[d_offset + col] = D_TYPE(scale * FLOAT_TYPE(data_a[a_offset + col]) * FLOAT_TYPE(data_b[b_offset + fastmod(col, p.ne10)]));
|
||||
FLOAT_TYPE value = scale * FLOAT_TYPE(data_a[a_offset + col]) * FLOAT_TYPE(data_b[b_offset + fastmod(col, p.ne10)]);
|
||||
#if RMS_NORM_ADD_FUSION
|
||||
value += FLOAT_TYPE(data_c[d_offset + col]);
|
||||
if (do_post_multiply) {
|
||||
value *= FLOAT_TYPE(data_e[0]);
|
||||
}
|
||||
#endif
|
||||
data_d[d_offset + col] = D_TYPE(value);
|
||||
}
|
||||
} else {
|
||||
[[unroll]] for (uint col = tid, idx = 0; idx < num_iters; col += BLOCK_SIZE, ++idx) {
|
||||
if (col >= ncols) {
|
||||
continue;
|
||||
}
|
||||
data_d[d_offset + col] = D_TYPE(scale * FLOAT_TYPE(data_a[a_offset + col]) * FLOAT_TYPE(data_b[b_offset + col]));
|
||||
FLOAT_TYPE value = scale * FLOAT_TYPE(data_a[a_offset + col]) * FLOAT_TYPE(data_b[b_offset + col]);
|
||||
#if RMS_NORM_ADD_FUSION
|
||||
value += FLOAT_TYPE(data_c[d_offset + col]);
|
||||
if (do_post_multiply) {
|
||||
value *= FLOAT_TYPE(data_e[0]);
|
||||
}
|
||||
#endif
|
||||
data_d[d_offset + col] = D_TYPE(value);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -10,11 +10,19 @@
|
||||
#define BLOCK_SIZE 128
|
||||
|
||||
layout (constant_id = 1) const bool do_multiply = false;
|
||||
#if RMS_NORM_ADD_FUSION
|
||||
layout (constant_id = 2) const bool do_post_multiply = false;
|
||||
#endif
|
||||
|
||||
layout(local_size_x = BLOCK_SIZE, local_size_y = 1, local_size_z = 1) in;
|
||||
|
||||
layout (binding = 3, std430) readonly buffer PartialsBuf {float partial_sums[];};
|
||||
|
||||
#if RMS_NORM_ADD_FUSION
|
||||
layout (binding = 4) readonly buffer C {float data_c[];};
|
||||
layout (binding = 5) readonly buffer E {float data_e[];};
|
||||
#endif
|
||||
|
||||
shared FLOAT_TYPE sumsh[BLOCK_SIZE];
|
||||
|
||||
void main() {
|
||||
@@ -55,9 +63,23 @@ void main() {
|
||||
|
||||
if (do_multiply) {
|
||||
if (ncols > p.ne10) {
|
||||
data_d[d_offset + col] = D_TYPE(scale * FLOAT_TYPE(data_a[a_offset + col]) * FLOAT_TYPE(data_b[b_offset + fastmod(col, p.ne10)]));
|
||||
FLOAT_TYPE value = scale * FLOAT_TYPE(data_a[a_offset + col]) * FLOAT_TYPE(data_b[b_offset + fastmod(col, p.ne10)]);
|
||||
#if RMS_NORM_ADD_FUSION
|
||||
value += FLOAT_TYPE(data_c[d_offset + col]);
|
||||
if (do_post_multiply) {
|
||||
value *= FLOAT_TYPE(data_e[0]);
|
||||
}
|
||||
#endif
|
||||
data_d[d_offset + col] = D_TYPE(value);
|
||||
} else {
|
||||
data_d[d_offset + col] = D_TYPE(scale * FLOAT_TYPE(data_a[a_offset + col]) * FLOAT_TYPE(data_b[b_offset + col]));
|
||||
FLOAT_TYPE value = scale * FLOAT_TYPE(data_a[a_offset + col]) * FLOAT_TYPE(data_b[b_offset + col]);
|
||||
#if RMS_NORM_ADD_FUSION
|
||||
value += FLOAT_TYPE(data_c[d_offset + col]);
|
||||
if (do_post_multiply) {
|
||||
value *= FLOAT_TYPE(data_e[0]);
|
||||
}
|
||||
#endif
|
||||
data_d[d_offset + col] = D_TYPE(value);
|
||||
}
|
||||
} else {
|
||||
data_d[d_offset + col] = D_TYPE(scale * FLOAT_TYPE(data_a[a_offset + col]));
|
||||
|
||||
@@ -303,6 +303,41 @@ struct block_q2_K_packed32
|
||||
#define DATA_A_QUANT_K
|
||||
#endif
|
||||
|
||||
#define QUANT_K_TQ1_0 256
|
||||
|
||||
// TQ1_0: base-3 packed trits, 5 per byte in `qs` (48B) and 4 in `qh` (4B).
|
||||
struct block_tq1_0
|
||||
{
|
||||
uint8_t qs[(QUANT_K_TQ1_0 - 4 * QUANT_K_TQ1_0 / 64) / 5];
|
||||
uint8_t qh[QUANT_K_TQ1_0 / 64];
|
||||
float16_t d;
|
||||
};
|
||||
|
||||
// Element e in [0,255] -> its packed byte (0..47 qs, 48..51 qh) and digit.
|
||||
uint tq1_0_byte_of(uint e) {
|
||||
return e < 160u ? (e % 32u)
|
||||
: e < 240u ? 32u + ((e - 160u) % 16u)
|
||||
: 48u + ((e - 240u) % 4u);
|
||||
}
|
||||
uint tq1_0_digit_of(uint e) {
|
||||
return e < 160u ? (e / 32u)
|
||||
: e < 240u ? ((e - 160u) / 16u)
|
||||
: ((e - 240u) / 4u);
|
||||
}
|
||||
// The 8-bit truncation below is part of the format, not an optimisation:
|
||||
// the C reference does `uint8_t q = qs[..] * pow3[n]`.
|
||||
uint tq1_0_trit(uint qbyte, uint t) {
|
||||
const uint POW3_PACKED = (1u << 28) | (3u << 21) | (9u << 14) | (27u << 7) | 81u;
|
||||
return ((((qbyte * ((POW3_PACKED >> (7u * (4u - t))) & 0x7Fu)) & 255u) * 3u) >> 8);
|
||||
}
|
||||
|
||||
#if defined(DATA_A_TQ1_0)
|
||||
#define QUANT_K QUANT_K_TQ1_0
|
||||
#define QUANT_R 1
|
||||
#define A_TYPE block_tq1_0
|
||||
#define DATA_A_QUANT_K
|
||||
#endif
|
||||
|
||||
#define QUANT_K_TQ2_0 256
|
||||
|
||||
// ternary (BitNet): 2-bit codes, w = (q - 1) * d; qs layout matches q2_K's
|
||||
|
||||
@@ -72,6 +72,7 @@ const std::vector<std::string> type_names = {
|
||||
"iq4_nl",
|
||||
"mxfp4",
|
||||
"nvfp4",
|
||||
"tq1_0",
|
||||
"tq2_0",
|
||||
"bf16",
|
||||
};
|
||||
@@ -734,7 +735,7 @@ void process_shaders() {
|
||||
for (const auto& tname : type_names) {
|
||||
// mul mat vec
|
||||
std::string data_a_key = "DATA_A_" + to_uppercase(tname);
|
||||
std::string shader = (string_ends_with(tname, "_k") || string_starts_with(tname, "iq1_") || string_starts_with(tname, "iq2_") || string_starts_with(tname, "iq3_") || tname == "tq2_0") ? "mul_mat_vec_" + tname + ".comp" : "mul_mat_vec.comp";
|
||||
std::string shader = (string_ends_with(tname, "_k") || string_starts_with(tname, "iq1_") || string_starts_with(tname, "iq2_") || string_starts_with(tname, "iq3_") || tname == "tq2_0" || tname == "tq1_0") ? "mul_mat_vec_" + tname + ".comp" : "mul_mat_vec.comp";
|
||||
|
||||
string_to_spv("mul_mat_vec_" + tname + "_f32_f32", shader, merge_maps(base_dict, {{data_a_key, "1"}, {"B_TYPE", "float"}, {"B_TYPEV2", "vec2"}, {"B_TYPEV4", "vec4"}, {"D_TYPE", "float"}}));
|
||||
string_to_spv("mul_mat_vec_" + tname + "_f16_f32", shader, merge_maps(base_dict, {{data_a_key, "1"}, {"B_TYPE", "float16_t"}, {"B_TYPEV2", "f16vec2"}, {"B_TYPEV4", "f16vec4"}, {"D_TYPE", "float"}}));
|
||||
@@ -805,6 +806,10 @@ void process_shaders() {
|
||||
string_to_spv("norm_f32", "norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}}));
|
||||
string_to_spv("group_norm_f32", "group_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}}));
|
||||
string_to_spv("rms_norm_f32", "rms_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}));
|
||||
string_to_spv("rms_norm_mul_add_f32", "rms_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}, {"RMS_NORM_ADD_FUSION", "1"}}));
|
||||
string_to_spv("rms_norm_mul_add_partials_f32", "rms_norm_partials.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}, {"RMS_NORM_ADD_FUSION", "1"}}));
|
||||
string_to_spv("rms_norm_set_rows_f32_f32", "rms_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}, {"RMS_NORM_SET_ROWS_FUSION", "1"}}));
|
||||
string_to_spv("rms_norm_set_rows_f32_f16", "rms_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float16_t"}, {"RMS_NORM_SET_ROWS_FUSION", "1"}}));
|
||||
string_to_spv("rms_norm_partials_f32", "rms_norm_partials.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}}));
|
||||
string_to_spv("rms_norm_mul_rope_f32_f32", "rms_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}, {"ROPE_D_TYPE", "float"}, {"RMS_NORM_ROPE_FUSION", "1"}}));
|
||||
string_to_spv("rms_norm_mul_rope_f32_f16", "rms_norm.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"B_TYPE", "float"}, {"D_TYPE", "float"}, {"ROPE_D_TYPE", "float16_t"}, {"RMS_NORM_ROPE_FUSION", "1"}}));
|
||||
@@ -1037,6 +1042,9 @@ void process_shaders() {
|
||||
string_to_spv("fwht_f32", "fwht.comp", {});
|
||||
string_to_spv("fwht_shmem_f32", "fwht.comp", {{"FWHT_SHMEM", "1"}});
|
||||
string_to_spv("count_equal_i32", "count_equal.comp", merge_maps(base_dict, {{"A_TYPE", "int"}, {"B_TYPE", "int"}, {"D_TYPE", "int"}}));
|
||||
string_to_spv("dsv4_hc_comb_f32", "dsv4_hc_comb.comp", {});
|
||||
string_to_spv("dsv4_hc_pre_f32", "dsv4_hc_pre.comp", {});
|
||||
string_to_spv("dsv4_hc_post_f32", "dsv4_hc_post.comp", {});
|
||||
string_to_spv("cumsum_f32", "cumsum.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}}));
|
||||
string_to_spv("cumsum_multipass1_f32", "cumsum_multipass1.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}}));
|
||||
string_to_spv("cumsum_multipass2_f32", "cumsum_multipass2.comp", merge_maps(base_dict, {{"A_TYPE", "float"}, {"D_TYPE", "float"}}));
|
||||
|
||||
@@ -4324,12 +4324,22 @@ static bool ggml_backend_webgpu_device_supports_op(ggml_backend_dev_t dev, const
|
||||
src0->type == GGML_TYPE_F32 && (src1->type == GGML_TYPE_I64 || src1->type == GGML_TYPE_I32));
|
||||
break;
|
||||
case GGML_OP_GET_ROWS:
|
||||
if (src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16 || ggml_webgpu_supported_qtype(src0->type)) {
|
||||
supports_op = (op->type == GGML_TYPE_F32);
|
||||
} else if (src0->type == GGML_TYPE_I32) {
|
||||
supports_op = op->type == GGML_TYPE_I32;
|
||||
{
|
||||
const size_t storage_alignment =
|
||||
ctx->webgpu_global_ctx->capabilities.limits.minStorageBufferOffsetAlignment;
|
||||
const size_t src_address_unit =
|
||||
src0->type == GGML_TYPE_F32 && op->ne[0] % 4 == 0 ? 4 * sizeof(float) : ggml_type_size(src0->type);
|
||||
if (ggml_webgpu_tensor_misalignment(src0, storage_alignment) % src_address_unit != 0) {
|
||||
break;
|
||||
}
|
||||
if (src0->type == GGML_TYPE_F32 || src0->type == GGML_TYPE_F16 ||
|
||||
ggml_webgpu_supported_qtype(src0->type)) {
|
||||
supports_op = (op->type == GGML_TYPE_F32);
|
||||
} else if (src0->type == GGML_TYPE_I32) {
|
||||
supports_op = op->type == GGML_TYPE_I32;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GGML_OP_MUL_MAT:
|
||||
{
|
||||
switch (src1->type) {
|
||||
|
||||
@@ -215,6 +215,7 @@ class Keys:
|
||||
KV_LORA_RANK_SWA = "{arch}.attention.kv_lora_rank_swa"
|
||||
SHARED_KV_LAYERS = "{arch}.attention.shared_kv_layers"
|
||||
SLIDING_WINDOW_PATTERN = "{arch}.attention.sliding_window_pattern"
|
||||
RECURRENT_LAYERS = "{arch}.attention.recurrent_layers"
|
||||
TEMPERATURE_SCALE = "{arch}.attention.temperature_scale"
|
||||
ROPE_PATTERN = "{arch}.attention.rope_pattern"
|
||||
|
||||
@@ -230,6 +231,8 @@ class Keys:
|
||||
COUNT = "{arch}.hyper_connection.count"
|
||||
SINKHORN_ITERATIONS = "{arch}.hyper_connection.sinkhorn_iterations"
|
||||
EPSILON = "{arch}.hyper_connection.epsilon"
|
||||
# scale of the post gate (DeepSeek-V4 hardcodes 2.0)
|
||||
MAGNITUDE = "{arch}.hyper_connection.magnitude"
|
||||
# absent means the mix projection is full rank (DeepSeek-V4 behaviour)
|
||||
LOW_RANK = "{arch}.hyper_connection.low_rank"
|
||||
|
||||
@@ -592,6 +595,7 @@ class MODEL_ARCH(IntEnum):
|
||||
HUNYUAN_DENSE = auto()
|
||||
HUNYUAN_VL = auto()
|
||||
HY_V3 = auto()
|
||||
HY_V4 = auto()
|
||||
SMOLLM3 = auto()
|
||||
GPT_OSS = auto()
|
||||
LFM2 = auto()
|
||||
@@ -616,6 +620,7 @@ class MODEL_ARCH(IntEnum):
|
||||
PADDLEOCR = auto()
|
||||
MIMO2 = auto()
|
||||
STEP35 = auto()
|
||||
SPARK2_5 = auto()
|
||||
LLAMA_EMBED = auto()
|
||||
MAINCODER = auto()
|
||||
KIMI_LINEAR = auto()
|
||||
@@ -1345,6 +1350,7 @@ MODEL_ARCH_NAMES: dict[MODEL_ARCH, str] = {
|
||||
MODEL_ARCH.HUNYUAN_DENSE: "hunyuan-dense",
|
||||
MODEL_ARCH.HUNYUAN_VL: "hunyuan_vl",
|
||||
MODEL_ARCH.HY_V3: "hy_v3",
|
||||
MODEL_ARCH.HY_V4: "hy_v4",
|
||||
MODEL_ARCH.SMOLLM3: "smollm3",
|
||||
MODEL_ARCH.GPT_OSS: "gpt-oss",
|
||||
MODEL_ARCH.LFM2: "lfm2",
|
||||
@@ -1369,6 +1375,7 @@ MODEL_ARCH_NAMES: dict[MODEL_ARCH, str] = {
|
||||
MODEL_ARCH.PADDLEOCR: "paddleocr",
|
||||
MODEL_ARCH.MIMO2: "mimo2",
|
||||
MODEL_ARCH.STEP35: "step35",
|
||||
MODEL_ARCH.SPARK2_5: "spark2_5",
|
||||
MODEL_ARCH.LLAMA_EMBED: "llama-embed",
|
||||
MODEL_ARCH.MAINCODER: "maincoder",
|
||||
MODEL_ARCH.KIMI_LINEAR: "kimi-linear",
|
||||
@@ -2290,6 +2297,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -2310,6 +2318,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -2333,6 +2342,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -2353,6 +2363,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -2398,6 +2409,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -2500,6 +2512,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.TOKEN_TYPES,
|
||||
MODEL_TENSOR.ATTN_NORM_2,
|
||||
MODEL_TENSOR.ATTN_OUT_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -2528,6 +2541,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.TOKEN_EMBD,
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -2557,6 +2571,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -2569,6 +2584,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -2596,6 +2612,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -2627,6 +2644,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -2642,6 +2660,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -2657,6 +2676,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -2671,6 +2691,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -2685,6 +2706,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -2705,6 +2727,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -2721,6 +2744,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -2776,6 +2800,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -2792,6 +2817,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -2932,6 +2958,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -3065,6 +3092,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -3080,6 +3108,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -3098,6 +3127,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.ROPE_FACTORS_LONG,
|
||||
MODEL_TENSOR.ROPE_FACTORS_SHORT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -3135,6 +3165,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.TOKEN_EMBD,
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -3147,6 +3178,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_ARCH.GEMMA2: [
|
||||
MODEL_TENSOR.TOKEN_EMBD,
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -3163,6 +3195,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.TOKEN_EMBD,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -3181,6 +3214,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.TOKEN_EMBD,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -3217,6 +3251,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.TOKEN_EMBD,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -3272,6 +3307,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.DENSE_2_OUT,
|
||||
MODEL_TENSOR.DENSE_3_OUT,
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -3292,6 +3328,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -3455,6 +3492,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -3484,6 +3522,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -3498,6 +3537,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.TOKEN_EMBD,
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -3512,6 +3552,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.TOKEN_EMBD,
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -3563,6 +3604,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_ARCH.OLMO: [
|
||||
MODEL_TENSOR.TOKEN_EMBD,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -3575,6 +3617,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.TOKEN_EMBD,
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -3590,6 +3633,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_ARCH.SEED_OSS: [
|
||||
MODEL_TENSOR.TOKEN_EMBD,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -3606,6 +3650,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_OUT,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -3656,6 +3701,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -3677,6 +3723,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -3739,6 +3786,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_A,
|
||||
MODEL_TENSOR.ATTN_Q_B,
|
||||
@@ -3861,6 +3909,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -3937,6 +3986,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_POST_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4082,6 +4132,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4096,6 +4147,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4117,6 +4169,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.SSM_D,
|
||||
MODEL_TENSOR.SSM_NORM,
|
||||
MODEL_TENSOR.SSM_OUT,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4136,6 +4189,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.SSM_D,
|
||||
MODEL_TENSOR.SSM_NORM,
|
||||
MODEL_TENSOR.SSM_OUT,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4166,6 +4220,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4181,6 +4236,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -4206,6 +4262,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -4237,6 +4294,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4251,6 +4309,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4276,6 +4335,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.SSM_D,
|
||||
MODEL_TENSOR.SSM_NORM,
|
||||
MODEL_TENSOR.SSM_OUT,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4339,6 +4399,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -4378,6 +4439,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4469,6 +4531,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -4532,6 +4595,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4547,6 +4611,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_POST_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4598,6 +4663,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4612,6 +4678,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4629,6 +4696,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
|
||||
# Attention components
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q, # Query projection
|
||||
MODEL_TENSOR.ATTN_K, # Key projection
|
||||
MODEL_TENSOR.ATTN_V, # Value projection
|
||||
@@ -4661,6 +4729,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -4681,6 +4750,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -4697,6 +4767,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -4739,12 +4810,55 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.NEXTN_SHARED_HEAD_HEAD,
|
||||
MODEL_TENSOR.NEXTN_SHARED_HEAD_NORM,
|
||||
],
|
||||
MODEL_ARCH.HY_V4: [
|
||||
MODEL_TENSOR.TOKEN_EMBD,
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.HC_HEAD_FN,
|
||||
MODEL_TENSOR.HC_HEAD_BASE,
|
||||
MODEL_TENSOR.HC_HEAD_SCALE,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_SINKS,
|
||||
MODEL_TENSOR.ATTN_Q_A,
|
||||
MODEL_TENSOR.ATTN_Q_A_NORM,
|
||||
MODEL_TENSOR.ATTN_Q_B,
|
||||
MODEL_TENSOR.ATTN_KV_A_MQA,
|
||||
MODEL_TENSOR.ATTN_KV_A_NORM,
|
||||
MODEL_TENSOR.ATTN_K_B,
|
||||
MODEL_TENSOR.ATTN_V_B,
|
||||
MODEL_TENSOR.ATTN_OUT,
|
||||
MODEL_TENSOR.ATTN_GATE,
|
||||
MODEL_TENSOR.INDEXER_K_NORM,
|
||||
MODEL_TENSOR.INDEXER_PROJ,
|
||||
MODEL_TENSOR.INDEXER_ATTN_K,
|
||||
MODEL_TENSOR.INDEXER_ATTN_Q_B,
|
||||
MODEL_TENSOR.HC_ATTN_FN,
|
||||
MODEL_TENSOR.HC_ATTN_BASE,
|
||||
MODEL_TENSOR.HC_ATTN_SCALE,
|
||||
MODEL_TENSOR.HC_FFN_FN,
|
||||
MODEL_TENSOR.HC_FFN_BASE,
|
||||
MODEL_TENSOR.HC_FFN_SCALE,
|
||||
MODEL_TENSOR.FFN_GATE_INP,
|
||||
MODEL_TENSOR.FFN_EXP_PROBS_B,
|
||||
MODEL_TENSOR.FFN_NORM,
|
||||
MODEL_TENSOR.FFN_GATE,
|
||||
MODEL_TENSOR.FFN_DOWN,
|
||||
MODEL_TENSOR.FFN_UP,
|
||||
MODEL_TENSOR.FFN_GATE_EXP,
|
||||
MODEL_TENSOR.FFN_DOWN_EXP,
|
||||
MODEL_TENSOR.FFN_UP_EXP,
|
||||
MODEL_TENSOR.FFN_GATE_SHEXP,
|
||||
MODEL_TENSOR.FFN_DOWN_SHEXP,
|
||||
MODEL_TENSOR.FFN_UP_SHEXP,
|
||||
],
|
||||
MODEL_ARCH.SMOLLM3: [
|
||||
MODEL_TENSOR.TOKEN_EMBD,
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4761,6 +4875,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_POST_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4784,6 +4899,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.ATTN_NORM, # operator_norm
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4804,6 +4920,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.ATTN_NORM, # operator_norm
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4819,6 +4936,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4838,6 +4956,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4855,6 +4974,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_OUT,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -4872,6 +4992,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -4910,6 +5031,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -4973,6 +5095,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -4990,6 +5113,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -5005,6 +5129,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -5158,6 +5283,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -5185,12 +5311,26 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.NEXTN_SHARED_HEAD_HEAD,
|
||||
MODEL_TENSOR.NEXTN_SHARED_HEAD_NORM,
|
||||
],
|
||||
MODEL_ARCH.SPARK2_5: [
|
||||
MODEL_TENSOR.TOKEN_EMBD,
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_GATE,
|
||||
MODEL_TENSOR.ATTN_OUT,
|
||||
MODEL_TENSOR.FFN_NORM,
|
||||
MODEL_TENSOR.FFN_GATE,
|
||||
MODEL_TENSOR.FFN_DOWN,
|
||||
MODEL_TENSOR.FFN_UP,
|
||||
],
|
||||
MODEL_ARCH.LLAMA_EMBED: [
|
||||
MODEL_TENSOR.TOKEN_EMBD,
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -5210,6 +5350,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_Q_NORM,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
@@ -5226,6 +5367,7 @@ MODEL_TENSORS: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.OUTPUT_NORM,
|
||||
MODEL_TENSOR.OUTPUT,
|
||||
MODEL_TENSOR.ATTN_NORM,
|
||||
MODEL_TENSOR.ATTN_QKV,
|
||||
MODEL_TENSOR.ATTN_Q,
|
||||
MODEL_TENSOR.ATTN_K,
|
||||
MODEL_TENSOR.ATTN_V,
|
||||
@@ -5438,6 +5580,10 @@ MODEL_TENSOR_SKIP: dict[MODEL_ARCH, list[MODEL_TENSOR]] = {
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_ROT_EMBD,
|
||||
],
|
||||
MODEL_ARCH.HY_V4: [
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
MODEL_TENSOR.ATTN_ROT_EMBD,
|
||||
],
|
||||
MODEL_ARCH.CHATGLM: [
|
||||
MODEL_TENSOR.ROPE_FREQS,
|
||||
],
|
||||
|
||||
@@ -841,6 +841,9 @@ class GGUFWriter:
|
||||
else:
|
||||
self.add_array(key, value)
|
||||
|
||||
def add_recurrent_layers(self, value: Sequence[bool]) -> None:
|
||||
self.add_array(Keys.Attention.RECURRENT_LAYERS.format(arch=self.arch), value)
|
||||
|
||||
def add_rope_pattern(self, value: Sequence[bool]) -> None:
|
||||
self.add_array(Keys.Attention.ROPE_PATTERN.format(arch=self.arch), value)
|
||||
|
||||
@@ -1055,6 +1058,9 @@ class GGUFWriter:
|
||||
def add_hyper_connection_epsilon(self, value: float) -> None:
|
||||
self.add_float32(Keys.HyperConnection.EPSILON.format(arch=self.arch), value)
|
||||
|
||||
def add_hyper_connection_magnitude(self, value: float) -> None:
|
||||
self.add_float32(Keys.HyperConnection.MAGNITUDE.format(arch=self.arch), value)
|
||||
|
||||
def add_hyper_connection_low_rank(self, value: int) -> None:
|
||||
self.add_uint32(Keys.HyperConnection.LOW_RANK.format(arch=self.arch), value)
|
||||
|
||||
|
||||
@@ -385,6 +385,7 @@ class TensorNameMap:
|
||||
MODEL_TENSOR.ATTN_SINKS: (
|
||||
"model.layers.{bid}.self_attn.sinks", # openai-moe
|
||||
"model.layers.{bid}.self_attn.attention_sink_bias", # mimov2
|
||||
"model.layers.{bid}.self_attn.learnable_sink_param", # hy-v4
|
||||
),
|
||||
|
||||
MODEL_TENSOR.ATTN_GATE: (
|
||||
@@ -392,6 +393,7 @@ class TensorNameMap:
|
||||
"model.layers.{bid}.linear_attn.in_proj_z", # qwen3.5
|
||||
"model.layers.{bid}.self_attn.g_proj", # step3.5 head-wise attention gate
|
||||
"model.layers.{bid}.self_attn.output_gate", # minimax-01
|
||||
"model.layers.{bid}.self_attn.linear_gate", # hy-v4
|
||||
),
|
||||
|
||||
# Feed-forward norm
|
||||
@@ -1329,6 +1331,42 @@ class TensorNameMap:
|
||||
"model.layers.{bid}.self_attn.index_q_norm", # MSA
|
||||
),
|
||||
|
||||
MODEL_TENSOR.HC_ATTN_FN: (
|
||||
"model.layers.{bid}.hc_attn_layer.hc_pre.hc_fn", # hy-v4
|
||||
),
|
||||
|
||||
MODEL_TENSOR.HC_ATTN_BASE: (
|
||||
"model.layers.{bid}.hc_attn_layer.hc_pre.hc_base", # hy-v4
|
||||
),
|
||||
|
||||
MODEL_TENSOR.HC_ATTN_SCALE: (
|
||||
"model.layers.{bid}.hc_attn_layer.hc_pre.hc_scale", # hy-v4
|
||||
),
|
||||
|
||||
MODEL_TENSOR.HC_FFN_FN: (
|
||||
"model.layers.{bid}.hc_mlp_layer.hc_pre.hc_fn", # hy-v4
|
||||
),
|
||||
|
||||
MODEL_TENSOR.HC_FFN_BASE: (
|
||||
"model.layers.{bid}.hc_mlp_layer.hc_pre.hc_base", # hy-v4
|
||||
),
|
||||
|
||||
MODEL_TENSOR.HC_FFN_SCALE: (
|
||||
"model.layers.{bid}.hc_mlp_layer.hc_pre.hc_scale", # hy-v4
|
||||
),
|
||||
|
||||
MODEL_TENSOR.HC_HEAD_FN: (
|
||||
"model.hc_head.hc_head_fn", # hy-v4
|
||||
),
|
||||
|
||||
MODEL_TENSOR.HC_HEAD_BASE: (
|
||||
"model.hc_head.hc_head_base", # hy-v4
|
||||
),
|
||||
|
||||
MODEL_TENSOR.HC_HEAD_SCALE: (
|
||||
"model.hc_head.hc_head_scale", # hy-v4
|
||||
),
|
||||
|
||||
############################################################################
|
||||
# TODO: these do not belong to block_mappings_cfg - move them to mappings_cfg
|
||||
MODEL_TENSOR.ENC_OUTPUT_NORM: (
|
||||
|
||||
@@ -23,4 +23,6 @@ These templates can be updated with the following commands:
|
||||
./scripts/get_chat_template.py Qwen/Qwen3-0.6B > models/templates/Qwen-Qwen3-0.6B.jinja
|
||||
./scripts/get_chat_template.py zai-org/GLM-4.5 > models/templates/zai-org-GLM-4.5.jinja
|
||||
./scripts/get_chat_template.py deepseek-ai/DeepSeek-V3.1 > models/templates/deepseek-ai-DeepSeek-V3.1.jinja
|
||||
./scripts/get_chat_template.py XHToken/Spark-X2.5-1.7B > models/templates/Spark2.5.jinja
|
||||
./scripts/get_chat_template.py XHToken/Spark-X2.5-4B > models/templates/Spark2.5.jinja
|
||||
```
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
{%- if not messages %}
|
||||
{{- raise_exception('No messages provided.') }}
|
||||
{%- endif %}
|
||||
|
||||
{%- set enable_thinking = enable_thinking | default(true) %}
|
||||
|
||||
{#- Render a string or a list of text blocks. -#}
|
||||
{%- macro render_content(content, context_name) %}
|
||||
{%- if content is string %}
|
||||
{{- content }}
|
||||
{%- elif content is none or content is undefined %}
|
||||
{{- '' }}
|
||||
{%- elif content is iterable and content is not mapping %}
|
||||
{%- for block in content %}
|
||||
{%- if block.type == 'text' %}
|
||||
{{- block.text }}
|
||||
{%- else %}
|
||||
{{- raise_exception('Unsupported ' ~ context_name ~ ' content block type: ' ~ (block.type | string)) }}
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
{%- else %}
|
||||
{{- raise_exception(context_name ~ ' content must be a string or a list of text blocks') }}
|
||||
{%- endif %}
|
||||
{%- endmacro %}
|
||||
|
||||
{#- Default system prompt. -#}
|
||||
{%- set default_system = 'you are a helpful assistant.' %}
|
||||
|
||||
{#- The first message-level system is placed in the initial system block. -#}
|
||||
{%- set ns = namespace(initial_system='') %}
|
||||
{%- if messages[0].role == 'system' %}
|
||||
{%- set ns.initial_system = render_content(messages[0].content, 'system') %}
|
||||
{%- endif %}
|
||||
|
||||
{#- System block. -#}
|
||||
{{- '<|start▁of▁sentence|><|System|>' + '\n' + default_system }}
|
||||
{%- if tools %}
|
||||
{{- '## Tools' + '\n' + 'You have access to the following functions:' + '\n' + '<tools>' }}
|
||||
{%- for tool in tools %}
|
||||
{{- '\n' + tool.function | tojson }}
|
||||
{%- endfor %}
|
||||
{{- '\n' + '</tools>' }}
|
||||
{%- endif %}
|
||||
{%- if ns.initial_system %}
|
||||
{{- '\n\n' + ns.initial_system }}
|
||||
{%- endif %}
|
||||
{{- '<|end▁of▁sentence|>' }}
|
||||
|
||||
{#- Conversation turns. -#}
|
||||
{%- for message in messages %}
|
||||
{%- if message.role == 'system' %}
|
||||
{#- The first system message was consumed by the initial block. -#}
|
||||
{%- if not loop.first %}
|
||||
{{- '<|start▁of▁sentence|><|System|>\n' + render_content(message.content, 'system') + '<|end▁of▁sentence|>' }}
|
||||
{%- endif %}
|
||||
{%- elif message.role == 'user' %}
|
||||
{{- '<|start▁of▁sentence|><|User|>' + render_content(message.content, 'user') + '<|end▁of▁sentence|>' }}
|
||||
{%- elif message.role == 'assistant' %}
|
||||
{%- set assistant_content = render_content(message.content, 'assistant') %}
|
||||
{%- if message.reasoning_content is defined and message.reasoning_content %}
|
||||
{%- set reasoning_content = message.reasoning_content %}
|
||||
{%- else %}
|
||||
{%- set reasoning_content = '' %}
|
||||
{%- endif %}
|
||||
{{- '<|start▁of▁sentence|><|Bot|>' }}
|
||||
{%- if reasoning_content %}
|
||||
{{- '<think>' + reasoning_content + '</think>' }}
|
||||
{%- else %}
|
||||
{{- '</think>' }}
|
||||
{%- endif %}
|
||||
{%- if assistant_content %}
|
||||
{{- assistant_content }}
|
||||
{%- endif %}
|
||||
{%- if message.tool_calls is defined and message.tool_calls is not none %}
|
||||
{%- for tool_call in message.tool_calls %}
|
||||
{%- if tool_call.function.arguments is not mapping %}
|
||||
{{- raise_exception('tool_call.function.arguments must be a dictionary; normalize JSON strings before apply_chat_template') }}
|
||||
{%- endif %}
|
||||
{%- set args = tool_call.function.arguments %}
|
||||
{{- '<tool_call>' + tool_call.function.name }}
|
||||
{%- for k, v in args.items() %}
|
||||
{{- '<arg_key>' ~ k ~ '</arg_key><arg_value>' ~ (v if v is string else v | tojson) ~ '</arg_value>' }}
|
||||
{%- endfor %}
|
||||
{{- '</tool_call>' }}
|
||||
{%- endfor %}
|
||||
{%- endif %}
|
||||
{{- '<|end▁of▁sentence|>' }}
|
||||
{%- elif message.role == 'tool' %}
|
||||
{%- if loop.previtem is undefined or loop.previtem.role != 'tool' %}
|
||||
{{- '<|start▁of▁sentence|><|Tool|>' }}
|
||||
{%- endif %}
|
||||
{{- '<tool_response>' ~ message.content ~ '</tool_response>' }}
|
||||
{%- if loop.nextitem is undefined or loop.nextitem.role != 'tool' %}
|
||||
{{- '<|end▁of▁sentence|>' }}
|
||||
{%- endif %}
|
||||
{%- else %}
|
||||
{{- raise_exception('Unsupported message role: ' ~ message.role) }}
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
|
||||
{#- Generation prompt. -#}
|
||||
{%- if add_generation_prompt %}
|
||||
{{- '<|start▁of▁sentence|><|Bot|>' }}
|
||||
{%- if enable_thinking is defined and enable_thinking %}
|
||||
{{- '<think>' }}
|
||||
{%- endif %}
|
||||
{%- if enable_thinking is defined and not enable_thinking %}
|
||||
{{- '</think>' }}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
@@ -120,6 +120,51 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Checking container images for commit ${SHA}..."
|
||||
NIGHTLY_TAG="$(git tag --points-at "${SHA}" | grep -E '(^|-)b[0-9]+(-[0-9a-f]{7})?$' | head -n 1 || true)"
|
||||
if [[ -z "${NIGHTLY_TAG}" ]]; then
|
||||
echo "Warning: no nightly tag points at ${SHA} - skipping container image check"
|
||||
elif [[ -z "${GITHUB_REPOSITORY:-}" ]]; then
|
||||
echo "Warning: GITHUB_REPOSITORY not set - skipping container image check (local run)"
|
||||
else
|
||||
CONTAINER_REPO="${GITHUB_REPOSITORY,,}" # lower-case owner/repo for ghcr.io
|
||||
GHCR_TOKEN="$(curl -fsSL \
|
||||
"https://ghcr.io/token?scope=repository:${CONTAINER_REPO}:pull&service=ghcr.io" \
|
||||
| grep -oP '"token"\s*:\s*"\K[^"]+')"
|
||||
|
||||
VARIANTS=("" "-cuda" "-cuda13" "-vulkan" "-rocm" "-intel" "-musa" "-openvino")
|
||||
TYPES=("full" "light" "server")
|
||||
CONTAINER_ERR=""
|
||||
for type in "${TYPES[@]}"; do
|
||||
for variant in "${VARIANTS[@]}"; do
|
||||
tag="${type}${variant}-${NIGHTLY_TAG}"
|
||||
STATUS="$(curl -s -o /dev/null -w "%{http_code}" \
|
||||
-H "Authorization: Bearer ${GHCR_TOKEN}" \
|
||||
-H "Accept: application/vnd.oci.image.index.v1+json,application/vnd.docker.distribution.manifest.list.v2+json" \
|
||||
"https://ghcr.io/v2/${CONTAINER_REPO}/manifests/${tag}")"
|
||||
if [[ "${STATUS}" == "200" ]]; then
|
||||
echo " ${tag} - OK"
|
||||
else
|
||||
echo " ${tag} - MISSING"
|
||||
CONTAINER_ERR+=" ${tag}"
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
if [[ -n "${CONTAINER_ERR}" ]]; then
|
||||
if [[ "$DRY_RUN" == "true" ]]; then
|
||||
echo "Warning: missing container images for ${NIGHTLY_TAG}:${CONTAINER_ERR} (dry run, continuing)."
|
||||
CHECKS_PASSED=false
|
||||
else
|
||||
echo "Error: missing container images for ${NIGHTLY_TAG}:${CONTAINER_ERR}"
|
||||
echo "The Docker workflow must complete successfully before making a release."
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "All container images found for ${NIGHTLY_TAG} - OK"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -n "${GITHUB_OUTPUT:-}" ]]; then
|
||||
echo "checks_passed=${CHECKS_PASSED}" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
+217
-43
@@ -15,7 +15,6 @@ set(HF_BUCKET "" CACHE STRING "Hugging Face bucket name")
|
||||
set(HF_VERSION "" CACHE STRING "Version to download (empty = resolve from git)")
|
||||
set(HF_ENABLED "" CACHE STRING "Whether to allow HF Bucket download (ON/OFF)")
|
||||
set(BUILD_UI "" CACHE STRING "Build UI via npm (ON/OFF)")
|
||||
set(LLAMA_UI_EMBED "" CACHE STRING "Path to llama-ui-embed helper")
|
||||
set(LLAMA_UI_GZIP "" CACHE STRING "Apply gzip compress to assets to save bandwidth")
|
||||
|
||||
set(DIST_DIR "${UI_BINARY_DIR}/dist")
|
||||
@@ -25,6 +24,223 @@ set(STAMP_FILE "${UI_BINARY_DIR}/.ui-stamp")
|
||||
set(UI_CPP "${UI_BINARY_DIR}/ui.cpp")
|
||||
set(UI_H "${UI_BINARY_DIR}/ui.h")
|
||||
|
||||
function(mime_from_ext name out_var)
|
||||
string(FIND "${name}" "." ext REVERSE)
|
||||
if(ext GREATER -1)
|
||||
string(SUBSTRING "${name}" ${ext} -1 ext_full)
|
||||
string(SUBSTRING "${ext_full}" 1 -1 ext_str)
|
||||
else()
|
||||
set(ext_str "")
|
||||
endif()
|
||||
if(ext_str STREQUAL "html")
|
||||
set(m "text/html; charset=utf-8")
|
||||
elseif(ext_str STREQUAL "css")
|
||||
set(m "text/css")
|
||||
elseif(ext_str STREQUAL "js")
|
||||
set(m "application/javascript")
|
||||
elseif(ext_str STREQUAL "json")
|
||||
set(m "application/json")
|
||||
elseif(ext_str STREQUAL "webmanifest")
|
||||
set(m "application/manifest+json")
|
||||
elseif(ext_str STREQUAL "svg")
|
||||
set(m "image/svg+xml")
|
||||
elseif(ext_str STREQUAL "png")
|
||||
set(m "image/png")
|
||||
elseif(ext_str STREQUAL "jpg" OR ext_str STREQUAL "jpeg")
|
||||
set(m "image/jpeg")
|
||||
elseif(ext_str STREQUAL "ico")
|
||||
set(m "image/x-icon")
|
||||
elseif(ext_str STREQUAL "woff")
|
||||
set(m "font/woff")
|
||||
elseif(ext_str STREQUAL "woff2")
|
||||
set(m "font/woff2")
|
||||
else()
|
||||
set(m "application/octet-stream")
|
||||
endif()
|
||||
set(${out_var} "${m}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Fail when a dist tree is present but is missing files the UI needs at
|
||||
# runtime; catches truncated/stale asset trees early with a useful message.
|
||||
function(ui_validate_assets files in_dir)
|
||||
list(LENGTH files n_assets)
|
||||
if(n_assets EQUAL 0)
|
||||
return()
|
||||
endif()
|
||||
|
||||
set(found_index FALSE)
|
||||
set(found_manifest FALSE)
|
||||
set(found_sw FALSE)
|
||||
set(found_build_json FALSE)
|
||||
set(found_version_json FALSE)
|
||||
set(found_bundle_js FALSE)
|
||||
set(found_bundle_css FALSE)
|
||||
set(found_workbox_js FALSE)
|
||||
|
||||
foreach(f ${files})
|
||||
get_filename_component(base "${f}" NAME)
|
||||
if(base STREQUAL "index.html")
|
||||
set(found_index TRUE)
|
||||
elseif(base STREQUAL "manifest.webmanifest")
|
||||
set(found_manifest TRUE)
|
||||
elseif(base STREQUAL "sw.js")
|
||||
set(found_sw TRUE)
|
||||
elseif(base STREQUAL "build.json")
|
||||
set(found_build_json TRUE)
|
||||
elseif(base STREQUAL "version.json")
|
||||
set(found_version_json TRUE)
|
||||
elseif(base MATCHES "^bundle.*\\.js$")
|
||||
set(found_bundle_js TRUE)
|
||||
elseif(base MATCHES "^bundle.*\\.css$")
|
||||
set(found_bundle_css TRUE)
|
||||
elseif(base MATCHES "^workbox.*\\.js$")
|
||||
set(found_workbox_js TRUE)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
set(missing "")
|
||||
if(NOT found_index)
|
||||
list(APPEND missing "index.html")
|
||||
endif()
|
||||
if(NOT found_manifest)
|
||||
list(APPEND missing "manifest.webmanifest")
|
||||
endif()
|
||||
if(NOT found_sw)
|
||||
list(APPEND missing "sw.js")
|
||||
endif()
|
||||
if(NOT found_build_json)
|
||||
list(APPEND missing "build.json")
|
||||
endif()
|
||||
if(NOT found_version_json)
|
||||
list(APPEND missing "version.json")
|
||||
endif()
|
||||
if(NOT found_bundle_js)
|
||||
list(APPEND missing "bundle[hash].js")
|
||||
endif()
|
||||
if(NOT found_bundle_css)
|
||||
list(APPEND missing "bundle[hash].css")
|
||||
endif()
|
||||
if(NOT found_workbox_js)
|
||||
list(APPEND missing "workbox[hash].js")
|
||||
endif()
|
||||
|
||||
if(missing)
|
||||
set(listing "")
|
||||
foreach(f ${files})
|
||||
string(APPEND listing " ${f}\n")
|
||||
endforeach()
|
||||
set(missing_list "")
|
||||
foreach(m ${missing})
|
||||
string(APPEND missing_list " ${m}\n")
|
||||
endforeach()
|
||||
message(FATAL_ERROR
|
||||
"UI: current asset files:\n${listing}"
|
||||
"UI: missing required asset(s):\n${missing_list}"
|
||||
"UI: hint: try cleaning your build directory: ${in_dir}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Generate ui.cpp/ui.h embedding every file of ${dist_dir} (empty table when
|
||||
# it has no index.html). When LLAMA_UI_GZIP is enabled, assets are compressed
|
||||
# first and served pre-gzipped (llama_ui_use_gzip()).
|
||||
function(emit_files dist_dir)
|
||||
set(embed_dir "${dist_dir}")
|
||||
set(use_gzip FALSE)
|
||||
|
||||
if(EXISTS "${dist_dir}/index.html")
|
||||
if(EXISTS "${dist_dir}/_gzip")
|
||||
# a _gzip tree inside dist_dir can only be a leftover from an
|
||||
# older version of this script that staged it there
|
||||
file(REMOVE_RECURSE "${dist_dir}/_gzip")
|
||||
message(STATUS "UI: removed stale gzip tree ${dist_dir}/_gzip")
|
||||
endif()
|
||||
if(LLAMA_UI_GZIP)
|
||||
# Compress every asset into a parallel _gzip/ tree under the build
|
||||
# directory (never write into the source or dist tree); the
|
||||
# structure stays the same: /abc/def --> /_gzip/abc/def.
|
||||
# FORMAT raw produces a bare gzip stream (no archive container)
|
||||
# that can be served with Content-Encoding: gzip. SOURCE_DATE_EPOCH
|
||||
# zeroes the header timestamp so identical inputs give identical
|
||||
# bytes (and therefore stable ETags) on every machine.
|
||||
if(NOT DEFINED ENV{SOURCE_DATE_EPOCH})
|
||||
set(ENV{SOURCE_DATE_EPOCH} 0)
|
||||
endif()
|
||||
set(gzip_root "${UI_BINARY_DIR}/ui-gzip")
|
||||
set(gzip_dir "${gzip_root}/_gzip")
|
||||
file(REMOVE_RECURSE "${gzip_root}")
|
||||
file(GLOB_RECURSE all_files RELATIVE "${dist_dir}" "${dist_dir}/*")
|
||||
list(FILTER all_files EXCLUDE REGEX "^_gzip/")
|
||||
foreach(f ${all_files})
|
||||
get_filename_component(asset_path "${dist_dir}/${f}" REALPATH)
|
||||
get_filename_component(dst_dir "${gzip_dir}/${f}" DIRECTORY)
|
||||
file(MAKE_DIRECTORY "${dst_dir}")
|
||||
file(ARCHIVE_CREATE
|
||||
OUTPUT "${gzip_dir}/${f}"
|
||||
PATHS "${asset_path}"
|
||||
FORMAT raw
|
||||
COMPRESSION GZip
|
||||
)
|
||||
endforeach()
|
||||
message(STATUS "UI: gzip compression applied (${gzip_dir})")
|
||||
set(embed_dir "${gzip_dir}")
|
||||
set(use_gzip TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(assets "")
|
||||
if(EXISTS "${embed_dir}/index.html")
|
||||
file(GLOB_RECURSE assets RELATIVE "${embed_dir}" "${embed_dir}/*")
|
||||
list(FILTER assets EXCLUDE REGEX "^_gzip/")
|
||||
list(SORT assets)
|
||||
ui_validate_assets("${assets}" "${embed_dir}")
|
||||
endif()
|
||||
|
||||
list(LENGTH assets n_assets)
|
||||
|
||||
# Only the per-asset data arrays and table rows are built here; all
|
||||
# static C++ lives in the ui.h.in / ui.cpp.in templates. configure_file
|
||||
# rewrites an output only when its contents change, so the library is
|
||||
# not recompiled needlessly. @ONLY keeps ${...} in the content literal;
|
||||
# mime types come from a fixed list.
|
||||
set(ASSET_ARRAYS "")
|
||||
set(ASSET_TABLE "")
|
||||
set(idx 0)
|
||||
|
||||
foreach(f IN LISTS assets)
|
||||
file(READ "${embed_dir}/${f}" hex HEX)
|
||||
if(hex STREQUAL "")
|
||||
message(FATAL_ERROR "UI: empty file: ${embed_dir}/${f}")
|
||||
endif()
|
||||
|
||||
string(REGEX REPLACE "(..)" "0x\\1," bytes "${hex}")
|
||||
file(SHA256 "${embed_dir}/${f}" etag)
|
||||
mime_from_ext("${f}" mime)
|
||||
|
||||
string(APPEND ASSET_ARRAYS
|
||||
"static const unsigned char asset_${idx}[] = {${bytes}};\n")
|
||||
|
||||
string(APPEND ASSET_TABLE
|
||||
" { \"${f}\", asset_${idx}, sizeof(asset_${idx}), \"\\\"${etag}\\\"\", \"${mime}\" },\n")
|
||||
|
||||
math(EXPR idx "${idx} + 1")
|
||||
endforeach()
|
||||
|
||||
set(LLAMA_UI_HAS_ASSETS 0)
|
||||
if(n_assets GREATER 0)
|
||||
set(LLAMA_UI_HAS_ASSETS 1)
|
||||
endif()
|
||||
set(N_ASSETS "${n_assets}")
|
||||
set(USE_GZIP false)
|
||||
if(use_gzip)
|
||||
set(USE_GZIP true)
|
||||
endif()
|
||||
|
||||
set(UI_TEMPLATE_DIR "${LLAMA_SOURCE_DIR}/tools/ui")
|
||||
configure_file("${UI_TEMPLATE_DIR}/ui.h.in" "${UI_H}" @ONLY)
|
||||
configure_file("${UI_TEMPLATE_DIR}/ui.cpp.in" "${UI_CPP}" @ONLY)
|
||||
message(STATUS "UI: embedded ${n_assets} assets")
|
||||
endfunction()
|
||||
|
||||
function(npm_build_should_skip out_var)
|
||||
set(${out_var} FALSE PARENT_SCOPE)
|
||||
|
||||
@@ -250,48 +466,6 @@ function(hf_download version out_var out_resolved)
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(emit_files dist_dir)
|
||||
# If gzip is requested, compress every asset into a parallel _gzip/ tree
|
||||
# the structure stays the same; for ex: /abc/def --> /_gzip/abc/def
|
||||
# embed.cpp will check for _gzip and will pick it up
|
||||
if(LLAMA_UI_GZIP AND EXISTS "${dist_dir}/index.html")
|
||||
find_program(GZIP_EXECUTABLE gzip)
|
||||
if(NOT GZIP_EXECUTABLE)
|
||||
message(WARNING "UI: LLAMA_UI_GZIP requested but gzip not found, embedding uncompressed")
|
||||
else()
|
||||
set(gzip_dir "${dist_dir}/_gzip")
|
||||
file(REMOVE_RECURSE "${gzip_dir}")
|
||||
file(GLOB_RECURSE all_files RELATIVE "${dist_dir}" "${dist_dir}/*")
|
||||
foreach(f ${all_files})
|
||||
get_filename_component(dst_dir "${gzip_dir}/${f}" DIRECTORY)
|
||||
file(MAKE_DIRECTORY "${dst_dir}")
|
||||
execute_process(
|
||||
COMMAND "${GZIP_EXECUTABLE}" -c "${dist_dir}/${f}"
|
||||
OUTPUT_FILE "${gzip_dir}/${f}"
|
||||
RESULT_VARIABLE gz_rc
|
||||
)
|
||||
if(NOT gz_rc EQUAL 0)
|
||||
message(FATAL_ERROR "UI: gzip failed for ${f}")
|
||||
endif()
|
||||
endforeach()
|
||||
message(STATUS "UI: gzip compression applied (${gzip_dir})")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(args "${UI_CPP}" "${UI_H}")
|
||||
if(EXISTS "${dist_dir}/index.html")
|
||||
list(APPEND args "${dist_dir}")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND "${LLAMA_UI_EMBED}" ${args}
|
||||
RESULT_VARIABLE rc
|
||||
)
|
||||
if(NOT rc EQUAL 0)
|
||||
message(FATAL_ERROR "UI: llama-ui-embed failed (${rc})")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# 1. Priority 1: pre-built assets supplied in tools/ui/dist
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -121,6 +121,7 @@ static const std::map<llm_arch, const char *> LLM_ARCH_NAMES = {
|
||||
{ LLM_ARCH_HUNYUAN_DENSE, "hunyuan-dense" },
|
||||
{ LLM_ARCH_HUNYUAN_VL, "hunyuan_vl" },
|
||||
{ LLM_ARCH_HY_V3, "hy_v3" },
|
||||
{ LLM_ARCH_HY_V4, "hy_v4" },
|
||||
{ LLM_ARCH_SMOLLM3, "smollm3" },
|
||||
{ LLM_ARCH_OPENAI_MOE, "gpt-oss" },
|
||||
{ LLM_ARCH_LFM2, "lfm2" },
|
||||
@@ -145,6 +146,7 @@ static const std::map<llm_arch, const char *> LLM_ARCH_NAMES = {
|
||||
{ LLM_ARCH_PADDLEOCR, "paddleocr" },
|
||||
{ LLM_ARCH_MIMO2, "mimo2" },
|
||||
{ LLM_ARCH_STEP35, "step35" },
|
||||
{ LLM_ARCH_SPARK2_5, "spark2_5" },
|
||||
{ LLM_ARCH_LLAMA_EMBED, "llama-embed" },
|
||||
{ LLM_ARCH_MAINCODER, "maincoder" },
|
||||
{ LLM_ARCH_KIMI_LINEAR, "kimi-linear" },
|
||||
@@ -294,6 +296,7 @@ static const std::map<llm_kv, const char *> LLM_KV_NAMES = {
|
||||
{ LLM_KV_HYPER_CONNECTION_COUNT, "%s.hyper_connection.count" },
|
||||
{ LLM_KV_HYPER_CONNECTION_SINKHORN_ITERATIONS, "%s.hyper_connection.sinkhorn_iterations" },
|
||||
{ LLM_KV_HYPER_CONNECTION_EPSILON, "%s.hyper_connection.epsilon" },
|
||||
{ LLM_KV_HYPER_CONNECTION_MAGNITUDE, "%s.hyper_connection.magnitude" },
|
||||
{ LLM_KV_HYPER_CONNECTION_LOW_RANK, "%s.hyper_connection.low_rank" },
|
||||
|
||||
{ LLM_KV_PLE_LAYERS, "%s.ple.layers" },
|
||||
@@ -1130,6 +1133,7 @@ bool llm_arch_supports_sm_tensor(const llm_arch & arch) {
|
||||
case LLM_ARCH_OLMOE:
|
||||
case LLM_ARCH_DEEPSEEK2:
|
||||
case LLM_ARCH_DEEPSEEK32:
|
||||
case LLM_ARCH_HY_V4:
|
||||
case LLM_ARCH_DOTS3NOTE:
|
||||
case LLM_ARCH_GLM_DSA:
|
||||
case LLM_ARCH_BITNET:
|
||||
|
||||
@@ -126,6 +126,7 @@ enum llm_arch {
|
||||
LLM_ARCH_HUNYUAN_DENSE,
|
||||
LLM_ARCH_HUNYUAN_VL,
|
||||
LLM_ARCH_HY_V3,
|
||||
LLM_ARCH_HY_V4,
|
||||
LLM_ARCH_SMOLLM3,
|
||||
LLM_ARCH_OPENAI_MOE,
|
||||
LLM_ARCH_LFM2,
|
||||
@@ -146,6 +147,7 @@ enum llm_arch {
|
||||
LLM_ARCH_PADDLEOCR,
|
||||
LLM_ARCH_MIMO2,
|
||||
LLM_ARCH_STEP35,
|
||||
LLM_ARCH_SPARK2_5,
|
||||
LLM_ARCH_LLAMA_EMBED,
|
||||
LLM_ARCH_MAINCODER,
|
||||
LLM_ARCH_KIMI_LINEAR,
|
||||
@@ -299,6 +301,7 @@ enum llm_kv {
|
||||
LLM_KV_HYPER_CONNECTION_COUNT,
|
||||
LLM_KV_HYPER_CONNECTION_SINKHORN_ITERATIONS,
|
||||
LLM_KV_HYPER_CONNECTION_EPSILON,
|
||||
LLM_KV_HYPER_CONNECTION_MAGNITUDE,
|
||||
LLM_KV_HYPER_CONNECTION_LOW_RANK,
|
||||
|
||||
LLM_KV_PLE_LAYERS,
|
||||
|
||||
@@ -2317,7 +2317,8 @@ uint32_t llama_context::graph_max_nodes(uint32_t n_tokens) const {
|
||||
(model.arch == LLM_ARCH_DFLASH && model.hparams.dsv4_hc_mult > 0) ||
|
||||
model.arch == LLM_ARCH_NANBEIGE ||
|
||||
model.arch == LLM_ARCH_MINIMAX_01 ||
|
||||
model.arch == LLM_ARCH_MINIMAX_M3) {
|
||||
model.arch == LLM_ARCH_MINIMAX_M3 ||
|
||||
model.arch == LLM_ARCH_HY_V4) {
|
||||
res = std::max<uint32_t>(n_tokens * 40, 32u * model.n_tensors());
|
||||
} else if (model.arch == LLM_ARCH_DFLASH && model.hparams.dflash_selector_rank > 0) {
|
||||
// DFlash2's convolutions and selector are shape work rather than matmuls,
|
||||
|
||||
@@ -492,7 +492,7 @@ const char * llama_grammar_parser::parse_sequence(
|
||||
total_rules = min_times;
|
||||
}
|
||||
|
||||
if (n_prev_rules * total_rules >= MAX_REPETITION_THRESHOLD) {
|
||||
if (n_prev_rules * total_rules > MAX_REPETITION_THRESHOLD) {
|
||||
throw std::runtime_error("number of rules that are going to be repeated multiplied by the new repetition exceeds sane defaults, please reduce the number of repetitions or rule complexity");
|
||||
}
|
||||
|
||||
|
||||
+86
-31
@@ -566,7 +566,10 @@ void llm_graph_input_attn_k_dsa::set_input(const llama_ubatch * ubatch) {
|
||||
|
||||
mctx->get_lid()->set_input_kq_mask(self_kq_mask_lid, ubatch, cparams.causal_attn);
|
||||
|
||||
mctx->get_lid()->set_input_k_rot(self_k_rot_lid);
|
||||
// left unallocated when the indexer does not use the rotation
|
||||
if (self_k_rot_lid && self_k_rot_lid->buffer) {
|
||||
mctx->get_lid()->set_input_k_rot(self_k_rot_lid);
|
||||
}
|
||||
}
|
||||
|
||||
bool llm_graph_input_attn_k_dsa::can_reuse(const llm_graph_params & params) {
|
||||
@@ -1620,8 +1623,26 @@ llm_graph_qkv llm_graph_context::build_qkv(
|
||||
int64_t n_head,
|
||||
int64_t n_head_kv,
|
||||
int il) const {
|
||||
const int64_t n_embd_q = n_embd_head * n_head;
|
||||
const int64_t n_embd_kv = n_embd_head * n_head_kv;
|
||||
return build_qkv(layer, cur,
|
||||
n_embd_head, n_head,
|
||||
n_embd_head, n_head_kv,
|
||||
n_embd_head, n_head_kv,
|
||||
il);
|
||||
}
|
||||
|
||||
llm_graph_qkv llm_graph_context::build_qkv(
|
||||
const llama_layer & layer,
|
||||
ggml_tensor * cur,
|
||||
int64_t n_embd_head_q,
|
||||
int64_t n_head_q,
|
||||
int64_t n_embd_head_k,
|
||||
int64_t n_head_k,
|
||||
int64_t n_embd_head_v,
|
||||
int64_t n_head_v,
|
||||
int il,
|
||||
bool reshape) const {
|
||||
const int64_t n_embd_q = n_embd_head_q * n_head_q;
|
||||
const int64_t n_embd_k = n_embd_head_k * n_head_k;
|
||||
|
||||
ggml_tensor * Qcur, * Kcur, * Vcur;
|
||||
|
||||
@@ -1632,59 +1653,93 @@ llm_graph_qkv llm_graph_context::build_qkv(
|
||||
if (layer.wqkv_b) {
|
||||
qkv = ggml_add(ctx0, qkv, layer.wqkv_b);
|
||||
cb(qkv, "wqkv_b", il);
|
||||
} else if (layer.wq_b && layer.wk_b && layer.wv_b) {
|
||||
// Fused weights may coexist with separate Q/K/V biases in legacy or custom GGUFs.
|
||||
ggml_tensor * qkv_b = ggml_concat(ctx0, ggml_concat(ctx0, layer.wq_b, layer.wk_b, 0), layer.wv_b, 0);
|
||||
qkv = ggml_add(ctx0, qkv, qkv_b);
|
||||
cb(qkv, "wqkv_b", il);
|
||||
}
|
||||
if (hparams.f_clamp_kqv > 0.0f) {
|
||||
if (reshape && hparams.f_clamp_kqv > 0.0f) {
|
||||
qkv = ggml_clamp(ctx0, qkv, -hparams.f_clamp_kqv, hparams.f_clamp_kqv);
|
||||
cb(qkv, "wqkv_clamped", il);
|
||||
}
|
||||
Qcur = ggml_view_3d(ctx0, qkv, n_embd_head, n_head, n_tokens,
|
||||
ggml_row_size(qkv->type, n_embd_head), qkv->nb[1], 0);
|
||||
Kcur = ggml_view_3d(ctx0, qkv, n_embd_head, n_head_kv, n_tokens,
|
||||
ggml_row_size(qkv->type, n_embd_head), qkv->nb[1],
|
||||
ggml_row_size(qkv->type, n_embd_q));
|
||||
Vcur = ggml_view_3d(ctx0, qkv, n_embd_head, n_head_kv, n_tokens,
|
||||
ggml_row_size(qkv->type, n_embd_head), qkv->nb[1],
|
||||
ggml_row_size(qkv->type, n_embd_q + n_embd_kv));
|
||||
if (reshape) {
|
||||
Qcur = ggml_view_3d(ctx0, qkv, n_embd_head_q, n_head_q, n_tokens,
|
||||
ggml_row_size(qkv->type, n_embd_head_q), qkv->nb[1], 0);
|
||||
Kcur = ggml_view_3d(ctx0, qkv, n_embd_head_k, n_head_k, n_tokens,
|
||||
ggml_row_size(qkv->type, n_embd_head_k), qkv->nb[1],
|
||||
ggml_row_size(qkv->type, n_embd_q));
|
||||
Vcur = ggml_view_3d(ctx0, qkv, n_embd_head_v, n_head_v, n_tokens,
|
||||
ggml_row_size(qkv->type, n_embd_head_v), qkv->nb[1],
|
||||
ggml_row_size(qkv->type, n_embd_q + n_embd_k));
|
||||
} else {
|
||||
Qcur = ggml_view_2d(ctx0, qkv, n_embd_q, n_tokens, qkv->nb[1], 0);
|
||||
Kcur = ggml_view_2d(ctx0, qkv, n_embd_k, n_tokens, qkv->nb[1],
|
||||
ggml_row_size(qkv->type, n_embd_q));
|
||||
Vcur = ggml_view_2d(ctx0, qkv, n_embd_head_v * n_head_v, n_tokens, qkv->nb[1],
|
||||
ggml_row_size(qkv->type, n_embd_q + n_embd_k));
|
||||
}
|
||||
if (!reshape) {
|
||||
Qcur = ggml_cont(ctx0, Qcur);
|
||||
Kcur = ggml_cont(ctx0, Kcur);
|
||||
Vcur = ggml_cont(ctx0, Vcur);
|
||||
}
|
||||
} else {
|
||||
// separate Q/K/V path
|
||||
Qcur = build_lora_mm(layer.wq, cur, layer.wq_s);
|
||||
cb(Qcur, "Qcur", il);
|
||||
if (layer.wq_b) {
|
||||
Qcur = ggml_add(ctx0, Qcur, layer.wq_b);
|
||||
if (reshape) {
|
||||
cb(Qcur, "Qcur", il);
|
||||
}
|
||||
if (hparams.f_clamp_kqv > 0.0f) {
|
||||
if (layer.wq_b) {
|
||||
Qcur = ggml_add(ctx0, Qcur, layer.wq_b);
|
||||
if (reshape) {
|
||||
cb(Qcur, "Qcur", il);
|
||||
}
|
||||
}
|
||||
if (reshape && hparams.f_clamp_kqv > 0.0f) {
|
||||
Qcur = ggml_clamp(ctx0, Qcur, -hparams.f_clamp_kqv, hparams.f_clamp_kqv);
|
||||
cb(Qcur, "Qcur_clamped", il);
|
||||
}
|
||||
Kcur = build_lora_mm(layer.wk, cur, layer.wk_s);
|
||||
cb(Kcur, "Kcur", il);
|
||||
if (layer.wk_b) {
|
||||
Kcur = ggml_add(ctx0, Kcur, layer.wk_b);
|
||||
if (reshape) {
|
||||
cb(Kcur, "Kcur", il);
|
||||
}
|
||||
if (hparams.f_clamp_kqv > 0.0f) {
|
||||
if (layer.wk_b) {
|
||||
Kcur = ggml_add(ctx0, Kcur, layer.wk_b);
|
||||
if (reshape) {
|
||||
cb(Kcur, "Kcur", il);
|
||||
}
|
||||
}
|
||||
if (reshape && hparams.f_clamp_kqv > 0.0f) {
|
||||
Kcur = ggml_clamp(ctx0, Kcur, -hparams.f_clamp_kqv, hparams.f_clamp_kqv);
|
||||
cb(Kcur, "Kcur_clamped", il);
|
||||
}
|
||||
Vcur = build_lora_mm(layer.wv, cur, layer.wv_s);
|
||||
cb(Vcur, "Vcur", il);
|
||||
if (layer.wv_b) {
|
||||
Vcur = ggml_add(ctx0, Vcur, layer.wv_b);
|
||||
if (reshape) {
|
||||
cb(Vcur, "Vcur", il);
|
||||
}
|
||||
if (hparams.f_clamp_kqv > 0.0f) {
|
||||
if (layer.wv_b) {
|
||||
Vcur = ggml_add(ctx0, Vcur, layer.wv_b);
|
||||
if (reshape) {
|
||||
cb(Vcur, "Vcur", il);
|
||||
}
|
||||
}
|
||||
if (reshape && hparams.f_clamp_kqv > 0.0f) {
|
||||
Vcur = ggml_clamp(ctx0, Vcur, -hparams.f_clamp_kqv, hparams.f_clamp_kqv);
|
||||
cb(Vcur, "Vcur_clamped", il);
|
||||
}
|
||||
Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens);
|
||||
Kcur = ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens);
|
||||
Vcur = ggml_reshape_3d(ctx0, Vcur, n_embd_head, n_head_kv, n_tokens);
|
||||
if (reshape) {
|
||||
Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head_q, n_head_q, n_tokens);
|
||||
Kcur = ggml_reshape_3d(ctx0, Kcur, n_embd_head_k, n_head_k, n_tokens);
|
||||
Vcur = ggml_reshape_3d(ctx0, Vcur, n_embd_head_v, n_head_v, n_tokens);
|
||||
}
|
||||
}
|
||||
|
||||
cb(Qcur, "Qcur", il);
|
||||
cb(Kcur, "Kcur", il);
|
||||
cb(Vcur, "Vcur", il);
|
||||
if (reshape) {
|
||||
cb(Qcur, "Qcur", il);
|
||||
cb(Kcur, "Kcur", il);
|
||||
cb(Vcur, "Vcur", il);
|
||||
}
|
||||
|
||||
return { Qcur, Kcur, Vcur };
|
||||
}
|
||||
@@ -2170,7 +2225,7 @@ ggml_tensor * llm_graph_context::build_moe_ffn(
|
||||
const float limit = hparams.swiglu_clamp_exp[il];
|
||||
constexpr float eps = 1e-6f;
|
||||
if (limit > eps) {
|
||||
if (arch == LLM_ARCH_DEEPSEEK4 || (arch == LLM_ARCH_DFLASH && hparams.dsv4_hc_mult > 0)) {
|
||||
if (arch == LLM_ARCH_DEEPSEEK4 || (arch == LLM_ARCH_DFLASH && hparams.dsv4_hc_mult > 0) || arch == LLM_ARCH_HY_V4) {
|
||||
cur = ggml_swiglu_clamp(ctx0, cur, up, limit);
|
||||
} else {
|
||||
up = ggml_clamp(ctx0, up, -limit, limit);
|
||||
|
||||
@@ -1079,6 +1079,19 @@ struct llm_graph_context {
|
||||
int64_t n_head_kv,
|
||||
int il) const;
|
||||
|
||||
// Set reshape to false to return contiguous projections before clamp/reshape.
|
||||
llm_graph_qkv build_qkv(
|
||||
const llama_layer & layer,
|
||||
ggml_tensor * cur,
|
||||
int64_t n_embd_head_q,
|
||||
int64_t n_head_q,
|
||||
int64_t n_embd_head_k,
|
||||
int64_t n_head_k,
|
||||
int64_t n_embd_head_v,
|
||||
int64_t n_head_v,
|
||||
int il,
|
||||
bool reshape = true) const;
|
||||
|
||||
ggml_tensor * build_ffn(
|
||||
ggml_tensor * cur,
|
||||
ggml_tensor * up,
|
||||
|
||||
@@ -297,6 +297,9 @@ struct llama_hparams {
|
||||
// 0 = full rank (DeepSeek-V4)
|
||||
uint32_t hc_low_rank = 0;
|
||||
|
||||
// scale of the hyper-connection post gate (DeepSeek-V4 hardcodes 2.0)
|
||||
float hc_magnitude = 0.0f;
|
||||
|
||||
uint32_t ple_ngram_size = 0;
|
||||
uint32_t ple_heads_per_ngram = 0;
|
||||
uint32_t ple_conv_kernel = 0;
|
||||
|
||||
@@ -27,6 +27,7 @@ bool llama_model_saver_supports_arch(llm_arch arch) {
|
||||
case LLM_ARCH_APERTUS:
|
||||
case LLM_ARCH_MIMO2:
|
||||
case LLM_ARCH_STEP35:
|
||||
case LLM_ARCH_SPARK2_5:
|
||||
case LLM_ARCH_MUSE_GLIMMER:
|
||||
case LLM_ARCH_MELLUM:
|
||||
case LLM_ARCH_LAGUNA:
|
||||
@@ -314,6 +315,7 @@ void llama_model_saver::add_kv_from_model() {
|
||||
add_kv(LLM_KV_HYPER_CONNECTION_COUNT, hparams.dsv4_hc_mult);
|
||||
add_kv(LLM_KV_HYPER_CONNECTION_SINKHORN_ITERATIONS, hparams.dsv4_hc_sinkhorn_iters);
|
||||
add_kv(LLM_KV_HYPER_CONNECTION_EPSILON, hparams.dsv4_hc_eps);
|
||||
add_kv(LLM_KV_HYPER_CONNECTION_MAGNITUDE, hparams.hc_magnitude);
|
||||
add_kv(LLM_KV_HASH_LAYER_COUNT, hparams.dsv4_hash_layer_count);
|
||||
add_kv(LLM_KV_HYPER_CONNECTION_LOW_RANK, hparams.hc_low_rank);
|
||||
|
||||
|
||||
+57
-1
@@ -288,6 +288,8 @@ static llama_model * llama_model_mapping(llm_arch arch, const llama_model_params
|
||||
return new llama_model_hunyuan_dense(params);
|
||||
case LLM_ARCH_HY_V3:
|
||||
return new llama_model_hy_v3(params);
|
||||
case LLM_ARCH_HY_V4:
|
||||
return new llama_model_hy_v4(params);
|
||||
case LLM_ARCH_SMOLLM3:
|
||||
return new llama_model_smollm3(params);
|
||||
case LLM_ARCH_OPENAI_MOE:
|
||||
@@ -336,6 +338,8 @@ static llama_model * llama_model_mapping(llm_arch arch, const llama_model_params
|
||||
return new llama_model_kimi_k3(params);
|
||||
case LLM_ARCH_STEP35:
|
||||
return new llama_model_step35(params);
|
||||
case LLM_ARCH_SPARK2_5:
|
||||
return new llama_model_spark2_5(params);
|
||||
default:
|
||||
throw std::runtime_error(std::string("unsupported model architecture: '") + llm_arch_name(arch) + "'");
|
||||
}
|
||||
@@ -2053,7 +2057,8 @@ void llama_model::print_info() const {
|
||||
|
||||
if (arch == LLM_ARCH_DEEPSEEK2 || arch == LLM_ARCH_DEEPSEEK2OCR ||
|
||||
arch == LLM_ARCH_DEEPSEEK32 || arch == LLM_ARCH_GLM_DSA ||
|
||||
arch == LLM_ARCH_DOTS3NOTE || arch == LLM_ARCH_MISTRAL4) {
|
||||
arch == LLM_ARCH_DOTS3NOTE || arch == LLM_ARCH_MISTRAL4 ||
|
||||
arch == LLM_ARCH_HY_V4) {
|
||||
LLAMA_LOG_INFO("%s: n_layer_dense_lead = %d\n", __func__, hparams.n_layer_dense_lead);
|
||||
LLAMA_LOG_INFO("%s: n_lora_q = %d\n", __func__, hparams.n_lora_q);
|
||||
LLAMA_LOG_INFO("%s: n_lora_kv = %d\n", __func__, hparams.n_lora_kv);
|
||||
@@ -2322,6 +2327,48 @@ llama_memory_i * llama_model::create_memory(const llama_memory_params & params,
|
||||
nullptr);
|
||||
}
|
||||
} break;
|
||||
case LLM_ARCH_HY_V4:
|
||||
{
|
||||
if (hparams.indexer_top_k == 0) {
|
||||
// full-attention checkpoint: no indexer, so no indexer key cache
|
||||
res = new llama_kv_cache(
|
||||
*this,
|
||||
hparams,
|
||||
params.type_k,
|
||||
params.type_v,
|
||||
!cparams.flash_attn,
|
||||
cparams.offload_kqv,
|
||||
cparams.kv_unified,
|
||||
cparams.n_ctx_seq,
|
||||
cparams.n_seq_max,
|
||||
1,
|
||||
hparams.n_swa,
|
||||
hparams.swa_type,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr);
|
||||
} else {
|
||||
// only "full" layers own an indexer, so the shared layers need no indexer cache
|
||||
llama_kv_cache::layer_filter_cb filter_lid = [&](uint32_t il) { return hparams.is_indexer_full(il); };
|
||||
|
||||
res = new llama_kv_cache_dsa(
|
||||
*this,
|
||||
params.type_k,
|
||||
params.type_v,
|
||||
!cparams.flash_attn,
|
||||
cparams.offload_kqv,
|
||||
cparams.kv_unified,
|
||||
cparams.n_ctx_seq,
|
||||
cparams.n_seq_max,
|
||||
1,
|
||||
hparams.n_swa,
|
||||
hparams.swa_type,
|
||||
nullptr,
|
||||
filter_lid,
|
||||
nullptr);
|
||||
}
|
||||
} break;
|
||||
case LLM_ARCH_DOTS3NOTE:
|
||||
{
|
||||
GGML_ASSERT(hparams.swa_type != LLAMA_SWA_TYPE_NONE);
|
||||
@@ -2881,6 +2928,8 @@ llama_rope_type llama_model_rope_type(const llama_model * model) {
|
||||
case LLM_ARCH_DOTS3NOTE:
|
||||
case LLM_ARCH_NANBEIGE:
|
||||
case LLM_ARCH_POCKETTTS:
|
||||
// HY_V4 rotates consecutive pairs, matching the reference implementation
|
||||
case LLM_ARCH_HY_V4:
|
||||
return LLAMA_ROPE_TYPE_NORM;
|
||||
|
||||
// the pairs of head values are offset by n_rot/2
|
||||
@@ -2952,6 +3001,7 @@ llama_rope_type llama_model_rope_type(const llama_model * model) {
|
||||
case LLM_ARCH_QWEN3NEXT:
|
||||
case LLM_ARCH_MIMO2:
|
||||
case LLM_ARCH_STEP35:
|
||||
case LLM_ARCH_SPARK2_5:
|
||||
case LLM_ARCH_TALKIE:
|
||||
case LLM_ARCH_MELLUM:
|
||||
return LLAMA_ROPE_TYPE_NEOX;
|
||||
@@ -3186,6 +3236,12 @@ void llama_model_base::create_tensor_qkv(llama_layer & layer, int bid,
|
||||
layer.wqkv = create_tensor(tn(LLM_TENSOR_ATTN_QKV, "weight", bid), {n_embd_, n_embd_qkv}, TENSOR_NOT_REQUIRED | TENSOR_SKIP_IF_VIRTUAL);
|
||||
if (layer.wqkv) {
|
||||
layer.wqkv_b = create_tensor(tn(LLM_TENSOR_ATTN_QKV, "bias", bid), {n_embd_qkv}, TENSOR_NOT_REQUIRED | TENSOR_SKIP_IF_VIRTUAL);
|
||||
// Fused weights may coexist with separate Q/K/V biases in legacy or custom GGUFs.
|
||||
if (!layer.wqkv_b) {
|
||||
layer.wq_b = create_tensor(tn(LLM_TENSOR_ATTN_Q, "bias", bid), {n_embd_q_}, TENSOR_NOT_REQUIRED);
|
||||
layer.wk_b = create_tensor(tn(LLM_TENSOR_ATTN_K, "bias", bid), {n_embd_k_}, TENSOR_NOT_REQUIRED);
|
||||
layer.wv_b = create_tensor(tn(LLM_TENSOR_ATTN_V, "bias", bid), {n_embd_v_}, TENSOR_NOT_REQUIRED);
|
||||
}
|
||||
} else {
|
||||
layer.wq = create_tensor(tn(LLM_TENSOR_ATTN_Q, "weight", bid), {n_embd_, n_embd_q_}, flags);
|
||||
layer.wk = create_tensor(tn(LLM_TENSOR_ATTN_K, "weight", bid), {n_embd_, n_embd_k_}, flags);
|
||||
|
||||
@@ -318,12 +318,21 @@ struct llm_tokenizer_bpe : llm_tokenizer {
|
||||
case LLAMA_VOCAB_PRE_TYPE_DEEPSEEK3_LLM:
|
||||
case LLAMA_VOCAB_PRE_TYPE_HUNYUAN_DENSE:
|
||||
case LLAMA_VOCAB_PRE_TYPE_JOYAI_LLM:
|
||||
case LLAMA_VOCAB_PRE_TYPE_HY_V4:
|
||||
regex_exprs = {
|
||||
"\\p{N}{1,3}",
|
||||
"[一-龥-ゟ゠-ヿ]+",
|
||||
"[!\"#$%&'()*+,\\-./:;<=>?@\\[\\\\\\]^_`{|}~][A-Za-z]+|[^\r\n\\p{L}\\p{P}\\p{S}]?[\\p{L}\\p{M}]+| ?[\\p{P}\\p{S}]+[\r\n]*|\\s*[\r\n]+|\\s+(?!\\S)|\\s+",
|
||||
};
|
||||
break;
|
||||
case LLAMA_VOCAB_PRE_TYPE_SPARK2_5:
|
||||
regex_exprs = {
|
||||
"\\p{N}{1,3}",
|
||||
"[一-龥-ゟ゠-ヿ]+",
|
||||
"[!\"#$%&'()*+,\\-./:;<=>?@\\[\\\\\\]^_`{|}~][A-Za-z]+|[^\r\n\\p{L}\\p{P}\\p{S}]?[\\p{L}\\p{M}]+| ?[\\p{P}\\p{S}]+|[\r\n]|\\s+(?!\\S)|\\s+",
|
||||
"\\p{N}",
|
||||
};
|
||||
break;
|
||||
case LLAMA_VOCAB_PRE_TYPE_YOUTU:
|
||||
regex_exprs = {
|
||||
"[가-힣ㄱ-ㆎ]+|[!…“”‘’—:;,、-〿︰-﹏]+|[ㄅ-ㄯ]+|[一-龥-ゟ゠-ヿ]+",
|
||||
@@ -2169,6 +2178,10 @@ void llama_vocab::impl::load(llama_model_loader & ml, const LLM_KV & kv) {
|
||||
tokenizer_pre == "deepseek-v3") {
|
||||
pre_type = LLAMA_VOCAB_PRE_TYPE_DEEPSEEK3_LLM;
|
||||
clean_spaces = false;
|
||||
} else if (
|
||||
tokenizer_pre == "spark2_5") {
|
||||
pre_type = LLAMA_VOCAB_PRE_TYPE_SPARK2_5;
|
||||
clean_spaces = false;
|
||||
} else if (
|
||||
tokenizer_pre == "youtu") {
|
||||
pre_type = LLAMA_VOCAB_PRE_TYPE_YOUTU;
|
||||
@@ -2350,6 +2363,10 @@ void llama_vocab::impl::load(llama_model_loader & ml, const LLM_KV & kv) {
|
||||
tokenizer_pre == "hunyuan-dense") {
|
||||
pre_type = LLAMA_VOCAB_PRE_TYPE_HUNYUAN_DENSE;
|
||||
clean_spaces = false;
|
||||
} else if (
|
||||
tokenizer_pre == "hy_v4") {
|
||||
pre_type = LLAMA_VOCAB_PRE_TYPE_HY_V4;
|
||||
clean_spaces = false;
|
||||
} else if (
|
||||
tokenizer_pre == "joyai-llm") {
|
||||
pre_type = LLAMA_VOCAB_PRE_TYPE_JOYAI_LLM;
|
||||
|
||||
@@ -65,6 +65,8 @@ enum llama_vocab_pre_type {
|
||||
LLAMA_VOCAB_PRE_TYPE_GRANITE_EMB_MULTI = 54,
|
||||
LLAMA_VOCAB_PRE_TYPE_MELLUM2 = 55,
|
||||
LLAMA_VOCAB_PRE_TYPE_LAGUNA = 56,
|
||||
LLAMA_VOCAB_PRE_TYPE_HY_V4 = 57,
|
||||
LLAMA_VOCAB_PRE_TYPE_SPARK2_5 = 58,
|
||||
};
|
||||
|
||||
struct LLM_KV;
|
||||
|
||||
@@ -280,8 +280,8 @@ llama_model_bailingmoe3::graph::graph(const llama_model & model, const llm_graph
|
||||
ggml_tensor * beta = ggml_mul_mat(ctx0, layer.ssm_beta, cur);
|
||||
beta = ggml_sigmoid(ctx0, ggml_reshape_4d(ctx0, beta, 1, n_head, n_seq_tokens, n_seqs));
|
||||
|
||||
q = ggml_l2_norm(ctx0, q, hparams.f_norm_rms_eps);
|
||||
k = ggml_l2_norm(ctx0, k, hparams.f_norm_rms_eps);
|
||||
q = build_gdn_l2_norm(ctx0, q, hparams.f_norm_rms_eps);
|
||||
k = build_gdn_l2_norm(ctx0, k, hparams.f_norm_rms_eps);
|
||||
|
||||
ggml_tensor * states_all = mctx_cur->get_s_l(il);
|
||||
ggml_tensor * state = build_rs(inp_rs, states_all, hparams.n_embd_s(), n_seqs);
|
||||
|
||||
@@ -475,21 +475,12 @@ llama_model_deepseek2::graph::graph(const llama_model & model, const llm_graph_p
|
||||
const int ocr_rope_type = GGML_ROPE_TYPE_NEOX;
|
||||
GGML_ASSERT(n_embed_head == n_embd_head_k && n_embed_head == n_embd_head_v);
|
||||
|
||||
ggml_tensor * Qcur = NULL;
|
||||
ggml_tensor * Kcur = NULL;
|
||||
ggml_tensor * Vcur = NULL;
|
||||
|
||||
Qcur = ggml_mul_mat(ctx0, model.layers[il].wq, cur);
|
||||
Kcur = ggml_mul_mat(ctx0, model.layers[il].wk, cur);
|
||||
Vcur = ggml_mul_mat(ctx0, model.layers[il].wv, cur);
|
||||
auto [Qcur, Kcur, Vcur] = build_qkv(model.layers[il], cur,
|
||||
n_embed_head, n_head, n_head, il);
|
||||
cb(Qcur, "q", il);
|
||||
cb(Kcur, "k", il);
|
||||
cb(Vcur, "v", il);
|
||||
|
||||
Qcur = ggml_reshape_3d(ctx0, Qcur, n_embed_head, n_head, n_tokens);
|
||||
Kcur = ggml_reshape_3d(ctx0, Kcur, n_embed_head, n_head, n_tokens);
|
||||
Vcur = ggml_reshape_3d(ctx0, Vcur, n_embed_head, n_head, n_tokens);
|
||||
|
||||
GGML_ASSERT(fabs(freq_base - 10000.0) < 1e-4);
|
||||
Qcur = ggml_rope_ext(ctx0, Qcur, inp_pos, nullptr, n_embed_head, ocr_rope_type, 0, freq_base, 1, 0, 1, 0, 0);
|
||||
Kcur = ggml_rope_ext(ctx0, Kcur, inp_pos, nullptr, n_embed_head, ocr_rope_type, 0, freq_base, 1, 0, 1, 0, 0);
|
||||
|
||||
@@ -40,9 +40,7 @@ void llama_model_deepseek2ocr::load_arch_tensors(llama_model_loader &) {
|
||||
for (int i = 0; i < n_layer; ++i) {
|
||||
auto & layer = layers[i];
|
||||
|
||||
layer.wq = create_tensor(tn(LLM_TENSOR_ATTN_Q, "weight", i), {n_embd, n_embd}, 0);
|
||||
layer.wk = create_tensor(tn(LLM_TENSOR_ATTN_K, "weight", i), {n_embd, n_embd}, 0);
|
||||
layer.wv = create_tensor(tn(LLM_TENSOR_ATTN_V, "weight", i), {n_embd, n_embd}, 0);
|
||||
create_tensor_qkv(layer, i, n_embd, n_embd, n_embd, n_embd, 0);
|
||||
layer.wo = create_tensor(tn(LLM_TENSOR_ATTN_OUT, "weight", i), {n_embd, n_embd}, 0);
|
||||
|
||||
// norm
|
||||
|
||||
@@ -176,7 +176,14 @@ llama_model_gemma3n::graph::graph(const llama_model & model, const llm_graph_par
|
||||
hparams.f_attention_scale, il);
|
||||
} else {
|
||||
// reuse KV cache of earlier layers
|
||||
ggml_tensor * Qcur = build_lora_mm(model.layers[il].wq, cur);
|
||||
ggml_tensor * Qcur;
|
||||
if (model.layers[il].wqkv) {
|
||||
ggml_tensor * qkv = build_lora_mm(model.layers[il].wqkv, cur);
|
||||
const int64_t q_dim = n_embd_head * n_head;
|
||||
Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, qkv, q_dim, n_tokens, qkv->nb[1], 0));
|
||||
} else {
|
||||
Qcur = build_lora_mm(model.layers[il].wq, cur);
|
||||
}
|
||||
cb(Qcur, "Qcur", il);
|
||||
Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens);
|
||||
|
||||
|
||||
+31
-9
@@ -75,9 +75,13 @@ void llama_model_gemma4::load_arch_tensors(llama_model_loader &) {
|
||||
layer.attn_norm = create_tensor(tn(LLM_TENSOR_ATTN_NORM, "weight", i), {n_embd}, 0);
|
||||
|
||||
// note: use_alternative_attention (v_proj is optional, if it's not present, use k_proj)
|
||||
layer.wq = create_tensor(tn(LLM_TENSOR_ATTN_Q, "weight", i), {n_embd, n_embd_head * n_head}, 0);
|
||||
layer.wk = create_tensor(tn(LLM_TENSOR_ATTN_K, "weight", i), {n_embd, n_embd_k}, kv_flags);
|
||||
layer.wv = create_tensor(tn(LLM_TENSOR_ATTN_V, "weight", i), {n_embd, n_embd_v}, TENSOR_NOT_REQUIRED);
|
||||
layer.wqkv = create_tensor(tn(LLM_TENSOR_ATTN_QKV, "weight", i),
|
||||
{n_embd, n_embd_head * n_head + n_embd_k + n_embd_v}, TENSOR_NOT_REQUIRED | TENSOR_SKIP_IF_VIRTUAL);
|
||||
if (!layer.wqkv) {
|
||||
layer.wq = create_tensor(tn(LLM_TENSOR_ATTN_Q, "weight", i), {n_embd, n_embd_head * n_head}, 0);
|
||||
layer.wk = create_tensor(tn(LLM_TENSOR_ATTN_K, "weight", i), {n_embd, n_embd_k}, kv_flags);
|
||||
layer.wv = create_tensor(tn(LLM_TENSOR_ATTN_V, "weight", i), {n_embd, n_embd_v}, TENSOR_NOT_REQUIRED);
|
||||
}
|
||||
layer.wo = create_tensor(tn(LLM_TENSOR_ATTN_OUT, "weight", i), {n_embd_head * n_head, n_embd}, 0);
|
||||
|
||||
layer.attn_q_norm = create_tensor(tn(LLM_TENSOR_ATTN_Q_NORM, "weight", i), {n_embd_head}, 0);
|
||||
@@ -202,9 +206,17 @@ llama_model_gemma4::graph::graph(const llama_model & model, const llm_graph_para
|
||||
|
||||
// Q projection (shared for both non-KV and KV layers)
|
||||
// this is to mirror Gemma4Attention in pytorch code
|
||||
ggml_tensor * qkv_fused = nullptr;
|
||||
ggml_tensor * Qcur;
|
||||
{
|
||||
if (model.layers[il].wqkv) {
|
||||
qkv_fused = build_lora_mm(model.layers[il].wqkv, cur, model.layers[il].wqkv_s);
|
||||
cb(qkv_fused, "wqkv", il);
|
||||
const int64_t q_dim = n_embd_head * n_head;
|
||||
Qcur = ggml_cont(ctx0, ggml_view_2d(ctx0, qkv_fused, q_dim, n_tokens, qkv_fused->nb[1], 0));
|
||||
} else {
|
||||
Qcur = build_lora_mm(model.layers[il].wq, cur, model.layers[il].wq_s);
|
||||
}
|
||||
{
|
||||
cb(Qcur, "Qcur", il);
|
||||
|
||||
Qcur = ggml_reshape_3d(ctx0, Qcur, n_embd_head, n_head, n_tokens);
|
||||
@@ -219,12 +231,22 @@ llama_model_gemma4::graph::graph(const llama_model & model, const llm_graph_para
|
||||
|
||||
// self-attention
|
||||
if (hparams.has_kv(il)) {
|
||||
ggml_tensor * Kcur = build_lora_mm(model.layers[il].wk, cur, model.layers[il].wk_s);
|
||||
ggml_tensor * Kcur;
|
||||
ggml_tensor * Vcur;
|
||||
if (qkv_fused) {
|
||||
const int64_t q_dim = n_embd_head * n_head;
|
||||
const int64_t k_dim = n_embd_head * n_head_kv;
|
||||
const int64_t v_dim = n_embd_head * n_head_kv;
|
||||
const size_t esize = ggml_element_size(qkv_fused);
|
||||
Kcur = ggml_cont(ctx0, ggml_view_2d(ctx0, qkv_fused, k_dim, n_tokens, qkv_fused->nb[1], q_dim * esize));
|
||||
Vcur = ggml_cont(ctx0, ggml_view_2d(ctx0, qkv_fused, v_dim, n_tokens, qkv_fused->nb[1], (q_dim + k_dim) * esize));
|
||||
} else {
|
||||
Kcur = build_lora_mm(model.layers[il].wk, cur, model.layers[il].wk_s);
|
||||
Vcur = model.layers[il].wv
|
||||
? build_lora_mm(model.layers[il].wv, cur, model.layers[il].wv_s)
|
||||
: Kcur; // if v_proj is not present, use Kcur as Vcur
|
||||
}
|
||||
cb(Kcur, "Kcur", il);
|
||||
|
||||
ggml_tensor * Vcur = model.layers[il].wv
|
||||
? build_lora_mm(model.layers[il].wv, cur, model.layers[il].wv_s)
|
||||
: Kcur; // if v_proj is not present, use Kcur as Vcur
|
||||
cb(Vcur, "Vcur", il);
|
||||
|
||||
Kcur = ggml_reshape_3d(ctx0, Kcur, n_embd_head, n_head_kv, n_tokens);
|
||||
|
||||
@@ -0,0 +1,601 @@
|
||||
#include "models.h"
|
||||
|
||||
#include "llama-kv-cache.h"
|
||||
#include "llama-kv-cache-dsa.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
// iHC (independent Hyper-Connections) helpers. Same layout as the DeepSeek-V4 HC, but without
|
||||
// the comb/sinkhorn term: hc_fn makes only 2*hc coefficients (pre + post). The streams mix
|
||||
// through the pre-reduce / post-distribute round trip instead.
|
||||
|
||||
static size_t hy_v4_elem_offset(const ggml_tensor * t, int64_t i) {
|
||||
return ggml_row_size(t->type, i);
|
||||
}
|
||||
|
||||
static ggml_tensor * hy_v4_view_1d(ggml_context * ctx, ggml_tensor * t, int64_t ne0, int64_t i0) {
|
||||
return ggml_view_1d(ctx, t, ne0, hy_v4_elem_offset(t, i0));
|
||||
}
|
||||
|
||||
static ggml_tensor * hy_v4_view_2d(ggml_context * ctx, ggml_tensor * t, int64_t ne0, int64_t ne1, int64_t i0) {
|
||||
return ggml_view_2d(ctx, t, ne0, ne1, t->nb[1], hy_v4_elem_offset(t, i0));
|
||||
}
|
||||
|
||||
void llama_model_hy_v4::load_arch_hparams(llama_model_loader & ml) {
|
||||
ml.get_key(LLM_KV_ATTENTION_LAYERNORM_RMS_EPS, hparams.f_norm_rms_eps);
|
||||
ml.get_key(LLM_KV_LEADING_DENSE_BLOCK_COUNT, hparams.n_layer_dense_lead, false);
|
||||
ml.get_key(LLM_KV_ATTENTION_Q_LORA_RANK, hparams.n_lora_q);
|
||||
ml.get_key(LLM_KV_ATTENTION_KV_LORA_RANK, hparams.n_lora_kv);
|
||||
ml.get_key(LLM_KV_ATTENTION_KEY_LENGTH_MLA, hparams.n_embd_head_k_mla_impl);
|
||||
ml.get_key(LLM_KV_ATTENTION_VALUE_LENGTH_MLA, hparams.n_embd_head_v_mla_impl);
|
||||
ml.get_key_or_arr(LLM_KV_EXPERT_FEED_FORWARD_LENGTH, hparams.n_ff_exp_arr, hparams.n_layer_all);
|
||||
ml.get_key(LLM_KV_EXPERT_SHARED_COUNT, hparams.n_expert_shared);
|
||||
ml.get_key(LLM_KV_EXPERT_WEIGHTS_SCALE, hparams.expert_weights_scale, false);
|
||||
ml.get_key(LLM_KV_EXPERT_WEIGHTS_NORM, hparams.expert_weights_norm, false);
|
||||
ml.get_key(LLM_KV_EXPERT_GATING_FUNC, hparams.expert_gating_func, false);
|
||||
|
||||
// routed-expert SwiGLU logits clamp (shared/dense experts are NOT clamped, so
|
||||
// swiglu_clamp_shexp is intentionally left at its 0 default)
|
||||
ml.get_key_or_arr(LLM_KV_SWIGLU_CLAMP_EXP, hparams.swiglu_clamp_exp, hparams.n_layer_all, false);
|
||||
|
||||
ml.get_key(LLM_KV_HYPER_CONNECTION_COUNT, hparams.dsv4_hc_mult);
|
||||
ml.get_key(LLM_KV_HYPER_CONNECTION_EPSILON, hparams.dsv4_hc_eps);
|
||||
ml.get_key(LLM_KV_HYPER_CONNECTION_MAGNITUDE, hparams.hc_magnitude);
|
||||
|
||||
// DSA is absent on the all-full_attention checkpoints, so indexer_top_k stays 0 there
|
||||
ml.get_key(LLM_KV_ATTENTION_INDEXER_HEAD_COUNT, hparams.indexer_n_head, false);
|
||||
ml.get_key(LLM_KV_ATTENTION_INDEXER_KEY_LENGTH, hparams.indexer_head_size, false);
|
||||
ml.get_key(LLM_KV_ATTENTION_INDEXER_TOP_K, hparams.indexer_top_k, false);
|
||||
|
||||
if (hparams.indexer_top_k > 0) {
|
||||
// the reference plumbs rms_norm_eps into the indexer k_norm LayerNorm, and build_norm
|
||||
// reads f_norm_eps for LLM_NORM
|
||||
hparams.f_norm_eps = hparams.f_norm_rms_eps;
|
||||
|
||||
if (hparams.indexer_n_head == 0 || hparams.indexer_head_size <= hparams.n_rot()) {
|
||||
throw std::runtime_error("hy_v4: bad indexer head count / key length");
|
||||
}
|
||||
|
||||
ml.get_key_or_arr(LLM_KV_ATTENTION_INDEXER_TYPES, hparams.is_indexer_full_impl, hparams.n_layer(), false);
|
||||
if (!hparams.is_indexer_full(0)) {
|
||||
throw std::runtime_error("hy_v4: layer 0 must own an indexer, nothing precedes it to share");
|
||||
}
|
||||
}
|
||||
|
||||
GGML_ASSERT(hparams.is_mla());
|
||||
|
||||
type = LLM_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
void llama_model_hy_v4::load_arch_tensors(llama_model_loader &) {
|
||||
LLAMA_LOAD_LOCALS;
|
||||
|
||||
const int64_t n_embd_head_k_mla = hparams.n_embd_head_k_mla();
|
||||
const int64_t n_embd_head_v_mla = hparams.n_embd_head_v_mla();
|
||||
const int64_t n_embd_head_qk_rope = hparams.n_rot();
|
||||
const int64_t n_embd_head_qk_nope = n_embd_head_k_mla - n_embd_head_qk_rope;
|
||||
GGML_ASSERT(n_embd_head_qk_nope >= 1);
|
||||
|
||||
const int64_t q_lora_rank = hparams.n_lora_q;
|
||||
const int64_t kv_lora_rank = hparams.n_lora_kv;
|
||||
const int64_t n_ff_exp = hparams.n_ff_exp();
|
||||
const int64_t n_expert_shared = hparams.n_expert_shared;
|
||||
const int64_t hc = hparams.dsv4_hc_mult;
|
||||
|
||||
tok_embd = create_tensor(tn(LLM_TENSOR_TOKEN_EMBD, "weight"), {n_embd, n_vocab}, 0);
|
||||
output_norm = create_tensor(tn(LLM_TENSOR_OUTPUT_NORM, "weight"), {n_embd}, 0);
|
||||
output = create_tensor(tn(LLM_TENSOR_OUTPUT, "weight"), {n_embd, n_vocab}, 0);
|
||||
|
||||
// global iHC head (collapses hc streams before the final norm)
|
||||
hc_head_fn = create_tensor(tn(LLM_TENSOR_HC_HEAD_FN, "weight"), {hc * n_embd, hc}, 0);
|
||||
hc_head_base = create_tensor(tn(LLM_TENSOR_HC_HEAD_BASE, "weight"), {hc}, 0);
|
||||
hc_head_scale = create_tensor(tn(LLM_TENSOR_HC_HEAD_SCALE, "weight"), {1}, 0);
|
||||
|
||||
for (int i = 0; i < n_layer; ++i) {
|
||||
auto & layer = layers[i];
|
||||
|
||||
layer.attn_norm = create_tensor(tn(LLM_TENSOR_ATTN_NORM, "weight", i), {n_embd}, 0);
|
||||
layer.attn_sinks = create_tensor(tn(LLM_TENSOR_ATTN_SINKS, "weight", i), {n_head}, 0);
|
||||
|
||||
layer.wq_a = create_tensor(tn(LLM_TENSOR_ATTN_Q_A, "weight", i), {n_embd, q_lora_rank}, 0);
|
||||
layer.attn_q_a_norm = create_tensor(tn(LLM_TENSOR_ATTN_Q_A_NORM, "weight", i), {q_lora_rank}, 0);
|
||||
layer.wq_b = create_tensor(tn(LLM_TENSOR_ATTN_Q_B, "weight", i), {q_lora_rank, n_head * n_embd_head_k_mla}, 0);
|
||||
layer.wkv_a_mqa = create_tensor(tn(LLM_TENSOR_ATTN_KV_A_MQA, "weight", i), {n_embd, kv_lora_rank + n_embd_head_qk_rope}, 0);
|
||||
layer.attn_kv_a_norm= create_tensor(tn(LLM_TENSOR_ATTN_KV_A_NORM,"weight", i), {kv_lora_rank}, 0);
|
||||
layer.wk_b = create_tensor(tn(LLM_TENSOR_ATTN_K_B, "weight", i), {n_embd_head_qk_nope, kv_lora_rank, n_head}, 0);
|
||||
layer.wv_b = create_tensor(tn(LLM_TENSOR_ATTN_V_B, "weight", i), {kv_lora_rank, n_embd_head_v_mla, n_head}, 0);
|
||||
layer.wo = create_tensor(tn(LLM_TENSOR_ATTN_OUT, "weight", i), {n_head * n_embd_head_v_mla, n_embd}, 0);
|
||||
layer.wqkv_gate = create_tensor(tn(LLM_TENSOR_ATTN_GATE, "weight", i), {n_embd, n_head * n_embd_head_v_mla}, 0);
|
||||
|
||||
// only "full" indexer layers ship weights; "shared" layers reuse their top-k
|
||||
if (hparams.indexer_top_k > 0 && hparams.is_indexer_full(i)) {
|
||||
const int64_t n_indexer_head = hparams.indexer_n_head;
|
||||
const int64_t n_embd_indexer = hparams.indexer_head_size;
|
||||
|
||||
layer.indexer_attn_q_b = create_tensor(tn(LLM_TENSOR_INDEXER_ATTN_Q_B, "weight", i), {q_lora_rank, n_indexer_head * n_embd_indexer}, 0);
|
||||
layer.indexer_attn_k = create_tensor(tn(LLM_TENSOR_INDEXER_ATTN_K, "weight", i), {n_embd, n_embd_indexer}, 0);
|
||||
layer.indexer_k_norm = create_tensor(tn(LLM_TENSOR_INDEXER_K_NORM, "weight", i), {n_embd_indexer}, 0);
|
||||
layer.indexer_k_norm_b = create_tensor(tn(LLM_TENSOR_INDEXER_K_NORM, "bias", i), {n_embd_indexer}, 0);
|
||||
layer.indexer_proj = create_tensor(tn(LLM_TENSOR_INDEXER_PROJ, "weight", i), {n_embd, n_indexer_head}, 0);
|
||||
}
|
||||
|
||||
layer.hc_attn_fn = create_tensor(tn(LLM_TENSOR_HC_ATTN_FN, "weight", i), {hc * n_embd, 2 * hc}, 0);
|
||||
layer.hc_attn_base = create_tensor(tn(LLM_TENSOR_HC_ATTN_BASE, "weight", i), {2 * hc}, 0);
|
||||
layer.hc_attn_scale = create_tensor(tn(LLM_TENSOR_HC_ATTN_SCALE, "weight", i), {2}, 0);
|
||||
layer.hc_ffn_fn = create_tensor(tn(LLM_TENSOR_HC_FFN_FN, "weight", i), {hc * n_embd, 2 * hc}, 0);
|
||||
layer.hc_ffn_base = create_tensor(tn(LLM_TENSOR_HC_FFN_BASE, "weight", i), {2 * hc}, 0);
|
||||
layer.hc_ffn_scale = create_tensor(tn(LLM_TENSOR_HC_FFN_SCALE, "weight", i), {2}, 0);
|
||||
|
||||
layer.ffn_norm = create_tensor(tn(LLM_TENSOR_FFN_NORM, "weight", i), {n_embd}, 0);
|
||||
|
||||
if (i < (int) hparams.n_layer_dense_lead) {
|
||||
layer.ffn_gate = create_tensor(tn(LLM_TENSOR_FFN_GATE, "weight", i), {n_embd, n_ff}, 0);
|
||||
layer.ffn_down = create_tensor(tn(LLM_TENSOR_FFN_DOWN, "weight", i), { n_ff, n_embd}, 0);
|
||||
layer.ffn_up = create_tensor(tn(LLM_TENSOR_FFN_UP, "weight", i), {n_embd, n_ff}, 0);
|
||||
} else {
|
||||
layer.ffn_gate_inp = create_tensor(tn(LLM_TENSOR_FFN_GATE_INP, "weight", i), {n_embd, n_expert}, 0);
|
||||
layer.ffn_exp_probs_b = create_tensor(tn(LLM_TENSOR_FFN_EXP_PROBS_B, "bias", i), {n_expert}, TENSOR_NOT_REQUIRED);
|
||||
|
||||
if (n_expert == 0) {
|
||||
throw std::runtime_error("n_expert must be > 0");
|
||||
}
|
||||
if (n_expert_used == 0) {
|
||||
throw std::runtime_error("n_expert_used must be > 0");
|
||||
}
|
||||
|
||||
layer.ffn_gate_exps = create_tensor(tn(LLM_TENSOR_FFN_GATE_EXPS, "weight", i), {n_embd, n_ff_exp, n_expert}, 0);
|
||||
layer.ffn_up_exps = create_tensor(tn(LLM_TENSOR_FFN_UP_EXPS, "weight", i), {n_embd, n_ff_exp, n_expert}, 0);
|
||||
layer.ffn_down_exps = create_tensor(tn(LLM_TENSOR_FFN_DOWN_EXPS, "weight", i), {n_ff_exp, n_embd, n_expert}, 0);
|
||||
|
||||
layer.ffn_gate_shexp = create_tensor(tn(LLM_TENSOR_FFN_GATE_SHEXP, "weight", i), {n_embd, n_ff_exp * n_expert_shared}, 0);
|
||||
layer.ffn_down_shexp = create_tensor(tn(LLM_TENSOR_FFN_DOWN_SHEXP, "weight", i), {n_ff_exp * n_expert_shared, n_embd}, 0);
|
||||
layer.ffn_up_shexp = create_tensor(tn(LLM_TENSOR_FFN_UP_SHEXP, "weight", i), {n_embd, n_ff_exp * n_expert_shared}, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<llm_graph_context> llama_model_hy_v4::build_arch_graph(const llm_graph_params & params) const {
|
||||
return std::make_unique<graph>(*this, params);
|
||||
}
|
||||
|
||||
// reduce hc streams x[:,i,:] weighted by w[i,:] -> [n_embd, n_tokens]
|
||||
// reference runs this in fp32 (inside the float() / autocast(fp32) context)
|
||||
static ggml_tensor * hy_v4_hc_reduce(ggml_context * ctx0, ggml_tensor * x, ggml_tensor * w, int64_t hc, int64_t n_embd, int64_t nt, ggml_type out_type) {
|
||||
ggml_tensor * x_f32 = ggml_cast(ctx0, x, GGML_TYPE_F32);
|
||||
ggml_tensor * result = nullptr;
|
||||
for (int64_t ih = 0; ih < hc; ++ih) {
|
||||
ggml_tensor * xh = ggml_view_2d(ctx0, x_f32, n_embd, nt, x_f32->nb[2], ih * x_f32->nb[1]);
|
||||
ggml_tensor * wh = ggml_view_2d(ctx0, w, 1, nt, w->nb[1], ih * w->nb[0]);
|
||||
ggml_tensor * cur = ggml_mul(ctx0, xh, wh);
|
||||
result = result ? ggml_add(ctx0, result, cur) : cur;
|
||||
}
|
||||
return ggml_cast(ctx0, result, out_type);
|
||||
}
|
||||
|
||||
ggml_tensor * llama_model_hy_v4::graph::build_hc_pre(
|
||||
ggml_tensor * x,
|
||||
ggml_tensor * hc_fn,
|
||||
ggml_tensor * hc_scale,
|
||||
ggml_tensor * hc_base,
|
||||
ggml_tensor ** post,
|
||||
int il) const {
|
||||
const int64_t hc = hparams.dsv4_hc_mult;
|
||||
const int64_t nt = x->ne[2];
|
||||
GGML_ASSERT(x->ne[0] == n_embd && x->ne[1] == hc);
|
||||
|
||||
ggml_tensor * flat = ggml_reshape_2d(ctx0, x, hc * n_embd, nt);
|
||||
ggml_tensor * flat_norm = ggml_rms_norm(ctx0, flat, hparams.f_norm_rms_eps);
|
||||
ggml_tensor * mixes = ggml_mul_mat(ctx0, hc_fn, flat_norm); // [2*hc, nt]
|
||||
cb(mixes, "hc_mixes", il);
|
||||
|
||||
ggml_tensor * scale_pre = hy_v4_view_1d(ctx0, hc_scale, 1, 0);
|
||||
ggml_tensor * scale_post = hy_v4_view_1d(ctx0, hc_scale, 1, 1);
|
||||
ggml_tensor * base_pre = hy_v4_view_1d(ctx0, hc_base, hc, 0);
|
||||
ggml_tensor * base_post = hy_v4_view_1d(ctx0, hc_base, hc, hc);
|
||||
|
||||
// pre = sigmoid(mixes[:hc]*scale_pre + base_pre) + eps
|
||||
ggml_tensor * pre = hy_v4_view_2d(ctx0, mixes, hc, nt, 0);
|
||||
pre = ggml_mul(ctx0, pre, scale_pre);
|
||||
pre = ggml_add(ctx0, pre, base_pre);
|
||||
pre = ggml_sigmoid(ctx0, pre);
|
||||
pre = ggml_scale_bias(ctx0, pre, 1.0f, hparams.dsv4_hc_eps);
|
||||
cb(pre, "hc_pre", il);
|
||||
|
||||
// post = magnitude*sigmoid(mixes[hc:2hc]*scale_post + base_post) + eps
|
||||
ggml_tensor * po = hy_v4_view_2d(ctx0, mixes, hc, nt, hc);
|
||||
po = ggml_mul(ctx0, po, scale_post);
|
||||
po = ggml_add(ctx0, po, base_post);
|
||||
po = ggml_sigmoid(ctx0, po);
|
||||
po = ggml_scale(ctx0, po, hparams.hc_magnitude);
|
||||
po = ggml_scale_bias(ctx0, po, 1.0f, hparams.dsv4_hc_eps);
|
||||
*post = po;
|
||||
cb(po, "hc_post_gate", il);
|
||||
|
||||
return hy_v4_hc_reduce(ctx0, x, pre, hc, n_embd, nt, x->type);
|
||||
}
|
||||
|
||||
ggml_tensor * llama_model_hy_v4::graph::build_hc_post(
|
||||
ggml_tensor * x,
|
||||
ggml_tensor * residual,
|
||||
ggml_tensor * post,
|
||||
int il) const {
|
||||
GGML_UNUSED(il);
|
||||
const int64_t hc = hparams.dsv4_hc_mult;
|
||||
const int64_t nt = x->ne[1];
|
||||
GGML_ASSERT(x->ne[0] == n_embd);
|
||||
GGML_ASSERT(residual->ne[1] == hc);
|
||||
|
||||
// reference HC post runs entirely in fp32 to avoid bf16 rounding accumulation
|
||||
// across 78 layers: post.float() * x.float() + residual.float() -> .to(dtype)
|
||||
ggml_tensor * x_f32 = ggml_cast(ctx0, x, GGML_TYPE_F32);
|
||||
ggml_tensor * post_f32 = ggml_cast(ctx0, post, GGML_TYPE_F32);
|
||||
ggml_tensor * res_f32 = ggml_cast(ctx0, residual, GGML_TYPE_F32);
|
||||
|
||||
ggml_tensor * out = nullptr;
|
||||
for (int64_t i = 0; i < hc; ++i) {
|
||||
ggml_tensor * res_i = ggml_view_2d(ctx0, res_f32, n_embd, nt, res_f32->nb[2], i * res_f32->nb[1]);
|
||||
ggml_tensor * post_i = ggml_view_2d(ctx0, post_f32, 1, nt, post_f32->nb[1], i * post_f32->nb[0]);
|
||||
ggml_tensor * cur = ggml_add(ctx0, res_i, ggml_mul(ctx0, x_f32, post_i));
|
||||
cur = ggml_reshape_3d(ctx0, cur, n_embd, 1, nt);
|
||||
out = out ? ggml_concat(ctx0, out, cur, 1) : cur;
|
||||
}
|
||||
|
||||
// cast back to the original type (bf16)
|
||||
out = ggml_cast(ctx0, out, residual->type);
|
||||
return out; // [n_embd, hc, nt]
|
||||
}
|
||||
|
||||
ggml_tensor * llama_model_hy_v4::graph::build_hc_head(
|
||||
ggml_tensor * x,
|
||||
ggml_tensor * hc_fn,
|
||||
ggml_tensor * hc_scale,
|
||||
ggml_tensor * hc_base) const {
|
||||
const int64_t hc = hparams.dsv4_hc_mult;
|
||||
const int64_t nt = x->ne[2];
|
||||
|
||||
ggml_tensor * flat = ggml_reshape_2d(ctx0, x, hc * n_embd, nt);
|
||||
ggml_tensor * flat_norm = ggml_rms_norm(ctx0, flat, hparams.f_norm_rms_eps);
|
||||
ggml_tensor * mixes = ggml_mul_mat(ctx0, hc_fn, flat_norm); // [hc, nt]
|
||||
cb(mixes, "hc_head_mixes", -1);
|
||||
|
||||
ggml_tensor * pre = ggml_mul(ctx0, mixes, hc_scale);
|
||||
pre = ggml_add(ctx0, pre, hc_base);
|
||||
pre = ggml_sigmoid(ctx0, pre);
|
||||
pre = ggml_scale_bias(ctx0, pre, 1.0f, hparams.dsv4_hc_eps);
|
||||
cb(pre, "hc_head_pre", -1);
|
||||
|
||||
return hy_v4_hc_reduce(ctx0, x, pre, hc, n_embd, nt, x->type);
|
||||
}
|
||||
|
||||
ggml_tensor * llama_model_hy_v4::graph::build_attention(
|
||||
const llama_model & model,
|
||||
llm_graph_input_attn_k * inp_attn,
|
||||
ggml_tensor * cur,
|
||||
ggml_tensor * inp_pos,
|
||||
float kq_scale,
|
||||
int il) const {
|
||||
const auto & layer = model.layers[il];
|
||||
|
||||
const int64_t n_embd_head_k = hparams.n_embd_head_k_mla();
|
||||
const int64_t n_embd_head_qk_rope = hparams.n_rot();
|
||||
const int64_t n_embd_head_qk_nope = n_embd_head_k - n_embd_head_qk_rope;
|
||||
const uint32_t kv_lora_rank = hparams.n_lora_kv;
|
||||
|
||||
ggml_tensor * q = ggml_mul_mat(ctx0, layer.wq_a, cur);
|
||||
q = build_norm(q, layer.attn_q_a_norm, nullptr, LLM_NORM_RMS, il);
|
||||
q = ggml_mul_mat(ctx0, layer.wq_b, q);
|
||||
|
||||
ggml_tensor * q_nope = ggml_view_3d(ctx0, q, n_embd_head_qk_nope, n_head, n_tokens,
|
||||
ggml_row_size(q->type, n_embd_head_k), ggml_row_size(q->type, n_embd_head_k) * n_head, 0);
|
||||
ggml_tensor * q_pe = ggml_view_3d(ctx0, q, n_embd_head_qk_rope, n_head, n_tokens,
|
||||
ggml_row_size(q->type, n_embd_head_k), ggml_row_size(q->type, n_embd_head_k) * n_head,
|
||||
ggml_row_size(q->type, n_embd_head_qk_nope));
|
||||
|
||||
ggml_tensor * kv_cmpr_pe = ggml_mul_mat(ctx0, layer.wkv_a_mqa, cur);
|
||||
ggml_tensor * kv_cmpr = ggml_view_2d(ctx0, kv_cmpr_pe, kv_lora_rank, n_tokens,
|
||||
ggml_row_size(kv_cmpr_pe->type, kv_lora_rank + n_embd_head_qk_rope), 0);
|
||||
ggml_tensor * k_pe = ggml_view_3d(ctx0, kv_cmpr_pe, n_embd_head_qk_rope, 1, n_tokens,
|
||||
ggml_row_size(kv_cmpr_pe->type, kv_lora_rank + n_embd_head_qk_rope),
|
||||
ggml_row_size(kv_cmpr_pe->type, kv_lora_rank + n_embd_head_qk_rope),
|
||||
ggml_row_size(kv_cmpr_pe->type, kv_lora_rank));
|
||||
|
||||
q_pe = ggml_rope_ext(ctx0, q_pe, inp_pos, nullptr, n_rot, rope_type, n_ctx_orig, freq_base, freq_scale,
|
||||
ext_factor, attn_factor, beta_fast, beta_slow);
|
||||
cb(q_pe, "q_pe", il);
|
||||
k_pe = ggml_rope_ext(ctx0, k_pe, inp_pos, nullptr, n_rot, rope_type, n_ctx_orig, freq_base, freq_scale,
|
||||
ext_factor, attn_factor, beta_fast, beta_slow);
|
||||
cb(k_pe, "k_pe", il);
|
||||
|
||||
kv_cmpr = build_norm(kv_cmpr, layer.attn_kv_a_norm, nullptr, LLM_NORM_RMS, il);
|
||||
cb(kv_cmpr, "kv_cmpr", il);
|
||||
|
||||
// MLA absorption: q_nope @ wk_b -> compressed space
|
||||
q_nope = ggml_permute(ctx0, q_nope, 0, 2, 1, 3);
|
||||
ggml_tensor * q_nope_absorbed = ggml_mul_mat(ctx0, layer.wk_b, q_nope);
|
||||
q_nope_absorbed = ggml_permute(ctx0, q_nope_absorbed, 0, 2, 1, 3);
|
||||
|
||||
// note: rope must go first for in-place context shifting in build_rope_shift()
|
||||
ggml_tensor * Qcur = ggml_concat(ctx0, q_nope_absorbed, q_pe, 0);
|
||||
|
||||
kv_cmpr = ggml_reshape_3d(ctx0, kv_cmpr, kv_lora_rank, 1, n_tokens);
|
||||
ggml_tensor * Kcur = ggml_concat(ctx0, kv_cmpr, k_pe, 0);
|
||||
ggml_tensor * Vcur = kv_cmpr;
|
||||
|
||||
// MLA-as-MQA; wo applied manually below so the gated-MLA gate can sit before o_proj
|
||||
ggml_tensor * attn = build_attn(inp_attn,
|
||||
nullptr, nullptr, nullptr,
|
||||
Qcur, Kcur, Vcur, nullptr, layer.attn_sinks, layer.wv_b, kq_scale, il);
|
||||
cb(attn, "attn_kqv", il); // [n_head * n_embd_head_v, n_tokens]
|
||||
|
||||
// gated MLA: elementwise sigmoid gate on the decompressed attention output
|
||||
ggml_tensor * gate = ggml_mul_mat(ctx0, layer.wqkv_gate, cur);
|
||||
gate = ggml_sigmoid(ctx0, gate);
|
||||
attn = ggml_mul(ctx0, attn, gate);
|
||||
cb(attn, "attn_gated", il);
|
||||
|
||||
ggml_tensor * out = build_lora_mm(layer.wo, attn);
|
||||
cb(out, "attn_out", il);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
ggml_tensor * llama_model_hy_v4::graph::build_indexer_top_k(
|
||||
const llama_model & model,
|
||||
llm_graph_input_attn_k_dsa * inp_attn_dsa,
|
||||
ggml_tensor * cur,
|
||||
ggml_tensor * qr,
|
||||
ggml_tensor * inp_pos,
|
||||
int il) const {
|
||||
const auto & layer = model.layers[il];
|
||||
|
||||
const int64_t n_indexer_head = hparams.indexer_n_head;
|
||||
const int64_t n_embd_indexer = hparams.indexer_head_size;
|
||||
const int64_t n_embd_indexer_rope = hparams.n_rot();
|
||||
const int64_t n_embd_indexer_nope = n_embd_indexer - n_embd_indexer_rope;
|
||||
|
||||
// nope rows come first, so rope only the last n_embd_indexer_rope rows, same as the MLA path
|
||||
ggml_tensor * iq = ggml_mul_mat(ctx0, layer.indexer_attn_q_b, qr);
|
||||
|
||||
iq = ggml_reshape_3d(ctx0, iq, n_embd_indexer, n_indexer_head, n_tokens);
|
||||
|
||||
iq = ggml_rope_ext(ctx0, iq, inp_pos, nullptr, n_rot, rope_type, n_ctx_orig, freq_base,
|
||||
freq_scale, ext_factor, attn_factor, beta_fast, beta_slow);
|
||||
iq = ggml_rope_set_offset(iq, n_embd_indexer_nope);
|
||||
cb(iq, "indexer_q", il);
|
||||
|
||||
ggml_tensor * ik = ggml_mul_mat(ctx0, layer.indexer_attn_k, cur);
|
||||
|
||||
ik = build_norm(ik, layer.indexer_k_norm, layer.indexer_k_norm_b, LLM_NORM, il);
|
||||
|
||||
ik = ggml_reshape_3d(ctx0, ik, n_embd_indexer, 1, n_tokens);
|
||||
|
||||
ik = ggml_rope_ext(ctx0, ik, inp_pos, nullptr, n_rot, rope_type, n_ctx_orig, freq_base,
|
||||
freq_scale, ext_factor, attn_factor, beta_fast, beta_slow);
|
||||
ik = ggml_rope_set_offset(ik, n_embd_indexer_nope);
|
||||
cb(ik, "indexer_k", il);
|
||||
|
||||
// the reference applies a Hadamard rotation here, but it only helps its FP8 kernels.
|
||||
// it is orthogonal, so it does not change q.k and we can skip it.
|
||||
|
||||
const auto * mctx_lid = inp_attn_dsa->mctx->get_lid();
|
||||
const auto & k_idxs_lid = inp_attn_dsa->get_k_idxs_lid();
|
||||
ggml_build_forward_expand(gf, mctx_lid->cpy_k(ctx0, ik, k_idxs_lid, il));
|
||||
|
||||
ggml_tensor * iw = ggml_mul_mat(ctx0, layer.indexer_proj, cur);
|
||||
|
||||
ik = mctx_lid->get_k(ctx0, il);
|
||||
|
||||
const auto n_stream = ik->ne[3];
|
||||
iq = ggml_view_4d(ctx0, iq, iq->ne[0], iq->ne[1], iq->ne[2]/n_stream, n_stream,
|
||||
iq->nb[1], iq->nb[2], iq->nb[3]/n_stream, 0);
|
||||
iw = ggml_view_4d(ctx0, iw, iw->ne[0], iw->ne[1]/n_stream, iw->ne[2], n_stream,
|
||||
iw->nb[1], iw->nb[2]/n_stream, iw->nb[3]/n_stream, 0);
|
||||
|
||||
// fold both reference scale factors into the weights before the big score tensor
|
||||
iw = ggml_scale(ctx0, iw, 1.0f / sqrtf(float(n_embd_indexer * n_indexer_head)));
|
||||
|
||||
ggml_tensor * score = nullptr;
|
||||
if (cparams.fused_lid) {
|
||||
score = ggml_lightning_indexer(ctx0, iq, ik, iw, inp_attn_dsa->get_kq_mask_lid());
|
||||
cb(score, "indexer_score", il);
|
||||
res->add_fused_node({LLM_FUSED_OP_LIGHTNING_INDEXER, score, il});
|
||||
} else {
|
||||
iq = ggml_permute(ctx0, iq, 0, 2, 1, 3);
|
||||
ik = ggml_permute(ctx0, ik, 0, 2, 1, 3);
|
||||
|
||||
score = ggml_mul_mat(ctx0, ik, iq);
|
||||
score = ggml_cont(ctx0, ggml_permute(ctx0, score, 2, 1, 0, 3));
|
||||
score = ggml_relu(ctx0, score);
|
||||
score = ggml_mul(ctx0, score, iw);
|
||||
score = ggml_sum_rows(ctx0, score);
|
||||
score = ggml_cont(ctx0, ggml_permute(ctx0, score, 2, 1, 0, 3));
|
||||
score = ggml_add(ctx0, score, inp_attn_dsa->get_kq_mask_lid());
|
||||
cb(score, "indexer_score", il);
|
||||
}
|
||||
|
||||
const uint32_t n_top_k = score->ne[0] < (int64_t) hparams.indexer_top_k ? score->ne[0] : hparams.indexer_top_k;
|
||||
|
||||
return ggml_cont(ctx0, ggml_top_k(ctx0, score, n_top_k));
|
||||
}
|
||||
|
||||
ggml_tensor * llama_model_hy_v4::graph::build_attention_dsa(
|
||||
const llama_model & model,
|
||||
llm_graph_input_attn_k_dsa * inp_attn_dsa,
|
||||
ggml_tensor * cur,
|
||||
ggml_tensor * inp_pos,
|
||||
ggml_tensor ** last_top_k,
|
||||
float kq_scale,
|
||||
int il) const {
|
||||
const auto & layer = model.layers[il];
|
||||
|
||||
const int64_t n_embd_head_k = hparams.n_embd_head_k_mla();
|
||||
const int64_t n_embd_head_qk_rope = hparams.n_rot();
|
||||
const int64_t n_embd_head_qk_nope = n_embd_head_k - n_embd_head_qk_rope;
|
||||
const uint32_t kv_lora_rank = hparams.n_lora_kv;
|
||||
|
||||
ggml_tensor * qr = ggml_mul_mat(ctx0, layer.wq_a, cur);
|
||||
qr = build_norm(qr, layer.attn_q_a_norm, nullptr, LLM_NORM_RMS, il);
|
||||
|
||||
if (hparams.is_indexer_full(il)) {
|
||||
*last_top_k = build_indexer_top_k(model, inp_attn_dsa, cur, qr, inp_pos, il);
|
||||
cb(*last_top_k, "top_k", il);
|
||||
}
|
||||
GGML_ASSERT(*last_top_k != nullptr);
|
||||
|
||||
ggml_tensor * q = ggml_mul_mat(ctx0, layer.wq_b, qr);
|
||||
|
||||
ggml_tensor * q_nope = ggml_view_3d(ctx0, q, n_embd_head_qk_nope, n_head, n_tokens,
|
||||
ggml_row_size(q->type, n_embd_head_k), ggml_row_size(q->type, n_embd_head_k) * n_head, 0);
|
||||
ggml_tensor * q_pe = ggml_view_3d(ctx0, q, n_embd_head_qk_rope, n_head, n_tokens,
|
||||
ggml_row_size(q->type, n_embd_head_k), ggml_row_size(q->type, n_embd_head_k) * n_head,
|
||||
ggml_row_size(q->type, n_embd_head_qk_nope));
|
||||
|
||||
ggml_tensor * kv_cmpr_pe = ggml_mul_mat(ctx0, layer.wkv_a_mqa, cur);
|
||||
ggml_tensor * kv_cmpr = ggml_view_2d(ctx0, kv_cmpr_pe, kv_lora_rank, n_tokens,
|
||||
ggml_row_size(kv_cmpr_pe->type, kv_lora_rank + n_embd_head_qk_rope), 0);
|
||||
ggml_tensor * k_pe = ggml_view_3d(ctx0, kv_cmpr_pe, n_embd_head_qk_rope, 1, n_tokens,
|
||||
ggml_row_size(kv_cmpr_pe->type, kv_lora_rank + n_embd_head_qk_rope),
|
||||
ggml_row_size(kv_cmpr_pe->type, kv_lora_rank + n_embd_head_qk_rope),
|
||||
ggml_row_size(kv_cmpr_pe->type, kv_lora_rank));
|
||||
|
||||
q_pe = ggml_rope_ext(ctx0, q_pe, inp_pos, nullptr, n_rot, rope_type, n_ctx_orig, freq_base, freq_scale,
|
||||
ext_factor, attn_factor, beta_fast, beta_slow);
|
||||
cb(q_pe, "q_pe", il);
|
||||
k_pe = ggml_rope_ext(ctx0, k_pe, inp_pos, nullptr, n_rot, rope_type, n_ctx_orig, freq_base, freq_scale,
|
||||
ext_factor, attn_factor, beta_fast, beta_slow);
|
||||
cb(k_pe, "k_pe", il);
|
||||
|
||||
kv_cmpr = build_norm(kv_cmpr, layer.attn_kv_a_norm, nullptr, LLM_NORM_RMS, il);
|
||||
cb(kv_cmpr, "kv_cmpr", il);
|
||||
|
||||
q_nope = ggml_permute(ctx0, q_nope, 0, 2, 1, 3);
|
||||
ggml_tensor * q_nope_absorbed = ggml_mul_mat(ctx0, layer.wk_b, q_nope);
|
||||
q_nope_absorbed = ggml_permute(ctx0, q_nope_absorbed, 0, 2, 1, 3);
|
||||
|
||||
ggml_tensor * Qcur = ggml_concat(ctx0, q_nope_absorbed, q_pe, 0);
|
||||
|
||||
kv_cmpr = ggml_reshape_3d(ctx0, kv_cmpr, kv_lora_rank, 1, n_tokens);
|
||||
ggml_tensor * Kcur = ggml_concat(ctx0, kv_cmpr, k_pe, 0);
|
||||
ggml_tensor * Vcur = kv_cmpr;
|
||||
|
||||
ggml_tensor * attn = build_attn(inp_attn_dsa,
|
||||
nullptr, nullptr, nullptr,
|
||||
Qcur, Kcur, Vcur, nullptr, layer.attn_sinks, layer.wv_b, *last_top_k, kq_scale, il);
|
||||
cb(attn, "attn_kqv", il);
|
||||
|
||||
ggml_tensor * gate = ggml_mul_mat(ctx0, layer.wqkv_gate, cur);
|
||||
gate = ggml_sigmoid(ctx0, gate);
|
||||
attn = ggml_mul(ctx0, attn, gate);
|
||||
cb(attn, "attn_gated", il);
|
||||
|
||||
ggml_tensor * out = build_lora_mm(layer.wo, attn);
|
||||
cb(out, "attn_out", il);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
llama_model_hy_v4::graph::graph(const llama_model & model, const llm_graph_params & params) :
|
||||
llm_graph_context(params) {
|
||||
const int64_t hc = hparams.dsv4_hc_mult;
|
||||
const int64_t n_embd_head_k = hparams.n_embd_head_k_mla();
|
||||
const float kq_scale = 1.0f / sqrtf(float(n_embd_head_k));
|
||||
|
||||
ggml_tensor * cur;
|
||||
|
||||
const bool is_dsa = hparams.indexer_top_k > 0;
|
||||
|
||||
ggml_tensor * inp = build_inp_embd(model.tok_embd);
|
||||
ggml_tensor * inp_pos = build_inp_pos();
|
||||
llm_graph_input_attn_k * inp_attn = is_dsa ? nullptr : build_attn_inp_k();
|
||||
llm_graph_input_attn_k_dsa * inp_attn_dsa = is_dsa ? build_attn_inp_k_dsa() : nullptr;
|
||||
ggml_tensor * inp_out_ids = build_inp_out_ids();
|
||||
|
||||
// top-k of the last "full" indexer layer, reused by the following "shared" layers
|
||||
ggml_tensor * last_top_k = nullptr;
|
||||
|
||||
// expand the single embedding into hc parallel residual streams
|
||||
ggml_tensor * inpL = ggml_reshape_3d(ctx0, inp, n_embd, 1, n_tokens);
|
||||
inpL = ggml_repeat_4d(ctx0, inpL, n_embd, hc, n_tokens, 1);
|
||||
cb(inpL, "hc_init", -1);
|
||||
|
||||
for (int il = 0; il < n_layer; ++il) {
|
||||
ggml_tensor * residual = inpL;
|
||||
ggml_tensor * post = nullptr;
|
||||
|
||||
cur = build_hc_pre(inpL, model.layers[il].hc_attn_fn, model.layers[il].hc_attn_scale,
|
||||
model.layers[il].hc_attn_base, &post, il);
|
||||
cur = build_norm(cur, model.layers[il].attn_norm, nullptr, LLM_NORM_RMS, il);
|
||||
cb(cur, "attn_norm", il);
|
||||
|
||||
cur = is_dsa
|
||||
? build_attention_dsa(model, inp_attn_dsa, cur, inp_pos, &last_top_k, kq_scale, il)
|
||||
: build_attention(model, inp_attn, cur, inp_pos, kq_scale, il);
|
||||
|
||||
inpL = build_hc_post(cur, residual, post, il);
|
||||
cb(inpL, "hc_attn_out", il);
|
||||
|
||||
residual = inpL;
|
||||
cur = build_hc_pre(inpL, model.layers[il].hc_ffn_fn, model.layers[il].hc_ffn_scale,
|
||||
model.layers[il].hc_ffn_base, &post, il);
|
||||
cur = build_norm(cur, model.layers[il].ffn_norm, nullptr, LLM_NORM_RMS, il);
|
||||
cb(cur, "ffn_norm", il);
|
||||
|
||||
const auto & layer = model.layers[il];
|
||||
if ((uint32_t) il < hparams.n_layer_dense_lead) {
|
||||
cur = build_ffn(cur,
|
||||
layer.ffn_up, NULL, NULL,
|
||||
layer.ffn_gate, NULL, NULL,
|
||||
layer.ffn_down, NULL, NULL,
|
||||
NULL, LLM_FFN_SILU, LLM_FFN_PAR, il);
|
||||
cb(cur, "ffn_out", il);
|
||||
} else {
|
||||
ggml_tensor * moe_out = build_moe_ffn(cur,
|
||||
layer.ffn_gate_inp,
|
||||
layer.ffn_up_exps,
|
||||
layer.ffn_gate_exps,
|
||||
layer.ffn_down_exps,
|
||||
layer.ffn_exp_probs_b,
|
||||
n_expert, n_expert_used,
|
||||
LLM_FFN_SILU, hparams.expert_weights_norm,
|
||||
hparams.expert_weights_scale,
|
||||
(llama_expert_gating_func_type) hparams.expert_gating_func,
|
||||
il,
|
||||
nullptr,
|
||||
nullptr);
|
||||
cb(moe_out, "ffn_moe_out", il);
|
||||
|
||||
ggml_tensor * ffn_shexp = build_ffn(cur,
|
||||
layer.ffn_up_shexp, NULL, NULL,
|
||||
layer.ffn_gate_shexp, NULL, NULL,
|
||||
layer.ffn_down_shexp, NULL, NULL,
|
||||
NULL, LLM_FFN_SILU, LLM_FFN_PAR, il);
|
||||
cb(ffn_shexp, "ffn_shexp", il);
|
||||
|
||||
cur = ggml_add(ctx0, moe_out, ffn_shexp);
|
||||
cb(cur, "ffn_out", il);
|
||||
}
|
||||
|
||||
inpL = build_hc_post(cur, residual, post, il);
|
||||
cb(inpL, "l_out", il);
|
||||
}
|
||||
|
||||
// prune to the requested output rows once, after all HC streams are done
|
||||
if (inp_out_ids) {
|
||||
ggml_tensor * flat = ggml_reshape_2d(ctx0, inpL, n_embd * hc, n_tokens);
|
||||
flat = ggml_get_rows(ctx0, flat, inp_out_ids);
|
||||
inpL = ggml_reshape_3d(ctx0, flat, n_embd, hc, n_outputs);
|
||||
}
|
||||
|
||||
cur = build_hc_head(inpL, model.hc_head_fn, model.hc_head_scale, model.hc_head_base);
|
||||
cb(cur, "hc_head", -1);
|
||||
|
||||
cur = build_norm(cur, model.output_norm, nullptr, LLM_NORM_RMS, -1);
|
||||
cb(cur, "result_norm", -1);
|
||||
res->t_embd = cur;
|
||||
|
||||
cur = ggml_mul_mat(ctx0, model.output, cur);
|
||||
cb(cur, "result_output", -1);
|
||||
res->t_logits = cur;
|
||||
|
||||
ggml_build_forward_expand(gf, cur);
|
||||
}
|
||||
@@ -29,15 +29,9 @@ void llama_model_jais2::load_arch_tensors(llama_model_loader &) {
|
||||
layer.attn_norm = create_tensor(tn(LLM_TENSOR_ATTN_NORM, "weight", i), {n_embd}, 0);
|
||||
layer.attn_norm_b = create_tensor(tn(LLM_TENSOR_ATTN_NORM, "bias", i), {n_embd}, 0);
|
||||
|
||||
layer.wq = create_tensor(tn(LLM_TENSOR_ATTN_Q, "weight", i), {n_embd, n_embd_head_k * n_head}, 0);
|
||||
layer.wk = create_tensor(tn(LLM_TENSOR_ATTN_K, "weight", i), {n_embd, n_embd_k_gqa}, 0);
|
||||
layer.wv = create_tensor(tn(LLM_TENSOR_ATTN_V, "weight", i), {n_embd, n_embd_v_gqa}, 0);
|
||||
create_tensor_qkv(layer, i, n_embd, n_embd_head_k * n_head, n_embd_k_gqa, n_embd_v_gqa, 0);
|
||||
layer.wo = create_tensor(tn(LLM_TENSOR_ATTN_OUT, "weight", i), {n_embd_head_k * n_head, n_embd}, 0);
|
||||
|
||||
// attention biases - all have shape n_embd (output dimension of projections)
|
||||
layer.wq_b = create_tensor(tn(LLM_TENSOR_ATTN_Q, "bias", i), {n_embd}, 0);
|
||||
layer.wk_b = create_tensor(tn(LLM_TENSOR_ATTN_K, "bias", i), {n_embd}, 0);
|
||||
layer.wv_b = create_tensor(tn(LLM_TENSOR_ATTN_V, "bias", i), {n_embd}, 0);
|
||||
layer.wo_b = create_tensor(tn(LLM_TENSOR_ATTN_OUT, "bias", i), {n_embd}, 0);
|
||||
|
||||
layer.ffn_norm = create_tensor(tn(LLM_TENSOR_FFN_NORM, "weight", i), {n_embd}, 0);
|
||||
|
||||
@@ -441,9 +441,9 @@ ggml_tensor * llama_model_kimi_k3::graph::build_kda_layer(
|
||||
ggml_tensor * state = build_rs(inp_rs, ssm_states_all, hparams.n_embd_s(), n_seqs);
|
||||
state = ggml_reshape_4d(ctx0, state, head_dim, head_dim, n_head_kda, n_seqs);
|
||||
|
||||
const float eps = hparams.f_norm_rms_eps;
|
||||
Qcur = ggml_l2_norm(ctx0, Qcur, eps);
|
||||
Kcur = ggml_l2_norm(ctx0, Kcur, eps);
|
||||
const float eps_norm = hparams.f_norm_rms_eps;
|
||||
Qcur = build_gdn_l2_norm(ctx0, Qcur, eps_norm);
|
||||
Kcur = build_gdn_l2_norm(ctx0, Kcur, eps_norm);
|
||||
|
||||
auto attn_out = build_delta_net(Qcur, Kcur, Vcur, g1, beta, state, il);
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ static ggml_tensor * causal_conv1d(ggml_cgraph * gf, ggml_context * ctx0, ggml_t
|
||||
// Causal Conv1d function for Q,K,V
|
||||
// When qkv is 0, it is Q, 1 is K, 2 is V
|
||||
// Step 1: Q, K, V projections -> [d_inner, n_tokens]
|
||||
ggml_tensor * x_proj = ggml_mul_mat(ctx0, proj_w, x);
|
||||
ggml_tensor * x_proj = proj_w ? ggml_mul_mat(ctx0, proj_w, x) : x;
|
||||
|
||||
// Reshape input: {d_inner, n_tokens} -> {d_inner, n_seq_tokens, n_seqs}
|
||||
ggml_tensor * x_3d = ggml_reshape_3d(ctx0, x_proj, d_inner, n_seq_tokens, n_seqs);
|
||||
@@ -295,9 +295,20 @@ llama_model_kimi_linear::graph::graph(const llama_model & model, const llm_graph
|
||||
ggml_tensor * conv_states_all = mctx_cur->get_r_l(il);
|
||||
cb(conv_states_all, "conv_states_all", il);
|
||||
ggml_tensor * conv_state_all = build_rs(inp_rs, conv_states_all, hparams.n_embd_r(), n_seqs);
|
||||
ggml_tensor * Qcur = causal_conv1d(gf, ctx0, conv_states_all, conv_state_all, 0, cur, layer.wq, layer.ssm_q_conv, d_conv, head_dim, n_head, n_seq_tokens, n_seqs, n_tokens, kv_head);
|
||||
ggml_tensor * Kcur = causal_conv1d(gf, ctx0, conv_states_all, conv_state_all, 1, cur, layer.wk, layer.ssm_k_conv, d_conv, head_dim, n_head, n_seq_tokens, n_seqs, n_tokens, kv_head);
|
||||
ggml_tensor * Vcur = causal_conv1d(gf, ctx0, conv_states_all, conv_state_all, 2, cur, layer.wv, layer.ssm_v_conv, d_conv, head_dim, n_head, n_seq_tokens, n_seqs, n_tokens, kv_head);
|
||||
ggml_tensor * q_in = cur, * k_in = cur, * v_in = cur;
|
||||
ggml_tensor * q_w = layer.wq, * k_w = layer.wk, * v_w = layer.wv;
|
||||
if (layer.wqkv) {
|
||||
ggml_tensor * qkv = ggml_mul_mat(ctx0, layer.wqkv, cur);
|
||||
const int64_t d_inner = head_dim * n_head;
|
||||
const size_t esize = ggml_element_size(qkv);
|
||||
q_in = ggml_cont(ctx0, ggml_view_2d(ctx0, qkv, d_inner, n_tokens, qkv->nb[1], 0));
|
||||
k_in = ggml_cont(ctx0, ggml_view_2d(ctx0, qkv, d_inner, n_tokens, qkv->nb[1], d_inner * esize));
|
||||
v_in = ggml_cont(ctx0, ggml_view_2d(ctx0, qkv, d_inner, n_tokens, qkv->nb[1], 2 * d_inner * esize));
|
||||
q_w = nullptr; k_w = nullptr; v_w = nullptr;
|
||||
}
|
||||
ggml_tensor * Qcur = causal_conv1d(gf, ctx0, conv_states_all, conv_state_all, 0, q_in, q_w, layer.ssm_q_conv, d_conv, head_dim, n_head, n_seq_tokens, n_seqs, n_tokens, kv_head);
|
||||
ggml_tensor * Kcur = causal_conv1d(gf, ctx0, conv_states_all, conv_state_all, 1, k_in, k_w, layer.ssm_k_conv, d_conv, head_dim, n_head, n_seq_tokens, n_seqs, n_tokens, kv_head);
|
||||
ggml_tensor * Vcur = causal_conv1d(gf, ctx0, conv_states_all, conv_state_all, 2, v_in, v_w, layer.ssm_v_conv, d_conv, head_dim, n_head, n_seq_tokens, n_seqs, n_tokens, kv_head);
|
||||
|
||||
// g1 = -exp(A_log) * softplus(f_b(f_a(x)) + dt_bias)
|
||||
ggml_tensor * f_a = ggml_mul_mat(ctx0, layer.ssm_f_a, cur);
|
||||
@@ -331,10 +342,11 @@ llama_model_kimi_linear::graph::graph(const llama_model & model, const llm_graph
|
||||
ggml_tensor * state = build_rs(inp_rs, ssm_states_all, hparams.n_embd_s(), n_seqs);
|
||||
state = ggml_reshape_4d(ctx0, state, head_dim, head_dim, n_head, n_seqs);
|
||||
|
||||
|
||||
const float eps_norm = hparams.f_norm_rms_eps;
|
||||
|
||||
Qcur = ggml_l2_norm(ctx0, Qcur, eps_norm);
|
||||
Kcur = ggml_l2_norm(ctx0, Kcur, eps_norm);
|
||||
Qcur = build_gdn_l2_norm(ctx0, Qcur, eps_norm);
|
||||
Kcur = build_gdn_l2_norm(ctx0, Kcur, eps_norm);
|
||||
|
||||
// Choose between build_delta_net_chunking and build_delta_net_recurrent based on n_tokens
|
||||
auto attn_out = build_delta_net(Qcur, Kcur, Vcur, g1, beta, state, il);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user