mirror of
https://github.com/ggml-org/llama.cpp.git
synced 2026-09-07 16:37:57 +02:00
Compare commits
40
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a693dd45c2 | ||
|
|
8635b58aae | ||
|
|
296b0f8881 | ||
|
|
b14462c0c9 | ||
|
|
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 |
@@ -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
|
||||
|
||||
@@ -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: |
|
||||
|
||||
@@ -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)",
|
||||
|
||||
+221
-58
@@ -8,6 +8,7 @@
|
||||
#include "json.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <future>
|
||||
@@ -534,15 +535,18 @@ static gguf_split_info get_gguf_split_info(const std::string & path) {
|
||||
}
|
||||
|
||||
// Q4_0 -> 4, F16 -> 16, NVFP4 -> 4, Q8_K_M -> 8, etc
|
||||
static int extract_quant_bits(const std::string & filename) {
|
||||
auto split = get_gguf_split_info(filename);
|
||||
static int quant_bits_from_tag(const std::string & tag) {
|
||||
auto pos = tag.find_first_of("0123456789");
|
||||
|
||||
auto pos = split.tag.find_first_of("0123456789");
|
||||
if (pos == std::string::npos) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return std::stoi(split.tag.substr(pos));
|
||||
return std::stoi(tag.substr(pos));
|
||||
}
|
||||
|
||||
static int extract_quant_bits(const std::string & filename) {
|
||||
return quant_bits_from_tag(get_gguf_split_info(filename).tag);
|
||||
}
|
||||
|
||||
static hf_cache::hf_files get_split_files(const hf_cache::hf_files & files,
|
||||
@@ -563,12 +567,127 @@ static hf_cache::hf_files get_split_files(const hf_cache::hf_files & files,
|
||||
return result;
|
||||
}
|
||||
|
||||
// pick the best sibling GGUF whose filename contains `keyword` (e.g. "mmproj" / "mtp"),
|
||||
// sidecar filename tokens, as used in `<quant>-<sidecar>` download tags,
|
||||
// e.g. `Q4_0-mtp` for `mtp-Model-Q4_0.gguf`, `BF16-mmproj` for `mmproj-BF16.gguf`
|
||||
static const std::vector<std::string> sidecar_tokens = {
|
||||
"mtp", "eagle3", "dflash", "dspark", "mmproj", "imatrix",
|
||||
};
|
||||
|
||||
static bool iequals(const std::string & a, const std::string & b) {
|
||||
return a.size() == b.size() &&
|
||||
std::equal(a.begin(), a.end(), b.begin(), [](char x, char y) {
|
||||
return std::tolower((unsigned char) x) == std::tolower((unsigned char) y);
|
||||
});
|
||||
}
|
||||
|
||||
// split a `<quant>-<sidecar>` tag into its parts, e.g. `Q4_0-mtp` -> {`Q4_0`, `mtp`};
|
||||
// a bare sidecar tag (`mtp`) yields an empty quant; no sidecar yields an empty token
|
||||
static std::pair<std::string, std::string> split_sidecar_tag(const std::string & tag) {
|
||||
for (const auto & t : sidecar_tokens) {
|
||||
if (tag.size() > t.size() + 1 && iequals(tag.substr(tag.size() - t.size() - 1), "-" + t)) {
|
||||
return { tag.substr(0, tag.size() - t.size() - 1), t };
|
||||
}
|
||||
if (iequals(tag, t)) {
|
||||
return { "", t };
|
||||
}
|
||||
}
|
||||
return { tag, "" };
|
||||
}
|
||||
|
||||
// filename with directory and extension removed, e.g. `sub/mtp-Model-Q4_0.gguf` -> `mtp-Model-Q4_0`
|
||||
static std::string stem_of(const std::string & path) {
|
||||
std::string base = path;
|
||||
if (auto pos = base.rfind('/'); pos != std::string::npos) {
|
||||
base = base.substr(pos + 1);
|
||||
}
|
||||
string_remove_suffix(base, ".gguf");
|
||||
return base;
|
||||
}
|
||||
|
||||
// a sidecar file carries its token as a name segment in any position and case,
|
||||
// e.g. `mmproj-Model-F16.gguf`, `Model-mtp-Q4_0.gguf`, `Model-Q4_0-mtp.gguf`
|
||||
// or the short `mmproj-F16.gguf`; the token must be a whole segment, so an
|
||||
// unrelated name that merely contains it (`smtp-Model.gguf`) is a plain model
|
||||
static std::string sidecar_token_of(const std::string & path) {
|
||||
std::string base = stem_of(path);
|
||||
|
||||
for (char & c : base) {
|
||||
c = (char) std::tolower((unsigned char) c);
|
||||
}
|
||||
if (base.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
for (const auto & t : sidecar_tokens) {
|
||||
if (base == t) {
|
||||
return t; // the sidecar file itself, e.g. `imatrix.gguf`
|
||||
}
|
||||
if (base.rfind(t + "-", 0) == 0) {
|
||||
return t; // `mtp-Model-Q4_0.gguf`
|
||||
}
|
||||
if (base.find("-" + t + "-") != std::string::npos) {
|
||||
return t; // `Model-mtp-Q4_0.gguf`
|
||||
}
|
||||
// `Model-Q4_0-mtp.gguf`, optionally with a `-draft` tail
|
||||
if (string_ends_with(base, "-" + t) || string_ends_with(base, "-" + t + "-draft")) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
// name with the sidecar token segment removed, lowercased for tag parsing,
|
||||
// e.g. `Model-MTP-Q4_0` -> `model-q4_0`
|
||||
static std::string strip_sidecar_token(const std::string & base, const std::string & token) {
|
||||
std::string lower = base;
|
||||
|
||||
for (char & c : lower) {
|
||||
c = (char) std::tolower((unsigned char) c);
|
||||
}
|
||||
|
||||
if (lower == token) {
|
||||
return {};
|
||||
}
|
||||
if (lower.rfind(token + "-", 0) == 0) {
|
||||
return lower.substr(token.size() + 1);
|
||||
}
|
||||
const std::string seg = "-" + token + "-";
|
||||
if (auto pos = lower.find(seg); pos != std::string::npos) {
|
||||
return lower.substr(0, pos) + "-" + lower.substr(pos + seg.size());
|
||||
}
|
||||
if (string_ends_with(lower, "-" + token + "-draft")) {
|
||||
return lower.substr(0, lower.size() - token.size() - 7);
|
||||
}
|
||||
if (string_ends_with(lower, "-" + token)) {
|
||||
return lower.substr(0, lower.size() - token.size() - 1);
|
||||
}
|
||||
return lower;
|
||||
}
|
||||
|
||||
// the quant a sidecar file belongs to, from its name with the token stripped;
|
||||
// a short-form name (`mmproj-F16.gguf`) leaves the bare quant, which has no
|
||||
// `-` separator for the tag regex, so it becomes the tag directly
|
||||
static std::string sidecar_quant(const std::string & path, const std::string & token) {
|
||||
std::string name = strip_sidecar_token(stem_of(path), token);
|
||||
std::string tag = get_gguf_split_info(name + ".gguf").tag;
|
||||
|
||||
if (tag.empty() && name.find('-') == std::string::npos) {
|
||||
for (char & c : name) {
|
||||
c = (char) std::toupper((unsigned char) c);
|
||||
}
|
||||
tag = name;
|
||||
}
|
||||
|
||||
return tag;
|
||||
}
|
||||
|
||||
// pick the best sibling GGUF carrying the sidecar `token` (e.g. "mmproj" / "mtp"),
|
||||
// preferring deeper shared directory prefix with the model, then exact `tag` match,
|
||||
// then closest quantization to the tag when given, or to the model otherwise
|
||||
// an empty `model` skips the directory constraint: the sidecar is matched by tag alone
|
||||
static hf_cache::hf_file find_best_sibling(const hf_cache::hf_files & files,
|
||||
const std::string & model,
|
||||
const std::string & keyword,
|
||||
const std::string & token,
|
||||
const std::string & tag = "") {
|
||||
hf_cache::hf_file best;
|
||||
size_t best_depth = 0;
|
||||
@@ -589,32 +708,32 @@ static hf_cache::hf_file find_best_sibling(const hf_cache::hf_files & files,
|
||||
model_bits = extract_quant_bits(model);
|
||||
}
|
||||
auto model_parts = string_split<std::string>(model, '/');
|
||||
auto model_dir = model_parts.end() - 1;
|
||||
|
||||
for (const auto & f : files) {
|
||||
if (!string_ends_with(f.path, ".gguf") ||
|
||||
f.path.find(keyword) == std::string::npos) {
|
||||
if (sidecar_token_of(f.path) != token) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto sib_parts = string_split<std::string>(f.path, '/');
|
||||
auto sib_dir = sib_parts.end() - 1;
|
||||
|
||||
auto [_, dir] = std::mismatch(model_parts.begin(), model_dir,
|
||||
sib_parts.begin(), sib_dir);
|
||||
if (dir != sib_dir) {
|
||||
continue;
|
||||
size_t depth = 0;
|
||||
if (!model.empty()) {
|
||||
auto model_dir = model_parts.end() - 1;
|
||||
auto [_, dir] = std::mismatch(model_parts.begin(), model_dir,
|
||||
sib_parts.begin(), sib_dir);
|
||||
if (dir != sib_dir) {
|
||||
continue;
|
||||
}
|
||||
depth = dir - sib_parts.begin();
|
||||
}
|
||||
|
||||
size_t depth = dir - sib_parts.begin();
|
||||
auto bits = extract_quant_bits(f.path);
|
||||
auto diff = std::abs(bits - model_bits);
|
||||
|
||||
std::string path_upper = f.path;
|
||||
for (char & c : path_upper) {
|
||||
c = (char) std::toupper((unsigned char) c);
|
||||
}
|
||||
bool exact = !tag_upper.empty() && path_upper.find("-" + tag_upper + ".") != std::string::npos;
|
||||
// rank by the quant the sidecar belongs to, with the token segment
|
||||
// stripped from its name
|
||||
auto tag = sidecar_quant(f.path, token);
|
||||
auto bits = quant_bits_from_tag(tag);
|
||||
auto diff = std::abs(bits - model_bits);
|
||||
bool exact = !tag_upper.empty() && tag == tag_upper;
|
||||
|
||||
if (!found || depth > best_depth ||
|
||||
(depth == best_depth && exact && !best_exact) ||
|
||||
@@ -637,43 +756,31 @@ static hf_cache::hf_file find_best_mmproj(const hf_cache::hf_files & files,
|
||||
static hf_cache::hf_file find_best_mtp(const hf_cache::hf_files & files,
|
||||
const std::string & model,
|
||||
const std::string & tag = "") {
|
||||
return find_best_sibling(files, model, "mtp-", tag);
|
||||
return find_best_sibling(files, model, "mtp", tag);
|
||||
}
|
||||
|
||||
static hf_cache::hf_file find_best_eagle3(const hf_cache::hf_files & files,
|
||||
const std::string & model,
|
||||
const std::string & tag = "") {
|
||||
return find_best_sibling(files, model, "eagle3-", tag);
|
||||
return find_best_sibling(files, model, "eagle3", tag);
|
||||
}
|
||||
|
||||
static hf_cache::hf_file find_best_dflash(const hf_cache::hf_files & files,
|
||||
const std::string & model,
|
||||
const std::string & tag = "") {
|
||||
return find_best_sibling(files, model, "dflash-", tag);
|
||||
return find_best_sibling(files, model, "dflash", tag);
|
||||
}
|
||||
|
||||
static hf_cache::hf_file find_best_dspark(const hf_cache::hf_files & files,
|
||||
const std::string & model,
|
||||
const std::string & tag = "") {
|
||||
return find_best_sibling(files, model, "dspark-", tag);
|
||||
return find_best_sibling(files, model, "dspark", tag);
|
||||
}
|
||||
|
||||
// a plain model file: a GGUF whose name carries no sidecar token segment,
|
||||
// so `smtp-Model.gguf` counts and every sidecar form does not
|
||||
static bool gguf_filename_is_model(const std::string & filepath) {
|
||||
if (!string_ends_with(filepath, ".gguf")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string filename = filepath;
|
||||
if (auto pos = filename.rfind('/'); pos != std::string::npos) {
|
||||
filename = filename.substr(pos + 1);
|
||||
}
|
||||
|
||||
return filename.find("mmproj") == std::string::npos &&
|
||||
filename.find("imatrix") == std::string::npos &&
|
||||
filename.find("mtp-") == std::string::npos &&
|
||||
filename.find("eagle3-") == std::string::npos &&
|
||||
filename.find("dflash-") == std::string::npos &&
|
||||
filename.find("dspark-") == std::string::npos;
|
||||
return string_ends_with(filepath, ".gguf") && sidecar_token_of(filepath).empty();
|
||||
}
|
||||
|
||||
static hf_cache::hf_file find_best_model(const hf_cache::hf_files & files,
|
||||
@@ -765,8 +872,27 @@ common_download_hf_plan common_download_get_hf_plan(const common_params_model &
|
||||
}
|
||||
} else {
|
||||
primary = find_best_model(all, tag);
|
||||
|
||||
// a `<quant>-<sidecar>` tag (e.g. `Q4_0-mtp`) requests that sidecar alone;
|
||||
// every token-bearing file is a sidecar (find_best_model skips them),
|
||||
// so the sidecar resolves here whenever the tag carries one
|
||||
auto [base_tag, sidecar] = split_sidecar_tag(tag);
|
||||
|
||||
if (primary.path.empty() && !sidecar.empty()) {
|
||||
auto found = find_best_sibling(all, "", sidecar, base_tag);
|
||||
|
||||
if (!found.path.empty()) {
|
||||
if (sidecar == "mtp") plan.mtp = found;
|
||||
else if (sidecar == "eagle3") plan.eagle3 = found;
|
||||
else if (sidecar == "dflash") plan.dflash = found;
|
||||
else if (sidecar == "dspark") plan.dspark = found;
|
||||
else plan.mmproj = found;
|
||||
}
|
||||
}
|
||||
|
||||
// a requested sidecar can resolve on its own, without a full model of the same tag
|
||||
if (primary.path.empty() && !opts.download_mtp && !opts.download_dflash && !opts.download_eagle3 && !opts.download_dspark) {
|
||||
if (primary.path.empty() && sidecar.empty() &&
|
||||
!opts.download_mtp && !opts.download_dflash && !opts.download_eagle3 && !opts.download_dspark) {
|
||||
LOG_ERR("%s: no GGUF files found in repository %s\n", __func__, repo.c_str());
|
||||
list_available_gguf_files(all);
|
||||
return plan;
|
||||
@@ -794,7 +920,7 @@ common_download_hf_plan common_download_get_hf_plan(const common_params_model &
|
||||
plan.dspark = find_best_dspark(all, primary.path, tag);
|
||||
}
|
||||
|
||||
if (primary.path.empty() &&
|
||||
if (primary.path.empty() && plan.mmproj.local_path.empty() &&
|
||||
plan.mtp.local_path.empty() && plan.dflash.local_path.empty() && plan.eagle3.local_path.empty() && plan.dspark.local_path.empty()) {
|
||||
LOG_ERR("%s: no GGUF files found in repository %s\n", __func__, repo.c_str());
|
||||
list_available_gguf_files(all);
|
||||
@@ -968,17 +1094,34 @@ std::vector<common_cached_model_info> common_list_cached_models() {
|
||||
auto files = hf_cache::get_cached_files();
|
||||
|
||||
for (const auto & f : files) {
|
||||
auto split = get_gguf_split_info(f.path);
|
||||
if (split.index != 1 || split.tag.empty() ||
|
||||
split.prefix.find("mmproj") != std::string::npos ||
|
||||
split.prefix.find("mtp-") != std::string::npos ||
|
||||
split.prefix.find("eagle3-") != std::string::npos ||
|
||||
split.prefix.find("dflash-") != std::string::npos ||
|
||||
split.prefix.find("dspark-") != std::string::npos) {
|
||||
continue;
|
||||
// a sidecar file is listed under its own `<quant>-<sidecar>` tag, so a
|
||||
// cached `mtp-Model-Q4_0.gguf`, `Model-mtp-Q4_0.gguf`, `Model-Q4_0-mtp.gguf`
|
||||
// or short `mmproj-F16.gguf` shows up as `<repo>:Q4_0-mtp` / `<repo>:F16-mmproj`;
|
||||
// files whose name carries no token stay loadable models
|
||||
auto token = sidecar_token_of(f.path);
|
||||
|
||||
std::string tag;
|
||||
if (token.empty()) {
|
||||
auto split = get_gguf_split_info(f.path);
|
||||
|
||||
if (split.index != 1 || split.tag.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tag = split.tag;
|
||||
} else {
|
||||
tag = sidecar_quant(f.path, token);
|
||||
|
||||
// a bare sidecar file has no tag to request it by, stay hidden
|
||||
if (tag.empty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tag += "-" + token;
|
||||
}
|
||||
if (seen.insert(f.repo_id + ":" + split.tag).second) {
|
||||
result.push_back({f.repo_id, split.tag});
|
||||
|
||||
if (seen.insert(f.repo_id + ":" + tag).second) {
|
||||
result.push_back({f.repo_id, tag});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1014,7 +1157,15 @@ bool common_download_remove(const std::string & hf_repo_with_tag) {
|
||||
return hf_cache::remove_cached_repo(repo_id);
|
||||
}
|
||||
|
||||
std::string tag_upper = tag;
|
||||
// a `<quant>-<sidecar>` tag (`Q4_0-mtp`) targets that sidecar alone; a bare
|
||||
// sidecar tag (`mtp`) is ambiguous across quants and is rejected
|
||||
auto [base_tag, sidecar] = split_sidecar_tag(tag);
|
||||
if (!sidecar.empty() && base_tag.empty()) {
|
||||
LOG_ERR("%s: bare sidecar tag '%s': use `<quant>-<sidecar>`\n", __func__, tag.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string tag_upper = sidecar.empty() ? tag : base_tag;
|
||||
for (char & c : tag_upper) {
|
||||
c = (char) std::toupper((unsigned char) c);
|
||||
}
|
||||
@@ -1024,13 +1175,25 @@ bool common_download_remove(const std::string & hf_repo_with_tag) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// collect snapshot entries whose tag matches
|
||||
// collect the snapshot entries the tag selects; sidecar files keep their
|
||||
// own tags, so a plain quant tag never removes them
|
||||
std::vector<fs::path> to_remove;
|
||||
for (const auto & f : files) {
|
||||
auto split = get_gguf_split_info(f.path);
|
||||
if (split.tag == tag_upper) {
|
||||
to_remove.emplace_back(f.local_path);
|
||||
auto token = sidecar_token_of(f.path);
|
||||
|
||||
if (sidecar.empty()) {
|
||||
if (!token.empty()) {
|
||||
continue;
|
||||
}
|
||||
if (get_gguf_split_info(f.path).tag != tag_upper) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (token != sidecar || sidecar_quant(f.path, sidecar) != tag_upper) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
to_remove.emplace_back(f.local_path);
|
||||
}
|
||||
|
||||
if (to_remove.empty()) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -255,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",
|
||||
|
||||
+94
-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)
|
||||
|
||||
@@ -1543,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"
|
||||
|
||||
+22
-89
@@ -9,20 +9,6 @@ from .base import ModelBase, gguf, logger
|
||||
from .deepseek import DeepseekV2Model
|
||||
|
||||
|
||||
def split_kv_b_proj(weight: torch.Tensor, n_head: int, qk_nope: int, v_head_dim: int):
|
||||
"""Split kv_b_proj into k_b (transposed) and v_b, matching DeepSeek MLA absorption.
|
||||
|
||||
weight: [n_head*(qk_nope+v_head_dim), kv_lora_rank].
|
||||
Returns (k_b, v_b): k_b [n_head, kv_lora_rank, qk_nope], v_b [n_head, v_head_dim, kv_lora_rank].
|
||||
"""
|
||||
kv_lora = weight.shape[-1]
|
||||
assert weight.shape[0] == n_head * (qk_nope + v_head_dim)
|
||||
kv_b = weight.view(n_head, qk_nope + v_head_dim, kv_lora)
|
||||
k_b, v_b = torch.split(kv_b, [qk_nope, v_head_dim], dim=1)
|
||||
k_b = k_b.transpose(1, 2).contiguous() # [n_head, kv_lora, qk_nope]
|
||||
return k_b, v_b.contiguous()
|
||||
|
||||
|
||||
def split_gate_up(weight: torch.Tensor, moe_intermediate_size: int):
|
||||
"""Split a fused stacked gate_up expert tensor into (gate, up).
|
||||
|
||||
@@ -36,6 +22,7 @@ def split_gate_up(weight: torch.Tensor, moe_intermediate_size: int):
|
||||
|
||||
|
||||
@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.
|
||||
|
||||
@@ -54,6 +41,8 @@ class HYV4Model(DeepseekV2Model):
|
||||
|
||||
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",
|
||||
@@ -186,6 +175,10 @@ class HYV4Model(DeepseekV2Model):
|
||||
)
|
||||
|
||||
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:
|
||||
@@ -227,85 +220,25 @@ class HYV4Model(DeepseekV2Model):
|
||||
|
||||
def modify_tensors(self, data_torch: torch.Tensor, name: str, bid: int | None) -> Iterable[tuple[str, torch.Tensor]]:
|
||||
hparams = self.hparams
|
||||
n_head = hparams["num_attention_heads"]
|
||||
qk_nope = hparams["qk_nope_head_dim"]
|
||||
v_head_dim = hparams["v_head_dim"]
|
||||
moe_inter = hparams["moe_intermediate_size"]
|
||||
|
||||
tn = self.format_tensor_name
|
||||
|
||||
# ---- global (non per-layer) ----
|
||||
if name == "model.embed_tokens.weight":
|
||||
return [(tn(gguf.MODEL_TENSOR.TOKEN_EMBD), data_torch)]
|
||||
if name == "model.norm.weight":
|
||||
return [(tn(gguf.MODEL_TENSOR.OUTPUT_NORM), data_torch)]
|
||||
if name == "lm_head.weight":
|
||||
return [(tn(gguf.MODEL_TENSOR.OUTPUT), data_torch)]
|
||||
if name == "model.hc_head.hc_head_fn":
|
||||
return [(tn(gguf.MODEL_TENSOR.HC_HEAD_FN), data_torch)]
|
||||
if name == "model.hc_head.hc_head_base":
|
||||
return [(tn(gguf.MODEL_TENSOR.HC_HEAD_BASE), data_torch)]
|
||||
if name == "model.hc_head.hc_head_scale":
|
||||
return [(tn(gguf.MODEL_TENSOR.HC_HEAD_SCALE), data_torch)]
|
||||
|
||||
assert bid is not None, f"expected a per-layer tensor, got {name!r}"
|
||||
|
||||
# ---- per-layer, keyed by suffix after 'model.layers.{bid}.' ----
|
||||
suffix = name.split(f"model.layers.{bid}.", 1)[-1]
|
||||
|
||||
# note: q_b_proj and kv_a_proj_with_mqa are mapped straight through (no RoPE permute),
|
||||
# the graph rotates consecutive pairs so the rows need no reordering
|
||||
simple = {
|
||||
"input_layernorm.weight": (gguf.MODEL_TENSOR.ATTN_NORM, ".weight"),
|
||||
"post_attention_layernorm.weight": (gguf.MODEL_TENSOR.FFN_NORM, ".weight"),
|
||||
"self_attn.q_a_proj.weight": (gguf.MODEL_TENSOR.ATTN_Q_A, ".weight"),
|
||||
"self_attn.q_a_layernorm.weight": (gguf.MODEL_TENSOR.ATTN_Q_A_NORM, ".weight"),
|
||||
"self_attn.q_b_proj.weight": (gguf.MODEL_TENSOR.ATTN_Q_B, ".weight"),
|
||||
"self_attn.kv_a_proj_with_mqa.weight": (gguf.MODEL_TENSOR.ATTN_KV_A_MQA, ".weight"),
|
||||
"self_attn.kv_a_layernorm.weight": (gguf.MODEL_TENSOR.ATTN_KV_A_NORM, ".weight"),
|
||||
"self_attn.o_proj.weight": (gguf.MODEL_TENSOR.ATTN_OUT, ".weight"),
|
||||
"self_attn.linear_gate.weight": (gguf.MODEL_TENSOR.ATTN_GATE, ".weight"),
|
||||
"self_attn.learnable_sink_param": (gguf.MODEL_TENSOR.ATTN_SINKS, ".weight"),
|
||||
"self_attn.indexer.wq_b.weight": (gguf.MODEL_TENSOR.INDEXER_ATTN_Q_B, ".weight"),
|
||||
"self_attn.indexer.wk.weight": (gguf.MODEL_TENSOR.INDEXER_ATTN_K, ".weight"),
|
||||
"self_attn.indexer.k_norm.weight": (gguf.MODEL_TENSOR.INDEXER_K_NORM, ".weight"),
|
||||
"self_attn.indexer.k_norm.bias": (gguf.MODEL_TENSOR.INDEXER_K_NORM, ".bias"),
|
||||
"self_attn.indexer.weights_proj.weight": (gguf.MODEL_TENSOR.INDEXER_PROJ, ".weight"),
|
||||
"hc_attn_layer.hc_pre.hc_fn": (gguf.MODEL_TENSOR.HC_ATTN_FN, ".weight"),
|
||||
"hc_attn_layer.hc_pre.hc_base": (gguf.MODEL_TENSOR.HC_ATTN_BASE, ".weight"),
|
||||
"hc_attn_layer.hc_pre.hc_scale": (gguf.MODEL_TENSOR.HC_ATTN_SCALE, ".weight"),
|
||||
"hc_mlp_layer.hc_pre.hc_fn": (gguf.MODEL_TENSOR.HC_FFN_FN, ".weight"),
|
||||
"hc_mlp_layer.hc_pre.hc_base": (gguf.MODEL_TENSOR.HC_FFN_BASE, ".weight"),
|
||||
"hc_mlp_layer.hc_pre.hc_scale": (gguf.MODEL_TENSOR.HC_FFN_SCALE, ".weight"),
|
||||
"mlp.gate.weight": (gguf.MODEL_TENSOR.FFN_GATE_INP, ".weight"),
|
||||
"mlp.gate.e_score_correction.bias":(gguf.MODEL_TENSOR.FFN_EXP_PROBS_B, ".bias"),
|
||||
"mlp.gate_proj.weight": (gguf.MODEL_TENSOR.FFN_GATE, ".weight"),
|
||||
"mlp.up_proj.weight": (gguf.MODEL_TENSOR.FFN_UP, ".weight"),
|
||||
"mlp.down_proj.weight": (gguf.MODEL_TENSOR.FFN_DOWN, ".weight"),
|
||||
"mlp.shared_experts.gate_proj.weight": (gguf.MODEL_TENSOR.FFN_GATE_SHEXP, ".weight"),
|
||||
"mlp.shared_experts.up_proj.weight": (gguf.MODEL_TENSOR.FFN_UP_SHEXP, ".weight"),
|
||||
"mlp.shared_experts.down_proj.weight": (gguf.MODEL_TENSOR.FFN_DOWN_SHEXP, ".weight"),
|
||||
}
|
||||
if suffix in simple:
|
||||
key, sfx = simple[suffix]
|
||||
return [(tn(key, bid, sfx), data_torch)]
|
||||
|
||||
# kv_b_proj: split into k_b (transposed) and v_b
|
||||
if suffix == "self_attn.kv_b_proj.weight":
|
||||
k_b, v_b = split_kv_b_proj(data_torch, n_head, qk_nope, v_head_dim)
|
||||
return [
|
||||
(tn(gguf.MODEL_TENSOR.ATTN_K_B, bid), k_b),
|
||||
(tn(gguf.MODEL_TENSOR.ATTN_V_B, bid), v_b),
|
||||
]
|
||||
|
||||
# fused stacked experts: split gate_up into gate/up
|
||||
if suffix == "mlp.experts.gate_up_proj":
|
||||
if name.endswith("mlp.experts.gate_up_proj"):
|
||||
gate, up = split_gate_up(data_torch, moe_inter)
|
||||
return [
|
||||
(tn(gguf.MODEL_TENSOR.FFN_GATE_EXP, bid), gate),
|
||||
(tn(gguf.MODEL_TENSOR.FFN_UP_EXP, bid), up),
|
||||
]
|
||||
if suffix == "mlp.experts.down_proj":
|
||||
return [(tn(gguf.MODEL_TENSOR.FFN_DOWN_EXP, bid), data_torch)]
|
||||
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
|
||||
|
||||
raise ValueError(f"Unsupported HY_V4 tensor {name!r} (suffix {suffix!r})")
|
||||
# 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:
|
||||
|
||||
@@ -191,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];
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
static constexpr __host__ __device__ ggml_cuda_mmq_config ggml_cuda_mmq_get_config_ampere(ggml_type type, int J, bool fallback) {
|
||||
constexpr bool use_typical_moe_ncols = false;
|
||||
CASE(GGML_TYPE_Q1_0, 256, 1, 128, 8, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, true, true);
|
||||
CASE(GGML_TYPE_Q1_0, 256, 1, 128, 16, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, true, true);
|
||||
CASE(GGML_TYPE_Q1_0, 256, 1, 128, 32, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, true, true);
|
||||
@@ -379,5 +380,5 @@ static constexpr __host__ __device__ ggml_cuda_mmq_config ggml_cuda_mmq_get_conf
|
||||
CASE(GGML_TYPE_NVFP4, 256, 1, 128, 112, GGML_CUDA_MMQ_SRAM_LAYOUT_NVFP4, MMQ_ITER_K, true, false);
|
||||
CASE(GGML_TYPE_NVFP4, 256, 1, 128, 128, GGML_CUDA_MMQ_SRAM_LAYOUT_NVFP4, MMQ_ITER_K, true, false);
|
||||
|
||||
return ggml_cuda_mmq_config(GGML_TYPE_COUNT, 256, 1, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, 256, false, true);
|
||||
return ggml_cuda_mmq_config(GGML_TYPE_COUNT, 256, 1, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, 256, use_typical_moe_ncols, false, true);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
static constexpr __host__ __device__ ggml_cuda_mmq_config ggml_cuda_mmq_get_config_blackwell(ggml_type type, int J, bool fallback) {
|
||||
constexpr bool use_typical_moe_ncols = false;
|
||||
CASE(GGML_TYPE_MXFP4, 256, 1, 128, 8, GGML_CUDA_MMQ_SRAM_LAYOUT_FP4, MMQ_ITER_K_FP4, true, true);
|
||||
CASE(GGML_TYPE_MXFP4, 256, 1, 128, 16, GGML_CUDA_MMQ_SRAM_LAYOUT_FP4, MMQ_ITER_K_FP4, true, true);
|
||||
CASE(GGML_TYPE_MXFP4, 256, 1, 128, 32, GGML_CUDA_MMQ_SRAM_LAYOUT_FP4, MMQ_ITER_K_FP4, true, true);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
static constexpr __host__ __device__ ggml_cuda_mmq_config ggml_cuda_mmq_get_config_cdna(ggml_type type, int J, bool fallback) {
|
||||
constexpr bool use_typical_moe_ncols = false;
|
||||
CASE(GGML_TYPE_Q1_0, 512, 1, 128, 16, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, true, true);
|
||||
CASE(GGML_TYPE_Q1_0, 512, 1, 128, 32, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, true, true);
|
||||
CASE(GGML_TYPE_Q1_0, 512, 1, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, true, true);
|
||||
@@ -181,5 +182,5 @@ static constexpr __host__ __device__ ggml_cuda_mmq_config ggml_cuda_mmq_get_conf
|
||||
CASE(GGML_TYPE_NVFP4, 512, 1, 128, 48, GGML_CUDA_MMQ_SRAM_LAYOUT_NVFP4, MMQ_ITER_K, true, false);
|
||||
CASE(GGML_TYPE_NVFP4, 512, 1, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_NVFP4, MMQ_ITER_K, true, false);
|
||||
|
||||
return ggml_cuda_mmq_config(GGML_TYPE_COUNT, 512, 1, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, 256, false, true);
|
||||
return ggml_cuda_mmq_config(GGML_TYPE_COUNT, 512, 1, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, 256, use_typical_moe_ncols, false, true);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
static constexpr __host__ __device__ ggml_cuda_mmq_config ggml_cuda_mmq_get_config_pascal_dp4a(ggml_type type, int J, bool fallback) {
|
||||
constexpr bool use_typical_moe_ncols = false;
|
||||
CASE(GGML_TYPE_Q1_0, 256, 2, 64, 8, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, false, true);
|
||||
CASE(GGML_TYPE_Q1_0, 256, 2, 64, 16, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, false, true);
|
||||
CASE(GGML_TYPE_Q1_0, 256, 2, 64, 32, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, false, true);
|
||||
@@ -269,5 +270,5 @@ static constexpr __host__ __device__ ggml_cuda_mmq_config ggml_cuda_mmq_get_conf
|
||||
CASE(GGML_TYPE_NVFP4, 256, 2, 64, 48, GGML_CUDA_MMQ_SRAM_LAYOUT_NVFP4, MMQ_ITER_K, false, false);
|
||||
CASE(GGML_TYPE_NVFP4, 256, 2, 64, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_NVFP4, MMQ_ITER_K, false, false);
|
||||
|
||||
return ggml_cuda_mmq_config(GGML_TYPE_COUNT, 256, 2, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, 256, false, true);
|
||||
return ggml_cuda_mmq_config(GGML_TYPE_COUNT, 256, 2, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, 256, use_typical_moe_ncols, false, true);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
static constexpr __host__ __device__ ggml_cuda_mmq_config ggml_cuda_mmq_get_config_pascal_older(ggml_type type, int J, bool fallback) {
|
||||
constexpr bool use_typical_moe_ncols = false;
|
||||
CASE(GGML_TYPE_Q1_0, 256, 2, 64, 8, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, false, true);
|
||||
CASE(GGML_TYPE_Q1_0, 256, 2, 64, 16, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, false, true);
|
||||
CASE(GGML_TYPE_Q1_0, 256, 2, 64, 32, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, false, true);
|
||||
@@ -269,5 +270,5 @@ static constexpr __host__ __device__ ggml_cuda_mmq_config ggml_cuda_mmq_get_conf
|
||||
CASE(GGML_TYPE_NVFP4, 256, 2, 64, 48, GGML_CUDA_MMQ_SRAM_LAYOUT_NVFP4, MMQ_ITER_K, false, false);
|
||||
CASE(GGML_TYPE_NVFP4, 256, 2, 64, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_NVFP4, MMQ_ITER_K, false, false);
|
||||
|
||||
return ggml_cuda_mmq_config(GGML_TYPE_COUNT, 256, 2, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, 256, false, true);
|
||||
return ggml_cuda_mmq_config(GGML_TYPE_COUNT, 256, 2, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, 256, use_typical_moe_ncols, false, true);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
static constexpr __host__ __device__ ggml_cuda_mmq_config ggml_cuda_mmq_get_config_rdna2(ggml_type type, int J, bool fallback) {
|
||||
constexpr bool use_typical_moe_ncols = false;
|
||||
CASE(GGML_TYPE_Q1_0, 256, 2, 128, 8, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, false, true);
|
||||
CASE(GGML_TYPE_Q1_0, 256, 2, 128, 16, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, false, true);
|
||||
CASE(GGML_TYPE_Q1_0, 256, 2, 128, 32, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, false, true);
|
||||
@@ -269,5 +270,5 @@ static constexpr __host__ __device__ ggml_cuda_mmq_config ggml_cuda_mmq_get_conf
|
||||
CASE(GGML_TYPE_NVFP4, 256, 2, 128, 48, GGML_CUDA_MMQ_SRAM_LAYOUT_NVFP4, MMQ_ITER_K, false, false);
|
||||
CASE(GGML_TYPE_NVFP4, 256, 2, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_NVFP4, MMQ_ITER_K, false, false);
|
||||
|
||||
return ggml_cuda_mmq_config(GGML_TYPE_COUNT, 256, 2, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, 256, false, true);
|
||||
return ggml_cuda_mmq_config(GGML_TYPE_COUNT, 256, 2, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, 256, use_typical_moe_ncols, false, true);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
static constexpr __host__ __device__ ggml_cuda_mmq_config ggml_cuda_mmq_get_config_rdna3_5(ggml_type type, int J, bool fallback) {
|
||||
constexpr bool use_typical_moe_ncols = false;
|
||||
CASE(GGML_TYPE_Q1_0, 128, 2, 64, 16, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, false, true);
|
||||
CASE(GGML_TYPE_Q1_0, 128, 2, 64, 32, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, false, true);
|
||||
CASE(GGML_TYPE_Q1_0, 256, 2, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, false, true);
|
||||
@@ -286,5 +287,5 @@ static constexpr __host__ __device__ ggml_cuda_mmq_config ggml_cuda_mmq_get_conf
|
||||
CASE(GGML_TYPE_NVFP4, 256, 2, 128, 112, GGML_CUDA_MMQ_SRAM_LAYOUT_NVFP4, MMQ_ITER_K, false, false);
|
||||
CASE(GGML_TYPE_NVFP4, 256, 2, 128, 128, GGML_CUDA_MMQ_SRAM_LAYOUT_NVFP4, MMQ_ITER_K, false, false);
|
||||
|
||||
return ggml_cuda_mmq_config(GGML_TYPE_COUNT, 256, 2, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, 256, false, true);
|
||||
return ggml_cuda_mmq_config(GGML_TYPE_COUNT, 256, 2, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, 256, use_typical_moe_ncols, false, true);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
static constexpr __host__ __device__ ggml_cuda_mmq_config ggml_cuda_mmq_get_config_rdna3(ggml_type type, int J, bool fallback) {
|
||||
constexpr bool use_typical_moe_ncols = true;
|
||||
CASE(GGML_TYPE_Q1_0, 128, 2, 64, 16, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, false, true);
|
||||
CASE(GGML_TYPE_Q1_0, 128, 2, 64, 32, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, false, true);
|
||||
CASE(GGML_TYPE_Q1_0, 128, 2, 64, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, false, true);
|
||||
@@ -270,5 +271,5 @@ static constexpr __host__ __device__ ggml_cuda_mmq_config ggml_cuda_mmq_get_conf
|
||||
CASE(GGML_TYPE_NVFP4, 256, 2, 128, 96, GGML_CUDA_MMQ_SRAM_LAYOUT_NVFP4, MMQ_ITER_K, false, false);
|
||||
CASE(GGML_TYPE_NVFP4, 256, 2, 128, 128, GGML_CUDA_MMQ_SRAM_LAYOUT_NVFP4, MMQ_ITER_K, false, false);
|
||||
|
||||
return ggml_cuda_mmq_config(GGML_TYPE_COUNT, 256, 2, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, 256, false, true);
|
||||
return ggml_cuda_mmq_config(GGML_TYPE_COUNT, 256, 2, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, 256, use_typical_moe_ncols, false, true);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
static constexpr __host__ __device__ ggml_cuda_mmq_config ggml_cuda_mmq_get_config_rdna4(ggml_type type, int J, bool fallback) {
|
||||
constexpr bool use_typical_moe_ncols = true;
|
||||
CASE(GGML_TYPE_Q1_0, 128, 2, 64, 16, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, false, true);
|
||||
CASE(GGML_TYPE_Q1_0, 128, 2, 64, 32, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, false, true);
|
||||
CASE(GGML_TYPE_Q1_0, 128, 2, 64, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, MMQ_ITER_K, false, true);
|
||||
@@ -286,5 +287,5 @@ static constexpr __host__ __device__ ggml_cuda_mmq_config ggml_cuda_mmq_get_conf
|
||||
CASE(GGML_TYPE_NVFP4, 256, 2, 128, 112, GGML_CUDA_MMQ_SRAM_LAYOUT_NVFP4, MMQ_ITER_K, false, false);
|
||||
CASE(GGML_TYPE_NVFP4, 256, 2, 128, 128, GGML_CUDA_MMQ_SRAM_LAYOUT_NVFP4, MMQ_ITER_K, false, false);
|
||||
|
||||
return ggml_cuda_mmq_config(GGML_TYPE_COUNT, 256, 2, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, 256, false, true);
|
||||
return ggml_cuda_mmq_config(GGML_TYPE_COUNT, 256, 2, 128, 64, GGML_CUDA_MMQ_SRAM_LAYOUT_Q8_0, 256, use_typical_moe_ncols, false, true);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -170,12 +170,13 @@ struct ggml_cuda_mmq_config {
|
||||
int J; // SRAM tile width in src1->ne[1]/dst->ne[1] direction.
|
||||
ggml_cuda_mmq_sram_layout sram_layout; // SRAM tile length in src0->ne[0]/src1->ne[0] direction (physical 32 bit elements).
|
||||
int K_vram; // VRAM tile length in src0->ne[0]/src1->ne[0] direction (logical elements).
|
||||
bool use_typical_moe_ncols;
|
||||
bool stream_k; // Whether or not to use stream-k decomposition.
|
||||
bool fallback; // Whether a fallback for out-of-bounds check in src0->ne[1] direction is needed.
|
||||
|
||||
constexpr __host__ __device__ ggml_cuda_mmq_config(
|
||||
ggml_type type, int nthreads, int occupancy, int I, int J, ggml_cuda_mmq_sram_layout sram_layout, int K_vram, bool stream_k, bool fallback) :
|
||||
type(type), nthreads(nthreads), occupancy(occupancy), I(I), J(J), sram_layout(sram_layout), K_vram(K_vram), stream_k(stream_k), fallback(fallback) {}
|
||||
ggml_type type, int nthreads, int occupancy, int I, int J, ggml_cuda_mmq_sram_layout sram_layout, int K_vram, bool use_typical_moe_ncols, bool stream_k, bool fallback) :
|
||||
type(type), nthreads(nthreads), occupancy(occupancy), I(I), J(J), sram_layout(sram_layout), K_vram(K_vram), use_typical_moe_ncols(use_typical_moe_ncols), stream_k(stream_k), fallback(fallback) {}
|
||||
|
||||
constexpr __device__ int rows_per_warp() const {
|
||||
#if defined(AMD_MFMA_AVAILABLE) || defined(AMD_WMMA_AVAILABLE)
|
||||
@@ -210,7 +211,7 @@ struct ggml_cuda_mmq_config {
|
||||
static_assert((I_) % 32 == 0, "bad I"); \
|
||||
static_assert((J_) % 8 == 0, "bad J"); \
|
||||
static_assert((K_vram_) % 256 == 0, "bad K_vram"); \
|
||||
return ggml_cuda_mmq_config((type_), (nthreads_), (occupancy_), (I_), (J_), (sram_layout_), (K_vram_), (stream_k_), (fallback_)); \
|
||||
return ggml_cuda_mmq_config((type_), (nthreads_), (occupancy_), (I_), (J_), (sram_layout_), (K_vram_), use_typical_moe_ncols, (stream_k_), (fallback_)); \
|
||||
} \
|
||||
|
||||
#include "mmq-config-pascal-older.cuh"
|
||||
@@ -1473,6 +1474,20 @@ void mul_mat_q_switch_J(ggml_backend_cuda_context & ctx, const mmq_args & args,
|
||||
const int cc = ggml_cuda_info().devices[id].cc;
|
||||
const size_t smpbo = ggml_cuda_info().devices[id].smpbo;
|
||||
|
||||
int64_t ncols_picker = args.ncols_max;
|
||||
if (args.expert_bounds != nullptr && args.nchannels_x > 0) {
|
||||
const int J_max = ggml_cuda_mmq_get_J_max(type, fallback, cc, 128);
|
||||
const ggml_cuda_mmq_config config_max = ggml_cuda_mmq_get_config(type, J_max, fallback, cc);
|
||||
if (config_max.use_typical_moe_ncols) {
|
||||
// Use the typical expert width only for tile selection.
|
||||
// The launch grid still uses args.ncols_max.
|
||||
const int64_t ncols_typical = (args.ncols_dst + args.nchannels_x - 1) / args.nchannels_x;
|
||||
if (ncols_typical >= 1 && ncols_typical < J_max && ncols_typical < ncols_picker) {
|
||||
ncols_picker = ncols_typical;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int J_best = 0;
|
||||
int ntiles_J_best = INT_MAX;
|
||||
|
||||
@@ -1486,7 +1501,7 @@ void mul_mat_q_switch_J(ggml_backend_cuda_context & ctx, const mmq_args & args,
|
||||
continue;
|
||||
}
|
||||
|
||||
const int ntiles_x = (args.ncols_max + config.J - 1) / config.J;
|
||||
const int ntiles_x = (ncols_picker + config.J - 1) / config.J;
|
||||
|
||||
if (ntiles_x < ntiles_J_best) {
|
||||
J_best = J;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -619,6 +620,7 @@ class MODEL_ARCH(IntEnum):
|
||||
PADDLEOCR = auto()
|
||||
MIMO2 = auto()
|
||||
STEP35 = auto()
|
||||
SPARK2_5 = auto()
|
||||
LLAMA_EMBED = auto()
|
||||
MAINCODER = auto()
|
||||
KIMI_LINEAR = auto()
|
||||
@@ -1373,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",
|
||||
@@ -2294,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,
|
||||
@@ -2314,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,
|
||||
@@ -2337,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,
|
||||
@@ -2357,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,
|
||||
@@ -2402,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,
|
||||
@@ -2504,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,
|
||||
@@ -2532,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,
|
||||
@@ -2561,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,
|
||||
@@ -2573,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,
|
||||
@@ -2600,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,
|
||||
@@ -2631,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,
|
||||
@@ -2646,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,
|
||||
@@ -2661,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,
|
||||
@@ -2675,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,
|
||||
@@ -2689,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,
|
||||
@@ -2709,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,
|
||||
@@ -2725,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,
|
||||
@@ -2780,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,
|
||||
@@ -2796,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,
|
||||
@@ -2936,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,
|
||||
@@ -3069,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,
|
||||
@@ -3084,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,
|
||||
@@ -3102,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,
|
||||
@@ -3139,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,
|
||||
@@ -3151,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,
|
||||
@@ -3167,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,
|
||||
@@ -3185,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,
|
||||
@@ -3221,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,
|
||||
@@ -3276,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,
|
||||
@@ -3296,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,
|
||||
@@ -3459,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,
|
||||
@@ -3488,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,
|
||||
@@ -3502,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,
|
||||
@@ -3516,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,
|
||||
@@ -3567,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,
|
||||
@@ -3579,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,
|
||||
@@ -3594,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,
|
||||
@@ -3610,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,
|
||||
@@ -3660,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,
|
||||
@@ -3681,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,
|
||||
@@ -3743,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,
|
||||
@@ -3865,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,
|
||||
@@ -3941,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,
|
||||
@@ -4086,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,
|
||||
@@ -4100,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,
|
||||
@@ -4121,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,
|
||||
@@ -4140,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,
|
||||
@@ -4170,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,
|
||||
@@ -4185,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,
|
||||
@@ -4210,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,
|
||||
@@ -4241,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,
|
||||
@@ -4255,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,
|
||||
@@ -4280,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,
|
||||
@@ -4343,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,
|
||||
@@ -4382,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,
|
||||
@@ -4473,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,
|
||||
@@ -4536,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,
|
||||
@@ -4551,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,
|
||||
@@ -4602,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,
|
||||
@@ -4616,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,
|
||||
@@ -4633,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
|
||||
@@ -4665,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,
|
||||
@@ -4685,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,
|
||||
@@ -4701,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,
|
||||
@@ -4791,6 +4858,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,
|
||||
@@ -4807,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,
|
||||
@@ -4830,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,
|
||||
@@ -4850,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,
|
||||
@@ -4865,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,
|
||||
@@ -4884,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,
|
||||
@@ -4901,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,
|
||||
@@ -4918,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,
|
||||
@@ -4956,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,
|
||||
@@ -5019,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,
|
||||
@@ -5036,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,
|
||||
@@ -5051,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,
|
||||
@@ -5204,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,
|
||||
@@ -5231,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,
|
||||
@@ -5256,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,
|
||||
@@ -5272,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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
@@ -146,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" },
|
||||
|
||||
@@ -147,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,
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
|
||||
|
||||
+81
-29
@@ -1623,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;
|
||||
|
||||
@@ -1635,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 };
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -338,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) + "'");
|
||||
}
|
||||
@@ -2999,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;
|
||||
@@ -3233,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);
|
||||
|
||||
@@ -325,6 +325,14 @@ struct llm_tokenizer_bpe : llm_tokenizer {
|
||||
"[!\"#$%&'()*+,\\-./:;<=>?@\\[\\\\\\]^_`{|}~][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 = {
|
||||
"[가-힣ㄱ-ㆎ]+|[!…“”‘’—:;,、-〿︰-﹏]+|[ㄅ-ㄯ]+|[一-龥-ゟ゠-ヿ]+",
|
||||
@@ -2170,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;
|
||||
|
||||
@@ -66,6 +66,7 @@ enum llama_vocab_pre_type {
|
||||
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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -36,12 +36,7 @@ void llama_model_llada::load_arch_tensors(llama_model_loader &) {
|
||||
|
||||
layer.attn_norm = create_tensor(tn(LLM_TENSOR_ATTN_NORM, "weight", i), { n_embd }, 0);
|
||||
|
||||
// Use separate Q, K, V projections without bias, matching LLaDALlamaBlock
|
||||
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);
|
||||
// No bias for QKV projections as per config: include_bias=false, include_qkv_bias=false
|
||||
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);
|
||||
layer.wo_b = create_tensor(tn(LLM_TENSOR_ATTN_OUT, "bias", i), { n_embd }, TENSOR_NOT_REQUIRED);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user